mirror of
https://github.com/grafana/grafana.git
synced 2025-08-03 06:12:20 +08:00
enhance quota support.
now includes: - perOrg (users, dashboards, datasources, api_keys) - perUser (orgs) - global (users, orgs, dashboards, datasources, api_keys, sessions)
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -254,33 +255,95 @@ func (ctx *Context) JsonApiErr(status int, message string, err error) {
|
||||
ctx.JSON(status, resp)
|
||||
}
|
||||
|
||||
func LimitQuota(target m.QuotaTarget) macaron.Handler {
|
||||
func Quota(target string) macaron.Handler {
|
||||
return func(c *Context) {
|
||||
limitReached, err := QuotaReached(c.OrgId, target)
|
||||
limitReached, err := QuotaReached(c, target)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "failed to get quota", err)
|
||||
return
|
||||
}
|
||||
if limitReached {
|
||||
c.JsonApiErr(403, "Quota reached", nil)
|
||||
c.JsonApiErr(403, fmt.Sprintf("%s Quota reached", target), nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func QuotaReached(org_id int64, target m.QuotaTarget) (bool, error) {
|
||||
func QuotaReached(c *Context, target string) (bool, error) {
|
||||
if !setting.Quota.Enabled {
|
||||
return false, nil
|
||||
}
|
||||
if !target.IsValid() {
|
||||
return true, m.ErrInvalidQuotaTarget
|
||||
|
||||
// get the list of scopes that this target is valid for. Org, User, Global
|
||||
scopes, err := m.GetQuotaScopes(target)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
query := m.GetQuotaByTargetQuery{OrgId: org_id, Target: target}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return true, err
|
||||
}
|
||||
if query.Result.Used >= query.Result.Limit {
|
||||
return true, nil
|
||||
log.Info(fmt.Sprintf("checking quota for %s in scopes %v", target, scopes))
|
||||
|
||||
for _, scope := range scopes {
|
||||
log.Info(fmt.Sprintf("checking scope %s", scope.Name))
|
||||
switch scope.Name {
|
||||
case "global":
|
||||
if scope.DefaultLimit < 0 {
|
||||
continue
|
||||
}
|
||||
if scope.DefaultLimit == 0 {
|
||||
return true, nil
|
||||
}
|
||||
if target == "session" {
|
||||
usedSessions := sessionManager.Count()
|
||||
if int64(usedSessions) > scope.DefaultLimit {
|
||||
log.Info(fmt.Sprintf("%d sessions active, limit is %d", usedSessions, scope.DefaultLimit))
|
||||
return true, nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
query := m.GetGlobalQuotaByTargetQuery{Target: scope.Target}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return true, err
|
||||
}
|
||||
if query.Result.Used >= scope.DefaultLimit {
|
||||
return true, nil
|
||||
}
|
||||
case "org":
|
||||
if !c.IsSignedIn {
|
||||
continue
|
||||
}
|
||||
query := m.GetOrgQuotaByTargetQuery{OrgId: c.OrgId, Target: scope.Target, Default: scope.DefaultLimit}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return true, err
|
||||
}
|
||||
if query.Result.Limit < 0 {
|
||||
continue
|
||||
}
|
||||
if query.Result.Limit == 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if query.Result.Used >= query.Result.Limit {
|
||||
return true, nil
|
||||
}
|
||||
case "user":
|
||||
if !c.IsSignedIn || c.UserId == 0 {
|
||||
continue
|
||||
}
|
||||
query := m.GetUserQuotaByTargetQuery{UserId: c.UserId, Target: scope.Target, Default: scope.DefaultLimit}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return true, err
|
||||
}
|
||||
if query.Result.Limit < 0 {
|
||||
continue
|
||||
}
|
||||
if query.Result.Limit == 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if query.Result.Used >= query.Result.Limit {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user