Skip to content

Commit d8b7af4

Browse files
authored
SMQ-2739 - Prevent removing of all users from Built in admin role (#2835)
Signed-off-by: JeffMboya <jangina.mboya@gmail.com>
1 parent 798ed3a commit d8b7af4

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

api/http/common.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,8 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
233233
errors.Contains(err, apiutil.ErrMissingRoleMembers),
234234
errors.Contains(err, apiutil.ErrMissingDescription),
235235
errors.Contains(err, apiutil.ErrMissingEntityID),
236-
errors.Contains(err, apiutil.ErrInvalidRouteFormat):
236+
errors.Contains(err, apiutil.ErrInvalidRouteFormat),
237+
errors.Contains(err, svcerr.ErrRetainOneMember):
237238
err = unwrap(err)
238239
w.WriteHeader(http.StatusBadRequest)
239240

domains/service.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,15 +351,40 @@ func (svc *service) RemoveEntityMembers(ctx context.Context, session authn.Sessi
351351
return svc.ProvisionManageService.RemoveEntityMembers(ctx, session, entityID, members)
352352
}
353353

354-
func (svc *service) RoleRemoveMembers(ctx context.Context, session authn.Session, entityID, roleID string, members []string) (err error) {
355-
for _, member := range members {
356-
if err := svc.repo.DeleteInvitation(ctx, member, entityID); err != nil && err != repoerr.ErrNotFound {
354+
func (svc *service) RoleRemoveMembers(ctx context.Context, session authn.Session, entityID, roleID string, members []string) error {
355+
ro, err := svc.repo.RetrieveEntityRole(ctx, entityID, roleID)
356+
if err != nil {
357+
return errors.Wrap(svcerr.ErrViewEntity, err)
358+
}
359+
360+
if _, err := svc.ProvisionManageService.BuiltInRoleActions(roles.BuiltInRoleName(ro.Name)); err == nil {
361+
membersPage, err := svc.repo.RoleListMembers(ctx, ro.ID, 0, 0)
362+
if err != nil {
363+
return errors.Wrap(svcerr.ErrViewEntity, err)
364+
}
365+
if membersPage.Total <= uint64(len(members)) {
366+
return svcerr.ErrRetainOneMember
367+
}
368+
}
369+
370+
for _, memberID := range members {
371+
if err := svc.repo.DeleteInvitation(ctx, memberID, entityID); err != nil && err != repoerr.ErrNotFound {
357372
return err
358373
}
359374
}
375+
360376
return svc.ProvisionManageService.RoleRemoveMembers(ctx, session, entityID, roleID, members)
361377
}
362378

363-
func (svc *service) RoleRemoveAllMembers(ctx context.Context, session authn.Session, entityID, roleID string) (err error) {
364-
return svcerr.ErrNotFound
379+
func (svc *service) RoleRemoveAllMembers(ctx context.Context, session authn.Session, entityID, roleID string) error {
380+
ro, err := svc.repo.RetrieveEntityRole(ctx, entityID, roleID)
381+
if err != nil {
382+
return errors.Wrap(svcerr.ErrViewEntity, err)
383+
}
384+
385+
if _, err := svc.ProvisionManageService.BuiltInRoleActions(roles.BuiltInRoleName(ro.Name)); err == nil {
386+
return svcerr.ErrRetainOneMember
387+
}
388+
389+
return svc.ProvisionManageService.RoleRemoveAllMembers(ctx, session, entityID, roleID)
365390
}

pkg/errors/service/types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,7 @@ var (
8787

8888
// ErrUnauthorizedPAT indicates failure occurred while authorizing PAT.
8989
ErrUnauthorizedPAT = errors.New("failed to authorize PAT")
90+
91+
// ErrRetainOneMember indicates that at least one owner must be retained in the entity.
92+
ErrRetainOneMember = errors.New("must retain at least one member")
9093
)

pkg/roles/provisionmanage.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ func NewProvisionManageService(entityType string, repo Repository, policy polici
4949
return rm, nil
5050
}
5151

52+
func (pms ProvisionManageService) BuiltInRoleActions(name BuiltInRoleName) ([]Action, error) {
53+
actions, ok := pms.builtInRoles[name]
54+
if !ok {
55+
return nil, errors.Wrap(svcerr.ErrNotFound, fmt.Errorf("role %s not found", name))
56+
}
57+
return actions, nil
58+
}
59+
5260
func toRolesActions(actions []string) []Action {
5361
roActions := []Action{}
5462
for _, action := range actions {

0 commit comments

Comments
 (0)