diff --git a/entrypoint.go b/entrypoint.go index e012646..0075d62 100644 --- a/entrypoint.go +++ b/entrypoint.go @@ -426,7 +426,7 @@ func (r *Request) UpdateOne(set map[string]interface{}, id string) (data LibData PeerID: r.PeerID, Groups: r.Groups, Admin: r.admin, - }).UpdateOne(model.Deserialize(set, model), id) + }).UpdateOne(set, id) if err != nil { data = LibData{Data: d, Code: code, Err: err.Error()} return diff --git a/models/booking/booking_mongo_accessor.go b/models/booking/booking_mongo_accessor.go index b6000cd..6442de6 100644 --- a/models/booking/booking_mongo_accessor.go +++ b/models/booking/booking_mongo_accessor.go @@ -29,12 +29,14 @@ func NewAccessor(request *tools.APIRequest) *BookingMongoAccessor { /* * Nothing special here, just the basic CRUD operations */ -func (a *BookingMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - if set.(*Booking).State == 0 { +func (a *BookingMongoAccessor) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, int, error) { + if set["state"] == nil { return nil, 400, errors.New("state is required") } - realSet := &Booking{State: set.(*Booking).State} - return utils.GenericUpdateOne(realSet, id, a, &Booking{}) + set = map[string]interface{}{ + "state": set["state"], + } + return utils.GenericUpdateOne(set, id, a, &Booking{}) } func (a *BookingMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { diff --git a/models/collaborative_area/collaborative_area.go b/models/collaborative_area/collaborative_area.go index 3228fb4..661f0fa 100644 --- a/models/collaborative_area/collaborative_area.go +++ b/models/collaborative_area/collaborative_area.go @@ -91,10 +91,6 @@ func (d *CollaborativeArea) GetAccessor(request *tools.APIRequest) utils.Accesso return NewAccessor(request) // Create a new instance of the accessor } -func (d *CollaborativeArea) Trim() *CollaborativeArea { - return d -} - func (d *CollaborativeArea) StoreDraftDefault() { d.AllowedPeersGroup = map[string][]string{ d.CreatorID: {"*"}, diff --git a/models/collaborative_area/collaborative_area_mongo_accessor.go b/models/collaborative_area/collaborative_area_mongo_accessor.go index bdc1112..56fe031 100644 --- a/models/collaborative_area/collaborative_area_mongo_accessor.go +++ b/models/collaborative_area/collaborative_area_mongo_accessor.go @@ -53,8 +53,8 @@ func (a *collaborativeAreaMongoAccessor) DeleteOne(id string) (utils.DBObject, i } // UpdateOne updates a collaborative area in the database, given its ID and the new data, it automatically share to peers if the workspace is shared -func (a *collaborativeAreaMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - res, code, err := utils.GenericUpdateOne(set.(*CollaborativeArea).Trim(), id, a, &CollaborativeArea{}) +func (a *collaborativeAreaMongoAccessor) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, int, error) { + res, code, err := utils.GenericUpdateOne(set, id, a, &CollaborativeArea{}) // a.deleteToPeer(res.(*CollaborativeArea)) // delete the collaborative area on the peer a.sharedWorkflow(res.(*CollaborativeArea), id) // replace all shared workflows a.sharedWorkspace(res.(*CollaborativeArea), id) // replace all collaborative areas (not shared worspace obj but workspace one) @@ -76,7 +76,7 @@ func (a *collaborativeAreaMongoAccessor) StoreOne(data utils.DBObject) (utils.DB data.(*CollaborativeArea).CollaborativeAreaRule = &CollaborativeAreaRule{} } data.(*CollaborativeArea).CollaborativeAreaRule.Creator = pp.GetID() - d, code, err := utils.GenericStoreOne(data.(*CollaborativeArea).Trim(), a) + d, code, err := utils.GenericStoreOne(data, a) if code == 200 { a.sharedWorkflow(d.(*CollaborativeArea), d.GetID()) // create all shared workflows a.sharedWorkspace(d.(*CollaborativeArea), d.GetID()) // create all collaborative areas @@ -141,7 +141,9 @@ func (a *collaborativeAreaMongoAccessor) sharedWorkspace(shared *CollaborativeAr eld := eldest.(*CollaborativeArea) if eld.Workspaces != nil { // update all your workspaces in the eldest by replacing shared ref by an empty string for _, v := range eld.Workspaces { - a.workspaceAccessor.UpdateOne(&workspace.Workspace{Shared: ""}, v) + a.workspaceAccessor.UpdateOne(map[string]interface{}{ + "shared": "", + }, v) if a.GetCaller() != nil || a.GetCaller().URLS == nil || a.GetCaller().URLS[tools.WORKSPACE] == nil { continue } @@ -157,7 +159,10 @@ func (a *collaborativeAreaMongoAccessor) sharedWorkspace(shared *CollaborativeAr } if shared.Workspaces != nil { for _, v := range shared.Workspaces { // update all the collaborative areas - workspace, code, _ := a.workspaceAccessor.UpdateOne(&workspace.Workspace{Shared: shared.UUID}, v) // add the shared ref to workspace + workspace, code, _ := a.workspaceAccessor.UpdateOne( + map[string]interface{}{ + "shared": shared.UUID, + }, v) // add the shared ref to workspace if a.GetCaller() != nil || a.GetCaller().URLS == nil || a.GetCaller().URLS[tools.WORKSPACE] == nil { continue } @@ -197,7 +202,7 @@ func (a *collaborativeAreaMongoAccessor) sharedWorkflow(shared *CollaborativeAre } // kick the shared reference in your old shared workflow n := &w.Workflow{} n.Shared = new - a.workflowAccessor.UpdateOne(n, v) + a.workflowAccessor.UpdateOne(n.Serialize(n), v) if a.GetCaller() != nil || a.GetCaller().URLS == nil || a.GetCaller().URLS[tools.WORKFLOW] == nil { continue } @@ -219,7 +224,7 @@ func (a *collaborativeAreaMongoAccessor) sharedWorkflow(shared *CollaborativeAre s := data.(*w.Workflow) if !slices.Contains(s.Shared, id) { s.Shared = append(s.Shared, id) - workflow, code, _ := a.workflowAccessor.UpdateOne(s, v) + workflow, code, _ := a.workflowAccessor.UpdateOne(s.Serialize(s), v) if a.GetCaller() != nil || a.GetCaller().URLS == nil || a.GetCaller().URLS[tools.WORKFLOW] == nil { continue } diff --git a/models/live/live_mongo_accessor.go b/models/live/live_mongo_accessor.go index fd5e851..6100bac 100644 --- a/models/live/live_mongo_accessor.go +++ b/models/live/live_mongo_accessor.go @@ -66,7 +66,7 @@ func (a *computeUnitsMongoAccessor[T]) CopyOne(data utils.DBObject) (utils.DBObj b, _ := json.Marshal(res) json.Unmarshal(b, existingResource) live.SetResourceInstance(existingResource, instance) - resAccess.UpdateOne(existingResource, existingResource.GetID()) + resAccess.UpdateOne(existingResource.Serialize(existingResource), existingResource.GetID()) } if live.GetID() != "" { return a.LoadOne(live.GetID()) @@ -84,7 +84,7 @@ func (a *computeUnitsMongoAccessor[T]) CopyOne(data utils.DBObject) (utils.DBObj } live.SetResourcesID(res.GetID()) if live.GetID() != "" { - return a.UpdateOne(live, live.GetID()) + return a.UpdateOne(live.Serialize(live), live.GetID()) } else { return a.StoreOne(live) } diff --git a/models/peer/peer_cache.go b/models/peer/peer_cache.go index a420867..315bce4 100644 --- a/models/peer/peer_cache.go +++ b/models/peer/peer_cache.go @@ -44,7 +44,7 @@ func CheckPeerStatus(peerID string, appName string) (*Peer, bool) { fmt.Println(url) state, services := api.CheckRemotePeer(url) res.(*Peer).ServicesState = services // Update the services states of the peer - access.UpdateOne(res, peerID) // Update the peer in the db + access.UpdateOne(res.Serialize(res), peerID) // Update the peer in the db return res.(*Peer), state != tools.DEAD && services[appName] == 0 // Return the peer and its status } @@ -72,18 +72,18 @@ func (p *PeerCache) LaunchPeerExecution(peerID string, dataID string, DataID: dataID, } mypeer.AddExecution(*pexec) - NewShallowAccessor().UpdateOne(mypeer, peerID) // Update the peer in the db + NewShallowAccessor().UpdateOne(mypeer.Serialize(mypeer), peerID) // Update the peer in the db return map[string]interface{}{}, errors.New("peer is " + peerID + " not reachable") } else { if mypeer == nil { return map[string]interface{}{}, errors.New("peer " + peerID + " not found") } // If the peer is reachable, launch the execution - url = urlFormat((mypeer.APIUrl), dt) + path // Format the URL - tmp := mypeer.FailedExecution // Get the failed executions list - mypeer.FailedExecution = []PeerExecution{} // Reset the failed executions list - NewShallowAccessor().UpdateOne(mypeer, peerID) // Update the peer in the db - for _, v := range tmp { // Retry the failed executions + url = urlFormat((mypeer.APIUrl), dt) + path // Format the URL + tmp := mypeer.FailedExecution // Get the failed executions list + mypeer.FailedExecution = []PeerExecution{} // Reset the failed executions list + NewShallowAccessor().UpdateOne(mypeer.Serialize(mypeer), peerID) // Update the peer in the db + for _, v := range tmp { // Retry the failed executions go p.Exec(v.Url, tools.ToMethod(v.Method), v.Body, caller) } } diff --git a/models/resources/interfaces.go b/models/resources/interfaces.go index 3169fd0..6e632fe 100755 --- a/models/resources/interfaces.go +++ b/models/resources/interfaces.go @@ -10,7 +10,6 @@ import ( type ResourceInterface interface { utils.DBObject - Trim() FilterPeer(peerID string) *dbs.Filters GetBookingModes() map[booking.BookingMode]*pricing.PricingVariation ConvertToPricedResource(t tools.DataType, a *int, selectedPartnership *int, selectedBuyingStrategy *int, selectedStrategy *int, b *int, request *tools.APIRequest) (pricing.PricedItemITF, error) diff --git a/models/resources/native_tools.go b/models/resources/native_tools.go index 8b4ab0e..fdfc435 100644 --- a/models/resources/native_tools.go +++ b/models/resources/native_tools.go @@ -37,9 +37,6 @@ func (d *NativeTool) ClearEnv() utils.DBObject { return d } -func (d *NativeTool) Trim() { - /* EMPTY */ -} func (w *NativeTool) SetAllowedInstances(request *tools.APIRequest, ids ...string) { /* EMPTY */ } diff --git a/models/resources/resource.go b/models/resources/resource.go index d0ed42d..8cc58f3 100755 --- a/models/resources/resource.go +++ b/models/resources/resource.go @@ -150,17 +150,6 @@ func (abs *AbstractInstanciatedResource[T]) SetAllowedInstances(request *tools.A abs.Instances = VerifyAuthAction(abs.Instances, request, instanceID...) } -func (d *AbstractInstanciatedResource[T]) Trim() { - d.Type = d.GetType() - if ok, _ := utils.IsMySelf(d.CreatorID, (&peer.Peer{}).GetAccessor(&tools.APIRequest{ - Admin: true, - })); !ok { - for _, instance := range d.Instances { - instance.ClearPeerGroups() - } - } -} - func (abs *AbstractInstanciatedResource[T]) VerifyAuth(callName string, request *tools.APIRequest) bool { return len(VerifyAuthAction(abs.Instances, request)) > 0 || abs.AbstractObject.VerifyAuth(callName, request) } diff --git a/models/resources/resource_accessor.go b/models/resources/resource_accessor.go index eebd1c2..73b0216 100755 --- a/models/resources/resource_accessor.go +++ b/models/resources/resource_accessor.go @@ -55,12 +55,10 @@ func NewAccessor[T ResourceInterface](t tools.DataType, request *tools.APIReques * Nothing special here, just the basic CRUD operations */ -func (dca *ResourceMongoAccessor[T]) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { +func (dca *ResourceMongoAccessor[T]) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, int, error) { if dca.GetType() == tools.COMPUTE_RESOURCE { return nil, 404, errors.New("can't update a non existing computing units resource not reported onto compute units catalog") } - set.(T).Trim() - if d, c, err := utils.GenericUpdateOne(set, id, dca, dca.generateData()); err != nil { return d, c, err } else { @@ -72,7 +70,6 @@ func (dca *ResourceMongoAccessor[T]) StoreOne(data utils.DBObject) (utils.DBObje if dca.GetType() == tools.COMPUTE_RESOURCE { return nil, 404, errors.New("can't create a non existing computing units resource not reported onto compute units catalog") } - data.(T).Trim() return utils.GenericStoreOne(data, dca) } diff --git a/models/resources/tests/resource_test.go b/models/resources/tests/resource_test.go index 4eef4e3..83f5239 100644 --- a/models/resources/tests/resource_test.go +++ b/models/resources/tests/resource_test.go @@ -105,7 +105,6 @@ type FakeResource struct { resources.AbstractInstanciatedResource[*MockInstance] } -func (f *FakeResource) Trim() {} func (f *FakeResource) SetAllowedInstances(*tools.APIRequest, ...string) {} func (f *FakeResource) VerifyAuth(string, *tools.APIRequest) bool { return true } diff --git a/models/resources/tests/workflow_test.go b/models/resources/tests/workflow_test.go index 2fbd4b4..92ab83c 100644 --- a/models/resources/tests/workflow_test.go +++ b/models/resources/tests/workflow_test.go @@ -41,13 +41,6 @@ func TestWorkflowResource_ClearEnv(t *testing.T) { w := &resources.WorkflowResource{} assert.Equal(t, w, w.ClearEnv()) } - -func TestWorkflowResource_Trim(t *testing.T) { - w := &resources.WorkflowResource{} - w.Trim() - // nothing to assert; just test that it doesn't panic -} - func TestWorkflowResource_SetAllowedInstances(t *testing.T) { w := &resources.WorkflowResource{} w.SetAllowedInstances(&tools.APIRequest{}) diff --git a/models/resources/workflow.go b/models/resources/workflow.go index 63a2818..6ee6018 100755 --- a/models/resources/workflow.go +++ b/models/resources/workflow.go @@ -30,9 +30,6 @@ func (d *WorkflowResource) ClearEnv() utils.DBObject { return d } -func (d *WorkflowResource) Trim() { - /* EMPTY */ -} func (w *WorkflowResource) SetAllowedInstances(request *tools.APIRequest, ids ...string) { /* EMPTY */ } diff --git a/models/utils/abstracts.go b/models/utils/abstracts.go index 72b3b8e..684f09b 100755 --- a/models/utils/abstracts.go +++ b/models/utils/abstracts.go @@ -227,7 +227,7 @@ func (a *AbstractAccessor[T]) DeleteOne(id string) (DBObject, int, error) { return GenericDeleteOne(id, a) } -func (a *AbstractAccessor[T]) UpdateOne(set DBObject, id string) (DBObject, int, error) { +func (a *AbstractAccessor[T]) UpdateOne(set map[string]interface{}, id string) (DBObject, int, error) { if len(a.NotImplemented) > 0 && slices.Contains(a.NotImplemented, "UpdateOne") { return nil, 404, errors.New("not implemented") } diff --git a/models/utils/common.go b/models/utils/common.go index 56a81a7..4def085 100755 --- a/models/utils/common.go +++ b/models/utils/common.go @@ -86,18 +86,15 @@ func GenericDeleteOne(id string, a Accessor) (DBObject, int, error) { return res, 200, nil } -// GenericLoadOne loads one object from the database (generic) -// json expected in entry is a flatted object no need to respect the inheritance hierarchy -func GenericUpdateOne(set DBObject, id string, a Accessor, new DBObject) (DBObject, int, error) { +func ModelGenericUpdateOne(change map[string]interface{}, id string, a Accessor) (map[string]interface{}, int, error) { r, c, err := a.LoadOne(id) if err != nil { return nil, c, err } - ok, newSet := r.CanUpdate(set) + ok, r := r.CanUpdate(r) if !ok { return nil, 403, errors.New("you are not allowed to delete :" + a.GetType().String()) } - set = newSet r.UpToDate(a.GetUser(), a.GetPeerID(), false) if a.GetPeerID() == r.GetCreatorID() { r.Unsign() @@ -106,12 +103,21 @@ func GenericUpdateOne(set DBObject, id string, a Accessor, new DBObject) (DBObje if a.ShouldVerifyAuth() && !r.VerifyAuth("update", a.GetRequest()) { return nil, 403, errors.New("you are not allowed to access :" + a.GetType().String()) } - change := set.Serialize(set) // get the changes - loaded := r.Serialize(r) // get the loaded object + loaded := r.Serialize(r) // get the loaded object for k, v := range change { // apply the changes, with a flatten method loaded[k] = v } + return loaded, 200, nil +} + +// GenericLoadOne loads one object from the database (generic) +// json expected in entry is a flatted object no need to respect the inheritance hierarchy +func GenericUpdateOne(change map[string]interface{}, id string, a Accessor, new DBObject) (DBObject, int, error) { + loaded, c, err := ModelGenericUpdateOne(change, id, a) + if err != nil { + return nil, c, err + } id, code, err := mongo.MONGOService.UpdateOne(new.Deserialize(loaded, new), id, a.GetType().String()) if err != nil { a.GetLogger().Error().Msg("Could not update " + id + " to db. Error: " + err.Error()) diff --git a/models/utils/interfaces.go b/models/utils/interfaces.go index 0417ec9..579d78b 100755 --- a/models/utils/interfaces.go +++ b/models/utils/interfaces.go @@ -53,7 +53,7 @@ type Accessor interface { CopyOne(data DBObject) (DBObject, int, error) StoreOne(data DBObject) (DBObject, int, error) LoadAll(isDraft bool) ([]ShallowDBObject, int, error) - UpdateOne(set DBObject, id string) (DBObject, int, error) + UpdateOne(set map[string]interface{}, id string) (DBObject, int, error) Search(filters *dbs.Filters, search string, isDraft bool) ([]ShallowDBObject, int, error) GetExec(isDraft bool) func(DBObject) ShallowDBObject } diff --git a/models/workflow/workflow_mongo_accessor.go b/models/workflow/workflow_mongo_accessor.go index c269bad..8a34065 100644 --- a/models/workflow/workflow_mongo_accessor.go +++ b/models/workflow/workflow_mongo_accessor.go @@ -92,13 +92,17 @@ func (a *workflowMongoAccessor) share(realData *Workflow, delete bool, caller *t } // 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 map[string]interface{}, id string) (utils.DBObject, int, error) { // avoid the update if the schedule is the same - set = a.verifyResource(set) - if set.(*Workflow).Graph != nil && set.(*Workflow).Graph.Partial { + res, code, err := utils.GenericUpdateOne(set, id, a, &Workflow{}) + if code != 200 { + return nil, code, err + } + res = a.verifyResource(res) + if res.(*Workflow).Graph != nil && res.(*Workflow).Graph.Partial { return nil, 403, errors.New("you are not allowed to update a partial workflow") } - res, code, err := utils.GenericUpdateOne(set, id, a, &Workflow{}) + res, code, err = utils.GenericUpdateOne(res.Serialize(res), id, a, &Workflow{}) if code != 200 { return nil, code, err } @@ -154,7 +158,7 @@ func (a *workflowMongoAccessor) execute(workflow *Workflow, delete bool, active return } if err == nil && len(resource) > 0 { // if the workspace already exists, update it - a.workspaceAccessor.UpdateOne(&workspace.Workspace{ + w := &workspace.Workspace{ Active: active, ResourceSet: resources.ResourceSet{ Datas: workflow.Datas, @@ -163,7 +167,8 @@ func (a *workflowMongoAccessor) execute(workflow *Workflow, delete bool, active Workflows: workflow.Workflows, Computes: workflow.Computes, }, - }, resource[0].GetID()) + } + a.workspaceAccessor.UpdateOne(w.Serialize(w), resource[0].GetID()) } else { // if the workspace does not exist, create it a.workspaceAccessor.StoreOne(&workspace.Workspace{ Active: active, diff --git a/models/workflow_execution/workflow_execution_mongo_accessor.go b/models/workflow_execution/workflow_execution_mongo_accessor.go index c8951ad..b497efd 100755 --- a/models/workflow_execution/workflow_execution_mongo_accessor.go +++ b/models/workflow_execution/workflow_execution_mongo_accessor.go @@ -42,12 +42,13 @@ func NewAccessor(request *tools.APIRequest) *WorkflowExecutionMongoAccessor { } } -func (wfa *WorkflowExecutionMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - if set.(*WorkflowExecution).State == 0 { +func (wfa *WorkflowExecutionMongoAccessor) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, int, error) { + if set["state"] == nil { return nil, 400, errors.New("state is required") } - realSet := WorkflowExecution{State: set.(*WorkflowExecution).State} - return utils.GenericUpdateOne(&realSet, id, wfa, &WorkflowExecution{}) + return utils.GenericUpdateOne(map[string]interface{}{ + "state": set["state"], + }, id, wfa, &WorkflowExecution{}) } func (a *WorkflowExecutionMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { diff --git a/models/workspace/workspace_mongo_accessor.go b/models/workspace/workspace_mongo_accessor.go index b2acb12..5ef3fb0 100644 --- a/models/workspace/workspace_mongo_accessor.go +++ b/models/workspace/workspace_mongo_accessor.go @@ -48,16 +48,14 @@ func (a *workspaceMongoAccessor) DeleteOne(id string) (utils.DBObject, int, erro } // UpdateOne updates a workspace in the database, given its ID, it automatically share to peers if the workspace is shared -func (a *workspaceMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { - d := set.(*Workspace) // Get the workspace from the set - d.Clear() - if d.Active { // If the workspace is active, deactivate all the other workspaces +func (a *workspaceMongoAccessor) UpdateOne(set map[string]interface{}, id string) (utils.DBObject, int, error) { + if set["active"] == true { // If the workspace is active, deactivate all the other workspaces res, _, err := a.LoadAll(true) if err == nil { for _, r := range res { if r.GetID() != id { - r.(*Workspace).Active = false - a.UpdateOne(r.(*Workspace), r.GetID()) + set["active"] = false + a.UpdateOne(set, r.GetID()) } } }