mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Login: Remove single admin team restriction (#54534)
* Remove single member team restriction * Add label when permissions list is empty * Fix unit tests * Add co-author. Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
This commit is contained in:
parent
4bba3223a0
commit
d2bb72fb3c
@ -433,12 +433,6 @@ func updateTeamMember(sess *DBSession, orgID, teamID, userID int64, permission m
|
||||
|
||||
if permission != models.PERMISSION_ADMIN {
|
||||
permission = 0 // make sure we don't get invalid permission levels in store
|
||||
|
||||
// protect the last team admin
|
||||
_, err := isLastAdmin(sess, orgID, teamID, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
member.Permission = permission
|
||||
@ -464,11 +458,6 @@ func removeTeamMember(sess *DBSession, cmd *models.RemoveTeamMemberCommand) erro
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := isLastAdmin(sess, cmd.OrgId, cmd.TeamId, cmd.UserId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var rawSQL = "DELETE FROM team_member WHERE org_id=? and team_id=? and user_id=?"
|
||||
res, err := sess.Exec(rawSQL, cmd.OrgId, cmd.TeamId, cmd.UserId)
|
||||
if err != nil {
|
||||
@ -482,29 +471,6 @@ func removeTeamMember(sess *DBSession, cmd *models.RemoveTeamMemberCommand) erro
|
||||
return err
|
||||
}
|
||||
|
||||
func isLastAdmin(sess *DBSession, orgId int64, teamId int64, userId int64) (bool, error) {
|
||||
rawSQL := "SELECT user_id FROM team_member WHERE org_id=? and team_id=? and permission=?"
|
||||
userIds := []*int64{}
|
||||
err := sess.SQL(rawSQL, orgId, teamId, models.PERMISSION_ADMIN).Find(&userIds)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
isAdmin := false
|
||||
for _, adminId := range userIds {
|
||||
if userId == *adminId {
|
||||
isAdmin = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if isAdmin && len(userIds) == 1 {
|
||||
return true, models.ErrLastTeamAdmin
|
||||
}
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
// GetUserTeamMemberships return a list of memberships to teams granted to a user
|
||||
// If external is specified, only memberships provided by an external auth provider will be listed
|
||||
// This function doesn't perform any accesscontrol filtering.
|
||||
|
@ -251,25 +251,18 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
require.Equal(t, len(q2.Result), 0)
|
||||
})
|
||||
|
||||
t.Run("Should never remove the last admin of a team", func(t *testing.T) {
|
||||
t.Run("Should have empty teams", func(t *testing.T) {
|
||||
err = sqlStore.AddTeamMember(userIds[0], testOrgID, team1.Id, false, models.PERMISSION_ADMIN)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("A user should not be able to remove the last admin", func(t *testing.T) {
|
||||
err = sqlStore.RemoveTeamMember(context.Background(), &models.RemoveTeamMemberCommand{OrgId: testOrgID, TeamId: team1.Id, UserId: userIds[0]})
|
||||
require.Equal(t, err, models.ErrLastTeamAdmin)
|
||||
})
|
||||
|
||||
t.Run("A user should be able to remove an admin if there are other admins", func(t *testing.T) {
|
||||
err = sqlStore.AddTeamMember(userIds[1], testOrgID, team1.Id, false, models.PERMISSION_ADMIN)
|
||||
require.NoError(t, err)
|
||||
err = sqlStore.RemoveTeamMember(context.Background(), &models.RemoveTeamMemberCommand{OrgId: testOrgID, TeamId: team1.Id, UserId: userIds[1]})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("A user should not be able to remove the admin permission for the last admin", func(t *testing.T) {
|
||||
t.Run("A user should be able to remove the admin permission for the last admin", func(t *testing.T) {
|
||||
err = sqlStore.UpdateTeamMember(context.Background(), &models.UpdateTeamMemberCommand{OrgId: testOrgID, TeamId: team1.Id, UserId: userIds[0], Permission: 0})
|
||||
require.Error(t, err, models.ErrLastTeamAdmin)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("A user should be able to remove the last member", func(t *testing.T) {
|
||||
err = sqlStore.RemoveTeamMember(context.Background(), &models.RemoveTeamMemberCommand{OrgId: testOrgID, TeamId: team1.Id, UserId: userIds[0]})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("A user should be able to remove the admin permission if there are other admins", func(t *testing.T) {
|
||||
|
@ -26,6 +26,7 @@ type Type = 'users' | 'teams' | 'builtInRoles';
|
||||
export type Props = {
|
||||
title?: string;
|
||||
buttonLabel?: string;
|
||||
emptyLabel?: string;
|
||||
addPermissionTitle?: string;
|
||||
resource: string;
|
||||
resourceId: ResourceId;
|
||||
@ -35,6 +36,7 @@ export type Props = {
|
||||
export const Permissions = ({
|
||||
title = 'Permissions',
|
||||
buttonLabel = 'Add a permission',
|
||||
emptyLabel = 'There are no permissions',
|
||||
resource,
|
||||
resourceId,
|
||||
canSetPermissions,
|
||||
@ -145,6 +147,15 @@ export const Permissions = ({
|
||||
onCancel={() => setIsAdding(false)}
|
||||
/>
|
||||
</SlideDown>
|
||||
{items.length === 0 && (
|
||||
<table className="filter-table gf-form-group">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{emptyLabel}</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
<PermissionList
|
||||
title="Role"
|
||||
items={builtInRoles}
|
||||
|
@ -21,6 +21,7 @@ const TeamPermissions = (props: TeamPermissionsProps) => {
|
||||
title=""
|
||||
addPermissionTitle="Add member"
|
||||
buttonLabel="Add member"
|
||||
emptyLabel="There are no members in this team or you do not have the permissions to list the current members."
|
||||
resource="teams"
|
||||
resourceId={props.team.id}
|
||||
canSetPermissions={canSetPermissions}
|
||||
|
Loading…
Reference in New Issue
Block a user