diff --git a/conf/defaults.ini b/conf/defaults.ini index bfa13c231e5..e1c06a0223c 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -254,8 +254,8 @@ enabled = false path = /var/lib/grafana/dashboards [quota] +enabled = false user = 10 dashboard = 100 data_source = 10 -endpoint = 10 -collector = 10 + diff --git a/main.go b/main.go index cdbf248358c..045527a6811 100644 --- a/main.go +++ b/main.go @@ -15,7 +15,6 @@ import ( "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/metrics" - "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/eventpublisher" "github.com/grafana/grafana/pkg/services/notifications" @@ -57,8 +56,6 @@ func main() { eventpublisher.Init() plugins.Init() - models.InitQuotaDefaults() - if err := notifications.Init(); err != nil { log.Fatal(3, "Notification service failed to initialize", err) } diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index 132e838b534..cc6ccd29064 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -88,7 +88,7 @@ func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) { dash := cmd.GetDashboardModel() if dash.Id == 0 { - limitReached, err := m.QuotaReached(cmd.OrgId, m.QUOTA_DASHBOARD) + limitReached, err := middleware.QuotaReached(cmd.OrgId, m.QUOTA_DASHBOARD) if err != nil { c.JsonApiErr(500, "failed to get quota", err) return diff --git a/pkg/api/quota.go b/pkg/api/quota.go index 1811270c3a4..9c5dd615247 100644 --- a/pkg/api/quota.go +++ b/pkg/api/quota.go @@ -16,6 +16,17 @@ func GetOrgQuotas(c *middleware.Context) Response { return Json(200, query.Result) } +// allow users to query the quotas of their own org. +func GetQuotas(c *middleware.Context) Response { + query := m.GetQuotasQuery{OrgId: c.OrgId} + + if err := bus.Dispatch(&query); err != nil { + return ApiError(500, "Failed to get quotas", err) + } + + return Json(200, query.Result) +} + func UpdateOrgQuota(c *middleware.Context, cmd m.UpdateQuotaCmd) Response { cmd.OrgId = c.ParamsInt64(":orgId") cmd.Target = m.QuotaTarget(c.Params(":target")) diff --git a/pkg/middleware/middleware.go b/pkg/middleware/middleware.go index a6963af61ed..1b218a6eedc 100644 --- a/pkg/middleware/middleware.go +++ b/pkg/middleware/middleware.go @@ -256,7 +256,7 @@ func (ctx *Context) JsonApiErr(status int, message string, err error) { func LimitQuota(target m.QuotaTarget) macaron.Handler { return func(c *Context) { - limitReached, err := m.QuotaReached(c.OrgId, target) + limitReached, err := QuotaReached(c.OrgId, target) if err != nil { c.JsonApiErr(500, "failed to get quota", err) return @@ -267,3 +267,20 @@ func LimitQuota(target m.QuotaTarget) macaron.Handler { } } } + +func QuotaReached(org_id int64, target m.QuotaTarget) (bool, error) { + if !setting.Quota.Enabled { + return false, nil + } + if !target.IsValid() { + return true, m.ErrInvalidQuotaTarget + } + 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 + } + return false, nil +} diff --git a/pkg/models/quotas.go b/pkg/models/quotas.go index 27ab74cb1e2..75df5cd3765 100644 --- a/pkg/models/quotas.go +++ b/pkg/models/quotas.go @@ -2,7 +2,6 @@ package models import ( "errors" - "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/setting" "time" ) @@ -13,31 +12,15 @@ const ( QUOTA_USER QuotaTarget = "user" //SQL table to query. ie. "select count(*) from user where org_id=?" QUOTA_DATASOURCE QuotaTarget = "data_source" QUOTA_DASHBOARD QuotaTarget = "dashboard" - QUOTA_ENDPOINT QuotaTarget = "endpoint" - QUOTA_COLLECTOR QuotaTarget = "collector" ) var ErrInvalidQuotaTarget = errors.New("Invalid quota target") func (q QuotaTarget) IsValid() bool { - _, ok := DefaultQuotas[q] + _, ok := setting.Quota.Default[string(q)] return ok } -// defaults are set from settings package. -var DefaultQuotas map[QuotaTarget]int64 - -func InitQuotaDefaults() { - // set global defaults. - DefaultQuotas = make(map[QuotaTarget]int64) - quota := setting.Cfg.Section("quota") - DefaultQuotas[QUOTA_USER] = quota.Key("user").MustInt64(10) - DefaultQuotas[QUOTA_DATASOURCE] = quota.Key("data_source").MustInt64(10) - DefaultQuotas[QUOTA_DASHBOARD] = quota.Key("dashboard").MustInt64(10) - DefaultQuotas[QUOTA_ENDPOINT] = quota.Key("endpoint").MustInt64(10) - DefaultQuotas[QUOTA_COLLECTOR] = quota.Key("collector").MustInt64(10) -} - type Quota struct { Id int64 OrgId int64 @@ -70,17 +53,3 @@ type UpdateQuotaCmd struct { Limit int64 `json:"limit"` OrgId int64 `json:"-"` } - -func QuotaReached(org_id int64, target QuotaTarget) (bool, error) { - if !target.IsValid() { - return true, ErrInvalidQuotaTarget - } - query := 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 - } - return false, nil -} diff --git a/pkg/services/sqlstore/quota.go b/pkg/services/sqlstore/quota.go index a5ce44fc4b6..b54f6a83a57 100644 --- a/pkg/services/sqlstore/quota.go +++ b/pkg/services/sqlstore/quota.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/setting" ) func init() { @@ -25,7 +26,7 @@ func GetQuotaByTarget(query *m.GetQuotaByTargetQuery) error { if err != nil { return err } else if has == false { - quota.Limit = m.DefaultQuotas[query.Target] + quota.Limit = setting.Quota.Default[string(query.Target)] } //get quota used. @@ -57,11 +58,11 @@ func GetQuotas(query *m.GetQuotasQuery) error { seenTargets[q.Target] = true } - for t, v := range m.DefaultQuotas { - if _, ok := seenTargets[t]; !ok { + for t, v := range setting.Quota.Default { + if _, ok := seenTargets[m.QuotaTarget(t)]; !ok { quotas = append(quotas, &m.Quota{ OrgId: query.OrgId, - Target: t, + Target: m.QuotaTarget(t), Limit: v, }) } diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index a8b3383270e..8ff58402c20 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -126,6 +126,9 @@ var ( // SMTP email settings Smtp SmtpSettings + + // QUOTA + Quota QuotaSettings ) type CommandLineArgs struct { @@ -434,6 +437,7 @@ func NewConfigContext(args *CommandLineArgs) { readSessionConfig() readSmtpSettings() + readQuotaSettings() if VerifyEmailEnabled && !Smtp.Enabled { log.Warn("require_email_validation is enabled but smpt is disabled") diff --git a/pkg/setting/setting_quota.go b/pkg/setting/setting_quota.go new file mode 100644 index 00000000000..d6ca0cd7ba8 --- /dev/null +++ b/pkg/setting/setting_quota.go @@ -0,0 +1,17 @@ +package setting + +type QuotaSettings struct { + Enabled bool + Default map[string]int64 +} + +func readQuotaSettings() { + // set global defaults. + DefaultQuotas := make(map[string]int64) + quota := Cfg.Section("quota") + Quota.Enabled = quota.Key("enabled").MustBool(false) + DefaultQuotas["user"] = quota.Key("user").MustInt64(10) + DefaultQuotas["data_source"] = quota.Key("data_source").MustInt64(10) + DefaultQuotas["dashboard"] = quota.Key("dashboard").MustInt64(10) + Quota.Default = DefaultQuotas +}