143 lines
3.8 KiB
Go
143 lines
3.8 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
"go.infratographer.com/x/events"
|
|
"go.infratographer.com/x/gidx"
|
|
"go.opentelemetry.io/otel"
|
|
"go.uber.org/zap"
|
|
|
|
"go.equinixmetal.net/infra9-metal-bridge/internal/metal"
|
|
"go.equinixmetal.net/infra9-metal-bridge/internal/permissions"
|
|
)
|
|
|
|
const (
|
|
// TypeOrganization defines the organization type.
|
|
TypeOrganization ObjectType = "organization"
|
|
|
|
// TypeProject defines the project type.
|
|
TypeProject ObjectType = "project"
|
|
|
|
// TypeUser defines the user type.
|
|
TypeUser ObjectType = "user"
|
|
)
|
|
|
|
var tracer = otel.Tracer("go.equinixmetal.net/infra9-metal-bridge/internal/service")
|
|
|
|
// DefaultPrefixMap is the default id prefix to type relationship.
|
|
var DefaultPrefixMap = map[string]ObjectType{
|
|
TypeOrganization.Prefix(): TypeOrganization,
|
|
TypeProject.Prefix(): TypeProject,
|
|
TypeUser.Prefix(): TypeUser,
|
|
}
|
|
|
|
// ObjectType defines a type of object.
|
|
type ObjectType string
|
|
|
|
// Prefix returns the objects id prefix.
|
|
func (t ObjectType) Prefix() string {
|
|
switch t {
|
|
case TypeOrganization:
|
|
return "metlorg"
|
|
case TypeProject:
|
|
return "metlprj"
|
|
case TypeUser:
|
|
return "metlusr"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
// String returns a string fo the object type.
|
|
func (t ObjectType) String() string {
|
|
return string(t)
|
|
}
|
|
|
|
// Service defines a bridge service methods
|
|
type Service interface {
|
|
// IsOrganizationID checks if the provided id has an id prefix which is an organization.
|
|
IsOrganizationID(id gidx.PrefixedID) bool
|
|
// TouchOrganization triggers a sync of an organization.
|
|
TouchOrganization(ctx context.Context, id gidx.PrefixedID) error
|
|
// DeleteOrganization deletes an organization and all of its resources.
|
|
DeleteOrganization(ctx context.Context, id gidx.PrefixedID) error
|
|
|
|
// IsProjectID checks if the provided id has an id prefix which is a project.
|
|
IsProjectID(id gidx.PrefixedID) bool
|
|
// TouchProject triggers a sync of an organization
|
|
TouchProject(ctx context.Context, id gidx.PrefixedID) error
|
|
// DeleteProject deletes the project and all of its resources.
|
|
DeleteProject(ctx context.Context, id gidx.PrefixedID) error
|
|
|
|
// IsUser checks if the provided id has an id prefix which is a user.
|
|
IsUser(id gidx.PrefixedID) bool
|
|
// AssignUser assigns a user to the given resource.
|
|
AssignUser(ctx context.Context, userID gidx.PrefixedID, resourceIDs ...gidx.PrefixedID) error
|
|
// UnassignUser removes the users from the given resource.
|
|
UnassignUser(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
|
|
}
|
|
|
|
// EventPublisher defines the required methods to publish events.
|
|
type EventPublisher interface {
|
|
PublishChange(ctx context.Context, subjectType string, change events.ChangeMessage) error
|
|
}
|
|
|
|
var _ Service = &service{}
|
|
|
|
type service struct {
|
|
logger *zap.SugaredLogger
|
|
publisher EventPublisher
|
|
metal metal.Client
|
|
perms permissions.Client
|
|
idPrefixMap map[string]ObjectType
|
|
|
|
rootResource prefixedID
|
|
roles map[string][]string
|
|
}
|
|
|
|
type prefixedID struct {
|
|
id gidx.PrefixedID
|
|
}
|
|
|
|
func (r prefixedID) PrefixedID() gidx.PrefixedID {
|
|
return r.id
|
|
}
|
|
|
|
// New creates a new service.
|
|
func New(publisher EventPublisher, metal metal.Client, perms permissions.Client, options ...Option) (Service, error) {
|
|
svc := &service{
|
|
publisher: publisher,
|
|
metal: metal,
|
|
perms: perms,
|
|
idPrefixMap: make(map[string]ObjectType),
|
|
}
|
|
|
|
for _, opt := range options {
|
|
if err := opt(svc); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if svc.logger == nil {
|
|
svc.logger = zap.NewNop().Sugar()
|
|
}
|
|
|
|
if svc.rootResource.PrefixedID() == gidx.NullPrefixedID {
|
|
return nil, ErrRootTenantRequired
|
|
}
|
|
|
|
if svc.idPrefixMap == nil || len(svc.idPrefixMap) == 0 {
|
|
svc.idPrefixMap = DefaultPrefixMap
|
|
}
|
|
|
|
if svc.roles == nil {
|
|
svc.roles = make(map[string][]string)
|
|
}
|
|
|
|
return svc, nil
|
|
}
|