diff --git a/pkg/services/accesscontrol/database/database.go b/pkg/services/accesscontrol/database/database.go index c89b0801341..9e4d02f4b92 100644 --- a/pkg/services/accesscontrol/database/database.go +++ b/pkg/services/accesscontrol/database/database.go @@ -2,6 +2,7 @@ package database import ( "context" + "strconv" "strings" "github.com/grafana/grafana/pkg/services/accesscontrol" @@ -110,3 +111,46 @@ func deletePermissions(sess *sqlstore.DBSession, ids []int64) error { return nil } + +func (s *AccessControlStore) DeleteUserPermissions(ctx context.Context, userID int64) error { + err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + // Delete user role assignments + if _, err := sess.Exec("DELETE FROM user_role WHERE user_id = ?", userID); err != nil { + return err + } + + // Delete permissions that are scoped to user + if _, err := sess.Exec("DELETE FROM permission WHERE scope = ?", accesscontrol.Scope("users", "id", strconv.FormatInt(userID, 10))); err != nil { + return err + } + + var roleIDs []int64 + if err := sess.SQL("SELECT id FROM role WHERE name = ?", accesscontrol.ManagedUserRoleName(userID)).Find(&roleIDs); err != nil { + return err + } + + if len(roleIDs) == 0 { + return nil + } + + query := "DELETE FROM permission WHERE role_id IN(? " + strings.Repeat(",?", len(roleIDs)-1) + ")" + args := make([]interface{}, 0, len(roleIDs)+1) + args = append(args, query) + for _, id := range roleIDs { + args = append(args, id) + } + + // Delete managed user permissions + if _, err := sess.Exec(args...); err != nil { + return err + } + + // Delete managed user roles + if _, err := sess.Exec("DELETE FROM role WHERE name = ?", accesscontrol.ManagedUserRoleName(userID)); err != nil { + return err + } + + return nil + }) + return err +} diff --git a/pkg/services/accesscontrol/database/database_test.go b/pkg/services/accesscontrol/database/database_test.go index 094f27fd01c..1531523dc67 100644 --- a/pkg/services/accesscontrol/database/database_test.go +++ b/pkg/services/accesscontrol/database/database_test.go @@ -131,6 +131,31 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) { } } +func TestAccessControlStore_DeleteUserPermissions(t *testing.T) { + store, sql := setupTestEnv(t) + + user, _ := createUserAndTeam(t, sql, 1) + + _, err := store.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: user.ID}, types.SetResourcePermissionCommand{ + Actions: []string{"dashboards:write"}, + Resource: "dashboards", + ResourceID: "1", + }, nil) + require.NoError(t, err) + + err = store.DeleteUserPermissions(context.Background(), user.ID) + require.NoError(t, err) + + permissions, err := store.GetUserPermissions(context.Background(), accesscontrol.GetUserPermissionsQuery{ + OrgID: 1, + UserID: user.ID, + Roles: []string{"Admin"}, + Actions: []string{"dashboards:write"}, + }) + require.NoError(t, err) + assert.Len(t, permissions, 0) +} + func createUserAndTeam(t *testing.T, sql *sqlstore.SQLStore, orgID int64) (*user.User, models.Team) { t.Helper()