148 lines
3.5 KiB
Go
148 lines
3.5 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
"go.infratographer.com/x/gidx"
|
|
)
|
|
|
|
// IsUser checks the provided id has the metal user prefix.
|
|
func (s *service) IsUser(id gidx.PrefixedID) bool {
|
|
if idType, ok := s.idPrefixMap[id.Prefix()]; ok {
|
|
return idType == TypeUser
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// IsAssignableResource checks that the provided id is an id which can have memberships assignments.
|
|
func (s *service) IsAssignableResource(id gidx.PrefixedID) bool {
|
|
if idType, ok := s.idPrefixMap[id.Prefix()]; ok {
|
|
switch idType {
|
|
case TypeOrganization, TypeProject:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Assignuser assigns the provided users to the given resource ids.
|
|
func (s *service) AssignUser(ctx context.Context, userID gidx.PrefixedID, resourceIDs ...gidx.PrefixedID) error {
|
|
var totalResources, rolesChanged, assignmentsChanged int
|
|
|
|
mlogger := s.logger.With("member.id", userID.String())
|
|
|
|
memberID := prefixedID{userID}
|
|
|
|
for _, resourceID := range resourceIDs {
|
|
role, err := s.getUserResourceRole(ctx, userID, resourceID)
|
|
if err != nil {
|
|
mlogger.Warnw("failed to determine role for user resource", "error", err)
|
|
continue
|
|
}
|
|
|
|
if role == "" {
|
|
continue
|
|
}
|
|
|
|
roles, assignments := s.syncMemberships(ctx, Relationships{
|
|
Resource: prefixedID{resourceID},
|
|
Memberships: []ResourceMemberships{
|
|
{
|
|
Role: role,
|
|
Member: memberID,
|
|
},
|
|
},
|
|
}, true)
|
|
|
|
totalResources++
|
|
rolesChanged += roles
|
|
assignmentsChanged += assignments
|
|
}
|
|
|
|
mlogger.Infow("assignment sync complete",
|
|
"membership.roles_changed", rolesChanged,
|
|
"membership.assignments_changed", assignmentsChanged,
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// UnassignUser removes the assignment for the provided user id to the given resources.
|
|
func (s *service) UnassignUser(ctx context.Context, userID gidx.PrefixedID, resourceIDs ...gidx.PrefixedID) error {
|
|
for _, resourceID := range resourceIDs {
|
|
rlogger := s.logger.With("user.id", userID, "resource.id", resourceID)
|
|
|
|
role, err := s.getUserResourceRole(ctx, userID, resourceID)
|
|
if err != nil {
|
|
rlogger.Warnw("failed to determine role for user resource", "error", err)
|
|
|
|
continue
|
|
}
|
|
|
|
if role == "" {
|
|
continue
|
|
}
|
|
|
|
actions := s.roles[role]
|
|
|
|
rlogger = rlogger.With("role.name", role, "role.actions", actions)
|
|
|
|
resourceRole, err := s.perms.FindResourceRoleByActions(ctx, resourceID, actions)
|
|
if err != nil {
|
|
rlogger.Warnw("failed to find role by actions for resource", "error", err)
|
|
|
|
continue
|
|
}
|
|
|
|
rlogger = rlogger.With("role.id", resourceRole.ID)
|
|
|
|
assigned, err := s.perms.RoleHasAssignment(ctx, resourceRole.ID, userID)
|
|
if err != nil {
|
|
rlogger.Warnw("failed to check role assignment", "error", err)
|
|
|
|
continue
|
|
}
|
|
|
|
if !assigned {
|
|
rlogger.Warnw("unable to unassign member which is not assigned")
|
|
|
|
continue
|
|
}
|
|
|
|
if err = s.perms.UnassignRole(ctx, resourceRole.ID, userID); err != nil {
|
|
rlogger.Errorw("failed to unassign member from role", "error", err)
|
|
|
|
continue
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// getuserResourceRole fetches the appropriate object types user role for the given resource.
|
|
func (s *service) getUserResourceRole(ctx context.Context, userID, resourceID gidx.PrefixedID) (string, error) {
|
|
var (
|
|
role string
|
|
err error
|
|
)
|
|
|
|
if idType, ok := s.idPrefixMap[resourceID.Prefix()]; ok {
|
|
switch idType {
|
|
case TypeOrganization:
|
|
role, err = s.metal.GetUserOrganizationRole(ctx, userID, resourceID)
|
|
case TypeProject:
|
|
role, err = s.metal.GetUserProjectRole(ctx, userID, resourceID)
|
|
}
|
|
}
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return role, nil
|
|
}
|