Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions app/controlplane/pkg/biz/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,11 @@ func (uc *GroupUseCase) AddMemberToGroup(ctx context.Context, orgID uuid.UUID, o
return nil, fmt.Errorf("failed to find user by email: %w", err)
}

// Illegal. Org viewers cannot become maintainers
if userMembership != nil && userMembership.Role == authz.RoleViewer && opts.Maintainer {
return nil, NewErrValidationStr("org viewers cannot become group maintainers")
}

// If the user is not found in the organization, send an invitation
if userMembership == nil {
// We need a requester for creating invitations
Expand Down Expand Up @@ -764,24 +769,25 @@ func (uc *GroupUseCase) UpdateMemberMaintainerStatus(ctx context.Context, orgID
// Find the user by reference or email
var userUUID uuid.UUID
var userEmail string
var userMembership *Membership

// If UserReference is provided, use it to resolve the user ID
if opts.UserReference != nil && (opts.UserReference.ID != nil || opts.UserReference.Name != nil) {
// If ID is provided directly, use it
if opts.UserReference.ID != nil {
userUUID = *opts.UserReference.ID
// Look up the user to verify they exist and get their email
user, err := uc.membershipRepo.FindByOrgAndUser(ctx, orgID, userUUID)
userMembership, err = uc.membershipRepo.FindByOrgAndUser(ctx, orgID, userUUID)
if err != nil {
return fmt.Errorf("failed to find user by ID: %w", err)
}
if user == nil {
if userMembership == nil {
return NewErrNotFound("user")
}
userEmail = user.User.Email
userEmail = userMembership.User.Email
} else if opts.UserReference.Name != nil {
// If name (email) is provided, look up the user
userMembership, err := uc.membershipRepo.FindByOrgIDAndUserEmail(ctx, orgID, *opts.UserReference.Name)
userMembership, err = uc.membershipRepo.FindByOrgIDAndUserEmail(ctx, orgID, *opts.UserReference.Name)
if err != nil && !IsNotFound(err) {
return fmt.Errorf("failed to find user by email: %w", err)
}
Expand All @@ -793,7 +799,7 @@ func (uc *GroupUseCase) UpdateMemberMaintainerStatus(ctx context.Context, orgID
}
} else {
// Fall back to using UserEmail
userMembership, err := uc.membershipRepo.FindByOrgIDAndUserEmail(ctx, orgID, *opts.UserReference.Name)
userMembership, err = uc.membershipRepo.FindByOrgIDAndUserEmail(ctx, orgID, *opts.UserReference.Name)
if err != nil && !IsNotFound(err) {
return fmt.Errorf("failed to find user by email: %w", err)
}
Expand All @@ -804,6 +810,11 @@ func (uc *GroupUseCase) UpdateMemberMaintainerStatus(ctx context.Context, orgID
userEmail = *opts.UserReference.Name
}

// illegal combination: org viewers cannot become maintainers
if userMembership != nil && userMembership.Role == authz.RoleViewer && opts.IsMaintainer {
return NewErrValidationStr("org viewers cannot become group maintainers")
}

// Check if the user is a member of the group
existingMembership, err := uc.groupRepo.FindGroupMembershipByGroupAndID(ctx, resolvedGroupID, userUUID)
if err != nil && !IsNotFound(err) {
Expand Down
20 changes: 17 additions & 3 deletions app/controlplane/pkg/biz/group_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,6 @@ func (s *groupMembersIntegrationTestSuite) TestAddMemberToGroup() {
},
UserEmail: "add-user2@example.com",
RequesterID: uuid.MustParse(s.user.ID),
Maintainer: true,
}

_, err := s.Group.AddMemberToGroup(ctx, uuid.MustParse(s.org.ID), opts)
Expand All @@ -928,6 +927,22 @@ func (s *groupMembersIntegrationTestSuite) TestAddMemberToGroup() {
s.NoError(err)
s.Equal(3, count) // still the original 3 members
})

s.Run("a viewer cannot be maintainer", func() {
// Try to add user2 again (who we added in the first test)
opts := &biz.AddMemberToGroupOpts{
IdentityReference: &biz.IdentityReference{
ID: &s.group.ID,
},
UserEmail: "add-user2@example.com",
RequesterID: uuid.MustParse(s.user.ID),
Maintainer: true,
}

_, err := s.Group.AddMemberToGroup(ctx, uuid.MustParse(s.org.ID), opts)
s.Error(err)
s.True(biz.IsErrValidation(err))
})
}

// Test removing members from groups
Expand Down Expand Up @@ -1516,8 +1531,7 @@ func (s *groupMembersIntegrationTestSuite) TestUpdateMemberMaintainerStatus() {
UserReference: &biz.IdentityReference{
Name: &nonMemberEmail,
},
RequesterID: uuid.MustParse(s.user.ID),
IsMaintainer: true,
RequesterID: uuid.MustParse(s.user.ID),
}

err = s.Group.UpdateMemberMaintainerStatus(ctx, uuid.MustParse(s.org.ID), updateOpts)
Expand Down
Loading