RBAC: Fix delete team permissions on team delete (#83442)

* RBAC: Remove team permissions on delete

* Remove unecessary deletes from store function

* Nit on mock

* Add test to the database

* Nit on comment

* Add another test to check that other permissions remain
This commit is contained in:
Gabriel MABILLE
2024-02-27 12:21:26 +01:00
committed by GitHub
parent ffae7d111c
commit 8d9921a5ba
9 changed files with 178 additions and 5 deletions
@@ -241,3 +241,58 @@ func (s *AccessControlStore) DeleteUserPermissions(ctx context.Context, orgID, u
})
return err
}
func (s *AccessControlStore) DeleteTeamPermissions(ctx context.Context, orgID, teamID int64) error {
err := s.sql.WithDbSession(ctx, func(sess *db.Session) error {
roleDeleteQuery := "DELETE FROM team_role WHERE team_id = ? AND org_id = ?"
roleDeleteParams := []any{roleDeleteQuery, teamID, orgID}
// Delete team role assignments
if _, err := sess.Exec(roleDeleteParams...); err != nil {
return err
}
// Delete permissions that are scoped to the team
if _, err := sess.Exec("DELETE FROM permission WHERE scope = ?", accesscontrol.Scope("teams", "id", strconv.FormatInt(teamID, 10))); err != nil {
return err
}
// Delete the team managed role
roleQuery := "SELECT id FROM role WHERE name = ? AND org_id = ?"
roleParams := []any{accesscontrol.ManagedTeamRoleName(teamID), orgID}
var roleIDs []int64
if err := sess.SQL(roleQuery, roleParams...).Find(&roleIDs); err != nil {
return err
}
if len(roleIDs) == 0 {
return nil
}
permissionDeleteQuery := "DELETE FROM permission WHERE role_id IN(? " + strings.Repeat(",?", len(roleIDs)-1) + ")"
permissionDeleteParams := make([]any, 0, len(roleIDs)+1)
permissionDeleteParams = append(permissionDeleteParams, permissionDeleteQuery)
for _, id := range roleIDs {
permissionDeleteParams = append(permissionDeleteParams, id)
}
// Delete managed team permissions
if _, err := sess.Exec(permissionDeleteParams...); err != nil {
return err
}
managedRoleDeleteQuery := "DELETE FROM role WHERE id IN(? " + strings.Repeat(",?", len(roleIDs)-1) + ")"
managedRoleDeleteParams := []any{managedRoleDeleteQuery}
for _, id := range roleIDs {
managedRoleDeleteParams = append(managedRoleDeleteParams, id)
}
// Delete managed team role
if _, err := sess.Exec(managedRoleDeleteParams...); err != nil {
return err
}
return nil
})
return err
}
@@ -243,6 +243,77 @@ func TestAccessControlStore_DeleteUserPermissions(t *testing.T) {
})
}
func TestAccessControlStore_DeleteTeamPermissions(t *testing.T) {
t.Run("expect permissions related to team to be deleted", func(t *testing.T) {
store, permissionsStore, sql, teamSvc, _ := setupTestEnv(t)
user, team := createUserAndTeam(t, sql, teamSvc, 1)
// grant permission to the team
_, err := permissionsStore.SetTeamResourcePermission(context.Background(), 1, team.ID, rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:write"},
Resource: "dashboards",
ResourceAttribute: "uid",
ResourceID: "xxYYzz",
}, nil)
require.NoError(t, err)
// generate permissions scoped to the team
_, err = permissionsStore.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: user.ID}, rs.SetResourcePermissionCommand{
Actions: []string{"team:read"},
Resource: "teams",
ResourceAttribute: "id",
ResourceID: fmt.Sprintf("%d", team.ID),
}, nil)
require.NoError(t, err)
err = store.DeleteTeamPermissions(context.Background(), 1, team.ID)
require.NoError(t, err)
permissions, err := store.GetUserPermissions(context.Background(), accesscontrol.GetUserPermissionsQuery{
OrgID: 1,
UserID: user.ID,
Roles: []string{"Admin"},
TeamIDs: []int64{team.ID},
})
require.NoError(t, err)
assert.Len(t, permissions, 0)
})
t.Run("expect permissions not related to team to be kept", func(t *testing.T) {
store, permissionsStore, sql, teamSvc, _ := setupTestEnv(t)
user, team := createUserAndTeam(t, sql, teamSvc, 1)
// grant permission to the team
_, err := permissionsStore.SetTeamResourcePermission(context.Background(), 1, team.ID, rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:write"},
Resource: "dashboards",
ResourceAttribute: "uid",
ResourceID: "xxYYzz",
}, nil)
require.NoError(t, err)
// generate permissions scoped to another team
_, err = permissionsStore.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: user.ID}, rs.SetResourcePermissionCommand{
Actions: []string{"team:read"},
Resource: "teams",
ResourceAttribute: "id",
ResourceID: fmt.Sprintf("%d", team.ID+1),
}, nil)
require.NoError(t, err)
err = store.DeleteTeamPermissions(context.Background(), 1, team.ID)
require.NoError(t, err)
permissions, err := store.GetUserPermissions(context.Background(), accesscontrol.GetUserPermissionsQuery{
OrgID: 1,
UserID: user.ID,
Roles: []string{"Admin"},
TeamIDs: []int64{team.ID},
})
require.NoError(t, err)
assert.Len(t, permissions, 1)
})
}
func createUserAndTeam(t *testing.T, userSrv user.Service, teamSvc team.Service, orgID int64) (*user.User, team.Team) {
t.Helper()