add remaining org/proj/user initial sync
This commit is contained in:
@@ -55,7 +55,7 @@ func WithRootTenant(sid string) Option {
|
||||
return err
|
||||
}
|
||||
|
||||
s.rootResource = rootResource{id}
|
||||
s.rootResource = prefixedID{id}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ func (s *service) processMemberships(ctx context.Context, memberships []Resource
|
||||
roleActions[role] = s.roles[role]
|
||||
}
|
||||
|
||||
resourceRoleID[resourceID][role] = gidx.NullPrefixedID
|
||||
resourceRoleMembers[resourceID][role][memberID] = true
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,41 @@ import (
|
||||
"context"
|
||||
|
||||
"go.infratographer.com/x/gidx"
|
||||
|
||||
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
||||
)
|
||||
|
||||
func (s *service) buildProjectRelationships(project *models.ProjectDetails) (Relationships, error) {
|
||||
relations := Relationships{
|
||||
Relationships: []Relationship{
|
||||
// Relate project to organization.
|
||||
{
|
||||
Resource: project,
|
||||
Relation: RelateParent,
|
||||
RelatedResource: project.Organization,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, member := range project.Memberships {
|
||||
for _, role := range member.Roles {
|
||||
if _, ok := s.roles[role]; !ok {
|
||||
s.logger.Warnf("unrecognized project role '%s' for %s on %s", role, member.User.PrefixedID(), project.PrefixedID())
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
relations.Memberships = append(relations.Memberships, ResourceMemberships{
|
||||
Resource: project,
|
||||
Role: role,
|
||||
Member: member.User,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return relations, nil
|
||||
}
|
||||
|
||||
func (s *service) IsProjectID(id gidx.PrefixedID) bool {
|
||||
if idType, ok := s.idPrefixMap[id.Prefix()]; ok {
|
||||
return idType == TypeProject
|
||||
@@ -15,6 +48,27 @@ func (s *service) IsProjectID(id gidx.PrefixedID) bool {
|
||||
}
|
||||
|
||||
func (s *service) TouchProject(ctx context.Context, id gidx.PrefixedID) error {
|
||||
logger := s.logger.With("project.id", id.String())
|
||||
|
||||
project, err := s.metal.GetProjectDetails(ctx, id)
|
||||
if err != nil {
|
||||
logger.Errorw("failed to get project", "error", err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
relationships, err := s.buildProjectRelationships(project)
|
||||
if err != nil {
|
||||
logger.Errorw("failed to build project relationships", "error", err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
s.processRelationships(ctx, "metal-relation", relationships.Relationships)
|
||||
s.processMemberships(ctx, relationships.Memberships)
|
||||
|
||||
s.logger.Infow("project sync complete", "relationships", len(relationships.Relationships), "memberships", len(relationships.Memberships))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ package service
|
||||
|
||||
import (
|
||||
"go.infratographer.com/x/gidx"
|
||||
|
||||
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -60,5 +58,5 @@ type Relationship struct {
|
||||
type ResourceMemberships struct {
|
||||
Resource IDPrefixableResource
|
||||
Role string
|
||||
Member *models.UserDetails
|
||||
Member IDPrefixableResource
|
||||
}
|
||||
|
||||
@@ -47,10 +47,13 @@ type Service interface {
|
||||
|
||||
// IsUser checks if the provided id has an id prefix which is a user.
|
||||
IsUser(id gidx.PrefixedID) bool
|
||||
// TouchUser triggers a sync of a user and their permissions.
|
||||
TouchUser(ctx context.Context, id gidx.PrefixedID) error
|
||||
// DeleteUser deletes the user and their permissions.
|
||||
DeleteUser(ctx context.Context, id gidx.PrefixedID) error
|
||||
// AssignUser assigns a user to the given resource.
|
||||
AssignUser(ctx context.Context, userID gidx.PrefixedID, resourceIDs ...gidx.PrefixedID) error
|
||||
// RemoveUser removes the users from the given resource.
|
||||
RemoveUser(ctx context.Context, userID gidx.PrefixedID, resourceIDs ...gidx.PrefixedID) error
|
||||
|
||||
// IsAssignableResource checks if the provided resource ID may have assigned users.
|
||||
IsAssignableResource(id gidx.PrefixedID) bool
|
||||
}
|
||||
|
||||
var _ Service = &service{}
|
||||
@@ -62,15 +65,15 @@ type service struct {
|
||||
perms *permissions.Client
|
||||
idPrefixMap map[string]string
|
||||
|
||||
rootResource rootResource
|
||||
rootResource prefixedID
|
||||
roles map[string][]string
|
||||
}
|
||||
|
||||
type rootResource struct {
|
||||
type prefixedID struct {
|
||||
id gidx.PrefixedID
|
||||
}
|
||||
|
||||
func (r rootResource) PrefixedID() gidx.PrefixedID {
|
||||
func (r prefixedID) PrefixedID() gidx.PrefixedID {
|
||||
return r.id
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,59 @@ func (s *service) IsUser(id gidx.PrefixedID) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *service) TouchUser(ctx context.Context, id gidx.PrefixedID) error {
|
||||
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
|
||||
}
|
||||
|
||||
func (s *service) AssignUser(ctx context.Context, userID gidx.PrefixedID, resourceIDs ...gidx.PrefixedID) error {
|
||||
var memberships []ResourceMemberships
|
||||
|
||||
for _, resourceID := range resourceIDs {
|
||||
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
|
||||
}
|
||||
|
||||
if role == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
memberships = append(memberships, ResourceMemberships{
|
||||
Resource: prefixedID{resourceID},
|
||||
Role: role,
|
||||
Member: prefixedID{userID},
|
||||
})
|
||||
}
|
||||
|
||||
s.processMemberships(ctx, memberships)
|
||||
|
||||
s.logger.Infow("assignment sync complete", "memberships", len(memberships))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *service) DeleteUser(ctx context.Context, id gidx.PrefixedID) error {
|
||||
func (s *service) RemoveUser(ctx context.Context, userID gidx.PrefixedID, resourceIDs ...gidx.PrefixedID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user