add remaining org/proj/user initial sync
This commit is contained in:
@@ -3,10 +3,11 @@ package metal
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
|
||||||
provider "go.equinixmetal.net/infra9-metal-bridge/internal/metal/providers"
|
|
||||||
"go.infratographer.com/x/gidx"
|
"go.infratographer.com/x/gidx"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
||||||
|
provider "go.equinixmetal.net/infra9-metal-bridge/internal/metal/providers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is the Equinix Metal API Client struct.
|
// Client is the Equinix Metal API Client struct.
|
||||||
@@ -28,6 +29,14 @@ func (c *Client) GetUserDetails(ctx context.Context, id gidx.PrefixedID) (*model
|
|||||||
return c.provider.GetUserDetails(ctx, id)
|
return c.provider.GetUserDetails(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetUserOrganizationRole(ctx context.Context, userID, orgID gidx.PrefixedID) (string, error) {
|
||||||
|
return c.provider.GetUserOrganizationRole(ctx, userID, orgID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetUserProjectRole(ctx context.Context, userID, projID gidx.PrefixedID) (string, error) {
|
||||||
|
return c.provider.GetUserProjectRole(ctx, userID, projID)
|
||||||
|
}
|
||||||
|
|
||||||
// New creates a new Client.
|
// New creates a new Client.
|
||||||
func New(options ...Option) (*Client, error) {
|
func New(options ...Option) (*Client, error) {
|
||||||
client := new(Client)
|
client := new(Client)
|
||||||
|
|||||||
27
internal/metal/providers/emapi/helpers.go
Normal file
27
internal/metal/providers/emapi/helpers.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package emapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// idOrLinkID returns the id if not empty, otherwise it plucks the last subpath from the link.
|
||||||
|
// An empty string is returned if nothing is defined or an error occurs.
|
||||||
|
func idOrLinkID(id, link string) string {
|
||||||
|
if id != "" || link == "" {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
url, err := url.Parse(link)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(strings.TrimRight(url.Path, "/"), "/")
|
||||||
|
|
||||||
|
if len(parts) != 0 {
|
||||||
|
return parts[len(parts)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@@ -48,12 +48,18 @@ type Organization struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *Organization) ToDetails() *models.OrganizationDetails {
|
func (o *Organization) ToDetails() *models.OrganizationDetails {
|
||||||
if o == nil || o.ID == "" {
|
var id string
|
||||||
|
|
||||||
|
if o != nil {
|
||||||
|
id = idOrLinkID(o.ID, o.HREF)
|
||||||
|
}
|
||||||
|
|
||||||
|
if id == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
details := &models.OrganizationDetails{
|
details := &models.OrganizationDetails{
|
||||||
ID: o.ID,
|
ID: id,
|
||||||
Name: o.Name,
|
Name: o.Name,
|
||||||
Projects: o.Projects.ToDetails(),
|
Projects: o.Projects.ToDetails(),
|
||||||
}
|
}
|
||||||
@@ -66,7 +72,7 @@ func (o *Organization) ToDetails() *models.OrganizationDetails {
|
|||||||
func (c *Client) getOrganizationWithMemberships(ctx context.Context, id string) (*Organization, error) {
|
func (c *Client) getOrganizationWithMemberships(ctx context.Context, id string) (*Organization, error) {
|
||||||
var org Organization
|
var org Organization
|
||||||
|
|
||||||
_, err := c.DoRequest(ctx, http.MethodGet, organizationsPath+"/"+id+"?include=memberships.user,projects.memberships.user", nil, &org)
|
_, err := c.DoRequest(ctx, http.MethodGet, organizationsPath+"/"+id+"?include=memberships.user", nil, &org)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error loading organization: %w", err)
|
return nil, fmt.Errorf("error loading organization: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,12 +48,18 @@ type Project struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Project) ToDetails() *models.ProjectDetails {
|
func (p *Project) ToDetails() *models.ProjectDetails {
|
||||||
if p == nil || p.ID == "" {
|
var id string
|
||||||
|
|
||||||
|
if p != nil {
|
||||||
|
id = idOrLinkID(p.ID, p.HREF)
|
||||||
|
}
|
||||||
|
|
||||||
|
if id == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
details := &models.ProjectDetails{
|
details := &models.ProjectDetails{
|
||||||
ID: p.ID,
|
ID: id,
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
Organization: p.Organization.ToDetails(),
|
Organization: p.Organization.ToDetails(),
|
||||||
}
|
}
|
||||||
@@ -63,19 +69,19 @@ func (p *Project) ToDetails() *models.ProjectDetails {
|
|||||||
return details
|
return details
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getProject(ctx context.Context, id string) (*Project, error) {
|
func (c *Client) getProjectWithMemberships(ctx context.Context, id string) (*Project, error) {
|
||||||
var project Project
|
var project Project
|
||||||
|
|
||||||
_, err := c.DoRequest(ctx, http.MethodGet, c.baseURL.JoinPath(projectsPath, id).String(), nil, &project)
|
_, err := c.DoRequest(ctx, http.MethodGet, projectsPath+"/"+id+"?include=memberships.user", nil, &project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error loading project: %w", err)
|
return nil, fmt.Errorf("error loading organization: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &project, nil
|
return &project, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetProjectDetails(ctx context.Context, id gidx.PrefixedID) (*models.ProjectDetails, error) {
|
func (c *Client) GetProjectDetails(ctx context.Context, id gidx.PrefixedID) (*models.ProjectDetails, error) {
|
||||||
project, err := c.getProject(ctx, id.String()[gidx.PrefixPartLength+1:])
|
project, err := c.getProjectWithMemberships(ctx, id.String()[gidx.PrefixPartLength+1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,12 +47,18 @@ type User struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) ToDetails() *models.UserDetails {
|
func (u *User) ToDetails() *models.UserDetails {
|
||||||
if u.ID == "" {
|
var id string
|
||||||
|
|
||||||
|
if u != nil {
|
||||||
|
id = idOrLinkID(u.ID, u.HREF)
|
||||||
|
}
|
||||||
|
|
||||||
|
if id == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &models.UserDetails{
|
return &models.UserDetails{
|
||||||
ID: u.ID,
|
ID: id,
|
||||||
FullName: u.FullName,
|
FullName: u.FullName,
|
||||||
Organizations: nil,
|
Organizations: nil,
|
||||||
Projects: u.Projects.ToDetails(),
|
Projects: u.Projects.ToDetails(),
|
||||||
@@ -62,9 +68,9 @@ func (u *User) ToDetails() *models.UserDetails {
|
|||||||
func (c *Client) getUser(ctx context.Context, id string) (*User, error) {
|
func (c *Client) getUser(ctx context.Context, id string) (*User, error) {
|
||||||
var user User
|
var user User
|
||||||
|
|
||||||
_, err := c.DoRequest(ctx, http.MethodGet, c.baseURL.JoinPath(usersPath, id).String(), nil, &user)
|
_, err := c.DoRequest(ctx, http.MethodGet, usersPath+"/"+id, nil, &user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error loading user: %w", err)
|
return nil, fmt.Errorf("error loading organization: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &user, nil
|
return &user, nil
|
||||||
@@ -78,3 +84,11 @@ func (c *Client) GetUserDetails(ctx context.Context, id gidx.PrefixedID) (*model
|
|||||||
|
|
||||||
return user.ToDetails(), nil
|
return user.ToDetails(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetUserOrganizationRole(ctx context.Context, userID, orgID gidx.PrefixedID) (string, error) {
|
||||||
|
return "collaborator", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetUserProjectRole(ctx context.Context, userID, projectID gidx.PrefixedID) (string, error) {
|
||||||
|
return "collaborator", nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,10 +3,19 @@ package emgql
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
|
||||||
"go.infratographer.com/x/gidx"
|
"go.infratographer.com/x/gidx"
|
||||||
|
|
||||||
|
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) GetUserDetails(ctx context.Context, id gidx.PrefixedID) (*models.UserDetails, error) {
|
func (c *Client) GetUserDetails(ctx context.Context, id gidx.PrefixedID) (*models.UserDetails, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetUserOrganizationRole(ctx context.Context, userID, orgID gidx.PrefixedID) (string, error) {
|
||||||
|
return "collaborator", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetUserProjectRole(ctx context.Context, userID, projID gidx.PrefixedID) (string, error) {
|
||||||
|
return "collaborator", nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ package provider
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
|
||||||
"go.infratographer.com/x/gidx"
|
"go.infratographer.com/x/gidx"
|
||||||
|
|
||||||
|
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
GetOrganizationDetails(ctx context.Context, id gidx.PrefixedID) (*models.OrganizationDetails, error)
|
GetOrganizationDetails(ctx context.Context, id gidx.PrefixedID) (*models.OrganizationDetails, error)
|
||||||
GetProjectDetails(ctx context.Context, id gidx.PrefixedID) (*models.ProjectDetails, error)
|
GetProjectDetails(ctx context.Context, id gidx.PrefixedID) (*models.ProjectDetails, error)
|
||||||
GetUserDetails(ctx context.Context, id gidx.PrefixedID) (*models.UserDetails, error)
|
GetUserDetails(ctx context.Context, id gidx.PrefixedID) (*models.UserDetails, error)
|
||||||
|
GetUserOrganizationRole(ctx context.Context, userID, orgID gidx.PrefixedID) (string, error)
|
||||||
|
GetUserProjectRole(ctx context.Context, userID, projID gidx.PrefixedID) (string, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,13 +51,15 @@ func (c *Client) CreateRole(ctx context.Context, resourceID gidx.PrefixedID, act
|
|||||||
func (c *Client) ListResourceRoles(ctx context.Context, resourceID gidx.PrefixedID) (ResourceRoles, error) {
|
func (c *Client) ListResourceRoles(ctx context.Context, resourceID gidx.PrefixedID) (ResourceRoles, error) {
|
||||||
path := fmt.Sprintf("/api/v1/resources/%s/roles", resourceID.String())
|
path := fmt.Sprintf("/api/v1/resources/%s/roles", resourceID.String())
|
||||||
|
|
||||||
var response ResourceRoles
|
var response struct {
|
||||||
|
Data ResourceRoles `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := c.DoRequest(ctx, http.MethodGet, path, nil, &response); err != nil {
|
if _, err := c.DoRequest(ctx, http.MethodGet, path, nil, &response); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return response, nil
|
return response.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) FindResourceRoleByActions(ctx context.Context, resourceID gidx.PrefixedID, actions []string) (ResourceRole, error) {
|
func (c *Client) FindResourceRoleByActions(ctx context.Context, resourceID gidx.PrefixedID, actions []string) (ResourceRole, error) {
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ func (s *Subscriber) handleTouchEvent(ctx context.Context, msg *message.Message,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.svc.IsUser(changeMsg.SubjectID) {
|
if s.svc.IsUser(changeMsg.SubjectID) {
|
||||||
if err := s.svc.TouchUser(ctx, changeMsg.SubjectID); err != nil {
|
if err := s.svc.AssignUser(ctx, changeMsg.SubjectID, changeMsg.AdditionalSubjectIDs...); err != nil {
|
||||||
// TODO: only return errors on retryable errors
|
// TODO: only return errors on retryable errors
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ func (s *Subscriber) handleDeleteEvent(ctx context.Context, msg *message.Message
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.svc.IsUser(changeMsg.SubjectID) {
|
if s.svc.IsUser(changeMsg.SubjectID) {
|
||||||
if err := s.svc.DeleteUser(ctx, changeMsg.SubjectID); err != nil {
|
if err := s.svc.RemoveUser(ctx, changeMsg.SubjectID, changeMsg.AdditionalSubjectIDs...); err != nil {
|
||||||
// TODO: only return errors on retryable errors
|
// TODO: only return errors on retryable errors
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ func WithRootTenant(sid string) Option {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.rootResource = rootResource{id}
|
s.rootResource = prefixedID{id}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ func (s *service) processMemberships(ctx context.Context, memberships []Resource
|
|||||||
roleActions[role] = s.roles[role]
|
roleActions[role] = s.roles[role]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resourceRoleID[resourceID][role] = gidx.NullPrefixedID
|
||||||
resourceRoleMembers[resourceID][role][memberID] = true
|
resourceRoleMembers[resourceID][role][memberID] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,41 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"go.infratographer.com/x/gidx"
|
"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 {
|
func (s *service) IsProjectID(id gidx.PrefixedID) bool {
|
||||||
if idType, ok := s.idPrefixMap[id.Prefix()]; ok {
|
if idType, ok := s.idPrefixMap[id.Prefix()]; ok {
|
||||||
return idType == TypeProject
|
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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"go.infratographer.com/x/gidx"
|
"go.infratographer.com/x/gidx"
|
||||||
|
|
||||||
"go.equinixmetal.net/infra9-metal-bridge/internal/metal/models"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -60,5 +58,5 @@ type Relationship struct {
|
|||||||
type ResourceMemberships struct {
|
type ResourceMemberships struct {
|
||||||
Resource IDPrefixableResource
|
Resource IDPrefixableResource
|
||||||
Role string
|
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 checks if the provided id has an id prefix which is a user.
|
||||||
IsUser(id gidx.PrefixedID) bool
|
IsUser(id gidx.PrefixedID) bool
|
||||||
// TouchUser triggers a sync of a user and their permissions.
|
// AssignUser assigns a user to the given resource.
|
||||||
TouchUser(ctx context.Context, id gidx.PrefixedID) error
|
AssignUser(ctx context.Context, userID gidx.PrefixedID, resourceIDs ...gidx.PrefixedID) error
|
||||||
// DeleteUser deletes the user and their permissions.
|
// RemoveUser removes the users from the given resource.
|
||||||
DeleteUser(ctx context.Context, id gidx.PrefixedID) error
|
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{}
|
var _ Service = &service{}
|
||||||
@@ -62,15 +65,15 @@ type service struct {
|
|||||||
perms *permissions.Client
|
perms *permissions.Client
|
||||||
idPrefixMap map[string]string
|
idPrefixMap map[string]string
|
||||||
|
|
||||||
rootResource rootResource
|
rootResource prefixedID
|
||||||
roles map[string][]string
|
roles map[string][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type rootResource struct {
|
type prefixedID struct {
|
||||||
id gidx.PrefixedID
|
id gidx.PrefixedID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r rootResource) PrefixedID() gidx.PrefixedID {
|
func (r prefixedID) PrefixedID() gidx.PrefixedID {
|
||||||
return r.id
|
return r.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,59 @@ func (s *service) IsUser(id gidx.PrefixedID) bool {
|
|||||||
return false
|
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
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user