mirror of
https://github.com/passbolt/go-passbolt.git
synced 2025-05-10 01:48:22 +00:00
add group helper functions
This commit is contained in:
parent
0731d52273
commit
a18a6bac6f
1 changed files with 186 additions and 0 deletions
186
helper/group.go
Normal file
186
helper/group.go
Normal file
|
@ -0,0 +1,186 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/speatzle/go-passbolt/api"
|
||||
)
|
||||
|
||||
// GroupMembershipOperation creates/modifies/deletes a group membership
|
||||
type GroupMembershipOperation struct {
|
||||
GroupMembership
|
||||
Delete bool
|
||||
}
|
||||
|
||||
// GroupMembership containes who and what kind of membership they have with a group
|
||||
type GroupMembership struct {
|
||||
UserID string
|
||||
IsGroupManager bool
|
||||
}
|
||||
|
||||
// CreateGroup creates a Groups with Name and Memberships
|
||||
func CreateGroup(ctx context.Context, c *api.Client, name string, operations []GroupMembershipOperation) (string, error) {
|
||||
memberships := []api.GroupMembership{}
|
||||
for _, o := range operations {
|
||||
if o.Delete {
|
||||
return "", fmt.Errorf("Cannot Delete Membership during Group Creation")
|
||||
}
|
||||
memberships = append(memberships, api.GroupMembership{
|
||||
UserID: o.UserID,
|
||||
IsAdmin: o.IsGroupManager,
|
||||
})
|
||||
}
|
||||
group, err := c.CreateGroup(ctx, api.Group{
|
||||
Name: name,
|
||||
GroupUsers: memberships,
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Creating Group: %w", err)
|
||||
}
|
||||
return group.ID, nil
|
||||
}
|
||||
|
||||
// GetGroup gets a Groups Name and Memberships
|
||||
func GetGroup(ctx context.Context, c *api.Client, groupID string) (string, []GroupMembership, error) {
|
||||
// for some reason the groups index api call does not give back the groups_users even though it is supposed to, so i have to do this...
|
||||
groups, err := c.GetGroups(ctx, &api.GetGroupsOptions{
|
||||
ContainGroupUser: true,
|
||||
})
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("Getting Groups: %w", err)
|
||||
}
|
||||
|
||||
for _, g := range groups {
|
||||
if g.ID == groupID {
|
||||
memberships := []GroupMembership{}
|
||||
for _, m := range g.GroupUsers {
|
||||
memberships = append(memberships, GroupMembership{
|
||||
UserID: m.UserID,
|
||||
IsGroupManager: m.IsAdmin,
|
||||
})
|
||||
}
|
||||
return g.Name, memberships, nil
|
||||
}
|
||||
}
|
||||
return "", nil, fmt.Errorf("Cannot Find Group in API Response")
|
||||
}
|
||||
|
||||
// UpdateGroup Updates a Groups Name and Memberships
|
||||
func UpdateGroup(ctx context.Context, c *api.Client, groupID, name string, operations []GroupMembershipOperation) error {
|
||||
// for some reason the groups index api call does not give back the groups_users even though it is supposed to, so i have to do this...
|
||||
groups, err := c.GetGroups(ctx, &api.GetGroupsOptions{
|
||||
ContainGroupUser: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Getting Groups: %w", err)
|
||||
}
|
||||
|
||||
var currentMemberships []api.GroupMembership
|
||||
for _, g := range groups {
|
||||
if g.ID == groupID {
|
||||
currentMemberships = g.GroupUsers
|
||||
break
|
||||
}
|
||||
}
|
||||
if currentMemberships == nil {
|
||||
return fmt.Errorf("Cannot Find Group with ID %v", groupID)
|
||||
}
|
||||
|
||||
request := api.GroupUpdate{
|
||||
Name: name,
|
||||
GroupChanges: []api.GroupMembership{},
|
||||
Secrets: []api.Secret{},
|
||||
}
|
||||
|
||||
// Generate Group Membership changes based on current Group Memberships
|
||||
for _, operation := range operations {
|
||||
membership, err := getMembershipByUserID(currentMemberships, operation.UserID)
|
||||
if err != nil {
|
||||
// Membership does not Exist so we can only create a new one
|
||||
if operation.Delete {
|
||||
return fmt.Errorf("Cannot Delete User %v as it has no membership", operation.UserID)
|
||||
}
|
||||
request.GroupChanges = append(request.GroupChanges, api.GroupMembership{
|
||||
UserID: operation.UserID,
|
||||
IsAdmin: operation.IsGroupManager,
|
||||
})
|
||||
} else {
|
||||
// Membership Exists so we can modify or delete it
|
||||
request.GroupChanges = append(request.GroupChanges, api.GroupMembership{
|
||||
ID: membership.ID,
|
||||
IsAdmin: operation.IsGroupManager,
|
||||
Delete: operation.Delete,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
dryrun, err := c.UpdateGroupDryRun(ctx, groupID, request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Update Group Dryrun: %w", err)
|
||||
}
|
||||
|
||||
var users []api.User
|
||||
// We can skip Getting users if we don't need to reencrypt any secrets
|
||||
if len(dryrun.DryRun.SecretsNeeded) != 0 {
|
||||
users, err = c.GetUsers(ctx, &api.GetUsersOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Getting Users: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// The API gives it back nested so we just put it into a list here
|
||||
secrets := []api.Secret{}
|
||||
for _, container := range dryrun.DryRun.Secrets {
|
||||
secrets = append(secrets, container.Secret...)
|
||||
}
|
||||
|
||||
decryptedSecretCache := map[string]string{}
|
||||
for _, container := range dryrun.DryRun.SecretsNeeded {
|
||||
missingSecret := container.Secret
|
||||
// Deduplicate Secret Decrypting for when adding multiple users to a group
|
||||
if decryptedSecretCache[missingSecret.ResourceID] == "" {
|
||||
secret, err := getSecretByResourceID(secrets, missingSecret.ResourceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Get Secret from Dryrun Response: %w", err)
|
||||
}
|
||||
|
||||
msg, err := c.DecryptMessage(secret.Data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Decrypting Secret: %w", err)
|
||||
}
|
||||
|
||||
decryptedSecretCache[missingSecret.ResourceID] = msg
|
||||
}
|
||||
|
||||
pubkey, err := getPublicKeyByUserID(missingSecret.UserID, users)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Get pubkey for User: %w", err)
|
||||
}
|
||||
|
||||
newSecretData, err := c.EncryptMessageWithPublicKey(pubkey, decryptedSecretCache[missingSecret.ResourceID])
|
||||
if err != nil {
|
||||
return fmt.Errorf("Encrypting Secret: %w", err)
|
||||
}
|
||||
request.Secrets = append(request.Secrets, api.Secret{
|
||||
UserID: missingSecret.UserID,
|
||||
ResourceID: missingSecret.ResourceID,
|
||||
Data: newSecretData,
|
||||
})
|
||||
}
|
||||
|
||||
_, err = c.UpdateGroup(ctx, groupID, request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Updating Group: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteGroup Deletes a Group
|
||||
func DeleteGroup(ctx context.Context, c *api.Client, groupID string) error {
|
||||
err := c.DeleteGroup(ctx, groupID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Deleting Group: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Add table
Reference in a new issue