From 2c73f15839f0b6d56e1d9497e1136d629143ea58 Mon Sep 17 00:00:00 2001 From: Ieva Date: Wed, 15 Nov 2023 16:45:49 +0000 Subject: [PATCH] Revert "Revert "RBAC: remove dashboard ACL logic from dash store, service #78130" (#78203) Revert "Revert "RBAC: remove dashboard ACL logic from dash store, service #78130 (#78198)" This reverts commit 8057b9298de715d8cb4354e83198f6cdde5ead7b. --- pkg/api/admin_users.go | 6 - pkg/services/dashboards/dashboard.go | 6 - .../dashboards/dashboard_service_mock.go | 54 ---- pkg/services/dashboards/database/acl.go | 103 ------ pkg/services/dashboards/database/acl_test.go | 299 ------------------ pkg/services/dashboards/database/database.go | 30 -- .../database/database_folder_test.go | 27 ++ .../dashboards/database/database_test.go | 15 - pkg/services/dashboards/models.go | 6 - .../dashboards/service/dashboard_service.go | 12 - .../service/dashboard_service_test.go | 45 --- pkg/services/dashboards/store_mock.go | 54 ---- pkg/services/team/teamimpl/store_test.go | 145 --------- pkg/services/user/userimpl/store_test.go | 151 --------- 14 files changed, 27 insertions(+), 926 deletions(-) delete mode 100644 pkg/services/dashboards/database/acl.go delete mode 100644 pkg/services/dashboards/database/acl_test.go diff --git a/pkg/api/admin_users.go b/pkg/api/admin_users.go index 6539fb3de0b..65b231323bc 100644 --- a/pkg/api/admin_users.go +++ b/pkg/api/admin_users.go @@ -227,12 +227,6 @@ func (hs *HTTPServer) AdminDeleteUser(c *contextmodel.ReqContext) response.Respo } return nil }) - g.Go(func() error { - if err := hs.DashboardService.DeleteACLByUser(ctx, cmd.UserID); err != nil { - return err - } - return nil - }) g.Go(func() error { if err := hs.preferenceService.DeleteByUser(ctx, cmd.UserID); err != nil { return err diff --git a/pkg/services/dashboards/dashboard.go b/pkg/services/dashboards/dashboard.go index dd2a8268de7..c94da1f3f3b 100644 --- a/pkg/services/dashboards/dashboard.go +++ b/pkg/services/dashboards/dashboard.go @@ -17,15 +17,12 @@ type DashboardService interface { DeleteDashboard(ctx context.Context, dashboardId int64, orgId int64) error FindDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) GetDashboard(ctx context.Context, query *GetDashboardQuery) (*Dashboard, error) - GetDashboardACLInfoList(ctx context.Context, query *GetDashboardACLInfoListQuery) ([]*DashboardACLInfoDTO, error) GetDashboards(ctx context.Context, query *GetDashboardsQuery) ([]*Dashboard, error) GetDashboardTags(ctx context.Context, query *GetDashboardTagsQuery) ([]*DashboardTagCloudItem, error) GetDashboardUIDByID(ctx context.Context, query *GetDashboardRefByIDQuery) (*DashboardRef, error) ImportDashboard(ctx context.Context, dto *SaveDashboardDTO) (*Dashboard, error) SaveDashboard(ctx context.Context, dto *SaveDashboardDTO, allowUiUpdate bool) (*Dashboard, error) SearchDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) (model.HitList, error) - UpdateDashboardACL(ctx context.Context, uid int64, items []*DashboardACL) error - DeleteACLByUser(ctx context.Context, userID int64) error CountInFolder(ctx context.Context, orgID int64, folderUID string, user identity.Requester) (int64, error) } @@ -56,7 +53,6 @@ type Store interface { DeleteOrphanedProvisionedDashboards(ctx context.Context, cmd *DeleteOrphanedProvisionedDashboardsCommand) error FindDashboards(ctx context.Context, query *FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) GetDashboard(ctx context.Context, query *GetDashboardQuery) (*Dashboard, error) - GetDashboardACLInfoList(ctx context.Context, query *GetDashboardACLInfoListQuery) ([]*DashboardACLInfoDTO, error) GetDashboardUIDByID(ctx context.Context, query *GetDashboardRefByIDQuery) (*DashboardRef, error) GetDashboards(ctx context.Context, query *GetDashboardsQuery) ([]*Dashboard, error) // GetDashboardsByPluginID retrieves dashboards identified by plugin. @@ -70,10 +66,8 @@ type Store interface { SaveDashboard(ctx context.Context, cmd SaveDashboardCommand) (*Dashboard, error) SaveProvisionedDashboard(ctx context.Context, cmd SaveDashboardCommand, provisioning *DashboardProvisioning) (*Dashboard, error) UnprovisionDashboard(ctx context.Context, id int64) error - UpdateDashboardACL(ctx context.Context, uid int64, items []*DashboardACL) error // ValidateDashboardBeforeSave validates a dashboard before save. ValidateDashboardBeforeSave(ctx context.Context, dashboard *Dashboard, overwrite bool) (bool, error) - DeleteACLByUser(context.Context, int64) error Count(context.Context, *quota.ScopeParameters) (*quota.Map, error) // CountDashboardsInFolder returns the number of dashboards associated with diff --git a/pkg/services/dashboards/dashboard_service_mock.go b/pkg/services/dashboards/dashboard_service_mock.go index e4c47eb8c5e..987252cab7d 100644 --- a/pkg/services/dashboards/dashboard_service_mock.go +++ b/pkg/services/dashboards/dashboard_service_mock.go @@ -64,20 +64,6 @@ func (_m *FakeDashboardService) CountInFolder(ctx context.Context, orgID int64, return r0, r1 } -// DeleteACLByUser provides a mock function with given fields: ctx, userID -func (_m *FakeDashboardService) DeleteACLByUser(ctx context.Context, userID int64) error { - ret := _m.Called(ctx, userID) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { - r0 = rf(ctx, userID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - // DeleteDashboard provides a mock function with given fields: ctx, dashboardId, orgId func (_m *FakeDashboardService) DeleteDashboard(ctx context.Context, dashboardId int64, orgId int64) error { ret := _m.Called(ctx, dashboardId, orgId) @@ -144,32 +130,6 @@ func (_m *FakeDashboardService) GetDashboard(ctx context.Context, query *GetDash return r0, r1 } -// GetDashboardACLInfoList provides a mock function with given fields: ctx, query -func (_m *FakeDashboardService) GetDashboardACLInfoList(ctx context.Context, query *GetDashboardACLInfoListQuery) ([]*DashboardACLInfoDTO, error) { - ret := _m.Called(ctx, query) - - var r0 []*DashboardACLInfoDTO - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardACLInfoListQuery) ([]*DashboardACLInfoDTO, error)); ok { - return rf(ctx, query) - } - if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardACLInfoListQuery) []*DashboardACLInfoDTO); ok { - r0 = rf(ctx, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*DashboardACLInfoDTO) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *GetDashboardACLInfoListQuery) error); ok { - r1 = rf(ctx, query) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // GetDashboardTags provides a mock function with given fields: ctx, query func (_m *FakeDashboardService) GetDashboardTags(ctx context.Context, query *GetDashboardTagsQuery) ([]*DashboardTagCloudItem, error) { ret := _m.Called(ctx, query) @@ -326,20 +286,6 @@ func (_m *FakeDashboardService) SearchDashboards(ctx context.Context, query *Fin return r0, r1 } -// UpdateDashboardACL provides a mock function with given fields: ctx, uid, items -func (_m *FakeDashboardService) UpdateDashboardACL(ctx context.Context, uid int64, items []*DashboardACL) error { - ret := _m.Called(ctx, uid, items) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, int64, []*DashboardACL) error); ok { - r0 = rf(ctx, uid, items) - } else { - r0 = ret.Error(0) - } - - return r0 -} - type mockConstructorTestingTNewFakeDashboardService interface { mock.TestingT Cleanup(func()) diff --git a/pkg/services/dashboards/database/acl.go b/pkg/services/dashboards/database/acl.go deleted file mode 100644 index 5fb35298280..00000000000 --- a/pkg/services/dashboards/database/acl.go +++ /dev/null @@ -1,103 +0,0 @@ -package database - -import ( - "context" - - "github.com/grafana/grafana/pkg/infra/db" - "github.com/grafana/grafana/pkg/services/dashboards" -) - -// GetDashboardACLInfoList returns a list of permissions for a dashboard. They can be fetched from three -// different places. -// 1) Permissions for the dashboard -// 2) permissions for its parent folder -// 3) if no specific permissions have been set for the dashboard or its parent folder then get the default permissions -func (d *dashboardStore) GetDashboardACLInfoList(ctx context.Context, query *dashboards.GetDashboardACLInfoListQuery) ([]*dashboards.DashboardACLInfoDTO, error) { - queryResult := make([]*dashboards.DashboardACLInfoDTO, 0) - outerErr := d.store.WithDbSession(ctx, func(dbSession *db.Session) error { - falseStr := d.store.GetDialect().BooleanStr(false) - - if query.DashboardID == 0 { - sql := `SELECT - da.id, - da.org_id, - da.dashboard_id, - da.user_id, - da.team_id, - da.permission, - da.role, - da.created, - da.updated, - '' as user_login, - '' as user_email, - '' as team, - '' as title, - '' as slug, - '' as uid,` + - falseStr + ` AS is_folder,` + - falseStr + ` AS inherited - FROM dashboard_acl as da - WHERE da.dashboard_id = -1` - return dbSession.SQL(sql).Find(&queryResult) - } - - rawSQL := ` - -- get permissions for the dashboard and its parent folder - SELECT - da.id, - da.org_id, - da.dashboard_id, - da.user_id, - da.team_id, - da.permission, - da.role, - da.created, - da.updated, - u.login AS user_login, - u.email AS user_email, - ug.name AS team, - ug.email AS team_email, - d.title, - d.slug, - d.uid, - d.is_folder, - CASE WHEN (da.dashboard_id = -1 AND d.folder_id > 0) OR da.dashboard_id = d.folder_id THEN ` + d.store.GetDialect().BooleanStr(true) + ` ELSE ` + falseStr + ` END AS inherited - FROM dashboard as d - LEFT JOIN dashboard folder on folder.id = d.folder_id - LEFT JOIN dashboard_acl AS da ON - da.dashboard_id = d.id OR - da.dashboard_id = d.folder_id OR - ( - -- include default permissions --> - da.org_id = -1 AND ( - (folder.id IS NOT NULL AND folder.has_acl = ` + falseStr + `) OR - (folder.id IS NULL AND d.has_acl = ` + falseStr + `) - ) - ) - LEFT JOIN ` + d.store.GetDialect().Quote("user") + ` AS u ON u.id = da.user_id - LEFT JOIN team ug on ug.id = da.team_id - WHERE d.org_id = ? AND d.id = ? AND da.id IS NOT NULL - ORDER BY da.id ASC - ` - - return dbSession.SQL(rawSQL, query.OrgID, query.DashboardID).Find(&queryResult) - }) - - if outerErr != nil { - return nil, outerErr - } - - for _, p := range queryResult { - p.PermissionName = p.Permission.String() - } - - return queryResult, nil -} - -func (d *dashboardStore) DeleteACLByUser(ctx context.Context, userID int64) error { - return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { - var rawSQL = "DELETE FROM dashboard_acl WHERE user_id = ?" - _, err := sess.Exec(rawSQL, userID) - return err - }) -} diff --git a/pkg/services/dashboards/database/acl_test.go b/pkg/services/dashboards/database/acl_test.go deleted file mode 100644 index ccf54681704..00000000000 --- a/pkg/services/dashboards/database/acl_test.go +++ /dev/null @@ -1,299 +0,0 @@ -package database - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/grafana/grafana/pkg/infra/db" - "github.com/grafana/grafana/pkg/services/dashboards" - "github.com/grafana/grafana/pkg/services/org" - "github.com/grafana/grafana/pkg/services/org/orgimpl" - "github.com/grafana/grafana/pkg/services/quota/quotaimpl" - "github.com/grafana/grafana/pkg/services/quota/quotatest" - "github.com/grafana/grafana/pkg/services/sqlstore" - "github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" - "github.com/grafana/grafana/pkg/services/tag/tagimpl" - "github.com/grafana/grafana/pkg/services/team/teamimpl" - "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/services/user/userimpl" -) - -func TestIntegrationDashboardACLDataAccess(t *testing.T) { - if testing.Short() { - t.Skip("skipping integration test") - } - var sqlStore *sqlstore.SQLStore - var currentUser user.User - var savedFolder, childDash *dashboards.Dashboard - var dashboardStore dashboards.Store - - setup := func(t *testing.T) int64 { - sqlStore = db.InitTestDB(t) - quotaService := quotatest.New(false, nil) - var err error - dashboardStore, err = ProvideDashboardStore(sqlStore, sqlStore.Cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService) - require.NoError(t, err) - currentUser = createUser(t, sqlStore, "viewer", "Viewer", false) - savedFolder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, "", true, "prod", "webapp") - childDash = insertTestDashboard(t, dashboardStore, "2 test dash", 1, savedFolder.ID, savedFolder.UID, false, "prod", "webapp") - return currentUser.OrgID - } - - t.Run("Dashboard permission with userId and teamId set to 0", func(t *testing.T) { - orgID := setup(t) - err := updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{ - OrgID: orgID, - DashboardID: savedFolder.ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Equal(t, dashboards.ErrDashboardACLInfoMissing, err) - }) - - t.Run("Folder acl should include default acl", func(t *testing.T) { - orgID := setup(t) - query := dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: orgID} - - queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query) - require.Nil(t, err) - - require.Equal(t, 2, len(queryResult)) - defaultPermissionsId := int64(-1) - require.Equal(t, defaultPermissionsId, queryResult[0].DashboardID) - require.Equal(t, org.RoleViewer, *queryResult[0].Role) - require.False(t, queryResult[0].Inherited) - require.Equal(t, defaultPermissionsId, queryResult[1].DashboardID) - require.Equal(t, org.RoleEditor, *queryResult[1].Role) - require.False(t, queryResult[1].Inherited) - }) - - t.Run("Dashboard acl should include acl for parent folder", func(t *testing.T) { - orgID := setup(t) - query := dashboards.GetDashboardACLInfoListQuery{DashboardID: childDash.ID, OrgID: orgID} - - queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query) - require.Nil(t, err) - - require.Equal(t, 2, len(queryResult)) - defaultPermissionsId := int64(-1) - require.Equal(t, defaultPermissionsId, queryResult[0].DashboardID) - require.Equal(t, org.RoleViewer, *queryResult[0].Role) - require.True(t, queryResult[0].Inherited) - require.Equal(t, defaultPermissionsId, queryResult[1].DashboardID) - require.Equal(t, org.RoleEditor, *queryResult[1].Role) - require.True(t, queryResult[1].Inherited) - }) - - t.Run("Folder with removed default permissions returns no acl items", func(t *testing.T) { - orgID := setup(t) - err := dashboardStore.UpdateDashboardACL(context.Background(), savedFolder.ID, nil) - require.Nil(t, err) - - query := dashboards.GetDashboardACLInfoListQuery{DashboardID: childDash.ID, OrgID: orgID} - queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query) - require.Nil(t, err) - - require.Equal(t, 0, len(queryResult)) - }) - - t.Run("Given a dashboard folder and a user", func(t *testing.T) { - t.Run("Given dashboard folder permission", func(t *testing.T) { - orgID := setup(t) - err := updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{ - OrgID: orgID, - UserID: currentUser.ID, - DashboardID: savedFolder.ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Nil(t, err) - - t.Run("When reading dashboard acl should include acl for parent folder", func(t *testing.T) { - query := dashboards.GetDashboardACLInfoListQuery{DashboardID: childDash.ID, OrgID: orgID} - - queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query) - require.Nil(t, err) - - require.Equal(t, 1, len(queryResult)) - require.Equal(t, savedFolder.ID, queryResult[0].DashboardID) - }) - - t.Run("Given child dashboard permission", func(t *testing.T) { - err := updateDashboardACL(t, dashboardStore, childDash.ID, dashboards.DashboardACL{ - OrgID: orgID, - UserID: currentUser.ID, - DashboardID: childDash.ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Nil(t, err) - - t.Run("When reading dashboard acl should include acl for parent folder and child", func(t *testing.T) { - query := dashboards.GetDashboardACLInfoListQuery{OrgID: orgID, DashboardID: childDash.ID} - - queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query) - require.Nil(t, err) - - require.Equal(t, 2, len(queryResult)) - require.Equal(t, savedFolder.ID, queryResult[0].DashboardID) - require.True(t, queryResult[0].Inherited) - require.Equal(t, childDash.ID, queryResult[1].DashboardID) - require.False(t, queryResult[1].Inherited) - }) - }) - }) - - t.Run("Reading dashboard acl should include default acl for parent folder and the child acl", func(t *testing.T) { - orgID := setup(t) - err := updateDashboardACL(t, dashboardStore, childDash.ID, dashboards.DashboardACL{ - OrgID: 1, - UserID: currentUser.ID, - DashboardID: childDash.ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Nil(t, err) - - query := dashboards.GetDashboardACLInfoListQuery{OrgID: orgID, DashboardID: childDash.ID} - - queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query) - require.Nil(t, err) - - defaultPermissionsId := int64(-1) - require.Equal(t, 3, len(queryResult)) - require.Equal(t, defaultPermissionsId, queryResult[0].DashboardID) - require.Equal(t, org.RoleViewer, *queryResult[0].Role) - require.True(t, queryResult[0].Inherited) - require.Equal(t, defaultPermissionsId, queryResult[1].DashboardID) - require.Equal(t, org.RoleEditor, *queryResult[1].Role) - require.True(t, queryResult[1].Inherited) - require.Equal(t, childDash.ID, queryResult[2].DashboardID) - require.False(t, queryResult[2].Inherited) - }) - - t.Run("Add and delete dashboard permission", func(t *testing.T) { - orgID := setup(t) - err := updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{ - OrgID: 1, - UserID: currentUser.ID, - DashboardID: savedFolder.ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Nil(t, err) - - q1 := &dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: orgID} - q1Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q1) - require.Nil(t, err) - - require.Equal(t, savedFolder.ID, q1Result[0].DashboardID) - require.Equal(t, dashboards.PERMISSION_EDIT, q1Result[0].Permission) - require.Equal(t, "Edit", q1Result[0].PermissionName) - require.Equal(t, currentUser.ID, q1Result[0].UserID) - require.Equal(t, currentUser.Login, q1Result[0].UserLogin) - require.Equal(t, currentUser.Email, q1Result[0].UserEmail) - - err = updateDashboardACL(t, dashboardStore, savedFolder.ID) - require.Nil(t, err) - - q3 := &dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: orgID} - q3Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q3) - require.Nil(t, err) - require.Equal(t, 0, len(q3Result)) - }) - - t.Run("Should be able to add a user permission for a team", func(t *testing.T) { - orgID := setup(t) - teamSvc := teamimpl.ProvideService(sqlStore, sqlStore.Cfg) - team1, err := teamSvc.CreateTeam("group1 name", "", 1) - require.Nil(t, err) - - err = updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{ - OrgID: 1, - TeamID: team1.ID, - DashboardID: savedFolder.ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Nil(t, err) - - q1 := &dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: orgID} - q1Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q1) - require.Nil(t, err) - require.Equal(t, savedFolder.ID, q1Result[0].DashboardID) - require.Equal(t, dashboards.PERMISSION_EDIT, q1Result[0].Permission) - require.Equal(t, team1.ID, q1Result[0].TeamID) - }) - - t.Run("Should be able to update an existing permission for a team", func(t *testing.T) { - orgID := setup(t) - teamSvc := teamimpl.ProvideService(sqlStore, sqlStore.Cfg) - team1, err := teamSvc.CreateTeam("group1 name", "", 1) - require.Nil(t, err) - err = updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{ - OrgID: 1, - TeamID: team1.ID, - DashboardID: savedFolder.ID, - Permission: dashboards.PERMISSION_ADMIN, - }) - require.Nil(t, err) - - q3 := &dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: orgID} - q3Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q3) - require.Nil(t, err) - require.Equal(t, 1, len(q3Result)) - require.Equal(t, savedFolder.ID, q3Result[0].DashboardID) - require.Equal(t, dashboards.PERMISSION_ADMIN, q3Result[0].Permission) - require.Equal(t, team1.ID, q3Result[0].TeamID) - }) - }) - - t.Run("Default permissions for root folder dashboards", func(t *testing.T) { - orgID := setup(t) - var rootFolderId int64 = 0 - //sqlStore := db.InitTestDB(t) - - query := dashboards.GetDashboardACLInfoListQuery{DashboardID: rootFolderId, OrgID: orgID} - - queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query) - require.Nil(t, err) - - require.Equal(t, 2, len(queryResult)) - defaultPermissionsId := int64(-1) - require.Equal(t, defaultPermissionsId, queryResult[0].DashboardID) - require.Equal(t, org.RoleViewer, *queryResult[0].Role) - require.False(t, queryResult[0].Inherited) - require.Equal(t, defaultPermissionsId, queryResult[1].DashboardID) - require.Equal(t, org.RoleEditor, *queryResult[1].Role) - require.False(t, queryResult[1].Inherited) - }) - - t.Run("Delete acl by user", func(t *testing.T) { - setup(t) - err := dashboardStore.DeleteACLByUser(context.Background(), currentUser.ID) - require.NoError(t, err) - }) -} - -func createUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role string, isAdmin bool) user.User { - t.Helper() - sqlStore.Cfg.AutoAssignOrg = true - sqlStore.Cfg.AutoAssignOrgId = 1 - sqlStore.Cfg.AutoAssignOrgRole = role - - qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg) - orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs) - require.NoError(t, err) - usrSvc, err := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, qs, supportbundlestest.NewFakeBundleService()) - require.NoError(t, err) - - o, err := orgService.CreateWithMember(context.Background(), &org.CreateOrgCommand{Name: fmt.Sprintf("test org %d", time.Now().UnixNano())}) - require.NoError(t, err) - - currentUserCmd := user.CreateUserCommand{Login: name, Email: name + "@test.com", Name: "a " + name, IsAdmin: isAdmin, OrgID: o.ID} - currentUser, err := usrSvc.Create(context.Background(), ¤tUserCmd) - require.NoError(t, err) - orgs, err := orgService.GetUserOrgList(context.Background(), &org.GetUserOrgListQuery{UserID: currentUser.ID}) - require.NoError(t, err) - require.Equal(t, org.RoleType(role), orgs[0].Role) - require.Equal(t, o.ID, orgs[0].OrgID) - return *currentUser -} diff --git a/pkg/services/dashboards/database/database.go b/pkg/services/dashboards/database/database.go index f7d237eeb19..66d70e1ddc8 100644 --- a/pkg/services/dashboards/database/database.go +++ b/pkg/services/dashboards/database/database.go @@ -171,36 +171,6 @@ func (d *dashboardStore) SaveDashboard(ctx context.Context, cmd dashboards.SaveD return result, err } -func (d *dashboardStore) UpdateDashboardACL(ctx context.Context, dashboardID int64, items []*dashboards.DashboardACL) error { - return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { - // delete existing items - _, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", dashboardID) - if err != nil { - return fmt.Errorf("deleting from dashboard_acl failed: %w", err) - } - - for _, item := range items { - if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) { - return dashboards.ErrDashboardACLInfoMissing - } - - if item.DashboardID == 0 { - return dashboards.ErrDashboardPermissionDashboardEmpty - } - - sess.Nullable("user_id", "team_id") - if _, err := sess.Insert(item); err != nil { - return err - } - } - - // Update dashboard HasACL flag - dashboard := dashboards.Dashboard{HasACL: true} - _, err = sess.Cols("has_acl").Where("id=?", dashboardID).Update(&dashboard) - return err - }) -} - func (d *dashboardStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*alertmodels.Alert) error { return d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error { existingAlerts, err := GetAlertsByDashboardId2(dashID, sess) diff --git a/pkg/services/dashboards/database/database_folder_test.go b/pkg/services/dashboards/database/database_folder_test.go index 43017d7c92a..788484996ed 100644 --- a/pkg/services/dashboards/database/database_folder_test.go +++ b/pkg/services/dashboards/database/database_folder_test.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -23,6 +24,7 @@ import ( "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org/orgimpl" + "github.com/grafana/grafana/pkg/services/quota/quotaimpl" "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" @@ -450,3 +452,28 @@ func moveDashboard(t *testing.T, dashboardStore dashboards.Store, orgId int64, d return dash } + +func createUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role string, isAdmin bool) user.User { + t.Helper() + sqlStore.Cfg.AutoAssignOrg = true + sqlStore.Cfg.AutoAssignOrgId = 1 + sqlStore.Cfg.AutoAssignOrgRole = role + + qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg) + orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs) + require.NoError(t, err) + usrSvc, err := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, qs, supportbundlestest.NewFakeBundleService()) + require.NoError(t, err) + + o, err := orgService.CreateWithMember(context.Background(), &org.CreateOrgCommand{Name: fmt.Sprintf("test org %d", time.Now().UnixNano())}) + require.NoError(t, err) + + currentUserCmd := user.CreateUserCommand{Login: name, Email: name + "@test.com", Name: "a " + name, IsAdmin: isAdmin, OrgID: o.ID} + currentUser, err := usrSvc.Create(context.Background(), ¤tUserCmd) + require.NoError(t, err) + orgs, err := orgService.GetUserOrgList(context.Background(), &org.GetUserOrgListQuery{UserID: currentUser.ID}) + require.NoError(t, err) + require.Equal(t, org.RoleType(role), orgs[0].Role) + require.Equal(t, o.ID, orgs[0].OrgID) + return *currentUser +} diff --git a/pkg/services/dashboards/database/database_test.go b/pkg/services/dashboards/database/database_test.go index 761fc9f151d..9dc76ede587 100644 --- a/pkg/services/dashboards/database/database_test.go +++ b/pkg/services/dashboards/database/database_test.go @@ -1188,21 +1188,6 @@ func insertTestDashboardForPlugin(t *testing.T, dashboardStore dashboards.Store, return dash } -func updateDashboardACL(t *testing.T, dashboardStore dashboards.Store, dashboardID int64, - items ...dashboards.DashboardACL) error { - t.Helper() - - var itemPtrs []*dashboards.DashboardACL - for _, it := range items { - item := it - item.Created = time.Now() - item.Updated = time.Now() - itemPtrs = append(itemPtrs, &item) - } - - return dashboardStore.UpdateDashboardACL(context.Background(), dashboardID, itemPtrs) -} - // testSearchDashboards is a (near) copy of the dashboard service // SearchDashboards, which is a wrapper around FindDashboards. func testSearchDashboards(d dashboards.Store, query *dashboards.FindPersistedDashboardsQuery) (model.HitList, error) { diff --git a/pkg/services/dashboards/models.go b/pkg/services/dashboards/models.go index ec75d6bcb9a..853ff83c803 100644 --- a/pkg/services/dashboards/models.go +++ b/pkg/services/dashboards/models.go @@ -477,12 +477,6 @@ func (dto *DashboardACLInfoDTO) IsDuplicateOf(other *DashboardACLInfoDTO) bool { return dto.hasSameRoleAs(other) || dto.hasSameUserAs(other) || dto.hasSameTeamAs(other) } -// QUERIES -type GetDashboardACLInfoListQuery struct { - DashboardID int64 - OrgID int64 -} - type FindPersistedDashboardsQuery struct { Title string OrgId int64 diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 3eb825392db..2e6d65579c2 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -224,10 +224,6 @@ func resolveUserID(user identity.Requester, log log.Logger) (int64, error) { return userID, nil } -func (dr *DashboardServiceImpl) UpdateDashboardACL(ctx context.Context, uid int64, items []*dashboards.DashboardACL) error { - return dr.dashboardStore.UpdateDashboardACL(ctx, uid, items) -} - func (dr *DashboardServiceImpl) DeleteOrphanedProvisionedDashboards(ctx context.Context, cmd *dashboards.DeleteOrphanedProvisionedDashboardsCommand) error { return dr.dashboardStore.DeleteOrphanedProvisionedDashboards(ctx, cmd) } @@ -589,18 +585,10 @@ func makeQueryResult(query *dashboards.FindPersistedDashboardsQuery, res []dashb return hitList } -func (dr *DashboardServiceImpl) GetDashboardACLInfoList(ctx context.Context, query *dashboards.GetDashboardACLInfoListQuery) ([]*dashboards.DashboardACLInfoDTO, error) { - return dr.dashboardStore.GetDashboardACLInfoList(ctx, query) -} - func (dr *DashboardServiceImpl) GetDashboardTags(ctx context.Context, query *dashboards.GetDashboardTagsQuery) ([]*dashboards.DashboardTagCloudItem, error) { return dr.dashboardStore.GetDashboardTags(ctx, query) } -func (dr *DashboardServiceImpl) DeleteACLByUser(ctx context.Context, userID int64) error { - return dr.dashboardStore.DeleteACLByUser(ctx, userID) -} - func (dr DashboardServiceImpl) CountInFolder(ctx context.Context, orgID int64, folderUID string, u identity.Requester) (int64, error) { folder, err := dr.folderService.Get(ctx, &folder.GetFolderQuery{UID: &folderUID, OrgID: orgID, SignedInUser: u}) if err != nil { diff --git a/pkg/services/dashboards/service/dashboard_service_test.go b/pkg/services/dashboards/service/dashboard_service_test.go index 12ca3232475..3b8c7eb0ea7 100644 --- a/pkg/services/dashboards/service/dashboard_service_test.go +++ b/pkg/services/dashboards/service/dashboard_service_test.go @@ -220,14 +220,6 @@ func TestDashboardService(t *testing.T) { err := service.DeleteDashboard(context.Background(), 1, 1) require.NoError(t, err) }) - - // t.Run("Delete ACL by user", func(t *testing.T) { - // fakeStore := dashboards.FakeDashboardStore{} - // args := 1 - // fakeStore.On("DeleteACLByUser", mock.Anything, args).Return(nil).Once() - // err := service.DeleteACLByUser(context.Background(), 1) - // require.NoError(t, err) - // }) }) t.Run("Count dashboards in folder", func(t *testing.T) { @@ -249,41 +241,4 @@ func TestDashboardService(t *testing.T) { require.NoError(t, err) }) }) - - t.Run("Delete user by acl", func(t *testing.T) { - fakeStore := dashboards.FakeDashboardStore{} - fakeStore.On("DeleteACLByUser", mock.Anything, mock.AnythingOfType("int64")).Return(nil) - defer fakeStore.AssertExpectations(t) - - service := &DashboardServiceImpl{ - cfg: setting.NewCfg(), - log: log.New("test.logger"), - dashboardStore: &fakeStore, - dashAlertExtractor: &dummyDashAlertExtractor{}, - } - err := service.DeleteACLByUser(context.Background(), 1) - require.NoError(t, err) - }) - - t.Run("When org user is deleted", func(t *testing.T) { - fakeStore := dashboards.FakeDashboardStore{} - fakeStore.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(nil, nil) - t.Run("Should remove dependent permissions for deleted org user", func(t *testing.T) { - permQuery := &dashboards.GetDashboardACLInfoListQuery{DashboardID: 1, OrgID: 1} - - permQueryResult, err := fakeStore.GetDashboardACLInfoList(context.Background(), permQuery) - require.NoError(t, err) - - require.Equal(t, len(permQueryResult), 0) - }) - - t.Run("Should not remove dashboard permissions for same user in another org", func(t *testing.T) { - fakeStore := dashboards.FakeDashboardStore{} - fakeStore.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardACLInfoListQuery")).Return(nil, nil) - permQuery := &dashboards.GetDashboardACLInfoListQuery{DashboardID: 2, OrgID: 3} - - _, err := fakeStore.GetDashboardACLInfoList(context.Background(), permQuery) - require.NoError(t, err) - }) - }) } diff --git a/pkg/services/dashboards/store_mock.go b/pkg/services/dashboards/store_mock.go index 0e23d220237..d4a696d6ae0 100644 --- a/pkg/services/dashboards/store_mock.go +++ b/pkg/services/dashboards/store_mock.go @@ -66,20 +66,6 @@ func (_m *FakeDashboardStore) CountDashboardsInFolder(ctx context.Context, reque return r0, r1 } -// DeleteACLByUser provides a mock function with given fields: _a0, _a1 -func (_m *FakeDashboardStore) DeleteACLByUser(_a0 context.Context, _a1 int64) error { - ret := _m.Called(_a0, _a1) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok { - r0 = rf(_a0, _a1) - } else { - r0 = ret.Error(0) - } - - return r0 -} - // DeleteDashboard provides a mock function with given fields: ctx, cmd func (_m *FakeDashboardStore) DeleteDashboard(ctx context.Context, cmd *DeleteDashboardCommand) error { ret := _m.Called(ctx, cmd) @@ -174,32 +160,6 @@ func (_m *FakeDashboardStore) GetDashboard(ctx context.Context, query *GetDashbo return r0, r1 } -// GetDashboardACLInfoList provides a mock function with given fields: ctx, query -func (_m *FakeDashboardStore) GetDashboardACLInfoList(ctx context.Context, query *GetDashboardACLInfoListQuery) ([]*DashboardACLInfoDTO, error) { - ret := _m.Called(ctx, query) - - var r0 []*DashboardACLInfoDTO - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardACLInfoListQuery) ([]*DashboardACLInfoDTO, error)); ok { - return rf(ctx, query) - } - if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardACLInfoListQuery) []*DashboardACLInfoDTO); ok { - r0 = rf(ctx, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*DashboardACLInfoDTO) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *GetDashboardACLInfoListQuery) error); ok { - r1 = rf(ctx, query) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - // GetDashboardTags provides a mock function with given fields: ctx, query func (_m *FakeDashboardStore) GetDashboardTags(ctx context.Context, query *GetDashboardTagsQuery) ([]*DashboardTagCloudItem, error) { ret := _m.Called(ctx, query) @@ -462,20 +422,6 @@ func (_m *FakeDashboardStore) UnprovisionDashboard(ctx context.Context, id int64 return r0 } -// UpdateDashboardACL provides a mock function with given fields: ctx, uid, items -func (_m *FakeDashboardStore) UpdateDashboardACL(ctx context.Context, uid int64, items []*DashboardACL) error { - ret := _m.Called(ctx, uid, items) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, int64, []*DashboardACL) error); ok { - r0 = rf(ctx, uid, items) - } else { - r0 = ret.Error(0) - } - - return r0 -} - // ValidateDashboardBeforeSave provides a mock function with given fields: ctx, dashboard, overwrite func (_m *FakeDashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashboard *Dashboard, overwrite bool) (bool, error) { ret := _m.Called(ctx, dashboard, overwrite) diff --git a/pkg/services/team/teamimpl/store_test.go b/pkg/services/team/teamimpl/store_test.go index 78d91645bd5..4a184c0e145 100644 --- a/pkg/services/team/teamimpl/store_test.go +++ b/pkg/services/team/teamimpl/store_test.go @@ -5,7 +5,6 @@ import ( "fmt" "strings" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -351,30 +350,6 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) { }) }) - t.Run("Should be able to remove a group with users and permissions", func(t *testing.T) { - groupID := team2.ID - err := teamSvc.AddTeamMember(userIds[1], testOrgID, groupID, false, 0) - require.NoError(t, err) - err = teamSvc.AddTeamMember(userIds[2], testOrgID, groupID, false, 0) - require.NoError(t, err) - err = updateDashboardACL(t, sqlStore, 1, &dashboards.DashboardACL{ - DashboardID: 1, OrgID: testOrgID, Permission: dashboards.PERMISSION_EDIT, TeamID: groupID, - }) - require.NoError(t, err) - err = teamSvc.DeleteTeam(context.Background(), &team.DeleteTeamCommand{OrgID: testOrgID, ID: groupID}) - require.NoError(t, err) - - query := &team.GetTeamByIDQuery{OrgID: testOrgID, ID: groupID} - _, err = teamSvc.GetTeamByID(context.Background(), query) - require.Equal(t, err, team.ErrTeamNotFound) - - permQuery := &dashboards.GetDashboardACLInfoListQuery{DashboardID: 1, OrgID: testOrgID} - permQueryResult, err := getDashboardACLInfoList(sqlStore, permQuery) - require.NoError(t, err) - - require.Equal(t, len(permQueryResult), 0) - }) - t.Run("Should not return hidden users in team member count", func(t *testing.T) { sqlStore = db.InitTestDB(t) setup() @@ -646,123 +621,3 @@ func hasWildcardScope(user identity.Requester, action string) bool { } return false } - -// TODO: Use FakeDashboardStore when org has its own service -func updateDashboardACL(t *testing.T, sqlStore *sqlstore.SQLStore, dashboardID int64, items ...*dashboards.DashboardACL) error { - t.Helper() - - err := sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { - _, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", dashboardID) - if err != nil { - return fmt.Errorf("deleting from dashboard_acl failed: %w", err) - } - - for _, item := range items { - item.Created = time.Now() - item.Updated = time.Now() - if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) { - return dashboards.ErrDashboardACLInfoMissing - } - - if item.DashboardID == 0 { - return dashboards.ErrDashboardPermissionDashboardEmpty - } - - sess.Nullable("user_id", "team_id") - if _, err := sess.Insert(item); err != nil { - return err - } - } - - // Update dashboard HasACL flag - dashboard := dashboards.Dashboard{HasACL: true} - _, err = sess.Cols("has_acl").Where("id=?", dashboardID).Update(&dashboard) - return err - }) - return err -} - -// This function was copied from pkg/services/dashboards/database to circumvent -// import cycles. When this org-related code is refactored into a service the -// tests can the real GetDashboardACLInfoList functions -func getDashboardACLInfoList(s *sqlstore.SQLStore, query *dashboards.GetDashboardACLInfoListQuery) ([]*dashboards.DashboardACLInfoDTO, error) { - queryResult := make([]*dashboards.DashboardACLInfoDTO, 0) - outerErr := s.WithDbSession(context.Background(), func(dbSession *db.Session) error { - falseStr := s.GetDialect().BooleanStr(false) - - if query.DashboardID == 0 { - sql := `SELECT - da.id, - da.org_id, - da.dashboard_id, - da.user_id, - da.team_id, - da.permission, - da.role, - da.created, - da.updated, - '' as user_login, - '' as user_email, - '' as team, - '' as title, - '' as slug, - '' as uid,` + - falseStr + ` AS is_folder,` + - falseStr + ` AS inherited - FROM dashboard_acl as da - WHERE da.dashboard_id = -1` - return dbSession.SQL(sql).Find(&queryResult) - } - - rawSQL := ` - -- get permissions for the dashboard and its parent folder - SELECT - da.id, - da.org_id, - da.dashboard_id, - da.user_id, - da.team_id, - da.permission, - da.role, - da.created, - da.updated, - u.login AS user_login, - u.email AS user_email, - ug.name AS team, - ug.email AS team_email, - d.title, - d.slug, - d.uid, - d.is_folder, - CASE WHEN (da.dashboard_id = -1 AND d.folder_id > 0) OR da.dashboard_id = d.folder_id THEN ` + s.GetDialect().BooleanStr(true) + ` ELSE ` + falseStr + ` END AS inherited - FROM dashboard as d - LEFT JOIN dashboard folder on folder.id = d.folder_id - LEFT JOIN dashboard_acl AS da ON - da.dashboard_id = d.id OR - da.dashboard_id = d.folder_id OR - ( - -- include default permissions --> - da.org_id = -1 AND ( - (folder.id IS NOT NULL AND folder.has_acl = ` + falseStr + `) OR - (folder.id IS NULL AND d.has_acl = ` + falseStr + `) - ) - ) - LEFT JOIN ` + s.GetDialect().Quote("user") + ` AS u ON u.id = da.user_id - LEFT JOIN team ug on ug.id = da.team_id - WHERE d.org_id = ? AND d.id = ? AND da.id IS NOT NULL - ORDER BY da.id ASC - ` - - return dbSession.SQL(rawSQL, query.OrgID, query.DashboardID).Find(&queryResult) - }) - - if outerErr != nil { - return nil, outerErr - } - - for _, p := range queryResult { - p.PermissionName = p.Permission.String() - } - - return queryResult, nil -} diff --git a/pkg/services/user/userimpl/store_test.go b/pkg/services/user/userimpl/store_test.go index ae6ced18c31..21a0cfbbee0 100644 --- a/pkg/services/user/userimpl/store_test.go +++ b/pkg/services/user/userimpl/store_test.go @@ -11,7 +11,6 @@ import ( "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/accesscontrol" - "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org/orgimpl" "github.com/grafana/grafana/pkg/services/quota/quotaimpl" @@ -378,12 +377,6 @@ func TestIntegrationUserDataAccess(t *testing.T) { }) require.Nil(t, err) - err = updateDashboardACL(t, ss, 1, &dashboards.DashboardACL{ - DashboardID: 1, OrgID: users[0].OrgID, UserID: users[1].ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Nil(t, err) - ss.CacheService.Flush() query := &user.GetSignedInUserQuery{OrgID: users[1].OrgID, UserID: users[1].ID} @@ -526,22 +519,10 @@ func TestIntegrationUserDataAccess(t *testing.T) { }) require.Nil(t, err) - err = updateDashboardACL(t, ss, 1, &dashboards.DashboardACL{ - DashboardID: 1, OrgID: users[0].OrgID, UserID: users[1].ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Nil(t, err) - // When the user is deleted err = userStore.Delete(context.Background(), users[1].ID) require.Nil(t, err) - permQuery := &dashboards.GetDashboardACLInfoListQuery{DashboardID: 1, OrgID: users[0].OrgID} - permQueryResult, err := userStore.getDashboardACLInfoList(permQuery) - require.Nil(t, err) - - require.Len(t, permQueryResult, 0) - // A user is an org member and has been assigned permissions // Re-init DB ss = db.InitTestDB(t) @@ -560,12 +541,6 @@ func TestIntegrationUserDataAccess(t *testing.T) { }) require.Nil(t, err) - err = updateDashboardACL(t, ss, 1, &dashboards.DashboardACL{ - DashboardID: 1, OrgID: users[0].OrgID, UserID: users[1].ID, - Permission: dashboards.PERMISSION_EDIT, - }) - require.Nil(t, err) - ss.CacheService.Flush() query3 := &user.GetSignedInUserQuery{OrgID: users[1].OrgID, UserID: users[1].ID} @@ -591,12 +566,6 @@ func TestIntegrationUserDataAccess(t *testing.T) { // the user is deleted err = userStore.Delete(context.Background(), users[1].ID) require.Nil(t, err) - - permQuery = &dashboards.GetDashboardACLInfoListQuery{DashboardID: 1, OrgID: users[0].OrgID} - permQueryResult, err = userStore.getDashboardACLInfoList(permQuery) - require.Nil(t, err) - - require.Len(t, permQueryResult, 0) }) t.Run("Testing DB - return list of users that the SignedInUser has permission to read", func(t *testing.T) { @@ -947,41 +916,6 @@ func createFiveTestUsers(t *testing.T, svc user.Service, fn func(i int) *user.Cr return users } -// TODO: Use FakeDashboardStore when org has its own service -func updateDashboardACL(t *testing.T, sqlStore db.DB, dashboardID int64, items ...*dashboards.DashboardACL) error { - t.Helper() - - err := sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { - _, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", dashboardID) - if err != nil { - return fmt.Errorf("deleting from dashboard_acl failed: %w", err) - } - - for _, item := range items { - item.Created = time.Now() - item.Updated = time.Now() - if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) { - return dashboards.ErrDashboardACLInfoMissing - } - - if item.DashboardID == 0 { - return dashboards.ErrDashboardPermissionDashboardEmpty - } - - sess.Nullable("user_id", "team_id") - if _, err := sess.Insert(item); err != nil { - return err - } - } - - // Update dashboard HasACL flag - dashboard := dashboards.Dashboard{HasACL: true} - _, err = sess.Cols("has_acl").Where("id=?", dashboardID).Update(&dashboard) - return err - }) - return err -} - func TestMetricsUsage(t *testing.T) { ss := db.InitTestDB(t) userStore := ProvideStore(ss, setting.NewCfg()) @@ -1029,91 +963,6 @@ func TestMetricsUsage(t *testing.T) { }) } -// This function was copied from pkg/services/dashboards/database to circumvent -// import cycles. When this org-related code is refactored into a service the -// tests can the real GetDashboardACLInfoList functions -func (ss *sqlStore) getDashboardACLInfoList(query *dashboards.GetDashboardACLInfoListQuery) ([]*dashboards.DashboardACLInfoDTO, error) { - queryResult := make([]*dashboards.DashboardACLInfoDTO, 0) - outerErr := ss.db.WithDbSession(context.Background(), func(dbSession *db.Session) error { - falseStr := ss.dialect.BooleanStr(false) - - if query.DashboardID == 0 { - sql := `SELECT - da.id, - da.org_id, - da.dashboard_id, - da.user_id, - da.team_id, - da.permission, - da.role, - da.created, - da.updated, - '' as user_login, - '' as user_email, - '' as team, - '' as title, - '' as slug, - '' as uid,` + - falseStr + ` AS is_folder,` + - falseStr + ` AS inherited - FROM dashboard_acl as da - WHERE da.dashboard_id = -1` - return dbSession.SQL(sql).Find(&queryResult) - } - - rawSQL := ` - -- get permissions for the dashboard and its parent folder - SELECT - da.id, - da.org_id, - da.dashboard_id, - da.user_id, - da.team_id, - da.permission, - da.role, - da.created, - da.updated, - u.login AS user_login, - u.email AS user_email, - ug.name AS team, - ug.email AS team_email, - d.title, - d.slug, - d.uid, - d.is_folder, - CASE WHEN (da.dashboard_id = -1 AND d.folder_id > 0) OR da.dashboard_id = d.folder_id THEN ` + ss.dialect.BooleanStr(true) + ` ELSE ` + falseStr + ` END AS inherited - FROM dashboard as d - LEFT JOIN dashboard folder on folder.id = d.folder_id - LEFT JOIN dashboard_acl AS da ON - da.dashboard_id = d.id OR - da.dashboard_id = d.folder_id OR - ( - -- include default permissions --> - da.org_id = -1 AND ( - (folder.id IS NOT NULL AND folder.has_acl = ` + falseStr + `) OR - (folder.id IS NULL AND d.has_acl = ` + falseStr + `) - ) - ) - LEFT JOIN ` + ss.dialect.Quote("user") + ` AS u ON u.id = da.user_id - LEFT JOIN team ug on ug.id = da.team_id - WHERE d.org_id = ? AND d.id = ? AND da.id IS NOT NULL - ORDER BY da.id ASC - ` - - return dbSession.SQL(rawSQL, query.OrgID, query.DashboardID).Find(&queryResult) - }) - - if outerErr != nil { - return nil, outerErr - } - - for _, p := range queryResult { - p.PermissionName = p.Permission.String() - } - - return queryResult, nil -} - func createOrgAndUserSvc(t *testing.T, store db.DB, cfg *setting.Cfg) (org.Service, user.Service) { t.Helper()