199 lines
6.9 KiB
Go
199 lines
6.9 KiB
Go
package workspace
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"cloud.o-forge.io/core/oc-lib/dbs"
|
|
"cloud.o-forge.io/core/oc-lib/models/collaborative_area/shallow_collaborative_area"
|
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
|
"cloud.o-forge.io/core/oc-lib/models/resources"
|
|
"cloud.o-forge.io/core/oc-lib/models/utils"
|
|
"cloud.o-forge.io/core/oc-lib/tools"
|
|
)
|
|
|
|
// trustedRelations holds peer relations that yield TrustMap = true for a resource.
|
|
var trustedRelations = map[peer.PeerRelation]bool{
|
|
peer.PARTNER: true,
|
|
peer.MASTER: true,
|
|
peer.NANO: true,
|
|
peer.ORGANIZATION_MASTER: true,
|
|
peer.ORGANIZATION_MEMBER: true,
|
|
peer.ORGANIZATION_PARTNER: true,
|
|
}
|
|
|
|
// Workspace is a struct that represents a workspace
|
|
type Workspace struct {
|
|
utils.AbstractObject // AbstractObject contains the basic fields of an object (id, name)
|
|
resources.WorkspaceResourceSet // WorkspaceResourceSet persists both IDs and complete resource objects
|
|
IsContextual bool `json:"is_contextual" bson:"is_contextual" default:"false"`
|
|
Active bool `json:"active" bson:"active" default:"false"`
|
|
Shared string `json:"shared,omitempty" bson:"shared,omitempty"`
|
|
|
|
// Notifications accumulates strings for auto-modifications (e.g. resource removed after peer blacklist).
|
|
// Cleared by the owner via the notifications update endpoint.
|
|
Notifications []string `json:"notifications,omitempty" bson:"notifications,omitempty"`
|
|
|
|
// TrustMap maps resource ID → trust bool based on the creator peer's relation.
|
|
// Not persisted (bson:"-") — recomputed on every load by ComputeTrustAndClean.
|
|
TrustMap map[string]bool `json:"trust_map,omitempty" bson:"-"`
|
|
}
|
|
|
|
func (d *Workspace) GetAccessor(request *tools.APIRequest) utils.Accessor {
|
|
return NewAccessor(request)
|
|
}
|
|
|
|
func (ao *Workspace) VerifyAuth(callName string, request *tools.APIRequest) bool {
|
|
if ao.Shared != "" {
|
|
shared, code, _ := shallow_collaborative_area.NewAccessor(request).LoadOne(ao.Shared)
|
|
if code != 200 || shared == nil {
|
|
return false
|
|
}
|
|
return shared.VerifyAuth(callName, request)
|
|
}
|
|
return ao.AbstractObject.VerifyAuth(callName, request)
|
|
}
|
|
|
|
// ComputeTrustAndClean populates TrustMap for all resources embedded in this workspace,
|
|
// removes resources whose creator peer is blacklisted, and appends a deletion notification
|
|
// for each removal. Returns true when at least one resource was removed (caller should persist).
|
|
func (w *Workspace) ComputeTrustAndClean() bool {
|
|
w.TrustMap = map[string]bool{}
|
|
|
|
selfPeer, _ := utils.GetMySelf(peer.NewShallowAccessor())
|
|
var selfPeerID string
|
|
if selfPeer != nil {
|
|
if p, ok := selfPeer.(*peer.Peer); ok {
|
|
selfPeerID = p.PeerID
|
|
}
|
|
}
|
|
|
|
// Cache peer relations to avoid redundant DB lookups per workspace load.
|
|
cache := map[string]peer.PeerRelation{}
|
|
relation := func(creatorID string) peer.PeerRelation {
|
|
if r, ok := cache[creatorID]; ok {
|
|
return r
|
|
}
|
|
if creatorID == selfPeerID {
|
|
cache[creatorID] = peer.SELF
|
|
return peer.SELF
|
|
}
|
|
results, _, _ := peer.NewShallowAccessor().Search(&dbs.Filters{
|
|
And: map[string][]dbs.Filter{
|
|
"peer_id": {{Operator: dbs.EQUAL.String(), Value: creatorID}},
|
|
},
|
|
}, "", false, 0, 1)
|
|
rel := peer.NONE
|
|
if len(results) > 0 {
|
|
if p, ok := results[0].(*peer.Peer); ok {
|
|
rel = p.Relation
|
|
}
|
|
}
|
|
cache[creatorID] = rel
|
|
return rel
|
|
}
|
|
|
|
setTrust := func(id, creatorID string, rel peer.PeerRelation) {
|
|
w.TrustMap[id] = (creatorID == selfPeerID) || trustedRelations[rel]
|
|
}
|
|
|
|
changed := false
|
|
|
|
var keptData []*resources.DataResource
|
|
for _, r := range w.DataResources {
|
|
if rel := relation(r.GetCreatorID()); rel == peer.BLACKLIST {
|
|
w.Notifications = append(w.Notifications, fmt.Sprintf("resource %s (%s) removed: creator peer blacklisted", r.GetName(), r.GetID()))
|
|
changed = true
|
|
} else {
|
|
setTrust(r.GetID(), r.GetCreatorID(), rel)
|
|
keptData = append(keptData, r)
|
|
}
|
|
}
|
|
w.DataResources = keptData
|
|
|
|
var keptCompute []*resources.ComputeResource
|
|
for _, r := range w.ComputeResources {
|
|
if rel := relation(r.GetCreatorID()); rel == peer.BLACKLIST {
|
|
w.Notifications = append(w.Notifications, fmt.Sprintf("resource %s (%s) removed: creator peer blacklisted", r.GetName(), r.GetID()))
|
|
changed = true
|
|
} else {
|
|
setTrust(r.GetID(), r.GetCreatorID(), rel)
|
|
keptCompute = append(keptCompute, r)
|
|
}
|
|
}
|
|
w.ComputeResources = keptCompute
|
|
|
|
var keptStorage []*resources.StorageResource
|
|
for _, r := range w.StorageResources {
|
|
if rel := relation(r.GetCreatorID()); rel == peer.BLACKLIST {
|
|
w.Notifications = append(w.Notifications, fmt.Sprintf("resource %s (%s) removed: creator peer blacklisted", r.GetName(), r.GetID()))
|
|
changed = true
|
|
} else {
|
|
setTrust(r.GetID(), r.GetCreatorID(), rel)
|
|
keptStorage = append(keptStorage, r)
|
|
}
|
|
}
|
|
w.StorageResources = keptStorage
|
|
|
|
var keptProcessing []*resources.ProcessingResource
|
|
for _, r := range w.ProcessingResources {
|
|
if rel := relation(r.GetCreatorID()); rel == peer.BLACKLIST {
|
|
w.Notifications = append(w.Notifications, fmt.Sprintf("resource %s (%s) removed: creator peer blacklisted", r.GetName(), r.GetID()))
|
|
changed = true
|
|
} else {
|
|
setTrust(r.GetID(), r.GetCreatorID(), rel)
|
|
keptProcessing = append(keptProcessing, r)
|
|
}
|
|
}
|
|
w.ProcessingResources = keptProcessing
|
|
|
|
var keptWorkflow []*resources.WorkflowResource
|
|
for _, r := range w.WorkflowResources {
|
|
if rel := relation(r.GetCreatorID()); rel == peer.BLACKLIST {
|
|
w.Notifications = append(w.Notifications, fmt.Sprintf("resource %s (%s) removed: creator peer blacklisted", r.GetName(), r.GetID()))
|
|
changed = true
|
|
} else {
|
|
setTrust(r.GetID(), r.GetCreatorID(), rel)
|
|
keptWorkflow = append(keptWorkflow, r)
|
|
}
|
|
}
|
|
w.WorkflowResources = keptWorkflow
|
|
|
|
var keptService []*resources.ServiceResource
|
|
for _, r := range w.ServiceResources {
|
|
if rel := relation(r.GetCreatorID()); rel == peer.BLACKLIST {
|
|
w.Notifications = append(w.Notifications, fmt.Sprintf("resource %s (%s) removed: creator peer blacklisted", r.GetName(), r.GetID()))
|
|
changed = true
|
|
} else {
|
|
setTrust(r.GetID(), r.GetCreatorID(), rel)
|
|
keptService = append(keptService, r)
|
|
}
|
|
}
|
|
w.ServiceResources = keptService
|
|
|
|
var keptDynamic []*resources.DynamicResource
|
|
for _, r := range w.DynamicResources {
|
|
if rel := relation(r.GetCreatorID()); rel == peer.BLACKLIST {
|
|
w.Notifications = append(w.Notifications, fmt.Sprintf("resource %s (%s) removed: creator peer blacklisted", r.GetName(), r.GetID()))
|
|
changed = true
|
|
} else {
|
|
setTrust(r.GetID(), r.GetCreatorID(), rel)
|
|
keptDynamic = append(keptDynamic, r)
|
|
}
|
|
}
|
|
w.DynamicResources = keptDynamic
|
|
|
|
var keptNative []*resources.NativeTool
|
|
for _, r := range w.NativeTools {
|
|
if rel := relation(r.GetCreatorID()); rel == peer.BLACKLIST {
|
|
w.Notifications = append(w.Notifications, fmt.Sprintf("resource %s (%s) removed: creator peer blacklisted", r.GetName(), r.GetID()))
|
|
changed = true
|
|
} else {
|
|
setTrust(r.GetID(), r.GetCreatorID(), rel)
|
|
keptNative = append(keptNative, r)
|
|
}
|
|
}
|
|
w.NativeTools = keptNative
|
|
|
|
return changed
|
|
}
|