Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid creating duplicate groups with the same name #1579

Merged
merged 15 commits into from
Mar 17, 2024
Merged
Show file tree
Hide file tree
Changes from 8 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
13 changes: 10 additions & 3 deletions management/server/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ const (
PublicCategory = "public"
PrivateCategory = "private"
UnknownCategory = "unknown"
GroupIssuedAPI = "api"
GroupIssuedJWT = "jwt"
GroupIssuedIntegration = "integration"
CacheExpirationMax = 7 * 24 * 3600 * time.Second // 7 days
CacheExpirationMin = 3 * 24 * 3600 * time.Second // 3 days
DefaultPeerLoginExpiration = 24 * time.Hour
Expand Down Expand Up @@ -543,6 +540,16 @@ func (a *Account) FindUser(userID string) (*User, error) {
return user, nil
}

// FindGroupByName looks for a given group in the Account by name or returns error if the group wasn't found.
func (a *Account) FindGroupByName(groupName string) (*Group, error) {
mlsmaycon marked this conversation as resolved.
Show resolved Hide resolved
for _, group := range a.Groups {
if group.Name == groupName {
return group, nil
}
}
return nil, status.Errorf(status.NotFound, "group %s not found", groupName)
}

// FindSetupKey looks for a given SetupKey in the Account or returns error if it wasn't found.
func (a *Account) FindSetupKey(setupKey string) (*SetupKey, error) {
key := a.SetupKeys[setupKey]
Expand Down
22 changes: 21 additions & 1 deletion management/server/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ func (e *GroupLinkError) Error() string {
return fmt.Sprintf("group has been linked to %s: %s", e.Resource, e.Name)
}

const (
GroupIssuedAPI = "api"
GroupIssuedJWT = "jwt"
GroupIssuedIntegration = "integration"
)

// Group of the peers for ACL
type Group struct {
// ID of the group
Expand All @@ -29,7 +35,7 @@ type Group struct {
// Name visible in the UI
Name string

// Issued of the group
// Issued defines how this group was created (enum of "api", "integration" or "jwt")
Issued string

// Peers list of the group
Expand Down Expand Up @@ -116,6 +122,20 @@ func (am *DefaultAccountManager) SaveGroup(accountID, userID string, newGroup *G
return err
}

group, err := account.FindGroupByName(newGroup.Name)
if err != nil {
s, ok := status.FromError(err)
if !ok || s.ErrorType != status.NotFound {
return err
}
}

// avoid duplicate groups only for the API issued groups. Integration or JWT groups can be duplicated as they are
// coming from the IdP that we don't have control of.
if group != nil && group.Issued == GroupIssuedAPI {
return status.Errorf(status.AlreadyExists, "group with name %s already exists", newGroup.Name)
}

for _, peerID := range newGroup.Peers {
if account.Peers[peerID] == nil {
return status.Errorf(status.InvalidArgument, "peer with ID \"%s\" not found", peerID)
Expand Down
19 changes: 19 additions & 0 deletions management/server/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ const (
groupAdminUserID = "testingAdminUser"
)

func TestDefaultAccountManager_CreateGroup(t *testing.T) {
am, err := createManager(t)
if err != nil {
t.Error("failed to create account manager")
}

account, err := initTestGroupAccount(am)
if err != nil {
t.Error("failed to init testing account")
}

for _, group := range account.Groups {
err = am.SaveGroup(account.Id, groupAdminUserID, group)
if err == nil {
t.Error("should not create group with the same name")
}
}
}

func TestDefaultAccountManager_DeleteGroup(t *testing.T) {
am, err := createManager(t)
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions management/server/http/api/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,10 @@ components:
type: integer
example: 2
issued:
description: How group was issued by API or from JWT token
braginini marked this conversation as resolved.
Show resolved Hide resolved
description: How the group was issued (api, integration, jwt)
type: string
enum: ["api", "integration", "jwt"]
example: api
type: string
example: api
required:
Expand Down Expand Up @@ -1094,7 +1097,7 @@ paths:
/api/accounts/{accountId}:
delete:
summary: Delete an Account
description: Deletes an account and all its resources. Only administrators and account owners can delete accounts.
description: Deletes an account and all its resources. Only account owners can delete accounts.
tags: [ Accounts ]
security:
- BearerAuth: [ ]
Expand Down
Loading