def deleteFlowLink(conductID, fromFlowID, toFlowID): conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductID) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: fromFlow = [x for x in conductObj.flow if x["flowID"] == fromFlowID] if len(fromFlow) > 0: fromFlow = fromFlow[0] for nextflow in fromFlow["next"]: if nextflow["flowID"] == toFlowID: if db.fieldACLAccess(api.g["sessionData"], conductObj.acl, "flow", "delete"): conductObj.flow[conductObj.flow.index( fromFlow)]["next"].remove(nextflow) conductObj.update(["flow"]) return {}, 200 return {}, 403 return {}, 404 else: return {}, 403
def newFlow(conductID): conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductID) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: data = json.loads(api.request.data) # Get new UUID store within current conduct flow and return UUID newFlowID = str(uuid.uuid4()) flow = {"flowID": newFlowID, "next": []} # Creating new object of model type _class = model._model().getAsClass(api.g["sessionData"], id=data["classID"]) if _class: subtype = _class[0].name _class = _class[0].classObject() newFlowObjectID = _class().new(flow["flowID"]).inserted_id # Working out by bruteforce which type this is ( try and load it by parent class and check for error) - get on trigger if it does not exist will return None modelFlowObjectType = "action" if len(trigger._trigger().getAsClass(api.g["sessionData"], id=newFlowObjectID)) > 0: modelFlowObjectType = "trigger" modelFlowObject = _class().getAsClass(api.g["sessionData"], id=newFlowObjectID) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] else: return {}, 404 modelFlowObject.acl = { "ids": [{ "accessID": api.g["sessionData"]["primaryGroup"], "read": True, "write": True, "delete": True }] } modelFlowObject.update(["acl"], sessionData=api.g["sessionData"]) flow["type"] = modelFlowObjectType if subtype != "action" and subtype != "trigger": flow["subtype"] = subtype flow["{0}{1}".format(modelFlowObjectType, "ID")] = str(newFlowObjectID) # Adding UI position for cloned object webui._modelUI().new(conductID, conductObj.acl, flow["flowID"], data["x"], data["y"], modelFlowObject.name) # Appending new object to conduct conductObj.flow.append(flow) conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {}, 201 else: return {}, 403 return {}, 404
def getModelSchema(modelName): class_ = loadModel(modelName) if class_: access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], class_.acl, "read") if access: return class_.classObject()().api_getSchema(), 200 else: return {}, 403 else: return {}, 404
def setConductFlowLogic(conductID, flowID, nextflowID): conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductID) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: flow = [x for x in conductObj.flow if x["flowID"] == flowID] data = json.loads(api.request.data) if len(flow) == 1: flow = flow[0] if "next" in flow: found = False for key, nextFlow in enumerate(flow["next"]): if type(nextFlow) is str: if nextFlow == nextflowID: nextFlow = {"flowID": nextflowID} found = True elif type(nextFlow) is dict: if nextFlow["flowID"] == nextflowID: found = True if found: if "true" == data["logic"].lower(): flow["next"][key] = { "flowID": nextFlow["flowID"], "logic": True } elif "false" == data["logic"].lower(): flow["next"][key] = { "flowID": nextFlow["flowID"], "logic": False } elif data["logic"].startswith("if"): flow["next"][key] = { "flowID": nextFlow["flowID"], "logic": data["logic"] } else: try: flow["next"][key] = { "flowID": nextFlow["flowID"], "logic": int(data["logic"]) } except ValueError: return {}, 403 conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {}, 200 else: return {}, 403 return {}, 404
def newConduct(): data = json.loads(api.request.data) if data["action"] == "new": class_ = model._model().getAsClass(api.g["sessionData"], query={"name": "conduct"}) if class_: class_ = class_[0] access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], class_.acl, "read") if access: conductID = str(conduct._conduct().new( data["name"]).inserted_id) return {"result": True, "conductID": conductID}, 201 return {}, 403
def deleteModelObject(modelName, objectID): class_ = loadModel(modelName) if class_: _class = class_.classObject()().getAsClass( api.g["sessionData"], id=objectID) if len(_class) == 1: _class = _class[0] access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], _class.acl, "delete") if access: result = class_.classObject()().api_delete(id=objectID) if result["result"]: return result, 200 else: return {}, 403 return {}, 404
def newModelObject(modelName): class_ = loadModel(modelName) if class_: access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], class_.acl, "read") if access: class_ = class_.classObject()() if api.g["sessionData"]: class_.acl = { "ids": [{ "accessID": api.g["sessionData"]["primaryGroup"], "read": True, "write": True, "delete": True }] } newObjectID = super(type(class_), class_).new().inserted_id return {"result": {"_id": str(newObjectID)}}, 200 return {}, 404
def newFlowLink(conductID, fromFlowID, toFlowID): conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductID) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: fromFlow = [x for x in conductObj.flow if x["flowID"] == fromFlowID][0] toFlow = [x for x in conductObj.flow if x["flowID"] == toFlowID][0] nextFlows = [x for x in fromFlow["next"] if x["flowID"] == toFlowID] if len(nextFlows) == 0: if toFlow["type"] != "trigger": fromFlow["next"].append({"flowID": toFlowID, "logic": True}) conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {}, 201 else: return {}, 403 return {}, 200 else: return {}, 403
def deleteFlow(conductID, flowID): conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductID) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: flow = [x for x in conductObj.flow if x["flowID"] == flowID] if len(flow) == 1: flow = flow[0] for flowItemsValue in conductObj.flow: for nextflowValue in flowItemsValue["next"]: if nextflowValue["flowID"] == flowID: conductObj.flow[conductObj.flow.index( flowItemsValue)]["next"].remove(nextflowValue) conductObj.flow.remove(flow) conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {}, 200 else: return {}, 404
def dropExistingObject(conductID): conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductID) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: data = json.loads(api.request.data) if data["action"] == "drop": newFlowID = str(uuid.uuid4()) flow = { "flowID": newFlowID, "type": data["flowType"], "{0}{1}".format(data["flowType"], "ID"): data["_id"], "next": [] } modelFlowObject = None if data["flowType"] == "trigger": modelFlowObject = trigger._trigger().getAsClass( api.g["sessionData"], id=data["_id"])[0] elif data["flowType"] == "action": modelFlowObject = action._action().getAsClass( api.g["sessionData"], id=data["_id"])[0] if modelFlowObject: name = modelFlowObject.name else: name = flow["flowID"] webui._modelUI().new(conductID, conductObj.acl, flow["flowID"], data["x"], data["y"], name) conductObj.flow.append(flow) conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {}, 201 return {}, 404
def updateModelObject(modelName, objectID): class_ = loadModel(modelName) if class_: data = json.loads(api.request.data) if data["action"] == "update": updateItemsList = [] changeLog = {} data = data["data"] _class = class_.classObject()().getAsClass( api.g["sessionData"], id=objectID) if len(_class) == 1: _class = _class[0] # Builds list of permitted ACL access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], _class.acl, "write") if access: for dataKey, dataValue in data.items(): fieldAccessPermitted = True # Checking if sessionData is permitted field level access if _class.acl and not adminBypass: fieldAccessPermitted = db.fieldACLAccess( api.g["sessionData"], _class.acl, dataKey, "write") if fieldAccessPermitted: # _id is a protected mongodb object and cant be updated if dataKey != "_id": if hasattr(_class, dataKey): changeLog[dataKey] = {} changeLog[dataKey][ "currentValue"] = getattr( _class, dataKey) if type(getattr(_class, dataKey)) is str: if dataValue: if _class.setAttribute( dataKey, str(dataValue), sessionData=api. g["sessionData"]): updateItemsList.append( dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) elif type(getattr(_class, dataKey)) is int: try: if _class.setAttribute( dataKey, int(dataValue), sessionData=api. g["sessionData"]): updateItemsList.append( dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) except ValueError: if _class.setAttribute( dataKey, 0, sessionData=api. g["sessionData"]): updateItemsList.append( dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) elif type(getattr( _class, dataKey)) is float: try: if _class.setAttribute( dataKey, float(dataValue), sessionData=api. g["sessionData"]): updateItemsList.append( dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) except ValueError: if _class.setAttribute( dataKey, 0, sessionData=api. g["sessionData"]): updateItemsList.append( dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) elif type(getattr( _class, dataKey)) is bool: # Convert string object to bool if type(dataValue) is str: if dataValue.lower( ) == "true": dataValue = True else: dataValue = False if _class.setAttribute( dataKey, dataValue, sessionData=api. g["sessionData"]): updateItemsList.append( dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) elif type(getattr( _class, dataKey)) is dict or type( getattr( _class, dataKey)) is list: if dataValue: if _class.setAttribute( dataKey, json.loads( dataValue), sessionData=api. g["sessionData"]): updateItemsList.append( dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) # Commit back to database if updateItemsList: _class.update(updateItemsList) # Adding audit record if "_id" in api.g["sessionData"]: audit._audit().add( "model", "update", { "_id": api.g["sessionData"]["_id"], "objects": helpers.unicodeEscapeDict( changeLog) }) else: audit._audit().add( "model", "update", { "objects": helpers.unicodeEscapeDict( changeLog) }) return {}, 200 else: return {}, 403 return {}, 404
def saveConduct(conductID): data = json.loads(api.request.data) conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductID) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 if data["action"] == "new": access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: # Get new UUID store within current conduct flow and return UUID newFlowID = str(uuid.uuid4()) flow = {"flowID": newFlowID, "next": []} conductObj.flow.append(flow) conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {"result": True, "flowID": newFlowID}, 201 else: return {}, 403 # Clone an existing object into a new object if data["action"] == "clone": access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: flow = [ x for x in conductObj.flow if x["flowID"] == data["operatorId"] ] if len(flow) == 1: flow = flow[0] data = json.loads(api.request.data) modelFlowObject = None # Check if the modelType and object are unchanged if "type" in flow: if flow["type"] == "trigger": modelFlowObject = trigger._trigger().getAsClass( api.g["sessionData"], id=flow["{0}{1}".format(flow["type"], "ID")]) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] modelFlowObjectType = "trigger" if flow["type"] == "action": modelFlowObject = action._action().getAsClass( api.g["sessionData"], id=flow["{0}{1}".format(flow["type"], "ID")]) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] modelFlowObjectType = "action" # Was it possible to load an existing object if modelFlowObject: # Create new flowItem newFlowID = str(uuid.uuid4()) flow = { "flowID": newFlowID, "type": flow["type"], "next": [] } # New object required _class = model._model().getAsClass( api.g["sessionData"], id=modelFlowObject.classID) if _class: _class = _class[0].classObject() # Bug exists as name value is not requried by db class but is for core models - this could result in an error if new model is added that does not accept name within new function override newFlowObjectID = _class().new( flow["flowID"]).inserted_id # Working out by bruteforce which type this is ( try and load it by parent class and check for error) - get on trigger if it does not exist will return None modelFlowObjectClone = _class().getAsClass( api.g["sessionData"], id=newFlowObjectID) if len(modelFlowObjectClone) == 1: modelFlowObjectClone = modelFlowObjectClone[0] else: return {}, 404 # Setting values in cloned object members = [ attr for attr in dir(modelFlowObject) if not callable(getattr(modelFlowObject, attr)) and not "__" in attr and attr ] dontCopy = ["_id", "name"] updateList = [] for member in members: if member not in dontCopy: setattr(modelFlowObjectClone, member, getattr(modelFlowObject, member)) updateList.append(member) modelFlowObjectClone.update( updateList, sessionData=api.g["sessionData"]) # Set conduct flow to correct type and objectID flow["{0}{1}".format(flow["type"], "ID")] = str(newFlowObjectID) conductObj.flow.append(flow) conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {"result": True, "flowID": newFlowID}, 201 else: return {}, 403 # Add existing object to flow elif data["action"] == "existing": access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: newFlowID = str(uuid.uuid4()) flow = {"flowID": newFlowID, "next": []} if data["type"] == "trigger": flow["type"] = "trigger" flow["triggerID"] = data["triggerID"] elif data["type"] == "action": flow["type"] = "action" flow["actionID"] = data["actionID"] conductObj.flow.append(flow) conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {"result": True, "flowID": newFlowID}, 201 else: return {}, 403 elif data["action"] == "save": access, accessIDs, adminBypass = db.ACLAccess(api.g["sessionData"], conductObj.acl, "write") if access: flowData = data["flowData"] newFlowData = {} flowPopList = [] for flow in flowData['links']: if flow != "{}>{}".format( flowData['links'][flow]['fromOperator'], flowData['links'][flow]['toOperator']): newFlowData["{}>{}".format( flowData['links'][flow]['fromOperator'], flowData['links'][flow] ['toOperator'])] = flowData['links'][flow] flowPopList.append(flow) if len(newFlowData) > 0: flowData['links'].update(newFlowData, sessionData=api.g["sessionData"]) for popItem in flowPopList: flowData['links'].pop(popItem) poplistOperator = [] poplistLink = [] for operatorID in flowData["operators"]: operatorFound = None for flow in conductObj.flow: flowID = flow["flowID"] if operatorID == flowID: operatorFound = flowID connections = [] for link in flowData["links"]: if flowData["links"][link][ "fromOperator"] == flowID: connections.append( flowData["links"][link]["toOperator"]) for connection in connections: foundFlow = False for index, nextFlowID in enumerate(conductObj.flow[ conductObj.flow.index(flow)]["next"]): if type(nextFlowID) is dict: if connection == nextFlowID["flowID"]: foundFlow = True conductObj.flow[conductObj.flow.index( flow)]["next"][index] = { "flowID": connection, "logic": nextFlowID["logic"] } else: if connection == nextFlowID: foundFlow = True conductObj.flow[conductObj.flow.index( flow)]["next"][index] = { "flowID": connection, "logic": True } if not foundFlow: conductObj.flow[conductObj.flow.index( flow)]["next"].append({ "flowID": connection, "logic": True }) notUpdatedPopList = [] for nextFlowID in conductObj.flow[ conductObj.flow.index(flow)]["next"]: if nextFlowID["flowID"] not in connections: notUpdatedPopList.append(nextFlowID) for notUpdatedPopItem in notUpdatedPopList: del conductObj.flow[conductObj.flow.index(flow)][ "next"][conductObj.flow[conductObj.flow.index( flow)]["next"].index(notUpdatedPopItem)] if not operatorFound: for link in flowData["links"]: if flowData["links"][link][ "toOperator"] == operatorID or flowData[ "links"][link][ "fromOperator"] == operatorID: poplistLink.append(link) poplistOperator.append(operatorID) # Checking to ensure every flow that exists is also still within the flowData i.e. it has not been deleted poplistFlow = [] for flow in conductObj.flow: flowID = flow["flowID"] if len([x for x in flowData["operators"] if x == flowID]) == 0: poplistFlow.append(flow) # Deleting any items that were found within flowData but not in the conduct flow for pop in poplistOperator: del flowData["operators"][pop] for pop in poplistLink: del flowData["links"][pop] for pop in poplistFlow: del conductObj.flow[conductObj.flow.index(pop)] # checking if conduct has been enabled or name changed if "conductName" in data: conductObj.name = data["conductName"] if "conductEnabled" in data: conductObj.enabled = data["conductEnabled"] if "conductACL" in data: try: conductObj.acl = json.loads(data["conductACL"]) except: pass # Updating all possible updated values conductObj.update(["flow", "name", "enabled", "acl"], sessionData=api.g["sessionData"]) existingFlow = webui._flowData().query( query={"conductID": conductID})["results"] if len(existingFlow) > 0: existingFlow = existingFlow[0] existingFlow = webui._flowData().load(existingFlow["_id"]) existingFlow.flowData = flowData existingFlow.update(["flowData"], sessionData=api.g["sessionData"]) else: webui._flowData().new(conductID, flowData) return {"result": True, "flowData": flowData}, 201 return {"result": True, "flowData": flowData}, 200 else: return {}, 403 return {"result": False}, 404
def setConductFlow(conductID, flowID): # List of attributes that are prevented from updating - this needs to be made more dynamic and part of class design unsafeUpdateList = [ "_id", "classID", "lastCheck", "lastRun", "lastResult", "workerID", "startCheck" ] conductObj = conduct._conduct().query(api.g["sessionData"], id=conductID)["results"] conductObj = conductObj[0] conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductObj["_id"]) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 flow = [x for x in conductObj.flow if x["flowID"] == flowID] if len(flow) == 1: flow = flow[0] data = json.loads(api.request.data) modelFlowObject = None # Check if the modelType and object are unchanged if "type" in flow: if flow["type"] == "trigger": modelFlowObject = trigger._trigger().getAsClass( api.g["sessionData"], id=flow["{0}{1}".format(flow["type"], "ID")]) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] modelFlowObjectType = "trigger" if flow["type"] == "action": modelFlowObject = action._action().getAsClass( api.g["sessionData"], id=flow["{0}{1}".format(flow["type"], "ID")]) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] modelFlowObjectType = "action" # Was it possible to load an existing object if modelFlowObject: # Check that the object model is still the same if modelFlowObject.classID == data["newClassID"]: # Get flow object correct class _class = model._model().getAsClass( api.g["sessionData"], id=modelFlowObject.classID) if len(_class) == 1: _class = _class[0] _class = _class.classObject() else: return {}, 404 modelFlowObject = _class().getAsClass( api.g["sessionData"], id=modelFlowObject._id) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] else: return {}, 404 else: modelFlowObject = None # New object required if not modelFlowObject: _class = model._model().getAsClass(api.g["sessionData"], id=data["newClassID"]) if _class: _class = _class[0].classObject() # Bug exists as name value is not requried by db class but is for core models - this could result in an error if new model is added that does not accept name within new function override newFlowObjectID = _class().new(flow["flowID"]).inserted_id # Working out by bruteforce which type this is ( try and load it by parent class and check for error) - get on trigger if it does not exist will return None modelFlowObjectType = "action" if len(trigger._trigger().getAsClass(api.g["sessionData"], id=newFlowObjectID)) > 0: modelFlowObjectType = "trigger" modelFlowObject = _class().getAsClass(api.g["sessionData"], id=newFlowObjectID) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] else: return {}, 404 modelFlowObject.acl = { "ids": [{ "accessID": api.g["sessionData"]["primaryGroup"], "read": True, "write": True, "delete": True }] } modelFlowObject.update(["acl"]) # Set conduct flow to correct type and objectID flow["type"] = modelFlowObjectType flow["{0}{1}".format(modelFlowObjectType, "ID")] = str(newFlowObjectID) conductObj.update(["flow"], sessionData=api.g["sessionData"]) # Updating new or existing modeFlowObject if modelFlowObject: updateItemsList = [] changeLog = {} # Getting schema information so types can be set correctly class_ = model._model().getAsClass(api.g["sessionData"], id=modelFlowObject.classID) if class_: _class = modelFlowObject # Builds list of permitted ACL access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], _class.acl, "write") if access: for dataKey, dataValue in data.items(): fieldAccessPermitted = True # Checking if sessionData is permitted field level access if _class.acl and not adminBypass: fieldAccessPermitted = db.fieldACLAccess( api.g["sessionData"], _class.acl, dataKey, "write") if fieldAccessPermitted: # Change update database entry _id if dataKey not in unsafeUpdateList: if hasattr(_class, dataKey): changeLog[dataKey] = {} changeLog[dataKey][ "currentValue"] = getattr( _class, dataKey) if type(getattr(_class, dataKey)) is str: if dataValue: if _class.setAttribute( dataKey, str(dataValue), sessionData=api. g["sessionData"]): updateItemsList.append(dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) elif type(getattr(_class, dataKey)) is int: try: if _class.setAttribute( dataKey, int(dataValue), sessionData=api. g["sessionData"]): updateItemsList.append(dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) except ValueError: if _class.setAttribute( dataKey, 0, sessionData=api. g["sessionData"]): updateItemsList.append(dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) elif type(getattr(_class, dataKey)) is float: try: if _class.setAttribute( dataKey, float(dataValue), sessionData=api. g["sessionData"]): updateItemsList.append(dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) except ValueError: if _class.setAttribute( dataKey, 0, sessionData=api. g["sessionData"]): updateItemsList.append(dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) elif type(getattr(_class, dataKey)) is bool: if _class.setAttribute( dataKey, bool(dataValue), sessionData=api. g["sessionData"]): updateItemsList.append(dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) elif type(getattr( _class, dataKey)) is dict or type( getattr(_class, dataKey)) is list: if dataValue: if _class.setAttribute( dataKey, json.loads(dataValue), sessionData=api. g["sessionData"]): updateItemsList.append(dataKey) changeLog[dataKey][ "newValue"] = getattr( _class, dataKey) # Commit back to database if updateItemsList: _class.update(updateItemsList, sessionData=api.g["sessionData"]) # Adding audit record if "_id" in api.g["sessionData"]: audit._audit().add( "model", "update", { "_id": api.g["sessionData"]["_id"], "objects": helpers.unicodeEscapeDict(changeLog) }) else: audit._audit().add("model", "update", { "objects": helpers.unicodeEscapeDict(changeLog) }) return {"type": modelFlowObjectType}, 200 else: return {}, 403 return {}, 404
def updateFlow(conductID, flowID): conductObj = conduct._conduct().getAsClass(api.g["sessionData"], id=conductID) if len(conductObj) == 1: conductObj = conductObj[0] else: return {}, 404 flow = [x for x in conductObj.flow if x["flowID"] == flowID] if len(flow) == 1: flow = flow[0] data = json.loads(api.request.data) if data["action"] == "update": access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], conductObj.acl, "write") if access: if "x" in data and "y" in data: try: x = int(data["x"]) y = int(data["y"]) except: return {}, 403 flowUI = webui._modelUI().getAsClass(api.g["sessionData"], query={ "flowID": flow["flowID"], "conductID": conductID }) if len(flowUI) == 1: flowUI = flowUI[0] if "x" in data and "y" in data: flowUI.x = x flowUI.y = y flowUI.update(["x", "y"], sessionData=api.g["sessionData"]) if "title" in data: flowUI.title = data["title"] flowUI.update(["title"], sessionData=api.g["sessionData"]) return {}, 200 else: webui._modelUI().new(conductID, conductObj.acl, flow["flowID"], x, y) return {}, 201 elif data["action"] == "copy": access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], conductObj.acl, "write") if access: flow = [ x for x in conductObj.flow if x["flowID"] == data["operatorId"] ] if len(flow) == 1: flow = flow[0] newFlowID = str(uuid.uuid4()) newFlow = { "flowID": newFlowID, "type": flow["type"], "{0}{1}".format(flow["type"], "ID"): flow["{0}{1}".format(flow["type"], "ID")], "next": [] } flowUI = webui._modelUI().getAsClass(api.g["sessionData"], query={ "flowID": flow["flowID"], "conductID": conductID })[0] webui._modelUI().new(conductID, conductObj.acl, newFlow["flowID"], data["x"], data["y"], flowUI.title) conductObj.flow.append(newFlow) conductObj.update(["flow"], sessionData=api.g["sessionData"]) return {}, 201 elif data["action"] == "clone": access, accessIDs, adminBypass = db.ACLAccess( api.g["sessionData"], conductObj.acl, "write") if access: flow = [ x for x in conductObj.flow if x["flowID"] == data["operatorId"] ] if len(flow) == 1: flow = flow[0] data = json.loads(api.request.data) modelFlowObject = None # Check if the modelType and object are unchanged if "type" in flow: if flow["type"] == "trigger": modelFlowObject = trigger._trigger().getAsClass( api.g["sessionData"], id=flow["{0}{1}".format(flow["type"], "ID")]) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] modelFlowObjectType = "trigger" if flow["type"] == "action": modelFlowObject = action._action().getAsClass( api.g["sessionData"], id=flow["{0}{1}".format(flow["type"], "ID")]) if len(modelFlowObject) == 1: modelFlowObject = modelFlowObject[0] modelFlowObjectType = "action" # Was it possible to load an existing object if modelFlowObject: # Create new flowItem newFlowID = str(uuid.uuid4()) flow = { "flowID": newFlowID, "type": flow["type"], "next": [] } # New object required _class = model._model().getAsClass( api.g["sessionData"], id=modelFlowObject.classID) if _class: _class = _class[0].classObject() # Bug exists as name value is not requried by db class but is for core models - this could result in an error if new model is added that does not accept name within new function override newFlowObjectID = _class().new( flow["flowID"]).inserted_id # Working out by bruteforce which type this is ( try and load it by parent class and check for error) - get on trigger if it does not exist will return None modelFlowObjectClone = _class().getAsClass( api.g["sessionData"], id=newFlowObjectID) if len(modelFlowObjectClone) == 1: modelFlowObjectClone = modelFlowObjectClone[ 0] else: return {}, 404 # Setting values in cloned object members = [ attr for attr in dir(modelFlowObject) if not callable( getattr(modelFlowObject, attr)) and not "__" in attr and attr ] dontCopy = ["_id", "name"] updateList = [] for member in members: if member not in dontCopy: setattr( modelFlowObjectClone, member, getattr(modelFlowObject, member)) updateList.append(member) modelFlowObjectClone.update( updateList, sessionData=api.g["sessionData"]) # Set conduct flow to correct type and objectID flow["{0}{1}".format( flow["type"], "ID")] = str(newFlowObjectID) conductObj.flow.append(flow) # Adding UI position for cloned object flowUI = webui._modelUI().getAsClass( api.g["sessionData"], query={ "flowID": flowID, "conductID": conductID })[0] webui._modelUI().new( conductID, conductObj.acl, flow["flowID"], data["x"], data["y"], "Copy - {0}".format(flowUI.title)) conductObj.update( ["flow"], sessionData=api.g["sessionData"]) return {"result": True}, 201 return {}, 404