Files
oc-lib/models/workspace/workspace.go
T
2026-06-23 09:40:33 +02:00

203 lines
7.1 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:"-"`
// StaleMap maps resource ID → stale bool. Populated at GET time from the
// verify campaign results stored in oc-workspace's stale cache. Not persisted.
StaleMap map[string]bool `json:"stale_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
}