This reverts commit 326ea86a57.
This commit is contained in:
@@ -98,6 +98,34 @@ func (m *SQLStoreMock) WithNewDbSession(ctx context.Context, callback sqlstore.D
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) GetOrgQuotas(ctx context.Context, query *models.GetOrgQuotasQuery) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) UpdateOrgQuota(ctx context.Context, cmd *models.UpdateOrgQuotaCmd) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) GetUserQuotaByTarget(ctx context.Context, query *models.GetUserQuotaByTargetQuery) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) GetUserQuotas(ctx context.Context, query *models.GetUserQuotasQuery) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) UpdateUserQuota(ctx context.Context, cmd *models.UpdateUserQuotaCmd) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) GetGlobalQuotaByTarget(ctx context.Context, query *models.GetGlobalQuotaByTargetQuery) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) WithTransactionalDbSession(ctx context.Context, callback sqlstore.DBTransactionFunc) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
const (
|
||||
alertRuleTarget = "alert_rule"
|
||||
dashboardTarget = "dashboard"
|
||||
filesTarget = "file"
|
||||
)
|
||||
|
||||
type targetCount struct {
|
||||
Count int64
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
quota := models.Quota{
|
||||
Target: query.Target,
|
||||
OrgId: query.OrgId,
|
||||
}
|
||||
has, err := sess.Get("a)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
quota.Limit = query.Default
|
||||
}
|
||||
|
||||
var used int64
|
||||
if query.Target != alertRuleTarget || query.UnifiedAlertingEnabled {
|
||||
// get quota used.
|
||||
rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM %s WHERE org_id=?",
|
||||
dialect.Quote(query.Target))
|
||||
|
||||
if query.Target == dashboardTarget {
|
||||
rawSQL += fmt.Sprintf(" AND is_folder=%s", dialect.BooleanStr(false))
|
||||
}
|
||||
// need to account for removing service accounts from the user table
|
||||
if query.Target == "org_user" {
|
||||
rawSQL = fmt.Sprintf("SELECT COUNT(*) as count from (select user_id from %s where org_id=? AND user_id IN (SELECT id as user_id FROM %s WHERE is_service_account=%s)) as subq",
|
||||
dialect.Quote(query.Target),
|
||||
dialect.Quote("user"),
|
||||
dialect.BooleanStr(false),
|
||||
)
|
||||
}
|
||||
resp := make([]*targetCount, 0)
|
||||
if err := sess.SQL(rawSQL, query.OrgId).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
used = resp[0].Count
|
||||
}
|
||||
|
||||
query.Result = &models.OrgQuotaDTO{
|
||||
Target: query.Target,
|
||||
Limit: quota.Limit,
|
||||
OrgId: query.OrgId,
|
||||
Used: used,
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetOrgQuotas(ctx context.Context, query *models.GetOrgQuotasQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
quotas := make([]*models.Quota, 0)
|
||||
if err := sess.Table("quota").Where("org_id=? AND user_id=0", query.OrgId).Find("as); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defaultQuotas := setting.Quota.Org.ToMap()
|
||||
|
||||
seenTargets := make(map[string]bool)
|
||||
for _, q := range quotas {
|
||||
seenTargets[q.Target] = true
|
||||
}
|
||||
|
||||
for t, v := range defaultQuotas {
|
||||
if _, ok := seenTargets[t]; !ok {
|
||||
quotas = append(quotas, &models.Quota{
|
||||
OrgId: query.OrgId,
|
||||
Target: t,
|
||||
Limit: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
result := make([]*models.OrgQuotaDTO, len(quotas))
|
||||
for i, q := range quotas {
|
||||
var used int64
|
||||
var rawSQL string
|
||||
if q.Target != alertRuleTarget || query.UnifiedAlertingEnabled {
|
||||
// get quota used.
|
||||
rawSQL = fmt.Sprintf("SELECT COUNT(*) as count from %s where org_id=?", dialect.Quote(q.Target))
|
||||
|
||||
// need to account for removing service accounts from the user table
|
||||
if q.Target == "org_user" {
|
||||
rawSQL = fmt.Sprintf("SELECT COUNT(*) as count from (select user_id from %s where org_id=? AND user_id IN (SELECT id as user_id FROM %s WHERE is_service_account=%s)) as subq",
|
||||
dialect.Quote(q.Target),
|
||||
dialect.Quote("user"),
|
||||
dialect.BooleanStr(false),
|
||||
)
|
||||
}
|
||||
resp := make([]*targetCount, 0)
|
||||
if err := sess.SQL(rawSQL, q.OrgId).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
used = resp[0].Count
|
||||
}
|
||||
result[i] = &models.OrgQuotaDTO{
|
||||
Target: q.Target,
|
||||
Limit: q.Limit,
|
||||
OrgId: q.OrgId,
|
||||
Used: used,
|
||||
}
|
||||
}
|
||||
query.Result = result
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) UpdateOrgQuota(ctx context.Context, cmd *models.UpdateOrgQuotaCmd) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
// Check if quota is already defined in the DB
|
||||
quota := models.Quota{
|
||||
Target: cmd.Target,
|
||||
OrgId: cmd.OrgId,
|
||||
}
|
||||
has, err := sess.Get("a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
quota.Updated = time.Now()
|
||||
quota.Limit = cmd.Limit
|
||||
if !has {
|
||||
quota.Created = time.Now()
|
||||
// No quota in the DB for this target, so create a new one.
|
||||
if _, err := sess.Insert("a); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// update existing quota entry in the DB.
|
||||
_, err := sess.ID(quota.Id).Update("a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetUserQuotaByTarget(ctx context.Context, query *models.GetUserQuotaByTargetQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
quota := models.Quota{
|
||||
Target: query.Target,
|
||||
UserId: query.UserId,
|
||||
}
|
||||
has, err := sess.Get("a)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
quota.Limit = query.Default
|
||||
}
|
||||
|
||||
var used int64
|
||||
if query.Target != alertRuleTarget || query.UnifiedAlertingEnabled {
|
||||
// get quota used.
|
||||
rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s where user_id=?", dialect.Quote(query.Target))
|
||||
resp := make([]*targetCount, 0)
|
||||
if err := sess.SQL(rawSQL, query.UserId).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
used = resp[0].Count
|
||||
}
|
||||
|
||||
query.Result = &models.UserQuotaDTO{
|
||||
Target: query.Target,
|
||||
Limit: quota.Limit,
|
||||
UserId: query.UserId,
|
||||
Used: used,
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetUserQuotas(ctx context.Context, query *models.GetUserQuotasQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
quotas := make([]*models.Quota, 0)
|
||||
if err := sess.Table("quota").Where("user_id=? AND org_id=0", query.UserId).Find("as); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defaultQuotas := setting.Quota.User.ToMap()
|
||||
|
||||
seenTargets := make(map[string]bool)
|
||||
for _, q := range quotas {
|
||||
seenTargets[q.Target] = true
|
||||
}
|
||||
|
||||
for t, v := range defaultQuotas {
|
||||
if _, ok := seenTargets[t]; !ok {
|
||||
quotas = append(quotas, &models.Quota{
|
||||
UserId: query.UserId,
|
||||
Target: t,
|
||||
Limit: v,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
result := make([]*models.UserQuotaDTO, len(quotas))
|
||||
for i, q := range quotas {
|
||||
var used int64
|
||||
if q.Target != alertRuleTarget || query.UnifiedAlertingEnabled {
|
||||
// get quota used.
|
||||
rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s where user_id=?", dialect.Quote(q.Target))
|
||||
resp := make([]*targetCount, 0)
|
||||
if err := sess.SQL(rawSQL, q.UserId).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
used = resp[0].Count
|
||||
}
|
||||
result[i] = &models.UserQuotaDTO{
|
||||
Target: q.Target,
|
||||
Limit: q.Limit,
|
||||
UserId: q.UserId,
|
||||
Used: used,
|
||||
}
|
||||
}
|
||||
query.Result = result
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) UpdateUserQuota(ctx context.Context, cmd *models.UpdateUserQuotaCmd) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
// Check if quota is already defined in the DB
|
||||
quota := models.Quota{
|
||||
Target: cmd.Target,
|
||||
UserId: cmd.UserId,
|
||||
}
|
||||
has, err := sess.Get("a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
quota.Updated = time.Now()
|
||||
quota.Limit = cmd.Limit
|
||||
if !has {
|
||||
quota.Created = time.Now()
|
||||
// No quota in the DB for this target, so create a new one.
|
||||
if _, err := sess.Insert("a); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// update existing quota entry in the DB.
|
||||
_, err := sess.ID(quota.Id).Update("a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetGlobalQuotaByTarget(ctx context.Context, query *models.GetGlobalQuotaByTargetQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
var used int64
|
||||
|
||||
if query.Target == filesTarget {
|
||||
// get quota used.
|
||||
rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM %s",
|
||||
dialect.Quote("file"))
|
||||
|
||||
notFolderCondition := fmt.Sprintf(" WHERE path NOT LIKE '%s'", "%/")
|
||||
resp := make([]*targetCount, 0)
|
||||
if err := sess.SQL(rawSQL + notFolderCondition).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
used = resp[0].Count
|
||||
} else if query.Target != alertRuleTarget || query.UnifiedAlertingEnabled {
|
||||
// get quota used.
|
||||
rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM %s",
|
||||
dialect.Quote(query.Target))
|
||||
|
||||
if query.Target == dashboardTarget {
|
||||
rawSQL += fmt.Sprintf(" WHERE is_folder=%s", dialect.BooleanStr(false))
|
||||
}
|
||||
// removing service accounts from count
|
||||
if query.Target == dialect.Quote("user") {
|
||||
rawSQL += fmt.Sprintf(" WHERE is_service_account=%s", dialect.BooleanStr(false))
|
||||
}
|
||||
resp := make([]*targetCount, 0)
|
||||
if err := sess.SQL(rawSQL).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
used = resp[0].Count
|
||||
}
|
||||
|
||||
query.Result = &models.GlobalQuotaDTO{
|
||||
Target: query.Target,
|
||||
Limit: query.Default,
|
||||
Used: used,
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIntegrationQuotaCommandsAndQueries(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
sqlStore := InitTestDB(t)
|
||||
userId := int64(1)
|
||||
orgId := int64(0)
|
||||
|
||||
setting.Quota = setting.QuotaSettings{
|
||||
Enabled: true,
|
||||
Org: &setting.OrgQuota{
|
||||
User: 5,
|
||||
Dashboard: 5,
|
||||
DataSource: 5,
|
||||
ApiKey: 5,
|
||||
AlertRule: 5,
|
||||
},
|
||||
User: &setting.UserQuota{
|
||||
Org: 5,
|
||||
},
|
||||
Global: &setting.GlobalQuota{
|
||||
Org: 5,
|
||||
User: 5,
|
||||
Dashboard: 5,
|
||||
DataSource: 5,
|
||||
ApiKey: 5,
|
||||
Session: 5,
|
||||
AlertRule: 5,
|
||||
},
|
||||
}
|
||||
createUserCmd := user.CreateUserCommand{
|
||||
Name: "TestUser",
|
||||
OrgID: orgId,
|
||||
SkipOrgSetup: true,
|
||||
}
|
||||
user, err := sqlStore.CreateUser(context.Background(), createUserCmd)
|
||||
require.NoError(t, err)
|
||||
// create a new org and add user_id 1 as admin.
|
||||
// we will then have an org with 1 user. and a user
|
||||
// with 1 org.
|
||||
userCmd := models.CreateOrgCommand{
|
||||
Name: "TestOrg",
|
||||
UserId: user.ID,
|
||||
}
|
||||
|
||||
err = sqlStore.CreateOrg(context.Background(), &userCmd)
|
||||
require.NoError(t, err)
|
||||
orgId = userCmd.Result.Id
|
||||
|
||||
t.Run("Given saved org quota for users", func(t *testing.T) {
|
||||
orgCmd := models.UpdateOrgQuotaCmd{
|
||||
OrgId: orgId,
|
||||
Target: "org_user",
|
||||
Limit: 10,
|
||||
}
|
||||
err := sqlStore.UpdateOrgQuota(context.Background(), &orgCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("Should be able to get saved quota by org id and target", func(t *testing.T) {
|
||||
query := models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: "org_user", Default: 1}
|
||||
err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(10), query.Result.Limit)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get default quota by org id and target", func(t *testing.T) {
|
||||
query := models.GetOrgQuotaByTargetQuery{OrgId: 123, Target: "org_user", Default: 11}
|
||||
err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(11), query.Result.Limit)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get used org quota when rows exist", func(t *testing.T) {
|
||||
query := models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: "org_user", Default: 11}
|
||||
err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(1), query.Result.Used)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get used org quota when no rows exist", func(t *testing.T) {
|
||||
query := models.GetOrgQuotaByTargetQuery{OrgId: 2, Target: "org_user", Default: 11}
|
||||
err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), query.Result.Used)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get zero used org alert quota when table does not exist (ngalert is not enabled - default case)", func(t *testing.T) {
|
||||
query := models.GetOrgQuotaByTargetQuery{OrgId: 2, Target: "alert", Default: 11}
|
||||
err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), query.Result.Used)
|
||||
})
|
||||
|
||||
t.Run("Should be able to quota list for org", func(t *testing.T) {
|
||||
query := models.GetOrgQuotasQuery{OrgId: orgId}
|
||||
err = sqlStore.GetOrgQuotas(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, query.Result, 5)
|
||||
for _, res := range query.Result {
|
||||
limit := int64(5) // default quota limit
|
||||
used := int64(0)
|
||||
if res.Target == "org_user" {
|
||||
limit = 10 // customized quota limit.
|
||||
used = 1
|
||||
}
|
||||
require.Equal(t, limit, res.Limit)
|
||||
require.Equal(t, used, res.Used)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Given saved org quota for dashboards", func(t *testing.T) {
|
||||
orgCmd := models.UpdateOrgQuotaCmd{
|
||||
OrgId: orgId,
|
||||
Target: dashboardTarget,
|
||||
Limit: 10,
|
||||
}
|
||||
err := sqlStore.UpdateOrgQuota(context.Background(), &orgCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("Should be able to get saved quota by org id and target", func(t *testing.T) {
|
||||
query := models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: dashboardTarget, Default: 1}
|
||||
err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(10), query.Result.Limit)
|
||||
require.Equal(t, int64(0), query.Result.Used)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Given saved user quota for org", func(t *testing.T) {
|
||||
userQuotaCmd := models.UpdateUserQuotaCmd{
|
||||
UserId: userId,
|
||||
Target: "org_user",
|
||||
Limit: 10,
|
||||
}
|
||||
err := sqlStore.UpdateUserQuota(context.Background(), &userQuotaCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("Should be able to get saved quota by user id and target", func(t *testing.T) {
|
||||
query := models.GetUserQuotaByTargetQuery{UserId: userId, Target: "org_user", Default: 1}
|
||||
err = sqlStore.GetUserQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(10), query.Result.Limit)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get default quota by user id and target", func(t *testing.T) {
|
||||
query := models.GetUserQuotaByTargetQuery{UserId: 9, Target: "org_user", Default: 11}
|
||||
err = sqlStore.GetUserQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(11), query.Result.Limit)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get used user quota when rows exist", func(t *testing.T) {
|
||||
query := models.GetUserQuotaByTargetQuery{UserId: userId, Target: "org_user", Default: 11}
|
||||
err = sqlStore.GetUserQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(1), query.Result.Used)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get used user quota when no rows exist", func(t *testing.T) {
|
||||
query := models.GetUserQuotaByTargetQuery{UserId: 2, Target: "org_user", Default: 11}
|
||||
err = sqlStore.GetUserQuotaByTarget(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), query.Result.Used)
|
||||
})
|
||||
|
||||
t.Run("Should be able to quota list for user", func(t *testing.T) {
|
||||
query := models.GetUserQuotasQuery{UserId: userId}
|
||||
err = sqlStore.GetUserQuotas(context.Background(), &query)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, query.Result, 1)
|
||||
require.Equal(t, int64(10), query.Result[0].Limit)
|
||||
require.Equal(t, int64(1), query.Result[0].Used)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Should be able to global user quota", func(t *testing.T) {
|
||||
query := models.GetGlobalQuotaByTargetQuery{Target: "user", Default: 5}
|
||||
err = sqlStore.GetGlobalQuotaByTarget(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, int64(5), query.Result.Limit)
|
||||
require.Equal(t, int64(1), query.Result.Used)
|
||||
})
|
||||
|
||||
t.Run("Should be able to global org quota", func(t *testing.T) {
|
||||
query := models.GetGlobalQuotaByTargetQuery{Target: "org", Default: 5}
|
||||
err = sqlStore.GetGlobalQuotaByTarget(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, int64(5), query.Result.Limit)
|
||||
require.Equal(t, int64(1), query.Result.Used)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get zero used global alert quota when table does not exist (ngalert is not enabled - default case)", func(t *testing.T) {
|
||||
query := models.GetGlobalQuotaByTargetQuery{Target: "alert_rule", Default: 5}
|
||||
err = sqlStore.GetGlobalQuotaByTarget(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, int64(5), query.Result.Limit)
|
||||
require.Equal(t, int64(0), query.Result.Used)
|
||||
})
|
||||
|
||||
t.Run("Should be able to global dashboard quota", func(t *testing.T) {
|
||||
query := models.GetGlobalQuotaByTargetQuery{Target: dashboardTarget, Default: 5}
|
||||
err = sqlStore.GetGlobalQuotaByTarget(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, int64(5), query.Result.Limit)
|
||||
require.Equal(t, int64(0), query.Result.Used)
|
||||
})
|
||||
|
||||
// related: https://github.com/grafana/grafana/issues/14342
|
||||
t.Run("Should org quota updating is successful even if it called multiple time", func(t *testing.T) {
|
||||
orgCmd := models.UpdateOrgQuotaCmd{
|
||||
OrgId: orgId,
|
||||
Target: "org_user",
|
||||
Limit: 5,
|
||||
}
|
||||
err := sqlStore.UpdateOrgQuota(context.Background(), &orgCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: "org_user", Default: 1}
|
||||
err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(5), query.Result.Limit)
|
||||
|
||||
// XXX: resolution of `Updated` column is 1sec, so this makes delay
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
orgCmd = models.UpdateOrgQuotaCmd{
|
||||
OrgId: orgId,
|
||||
Target: "org_user",
|
||||
Limit: 10,
|
||||
}
|
||||
err = sqlStore.UpdateOrgQuota(context.Background(), &orgCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
query = models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: "org_user", Default: 1}
|
||||
err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(10), query.Result.Limit)
|
||||
})
|
||||
|
||||
// related: https://github.com/grafana/grafana/issues/14342
|
||||
t.Run("Should user quota updating is successful even if it called multiple time", func(t *testing.T) {
|
||||
userQuotaCmd := models.UpdateUserQuotaCmd{
|
||||
UserId: userId,
|
||||
Target: "org_user",
|
||||
Limit: 5,
|
||||
}
|
||||
err := sqlStore.UpdateUserQuota(context.Background(), &userQuotaCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetUserQuotaByTargetQuery{UserId: userId, Target: "org_user", Default: 1}
|
||||
err = sqlStore.GetUserQuotaByTarget(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(5), query.Result.Limit)
|
||||
|
||||
// XXX: resolution of `Updated` column is 1sec, so this makes delay
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
userQuotaCmd = models.UpdateUserQuotaCmd{
|
||||
UserId: userId,
|
||||
Target: "org_user",
|
||||
Limit: 10,
|
||||
}
|
||||
err = sqlStore.UpdateUserQuota(context.Background(), &userQuotaCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
query = models.GetUserQuotaByTargetQuery{UserId: userId, Target: "org_user", Default: 1}
|
||||
err = sqlStore.GetUserQuotaByTarget(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(10), query.Result.Limit)
|
||||
})
|
||||
}
|
||||
@@ -23,6 +23,13 @@ type Store interface {
|
||||
GetSignedInUser(ctx context.Context, query *models.GetSignedInUserQuery) error
|
||||
WithDbSession(ctx context.Context, callback DBTransactionFunc) error
|
||||
WithNewDbSession(ctx context.Context, callback DBTransactionFunc) error
|
||||
GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error
|
||||
GetOrgQuotas(ctx context.Context, query *models.GetOrgQuotasQuery) error
|
||||
UpdateOrgQuota(ctx context.Context, cmd *models.UpdateOrgQuotaCmd) error
|
||||
GetUserQuotaByTarget(ctx context.Context, query *models.GetUserQuotaByTargetQuery) error
|
||||
GetUserQuotas(ctx context.Context, query *models.GetUserQuotasQuery) error
|
||||
UpdateUserQuota(ctx context.Context, cmd *models.UpdateUserQuotaCmd) error
|
||||
GetGlobalQuotaByTarget(ctx context.Context, query *models.GetGlobalQuotaByTargetQuery) error
|
||||
WithTransactionalDbSession(ctx context.Context, callback DBTransactionFunc) error
|
||||
InTransaction(ctx context.Context, fn func(ctx context.Context) error) error
|
||||
Migrate(bool) error
|
||||
|
||||
Reference in New Issue
Block a user