3
0
2021-01-25 18:05:24 +01:00

228 lines
6.4 KiB
Go

package service
import (
"context"
"encoding/json"
"fmt"
"io"
"time"
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/filter"
ss "github.com/cortezaproject/corteza-server/system/service"
st "github.com/cortezaproject/corteza-server/system/types"
)
type (
Sync struct {
syncer *Syncer
mapper *Mapper
sharedModuleService SharedModuleService
composeRecordService cs.RecordService
systemUserService ss.UserService
systemRoleService ss.RoleService
}
)
func NewSync(s *Syncer, m *Mapper, sm SharedModuleService, cs cs.RecordService, us ss.UserService, rs ss.RoleService) *Sync {
return &Sync{
syncer: s,
mapper: m,
sharedModuleService: sm,
composeRecordService: cs,
systemUserService: us,
systemRoleService: rs,
}
}
// CanUpdateSharedModule checks the origin and destination module
// compatibility of fields
// It currently checks if all of the fields are exactly the same
// TODO - check if any of the newly missing fields are actually being used so a safe update
// is possible
func (s *Sync) CanUpdateSharedModule(ctx context.Context, new *types.SharedModule, existing *types.SharedModule) (bool, error) {
// check for mapped fields
var (
fstr, f2str []byte
err error
)
if fstr, err = json.Marshal(new.Fields); err != nil {
return false, err
}
if f2str, err = json.Marshal(existing.Fields); err != nil {
return false, err
}
return string(fstr) == string(f2str), nil
}
// ProcessPayload passes the payload to the syncer lib
func (s *Sync) ProcessPayload(ctx context.Context, payload []byte, out chan Url, url types.SyncerURI, processer Processer) (ProcesserResponse, error) {
return s.syncer.Process(ctx, payload, out, url, processer)
}
// QueueUrl passes the url to the syncer
func (s *Sync) QueueUrl(url Url, out chan Url) {
s.syncer.Queue(url, out)
}
// FetchUrl passes the url to be fetched to the syncer
func (s *Sync) FetchUrl(ctx context.Context, url string) (io.Reader, error) {
return s.syncer.Fetch(ctx, url)
}
// CreateRecord wraps the compose Record service Create
func (s *Sync) CreateRecord(ctx context.Context, rec *ct.Record) (*ct.Record, error) {
return s.composeRecordService.Create(ctx, rec)
}
// UpdateRecord wraps the compose Record service Update
func (s *Sync) UpdateRecord(ctx context.Context, rec *ct.Record) (*ct.Record, error) {
return s.composeRecordService.Update(ctx, rec)
}
// DeleteRecord wraps the compose Record service Update
func (s *Sync) DeleteRecord(ctx context.Context, rec *ct.Record) error {
return s.composeRecordService.DeleteByID(ctx, rec.NamespaceID, rec.ModuleID, rec.ID)
}
// FindRecord find the record via federation label
func (s *Sync) FindRecords(ctx context.Context, filter ct.RecordFilter) (set ct.RecordSet, err error) {
set, _, err = s.composeRecordService.Find(ctx, filter)
return
}
// LookupSharedModule find the shared module if exists
func (s *Sync) LookupSharedModule(ctx context.Context, new *types.SharedModule) (*types.SharedModule, error) {
var sm *types.SharedModule
list, _, err := s.sharedModuleService.Find(ctx, types.SharedModuleFilter{
NodeID: new.NodeID,
ExternalFederationModuleID: new.ExternalFederationModuleID})
if err != nil {
return nil, err
}
if len(list) == 0 {
return nil, nil
}
sm = list[0]
return sm, nil
}
// UpdateSharedModule wraps the federation SharedModule service Update
func (s *Sync) UpdateSharedModule(ctx context.Context, updated *types.SharedModule) (*types.SharedModule, error) {
return s.sharedModuleService.Update(ctx, updated)
}
// CreateSharedModule wraps the federation SharedModule service Create
func (s *Sync) CreateSharedModule(ctx context.Context, new *types.SharedModule) (*types.SharedModule, error) {
return s.sharedModuleService.Create(ctx, new)
}
// GetPairedNodes finds successfuly paired nodes
func (s *Sync) GetPairedNodes(ctx context.Context) (types.NodeSet, error) {
set, _, err := DefaultNode.Search(ctx, types.NodeFilter{Status: types.NodeStatusPaired})
if err != nil {
return nil, err
}
return set, nil
}
func (s *Sync) GetSharedModules(ctx context.Context, nodeID uint64) (types.SharedModuleSet, error) {
set, _, err := DefaultSharedModule.Find(ctx, types.SharedModuleFilter{NodeID: nodeID})
if err != nil {
return nil, err
}
set, _ = set.Filter(func(sm *types.SharedModule) (bool, error) {
return len(sm.Fields) > 0, nil
})
return set, nil
}
func (s *Sync) GetModuleMappings(ctx context.Context, moduleID uint64) (out *types.ModuleMapping, err error) {
out, err = DefaultModuleMapping.FindByID(ctx, moduleID)
return
}
func (s *Sync) PrepareModuleMappings(ctx context.Context, mappings *types.ModuleMapping) (ct.RecordValueSet, error) {
return s.mapper.Prepare((*mappings).FieldMapping), nil
}
func (s *Sync) GetLastStructureSyncStatus(ctx context.Context, nodeID, externalFederationModuleID uint64) (syncStatus string, err error) {
var list types.NodeSyncSet
list, _, err = DefaultNodeSync.Search(ctx, types.NodeSyncFilter{
NodeID: nodeID,
ModuleID: externalFederationModuleID,
SyncType: types.NodeSyncTypeStructure,
Sorting: filter.Sorting{
Sort: filter.SortExprSet{
&filter.SortExpr{Column: "time_action", Descending: true},
},
},
Paging: filter.Paging{Limit: 1},
})
if err != nil {
syncStatus = types.NodeSyncStatusSuccess
return
}
if len(list) == 0 {
syncStatus = types.NodeSyncStatusSuccess
return
}
syncStatus = list[0].SyncStatus
return
}
func (s *Sync) GetLastSyncTime(ctx context.Context, nodeID uint64, syncType string) (*time.Time, error) {
ns, err := DefaultNodeSync.LookupLastSuccessfulSync(ctx, nodeID, syncType)
if err != nil || ns == nil {
return nil, err
}
return &ns.TimeOfAction, nil
}
// LoadUserWithRoles gets the federation user, that was
// created at node pairing process
func (s *Sync) LoadUserWithRoles(ctx context.Context, nodeID uint64) (*st.User, error) {
var (
u *st.User
err error
)
// get the federated user, associated for this node
if u, err = s.systemUserService.FindByHandle(ctx, fmt.Sprintf("federation_%d", nodeID)); err != nil {
return nil, err
}
// attach the roles
rr, _, err := s.systemRoleService.Find(ctx, st.RoleFilter{MemberID: u.ID})
if err != nil {
return nil, err
}
u.SetRoles(rr.IDs())
return u, nil
}