Skip to content

Commit 9c06a89

Browse files
JeffMboyaDušan Borovčanin
authored andcommitted
Refactor: Move role guard to domain
Signed-off-by: JeffMboya <jangina.mboya@gmail.com>
1 parent 53e6b11 commit 9c06a89

File tree

2 files changed

+68
-21
lines changed

2 files changed

+68
-21
lines changed

domains/service.go

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package domains
55

66
import (
77
"context"
8+
"fmt"
89
"time"
910

1011
"github.com/absmach/supermq"
@@ -351,15 +352,75 @@ func (svc *service) RemoveEntityMembers(ctx context.Context, session authn.Sessi
351352
return svc.ProvisionManageService.RemoveEntityMembers(ctx, session, entityID, members)
352353
}
353354

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 {
357-
return err
355+
func (svc *service) RoleRemoveMembers(ctx context.Context, session authn.Session, entityID, roleID string, members []string) error {
356+
if len(members) == 0 {
357+
return svcerr.ErrMalformedEntity
358+
}
359+
360+
ro, err := svc.repo.RetrieveEntityRole(ctx, entityID, roleID)
361+
if err != nil {
362+
return errors.Wrap(svcerr.ErrViewEntity, fmt.Errorf("failed to retrieve role '%s' for entity '%s': %w", roleID, entityID, err))
363+
}
364+
365+
isBuiltInRole := false
366+
if _, ok := svc.ProvisionManageService.BuiltInRoles[roles.BuiltInRoleName(ro.Name)]; ok {
367+
isBuiltInRole = true
368+
}
369+
370+
if isBuiltInRole {
371+
membersPage, listErr := svc.repo.RoleListMembers(ctx, ro.ID, 0, 0)
372+
if listErr != nil {
373+
return errors.Wrap(svcerr.ErrViewEntity, fmt.Errorf("failed to list members for built-in role '%s' to check count: %w", ro.Name, listErr))
374+
}
375+
376+
if membersPage.Total <= uint64(len(members)) {
377+
return errors.Wrap(svcerr.ErrRemoveEntity, fmt.Errorf("built-in role '%s' must retain at least one member. Attempting to remove %d member(s) from %d would leave too few.", ro.Name, len(members), membersPage.Total))
358378
}
359379
}
380+
381+
for _, memberID := range members {
382+
if err := svc.repo.DeleteInvitation(ctx, memberID, entityID); err != nil && err != repoerr.ErrNotFound {
383+
return errors.Wrap(svcerr.ErrRemoveEntity, fmt.Errorf("failed to delete invitation for member '%s' in domain '%s' from role '%s': %w", memberID, entityID, ro.Name, err))
384+
}
385+
}
386+
360387
return svc.ProvisionManageService.RoleRemoveMembers(ctx, session, entityID, roleID, members)
361388
}
362389

363390
func (svc *service) RoleRemoveAllMembers(ctx context.Context, session authn.Session, entityID, roleID string) error {
391+
ro, err := svc.repo.RetrieveEntityRole(ctx, entityID, roleID)
392+
if err != nil {
393+
return errors.Wrap(svcerr.ErrViewEntity, fmt.Errorf("failed to retrieve role '%s' for entity '%s': %w", roleID, entityID, err))
394+
}
395+
396+
isBuiltInRole := false
397+
if _, ok := svc.ProvisionManageService.BuiltInRoles[roles.BuiltInRoleName(ro.Name)]; ok {
398+
isBuiltInRole = true
399+
}
400+
401+
if isBuiltInRole {
402+
membersPage, listErr := svc.repo.RoleListMembers(ctx, ro.ID, 0, 0)
403+
if listErr != nil {
404+
return errors.Wrap(svcerr.ErrViewEntity, fmt.Errorf("failed to list members for built-in role '%s' to check count: %w", ro.Name, listErr))
405+
}
406+
407+
if membersPage.Total > 0 {
408+
return errors.Wrap(svcerr.ErrRemoveEntity, fmt.Errorf("built-in role '%s' must retain at least one member and cannot have all members removed", ro.Name))
409+
}
410+
}
411+
412+
currentMembersPage, listErr := svc.repo.RoleListMembers(ctx, ro.ID, 0, 0)
413+
if listErr != nil {
414+
return errors.Wrap(svcerr.ErrViewEntity, fmt.Errorf("failed to list members of role '%s' for invitation cleanup: %w", ro.Name, listErr))
415+
}
416+
417+
if len(currentMembersPage.Members) > 0 {
418+
for _, member := range currentMembersPage.Members {
419+
memberID := string(member)
420+
if err := svc.repo.DeleteInvitation(ctx, memberID, entityID); err != nil && err != repoerr.ErrNotFound {
421+
return errors.Wrap(svcerr.ErrRemoveEntity, fmt.Errorf("failed to delete invitation for member '%s' in domain '%s' from role '%s': %w", memberID, entityID, ro.Name, err))
422+
}
423+
}
424+
}
364425
return svc.ProvisionManageService.RoleRemoveAllMembers(ctx, session, entityID, roleID)
365426
}

pkg/roles/provisionmanage.go

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ type ProvisionManageService struct {
3434
sidProvider supermq.IDProvider
3535
policy policies.Service
3636
actions []Action
37-
builtInRoles map[BuiltInRoleName][]Action
37+
BuiltInRoles map[BuiltInRoleName][]Action
3838
}
3939

4040
func NewProvisionManageService(entityType string, repo Repository, policy policies.Service, sidProvider supermq.IDProvider, actions []Action, builtInRoles map[BuiltInRoleName][]Action) (ProvisionManageService, error) {
@@ -44,7 +44,7 @@ func NewProvisionManageService(entityType string, repo Repository, policy polici
4444
sidProvider: sidProvider,
4545
policy: policy,
4646
actions: actions,
47-
builtInRoles: builtInRoles,
47+
BuiltInRoles: builtInRoles,
4848
}
4949
return rm, nil
5050
}
@@ -143,7 +143,7 @@ func (r ProvisionManageService) AddNewEntitiesRoles(ctx context.Context, domainI
143143

144144
for _, entityID := range entityIDs {
145145
for defaultRole, defaultRoleMembers := range newBuiltInRoleMembers {
146-
actions, ok := r.builtInRoles[defaultRole]
146+
actions, ok := r.BuiltInRoles[defaultRole]
147147
if !ok {
148148
return []RoleProvision{}, fmt.Errorf("default role %s not found in in-built roles", defaultRole)
149149
}
@@ -559,16 +559,6 @@ func (r ProvisionManageService) RoleRemoveMembers(ctx context.Context, session a
559559
return errors.Wrap(svcerr.ErrRemoveEntity, err)
560560
}
561561

562-
if _, ok := r.builtInRoles[BuiltInRoleName(ro.Name)]; ok {
563-
page, err := r.repo.RoleListMembers(ctx, ro.ID, 0, 0)
564-
if err != nil {
565-
return errors.Wrap(svcerr.ErrViewEntity, err)
566-
}
567-
if page.Total <= uint64(len(members)) {
568-
return errors.Wrap(svcerr.ErrRemoveEntity, fmt.Errorf("built-in role '%s' must retain at least one member", ro.Name))
569-
}
570-
}
571-
572562
if len(members) == 0 {
573563
return svcerr.ErrMalformedEntity
574564
}
@@ -602,10 +592,6 @@ func (r ProvisionManageService) RoleRemoveAllMembers(ctx context.Context, sessio
602592
return errors.Wrap(svcerr.ErrRemoveEntity, err)
603593
}
604594

605-
if _, ok := r.builtInRoles[BuiltInRoleName(ro.Name)]; ok {
606-
return errors.Wrap(svcerr.ErrRemoveEntity, fmt.Errorf("removing all members from built-in role '%s' is not permitted", ro.Name))
607-
}
608-
609595
prs := policies.Policy{
610596
ObjectType: policies.RoleType,
611597
Object: ro.ID,

0 commit comments

Comments
 (0)