workflow partial allows

This commit is contained in:
mr 2025-02-05 16:41:16 +01:00
parent a8e2445c10
commit 7201cabb43
4 changed files with 87 additions and 8 deletions

View File

@ -13,6 +13,17 @@ type Owner struct {
Logo string `json:"logo,omitempty" bson:"logo,omitempty"` Logo string `json:"logo,omitempty" bson:"logo,omitempty"`
} }
func VerifyAccess(a Accessor, id string) error {
data, _, err := a.LoadOne(id)
if err != nil {
return err
}
if a.ShouldVerifyAuth() && !data.VerifyAuth(a.GetRequest()) {
return errors.New("you are not allowed to access :" + a.GetType().String())
}
return nil
}
// GenericLoadOne loads one object from the database (generic) // GenericLoadOne loads one object from the database (generic)
func GenericStoreOne(data DBObject, a Accessor) (DBObject, int, error) { func GenericStoreOne(data DBObject, a Accessor) (DBObject, int, error) {
data.GenerateID() data.GenerateID()

View File

@ -9,9 +9,29 @@ import (
// Graph is a struct that represents a graph // Graph is a struct that represents a graph
type Graph struct { type Graph struct {
Zoom float64 `bson:"zoom" json:"zoom" default:"1"` // Zoom is the graphical zoom of the graph Partial bool `json:"partial" default:"false"` // Partial is a flag that indicates if the graph is partial
Items map[string]GraphItem `bson:"items" json:"items" default:"{}" validate:"required"` // Items is the list of elements in the graph Zoom float64 `bson:"zoom" json:"zoom" default:"1"` // Zoom is the graphical zoom of the graph
Links []GraphLink `bson:"links" json:"links" default:"{}" validate:"required"` // Links is the list of links between elements in the graph Items map[string]GraphItem `bson:"items" json:"items" default:"{}" validate:"required"` // Items is the list of elements in the graph
Links []GraphLink `bson:"links" json:"links" default:"{}" validate:"required"` // Links is the list of links between elements in the graph
}
func (g *Graph) Clear(id string) {
realItems := map[string]GraphItem{}
for k, it := range g.Items {
if k == id {
realinks := []GraphLink{}
for _, link := range g.Links {
if link.Source.ID != id && link.Destination.ID != id {
realinks = append(realinks, link)
}
}
g.Links = realinks
g.Partial = true
} else {
realItems[k] = it
}
}
g.Items = realItems
} }
func (wf *Graph) IsProcessing(item GraphItem) bool { func (wf *Graph) IsProcessing(item GraphItem) bool {

View File

@ -28,3 +28,11 @@ func (g *GraphItem) GetResource() (tools.DataType, resources.ResourceInterface)
} }
return tools.INVALID, nil return tools.INVALID, nil
} }
func (g *GraphItem) Clear() {
g.Data = nil
g.Compute = nil
g.Workflow = nil
g.Processing = nil
g.Storage = nil
}

View File

@ -1,6 +1,8 @@
package workflow package workflow
import ( import (
"errors"
"cloud.o-forge.io/core/oc-lib/dbs" "cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/logs" "cloud.o-forge.io/core/oc-lib/logs"
"cloud.o-forge.io/core/oc-lib/models/collaborative_area/shallow_collaborative_area" "cloud.o-forge.io/core/oc-lib/models/collaborative_area/shallow_collaborative_area"
@ -47,7 +49,7 @@ func (a *workflowMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error
a.execute(res.(*Workflow), true, false) // up to date the workspace for the workflow a.execute(res.(*Workflow), true, false) // up to date the workspace for the workflow
a.share(res.(*Workflow), true, a.GetCaller()) a.share(res.(*Workflow), true, a.GetCaller())
} }
return res, code, err return a.verifyResource(res), code, err
} }
/* /*
@ -89,7 +91,11 @@ func (a *workflowMongoAccessor) share(realData *Workflow, delete bool, caller *t
// UpdateOne updates a workflow in the database // UpdateOne updates a workflow in the database
func (a *workflowMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { func (a *workflowMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) {
// avoid the update if the schedule is the same // avoid the update if the schedule is the same
res, code, err := utils.GenericUpdateOne(set, id, a, &Workflow{}) set = a.verifyResource(set)
if set.(*Workflow).Graph.Partial {
return nil, 403, errors.New("you are not allowed to update a partial workflow")
}
res, code, err := utils.GenericUpdateOne(a.verifyResource(set), id, a, &Workflow{})
if code != 200 { if code != 200 {
return nil, code, err return nil, code, err
} }
@ -101,7 +107,11 @@ func (a *workflowMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.
// StoreOne stores a workflow in the database // StoreOne stores a workflow in the database
func (a *workflowMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { func (a *workflowMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) {
data = a.verifyResource(data)
d := data.(*Workflow) d := data.(*Workflow)
if d.Graph.Partial {
return nil, 403, errors.New("you are not allowed to update a partial workflow")
}
res, code, err := utils.GenericStoreOne(d, a) res, code, err := utils.GenericStoreOne(d, a)
if err != nil || code != 200 { if err != nil || code != 200 {
return nil, code, err return nil, code, err
@ -121,7 +131,6 @@ func (a *workflowMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, in
// execute is a function that executes a workflow // execute is a function that executes a workflow
// it stores the workflow resources in a specific workspace to never have a conflict in UI and logic // it stores the workflow resources in a specific workspace to never have a conflict in UI and logic
func (a *workflowMongoAccessor) execute(workflow *Workflow, delete bool, active bool) { func (a *workflowMongoAccessor) execute(workflow *Workflow, delete bool, active bool) {
filters := &dbs.Filters{ filters := &dbs.Filters{
Or: map[string][]dbs.Filter{ // filter by standard workspace name attached to a workflow Or: map[string][]dbs.Filter{ // filter by standard workspace name attached to a workflow
"abstractobject.name": {{Operator: dbs.LIKE.String(), Value: workflow.Name + "_workspace"}}, "abstractobject.name": {{Operator: dbs.LIKE.String(), Value: workflow.Name + "_workspace"}},
@ -164,7 +173,7 @@ func (a *workflowMongoAccessor) LoadOne(id string) (utils.DBObject, int, error)
return utils.GenericLoadOne[*Workflow](id, func(d utils.DBObject) (utils.DBObject, int, error) { return utils.GenericLoadOne[*Workflow](id, func(d utils.DBObject) (utils.DBObject, int, error) {
w := d.(*Workflow) w := d.(*Workflow)
a.execute(w, false, true) // if no workspace is attached to the workflow, create it a.execute(w, false, true) // if no workspace is attached to the workflow, create it
return d, 200, nil return a.verifyResource(d), 200, nil
}, a) }, a)
} }
@ -173,5 +182,36 @@ func (a *workflowMongoAccessor) LoadAll(isDraft bool) ([]utils.ShallowDBObject,
} }
func (a *workflowMongoAccessor) Search(filters *dbs.Filters, search string, isDraft bool) ([]utils.ShallowDBObject, int, error) { func (a *workflowMongoAccessor) Search(filters *dbs.Filters, search string, isDraft bool) ([]utils.ShallowDBObject, int, error) {
return utils.GenericSearch[*Workflow](filters, search, (&Workflow{}).GetObjectFilters(search), func(d utils.DBObject) utils.ShallowDBObject { return d }, isDraft, a) return utils.GenericSearch[*Workflow](filters, search, (&Workflow{}).GetObjectFilters(search), func(d utils.DBObject) utils.ShallowDBObject { return a.verifyResource(d) }, isDraft, a)
}
func (a *workflowMongoAccessor) verifyResource(obj utils.DBObject) utils.DBObject {
wf := obj.(*Workflow)
if wf.Graph == nil {
return nil
}
for _, item := range wf.Graph.Items {
t, resource := item.GetResource()
if resource == nil {
continue
}
var access utils.Accessor
if t == tools.COMPUTE_RESOURCE {
access = resources.NewAccessor[*resources.ComputeResource](t, a.GetRequest(), func() utils.DBObject { return &resources.ComputeResource{} })
} else if t == tools.PROCESSING_RESOURCE {
access = resources.NewAccessor[*resources.ProcessingResource](t, a.GetRequest(), func() utils.DBObject { return &resources.ProcessingResource{} })
} else if t == tools.STORAGE_RESOURCE {
access = resources.NewAccessor[*resources.StorageResource](t, a.GetRequest(), func() utils.DBObject { return &resources.StorageResource{} })
} else if t == tools.WORKFLOW_RESOURCE {
access = resources.NewAccessor[*resources.WorkflowResource](t, a.GetRequest(), func() utils.DBObject { return &resources.WorkflowResource{} })
} else if t == tools.DATA_RESOURCE {
access = resources.NewAccessor[*resources.DataResource](t, a.GetRequest(), func() utils.DBObject { return &resources.DataResource{} })
} else {
wf.Graph.Clear(item.Data.GetID())
}
if error := utils.VerifyAccess(access, resource.GetID()); error != nil {
wf.Graph.Clear(item.Data.GetID())
}
}
return wf
} }