220 lines
5.7 KiB
Go
220 lines
5.7 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
cs "github.com/cortezaproject/corteza-server/compose/service"
|
|
ct "github.com/cortezaproject/corteza-server/compose/types"
|
|
"github.com/cortezaproject/corteza-server/federation/types"
|
|
"github.com/cortezaproject/corteza-server/pkg/actionlog"
|
|
"github.com/cortezaproject/corteza-server/store"
|
|
)
|
|
|
|
type (
|
|
moduleMapping struct {
|
|
store store.Storer
|
|
node node
|
|
ac moduleMappingAccessController
|
|
module cs.ModuleService
|
|
smodule SharedModuleService
|
|
namespace cs.NamespaceService
|
|
actionlog actionlog.Recorder
|
|
}
|
|
|
|
moduleMappingAccessController interface {
|
|
CanMapModule(ctx context.Context, r *types.SharedModule) bool
|
|
}
|
|
|
|
ModuleMappingService interface {
|
|
Find(ctx context.Context, filter types.ModuleMappingFilter) (types.ModuleMappingSet, types.ModuleMappingFilter, error)
|
|
FindByID(ctx context.Context, federationModuleID uint64) (*types.ModuleMapping, error)
|
|
Create(ctx context.Context, new *types.ModuleMapping) (*types.ModuleMapping, error)
|
|
Update(ctx context.Context, updated *types.ModuleMapping) (*types.ModuleMapping, error)
|
|
}
|
|
|
|
moduleMappingUpdateHandler func(ctx context.Context, c *types.ModuleMapping) (bool, bool, error)
|
|
)
|
|
|
|
func ModuleMapping() ModuleMappingService {
|
|
return &moduleMapping{
|
|
ac: DefaultAccessControl,
|
|
node: *DefaultNode,
|
|
store: DefaultStore,
|
|
actionlog: DefaultActionlog,
|
|
smodule: DefaultSharedModule,
|
|
module: cs.DefaultModule,
|
|
namespace: cs.DefaultNamespace,
|
|
}
|
|
}
|
|
|
|
func (svc moduleMapping) FindByID(ctx context.Context, federationModuleID uint64) (mm *types.ModuleMapping, err error) {
|
|
err = func() error {
|
|
var (
|
|
sm *types.SharedModule
|
|
)
|
|
|
|
if mm, err = store.LookupFederationModuleMappingByFederationModuleID(ctx, svc.store, federationModuleID); err != nil {
|
|
return err
|
|
}
|
|
|
|
// fetch shared module for access check
|
|
if sm, err = svc.smodule.FindByID(ctx, mm.NodeID, federationModuleID); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !svc.ac.CanMapModule(ctx, sm) {
|
|
return ModuleMappingErrNotAllowedToMap()
|
|
}
|
|
|
|
return nil
|
|
}()
|
|
|
|
return
|
|
}
|
|
|
|
func (svc moduleMapping) Find(ctx context.Context, filter types.ModuleMappingFilter) (set types.ModuleMappingSet, f types.ModuleMappingFilter, err error) {
|
|
// @todo - optimise this access check
|
|
filter.Check = func(res *types.ModuleMapping) (bool, error) {
|
|
// fetch shared module for this
|
|
sm, err := svc.smodule.FindByID(ctx, res.NodeID, res.FederationModuleID)
|
|
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if !svc.ac.CanMapModule(ctx, sm) {
|
|
return false, ModuleMappingErrNotAllowedToMap()
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
err = func() error {
|
|
if set, f, err = store.SearchFederationModuleMappings(ctx, svc.store, filter); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}()
|
|
|
|
set.Walk(func(mm *types.ModuleMapping) error {
|
|
mm.NodeID = f.NodeID
|
|
return nil
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
func (svc moduleMapping) Create(ctx context.Context, new *types.ModuleMapping) (*types.ModuleMapping, error) {
|
|
var (
|
|
aProps = &moduleMappingActionProps{created: new}
|
|
)
|
|
|
|
err := store.Tx(ctx, svc.store, func(ctx context.Context, s store.Storer) (err error) {
|
|
var (
|
|
m *ct.Module
|
|
sm *types.SharedModule
|
|
)
|
|
|
|
if _, err := svc.namespace.FindByID(ctx, new.ComposeNamespaceID); err != nil {
|
|
return ModuleMappingErrComposeNamespaceNotFound()
|
|
}
|
|
|
|
if _, err = svc.node.FindByID(ctx, new.NodeID); err != nil {
|
|
return ModuleMappingErrNodeNotFound()
|
|
}
|
|
|
|
// Check for federation module - compose.Module combo
|
|
if err = svc.uniqueCheck(ctx, new); err != nil {
|
|
return err
|
|
}
|
|
|
|
if m, err = svc.module.FindByID(ctx, new.ComposeNamespaceID, new.ComposeModuleID); err != nil {
|
|
return ModuleMappingErrComposeModuleNotFound()
|
|
}
|
|
|
|
if sm, err = svc.smodule.FindByID(ctx, new.NodeID, new.FederationModuleID); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !svc.ac.CanMapModule(ctx, sm) {
|
|
return ModuleMappingErrNotAllowedToMap()
|
|
}
|
|
|
|
if err = store.CreateFederationModuleMapping(ctx, s, new); err != nil {
|
|
return err
|
|
}
|
|
|
|
// set labels
|
|
AddFederationLabel(m, "federation", "")
|
|
|
|
if _, err := svc.module.Update(ctx, m); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
return new, svc.recordAction(ctx, aProps, ModuleMappingActionCreate, err)
|
|
}
|
|
|
|
func (svc moduleMapping) Update(ctx context.Context, updated *types.ModuleMapping) (*types.ModuleMapping, error) {
|
|
var (
|
|
aProps = &moduleMappingActionProps{changed: updated}
|
|
)
|
|
|
|
err := store.Tx(ctx, svc.store, func(ctx context.Context, s store.Storer) (err error) {
|
|
var (
|
|
m *ct.Module
|
|
sm *types.SharedModule
|
|
)
|
|
|
|
if _, err := svc.namespace.FindByID(ctx, updated.ComposeNamespaceID); err != nil {
|
|
return ModuleMappingErrComposeNamespaceNotFound()
|
|
}
|
|
|
|
if m, err = svc.module.FindByID(ctx, updated.ComposeNamespaceID, updated.ComposeModuleID); err != nil {
|
|
return ModuleMappingErrComposeModuleNotFound()
|
|
}
|
|
|
|
if sm, err = svc.smodule.FindByID(ctx, updated.NodeID, updated.FederationModuleID); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !svc.ac.CanMapModule(ctx, sm) {
|
|
return ModuleMappingErrNotAllowedToMap()
|
|
}
|
|
|
|
if err = store.UpdateFederationModuleMapping(ctx, s, updated); err != nil {
|
|
return err
|
|
}
|
|
|
|
// set labels
|
|
AddFederationLabel(m, "federation", "")
|
|
|
|
if _, err := svc.module.Update(ctx, m); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
return updated, svc.recordAction(ctx, aProps, ModuleMappingActionUpdate, err)
|
|
}
|
|
|
|
func (svc moduleMapping) uniqueCheck(ctx context.Context, m *types.ModuleMapping) (err error) {
|
|
f := types.ModuleMappingFilter{
|
|
FederationModuleID: m.FederationModuleID,
|
|
ComposeModuleID: m.ComposeModuleID,
|
|
ComposeNamespaceID: m.ComposeNamespaceID,
|
|
}
|
|
|
|
if set, _, err := store.SearchFederationModuleMappings(ctx, svc.store, f); len(set) > 0 && err == nil {
|
|
return ModuleMappingErrModuleMappingExists()
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
return err
|
|
}
|