Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

oe-workflow

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

oe-workflow - npm Package Compare versions

Comparing version 1.0.0 to 1.4.0

common/mixins/lib/maker-checker-helper-v2.js

10

CHANGELOG.md

@@ -0,1 +1,9 @@

2018-01-03, Version 1.2.0
=========================
* Implementation of Maker Checker Version 2
* Rework functionality for Maker Checker
* Additional attributes Due Date, Followup Date and Priority for User Task
* Input-Output variable mapping for Call Activity and Subprocess
2017-11-17, Version 1.1.1

@@ -19,2 +27,2 @@ =========================

* Initial Commit
* Initial Commit

@@ -257,2 +257,3 @@ /**

_status: 'public',
_verifiedBy: options.ctx.username,
_transactionType: null

@@ -338,2 +339,3 @@ };

'_transactionType': null,
'_verifiedBy': options.ctx.username,
'_status': 'public'

@@ -340,0 +342,0 @@ };

121

common/mixins/maker-checker-mixin.js

@@ -535,50 +535,2 @@ /**

beforeSaveUpdateHook(ctx, next);
} else if (ctx.data) {
// for UPDATE query - Upsert Variant
log.debug(ctx.options, 'beforeSaveWorkflowHook : UDPATE (Upsert)');
if (ctx.data._status === 'private' && ctx.data._isDeleted === true) {
err = new Error();
err.code = 'ATTACH_WORKFLOW_BAD_REQUEST';
err.statusCode = 400;
err.message = 'Delete not allowed while instance is in private state.';
err.retriable = false;
log.error(ctx.options, err);
return next(err);
} else if (ctx.data._isDeleted === true) {
// came from soft delete mixin but the instance is not intermediate instance
return next();
}
ctx.Model.findById(ctx.data.id, ctx.options, function fetchMI(err, currentInstance) {
if (err) {
err.statusCode = 400;
err.message = 'Unable to fetch currentInstance in Update(Upsert) [Thrown by Workflow Engine]';
log.error(ctx.options, err);
return next(err);
}
if (currentInstance._status === 'private' && currentInstance._transactionType !== 'update') {
err = new Error();
err.code = 'ATTACH_WORKFLOW_BAD_REQUEST';
err.statusCode = 400;
err.message = 'Update not allowed while instance is in private state.';
err.retriable = false;
log.error(ctx.options, err);
return next(err);
}
if (currentInstance._status === 'private' && currentInstance._transactionType === 'update' && ctx.options.ctx && ctx.options.ctx.username && currentInstance._modifiedBy !== ctx.options.ctx.username) {
err = new Error();
err.code = 'ATTACH_WORKFLOW_BAD_REQUEST';
err.statusCode = 400;
err.message = 'Update not allowed by a different user in private state.';
err.retriable = false;
log.error(ctx.options, err);
return next(err);
}
ctx.currentInstance = currentInstance;
beforeSaveUpdateHook(ctx, next);
});
} else {

@@ -638,5 +590,13 @@ log.debug(ctx.options, 'beforeSaveWorkflowHook : neither UPDATE nor CREATE');

ctx.options._workflowBody = mapping.workflowBody;
ctx.options._engineType = mapping.engineType;
ctx.options._transactionType = 'create';
let idName = ctx.Model.definition.idName();
// case id is not defined
if (typeof ctx.instance[idName] === 'undefined') {
ctx.instance.setAttribute(idName, uuidv4());
}
let key = '__workflow_mn_' + modelName + '_mid_' + ctx.instance[idName];
ctx.options[key] = {
_workflowBody: mapping.workflowBody,
_engineType: mapping.engineType,
_transactionType: 'create'
};
next();

@@ -723,5 +683,10 @@ } else {

ctx.options._workflowBody = mapping.workflowBody;
ctx.options._engineType = mapping.engineType;
ctx.options._transactionType = mapping.operation;
let idName = ctx.Model.definition.idName();
// case id is not defined
let key = '__workflow_mn_' + modelName + '_mid_' + ctx.currentInstance[idName];
ctx.options[key] = {
_workflowBody: mapping.workflowBody,
_engineType: mapping.engineType,
_transactionType: mapping.operation
};
next();

@@ -781,2 +746,4 @@ } else {

var modelName = ctx.Model.definition.name;
var idName = ctx.Model.definition.idName();
var key = '__workflow_mn_' + modelName + '_mid_' + ctx.instance[idName];
var options;

@@ -805,10 +772,10 @@ var engineType;

next();
} else if (ctx.instance && ctx.isNewInstance === false && (ctx.options._transactionType === 'update' || ctx.options._transactionType === 'save') && ctx.options._workflowBody) {
} else if (ctx.instance && ctx.isNewInstance === false && ctx.options[key] && (ctx.options[key]._transactionType === 'update' || ctx.options[key]._transactionType === 'save') && ctx.options[key]._workflowBody) {
log.debug(ctx.options, 'triggering workflow - during update');
options = ctx.options;
engineType = ctx.options._engineType;
engineType = ctx.options[key]._engineType;
variables = util.prepareWorkflowVariables(engineType, ctx.instance, ctx.Model);
workflowBody = ctx.options._workflowBody;
let transactionType = ctx.options._transactionType;
workflowBody = ctx.options[key]._workflowBody;
let transactionType = ctx.options[key]._transactionType;

@@ -822,11 +789,5 @@ xOptions = JSON.parse(JSON.stringify(options));

}
if (xOptions._transactionType) {
delete xOptions._transactionType;
if (xOptions[key]) {
delete xOptions[key];
}
if (xOptions._workflowBody) {
delete xOptions._workflowBody;
}
if (xOptions._engineType) {
delete xOptions._engineType;
}

@@ -846,9 +807,7 @@ handleReTrigger({

var workflowRef = res.id;
var operation = ctx.options._transactionType;
var operation = ctx.options[key]._transactionType;
if (operation === 'save') {
operation = operation + '-update';
}
delete ctx.options._workflowBody;
delete ctx.options._engineType;
delete ctx.options._transactionType;
delete ctx.options[key];
util.createWFRequest(engineType, modelName, ctx.instance.id, workflowRef, operation, options, next);

@@ -858,3 +817,3 @@ });

// update request anyway wont require after save workflow hook
} else if (ctx.instance && (ctx.options._transactionType === 'create' || ctx.options._transactionType === 'save') && ctx.options._workflowBody) {
} else if (ctx.instance && ctx.options[key] && (ctx.options[key]._transactionType === 'create' || ctx.options[key]._transactionType === 'save') && ctx.options[key]._workflowBody) {
// trigger workflow & create a WF request only if workflow was triggered

@@ -864,4 +823,4 @@ log.debug(ctx.options, 'triggering workflow - during create');

options = ctx.options;
workflowBody = ctx.options._workflowBody;
engineType = ctx.options._engineType;
workflowBody = ctx.options[key]._workflowBody;
engineType = ctx.options[key]._engineType;
variables = util.prepareWorkflowVariables(engineType, ctx.instance, ctx.Model);

@@ -876,11 +835,5 @@

}
if (xOptions._transactionType) {
delete xOptions._transactionType;
if (xOptions[key]) {
delete xOptions[key];
}
if (xOptions._workflowBody) {
delete xOptions._workflowBody;
}
if (xOptions._engineType) {
delete xOptions._engineType;
}

@@ -892,3 +845,3 @@ util.triggerWorkflow(engineType, variables, workflowBody, xOptions, function triggerWorkflowCb(err, res) {

}
var operation = ctx.options._transactionType;
var operation = ctx.options[key]._transactionType;
if (operation === 'save') {

@@ -898,5 +851,3 @@ operation = operation + '-create';

var workflowRef = res.id;
delete ctx.options._workflowBody;
delete ctx.options._engineType;
delete ctx.options._transactionType;
delete ctx.options[key];
util.createWFRequest(engineType, modelName, ctx.instance.id, workflowRef, operation, options, next);

@@ -903,0 +854,0 @@ });

{
"name": "bpmndata",
"base": "BaseEntity",
"description" : "Contains XML data of BPMN workflows",
"description": "Contains XML data of BPMN workflows",
"idInjection": true,

@@ -19,3 +19,6 @@ "options": {

"type": "string",
"required": true
"required": true,
"oracle": {
"dataType": "CLOB"
}
}

@@ -26,3 +29,12 @@ },

"acls": [],
"methods": {}
"methods": {
"processDefinitions": {
"type": "hasMany",
"model": "ProcessDefinition"
},
"workflowDefinition": {
"type": "hasOne",
"model": "WorkflowDefinition"
}
}
}

@@ -12,3 +12,2 @@ /**

var BPMNSubProcess = require('./subprocess.js');
var BPMNAssociation = require('./association.js');
var BPMNProcessDefinition = require('./processdefinition.js');

@@ -26,3 +25,2 @@ var BPMNLane = require('./lanes.js');

var finalSequenceFlow;
var finalassociation;
var finalLaneObject;

@@ -58,5 +56,5 @@ var flowObjectBpmnId;

processElements.flowObjects.push(finalFlowObject);
} else if (flowObjectType.indexOf('association') >= 0) {
finalassociation = BPMNAssociation.createBPMNAssociationElement(flowObject);
processElements.associations.push(finalassociation);
// } else if (flowObjectType.indexOf('association') >= 0) {
// finalassociation = BPMNAssociation.createBPMNAssociationElement(flowObject);
// processElements.associations.push(finalassociation);
} else if (flowObjectType.indexOf('laneSet') >= 0) {

@@ -93,15 +91,17 @@ finalLaneObject = BPMNLane.createBPMNLane(flowObject);

for (var flowObjectKey in defObject) {
if (flowObjectKey.indexOf('attributes') >= 0) {
continue;
}
if (defObject[flowObjectKey].constructor.name === 'Array') {
for (var element of defObject[flowObjectKey]) {
flowObject = element;
if (Object.prototype.hasOwnProperty.call(defObject, flowObjectKey)) {
if (flowObjectKey.indexOf('attributes') >= 0) {
continue;
}
if (defObject[flowObjectKey].constructor.name === 'Array') {
for (var element of defObject[flowObjectKey]) {
flowObject = element;
createFlowObject(flowObject, processElements);
}
} else if (defObject[flowObjectKey].constructor.name === 'Object') {
flowObject = defObject[flowObjectKey];
createFlowObject(flowObject, processElements);
} else {
log.error(log.defaultContext(), 'Flow object is neither array nor object');
}
} else if (defObject[flowObjectKey].constructor.name === 'Object') {
flowObject = defObject[flowObjectKey];
createFlowObject(flowObject, processElements);
} else {
log.error(log.defaultContext(), 'Flow object is neither array nor object');
}

@@ -108,0 +108,0 @@ }

@@ -17,2 +17,4 @@ /**

var checkAndAddMultiInstanceCharacteristics = require('./taskmarkers.js').checkAndAddMultiInstanceCharacteristics;
var extractInputOutputParameters = require('./parse-utils/input-output-parameters.js').extractInputOutputParameters;
var extractInOutMappings = require('./parse-utils/in-out-mappings.js').extractInOutMappings;

@@ -36,2 +38,8 @@ /**

checkAndAddMultiInstanceCharacteristics(flowObject, callActivityObject);
if (flowObject['bpmn2:extensionElements'] && flowObject['bpmn2:extensionElements']['camunda:inputOutput']) {
callActivityObject.inputOutputParameters = extractInputOutputParameters(flowObject['bpmn2:extensionElements']['camunda:inputOutput']);
}
if (flowObject['bpmn2:extensionElements'] ) {
callActivityObject.inOutMappings = extractInOutMappings(flowObject['bpmn2:extensionElements']);
}
return callActivityObject;

@@ -38,0 +46,0 @@ };

@@ -139,3 +139,3 @@ /**

for (var eventDefinition in defObject) {
if (eventDefinition.indexOf('Definition') >= 0) {
if (Object.prototype.hasOwnProperty.call(defObject, eventDefinition) && eventDefinition.indexOf('Definition') >= 0) {
var eventDefinitionType = defObject[eventDefinition].attributes_ns.local;

@@ -142,0 +142,0 @@ if (isSignalEventName(eventDefinitionType)) {

@@ -46,21 +46,23 @@ /**

for (var key in rawParsedDefinition) {
if (key.indexOf('attributes_') >= 0) {
continue;
} else {
var bpmnprocessDef = rawParsedDefinition[key];
var processdef;
if (rawParsedDefinition[key].constructor.name === 'Array') {
if (key.indexOf('process') >= 0) {
for (processdef of bpmnprocessDef) {
BPMNProcessDefinitions.push(BPMNProcessDefinition.createBPMNProcessDefinition(processdef));
if (Object.prototype.hasOwnProperty.call(rawParsedDefinition, key)) {
if (key.indexOf('attributes_') >= 0) {
continue;
} else {
var bpmnprocessDef = rawParsedDefinition[key];
var processdef;
if (rawParsedDefinition[key].constructor.name === 'Array') {
if (key.indexOf('process') >= 0) {
for (processdef of bpmnprocessDef) {
BPMNProcessDefinitions.push(BPMNProcessDefinition.createBPMNProcessDefinition(processdef));
}
} else if (key.indexOf('collaboration') >= 0 ) {
for (processdef of bpmnprocessDef) {
BPMNProcessDefinitions.push(collaborationDefinition.createBPMNCollaborationDefinition(processdef));
}
}
} else if (key.indexOf('collaboration') >= 0 ) {
for (processdef of bpmnprocessDef) {
BPMNProcessDefinitions.push(collaborationDefinition.createBPMNCollaborationDefinition(processdef));
}
} else if (key.indexOf('process') >= 0) {
BPMNProcessDefinitions.push(BPMNProcessDefinition.createBPMNProcessDefinition(bpmnprocessDef));
} else if (key.indexOf('collaboration') >= 0) {
BPMNProcessDefinitions.push(collaborationDefinition.createBPMNCollaborationDefinition(bpmnprocessDef));
}
} else if (key.indexOf('process') >= 0) {
BPMNProcessDefinitions.push(BPMNProcessDefinition.createBPMNProcessDefinition(bpmnprocessDef));
} else if (key.indexOf('collaboration') >= 0) {
BPMNProcessDefinitions.push(collaborationDefinition.createBPMNCollaborationDefinition(bpmnprocessDef));
}

@@ -67,0 +69,0 @@ }

@@ -10,3 +10,2 @@ /**

var log = logger('ProcessDefinition-Parser');
var parserUtils = require('./parserutils');
var BPMNFlowObject = require('./buildFlowObjects.js');

@@ -16,21 +15,2 @@ var BPMNProcessDefinition;

/**
* Check if the name is of process
* @param {String} localName name without namespace prefix
* @return {Boolean} isProcessName
*/
exports.isProcessName = function isProcessName(localName) {
return (localName === 'process');
};
/**
* Check if node is executable
* @param {Object} node Node
* @return {Boolean} isExecutable
*/
exports.isExecutable = function isExecutable(node) {
var isExecutable = parserUtils.getAttributesValue(node, 'isExecutable');
return (!isExecutable || isExecutable === 'true');
};
/**
* create a bpmn process definition

@@ -90,135 +70,2 @@ * @param {Object} defObject DefinitionObject

/**
* get the process element
* @param {String} bpmnId BpmnId
* @return {*} getProcessElement
*/
BPMNProcessDefinition.prototype.getProcessElement = function getProcessElement(bpmnId) {
if (!(this.processElementIndex)) {
this.processElementIndex = this._buildIndex();
}
return this.processElementIndex[bpmnId];
};
/**
* get the flow object
* @param {String} bpmnId BpmnId
* @return {BPMNFlowObject} getFlowObject
*/
BPMNProcessDefinition.prototype.getFlowObject = function getFlowObject(bpmnId) {
return this.getProcessElement(bpmnId);
};
/**
* get the source flow object
* @param {{sourceRef: String}} flow Flow
* @return {BPMNFlowObject} getSourceFlowObject
*/
BPMNProcessDefinition.prototype.getSourceFlowObject = function getSourceFlowObject(flow) {
return this.getProcessElement(flow.sourceRef);
};
/**
* get the start events
* @return {[BPMNActivity]} getStartEvents
*/
exports.getStartEvents = function getStartEvents() {
return this.flowObjects.filter(function iterateFlowObjects(flowObject) {
return (flowObject.isStartEvent);
});
};
/**
* get the boundary events
* @return {[BPMNActivity]} getBoundaryEvents
*/
BPMNProcessDefinition.prototype.getBoundaryEvents = function getBoundaryEvents() {
return this.flowObjects.filter(function iterateFlowObjects(flowObject) {
return (flowObject.isBoundaryEvent);
});
};
/**
* get the the boundary events at bpmn id
* @param {BPMNActivity} activity Activity
* @return {[BPMNActivity]} getBoundaryEventsAt
*/
BPMNProcessDefinition.prototype.getBoundaryEventsAt = function getBoundaryEventsAt(activity) {
if (!this.boundaryEventsByAttachmentIndex) {
this.boundaryEventsByAttachmentIndex = this.buildBoundaryEventsByAttachmentIndex();
}
return (this.boundaryEventsByAttachmentIndex[activity.bpmnId] || []);
};
/*
* build boundary events by attachment index
*/
BPMNProcessDefinition.prototype.buildBoundaryEventsByAttachmentIndex = function buildBoundaryEventsByAttachmentIndex() {
var index = {};
var self = this;
var boundaryEvents = this.getBoundaryEvents();
boundaryEvents.forEach(function iterateBoundaryEvents(boundaryEvent) {
var attachedToRef = boundaryEvent.attachedToRef;
var activity = self.getFlowObject(attachedToRef);
if (activity) {
if (activity.isWaitTask || activity.isSubProcess || activity.isInsideTransaction) {
var entry = index[attachedToRef];
if (entry) {
entry.push(boundaryEvent);
} else {
index[attachedToRef] = [boundaryEvent];
}
} else {
log.error(log.defaultContext(), "The activity '" + activity.name + "' has a boundary event but this is allowed only for wait tasks such as user or receive tasks.");
}
} else {
log.error(log.defaultContext(), "Cannot find the activity the boundary event '" + boundaryEvent.name +
"' is attached to (activity BPMN ID: '" + boundaryEvent.attachedToRef + "'.");
}
});
return index;
};
/**
* get the flow object name
* @param {String} name Name
* @return {BPMNFlowObject} getFlowObjectByName
*/
BPMNProcessDefinition.prototype.getFlowObjectByName = function getFlowObjectByName(name) {
var bpmnId = this.getIdByName(name);
return this.getFlowObject(bpmnId);
};
/**
* get the id by name
* @param {String} name Name
* @return {String} getIdByName
*/
BPMNProcessDefinition.prototype.getIdByName = function getIdByName(name) {
if (!(this.nameMap)) {
this.nameMap = buildNameMap(this.getFlowObjects());
}
return this.nameMap[name];
};
/**
* get the nextt flow objects
* @param {BPMNFlowObject} flowObject FlowObject
* @return {Array.<BPMNFlowObject>} getNextFlowObjects
*/
BPMNProcessDefinition.prototype.getNextFlowObjects = function getNextFlowObjects(flowObject) {
var nextFlowObjects = [];
var self = this;
var outgoingSequenceFlows = this.getOutgoingSequenceFlows(flowObject);
outgoingSequenceFlows.forEach(function iterateOutgoingSequenceFlows(flow) {
nextFlowObjects.push(self.getProcessElement(flow.targetRef));
});
return nextFlowObjects;
};
/**
* get the incoming sequence flows

@@ -246,2 +93,15 @@ * @param {BPMNFlowObject} flowObject FlowObject

/**
* get the process element
* @param {String} bpmnId BpmnId
* @return {*} getProcessElement
*/
BPMNProcessDefinition.prototype.getProcessElement = function getProcessElement(bpmnId) {
if (!(this.processElementIndex)) {
this.processElementIndex = this._buildIndex();
}
return this.processElementIndex[bpmnId];
};
/**
* get the outgoing sequence flows

@@ -256,12 +116,2 @@ * @param {BPMNFlowObject} flowObject FlowObject

/**
* add a sequence flow entry
* @param {BPMNSequenceFlow} sequenceFlow SequenceFlow
*/
BPMNProcessDefinition.prototype.addSequenceFlow = function addSequenceFlow(sequenceFlow) {
this.sequenceFlowBySourceIndex = null;
this.sequenceFlowByTargetIndex = null;
this.sequenceFlows.push(sequenceFlow);
};
/**
* Check if flow object has outgoing sequence flows

@@ -280,13 +130,2 @@ * @param {BPMNFlowObject} flowObject FlowObject

/**
* Add a flow object entry
* @param {BPMNFlowObject} flowObject FlowObject
*/
BPMNProcessDefinition.prototype.addFlowObject = function addFlowObject(flowObject) {
this.processElementIndex = null;
this.nameMap = null;
this.boundaryEventsByAttachmentIndex = null;
this.flowObjects.push(flowObject);
};
/**
* get the flow objects

@@ -299,27 +138,4 @@ * @return {[BPMNFlowObject]} getFlowObjects

/**
* add an association entry
* @param {Object} association Association
*/
BPMNProcessDefinition.prototype.addAssociations = function addAssociations(association) {
this.associations.push(association);
};
/**
* get associations
* @returns {Array} Associations
*/
BPMNProcessDefinition.prototype.getAssociations = function getAssociations() {
return this.associations;
};
BPMNProcessDefinition.prototype.addLane = function addLane(lane) {
this.lanes.push(lane);
};
BPMNProcessDefinition.prototype.getLanes = function getLanes() {
return this.lanes;
};
/**
* get the process elements

@@ -369,14 +185,2 @@ * @return {[Object]} getProcessElements

/**
* get the participant by participant id
* @param {String} processDefinitionId ProcessDefinitionId
* @return {BPMNParticipant} ParticipantById
*/
BPMNProcessDefinition.prototype.getParticipantById = function getParticipantById(processDefinitionId) {
var participants = this.collaboratingParticipants.filter(function iterateParticipants(participant) {
return (participant.processRef === processDefinitionId);
});
return participants[0];
};
/**
* get the collaborating participants

@@ -403,35 +207,2 @@ * @return {[BPMNParticipant]} CollaboratingParticipants

/**
* get the incoming message flows
* @param {BPMNFlowObject} flowObject FlowObject
* @return {[BPMNMessageFlow]} IncomingMessageFlows
*/
BPMNProcessDefinition.prototype.getIncomingMessageFlows = function getIncomingMessageFlows(flowObject) {
return this._getFlows('messageFlowByTargetIndex', 'messageFlows', flowObject, false);
};
/**
* get the outgoing message flows
* @param {BPMNFlowObject} flowObject FlowObject
* @return {[BPMNMessageFlow]} OutgoingMessageFlows
*/
BPMNProcessDefinition.prototype.getOutgoingMessageFlows = function getOutgoingMessageFlows(flowObject) {
return this._getFlows('messageFlowBySourceIndex', 'messageFlows', flowObject, true);
};
/**
* get the message flows by flowb object name
* @param {String} flowObjectName FlowObjectName
* @return {[BPMNMessageFlow]} MessageFlowsBySourceName
*/
BPMNProcessDefinition.prototype.getMessageFlowsBySourceName = function getMessageFlowsBySourceName(flowObjectName) {
var flowObject = this.getFlowObjectByName(flowObjectName);
return this.getOutgoingMessageFlows(flowObject);
};
BPMNProcessDefinition.prototype.getRestEndPoint = function getRestEndPoint(currentActivity) {
var flowObject = this.getFlowObjectByName(currentActivity);
return JSON.parse(flowObject.restEndpoint);
};
/**
* add message flows entry

@@ -506,61 +277,2 @@ * @param {[BPMNMessageFlow]} messageFlows MessageFlows

/**
* build name for map
* @param {[{name: string, bpmnId: string}]} objects Objects name and bpmid
* @return {Object} buildNameMapObjects
* @private
*/
function buildNameMap(objects) {
var map = {};
objects.forEach(function iterateObjects(object) {
var name = object.name;
if (map[name]) {
log.error(log.defaultContext(), "Process element name '" + name + "' must be unique.");
} else {
map[name] = object.bpmnId;
}
});
return map;
}
/**
* add data object reference
* @param {Object} dataObjectReference DataObjectReference
*/
BPMNProcessDefinition.prototype.addDataObjectReference = function addDataObjectReference(dataObjectReference) {
this.dataObjectReferences.push(dataObjectReference);
};
/**
* get data object reference
* @returns {*|Array} DataObjectReferences
*/
BPMNProcessDefinition.prototype.getDataObjectReferences = function getDataObjectReferences() {
return this.dataObjectReferences;
};
/**
* get event sub processes
* @returns {Array.<*>} EventSubProcesses
*/
BPMNProcessDefinition.prototype.getEventSubProcesses = function getEventSubProcesses() {
return this.flowObjects.filter(function iterateFlowObjects(flowObject) {
return (flowObject.isSubProcess && flowObject.triggeredByEvent === 'true');
});
};
/**
* get the transaction sub processes
* @returns {Array.<*>} TransactionSubProcesses
*/
BPMNProcessDefinition.prototype.getTransactionSubProcesses = function getTransactionSubProcesses() {
return this.flowObjects.filter(function iterateFlowObjects(flowObject) {
return (flowObject.isSubProcess && flowObject.type === 'transaction');
});
};
/**
* create a bpmn process definition

@@ -567,0 +279,0 @@ * @param {Object} defObject DefinitionObject

@@ -14,2 +14,3 @@ /**

var checkAndAddMultiInstanceCharacteristics = require('./taskmarkers.js').checkAndAddMultiInstanceCharacteristics;
var extractInputOutputParameters = require('./parse-utils/input-output-parameters.js').extractInputOutputParameters;

@@ -40,2 +41,5 @@ var logger = require('oe-logger');

checkAndAddMultiInstanceCharacteristics(flowObject, subprocessObject);
if (flowObject['bpmn2:extensionElements'] && flowObject['bpmn2:extensionElements']['camunda:inputOutput']) {
subprocessObject.inputOutputParameters = extractInputOutputParameters(flowObject['bpmn2:extensionElements']['camunda:inputOutput']);
}
return subprocessObject;

@@ -42,0 +46,0 @@ };

@@ -15,3 +15,3 @@ /**

var checkAndAddMultiInstanceCharacteristics = require('./taskmarkers.js').checkAndAddMultiInstanceCharacteristics;
var extractInputOutputParameters = require('./parse-utils/input-output-parameters.js').extractInputOutputParameters;
/**

@@ -82,2 +82,13 @@ * Subsumes all kind of tasks

var currentProcessElement = this;
if (defObject.attributes_['camunda:taskCategory']) {
if (defObject.attributes_['camunda:taskCategory'].value === 'multiMaker') {
currentProcessElement.isMultiMaker = true;
}
if (defObject.attributes_['camunda:taskCategory'].value === 'checker') {
currentProcessElement.isChecker = true;
}
if (defObject.attributes_['camunda:taskCategory'].value === 'checkerAutoFinalize') {
currentProcessElement.isCheckerAutoFinalize = true;
}
}
if (defObject.attributes_['camunda:candidateUsers']) {

@@ -107,5 +118,13 @@ var candidateUsers = defObject.attributes_['camunda:candidateUsers'].value;

}
if (defObject.attributes_['camunda:dueDate']) {
currentProcessElement.dueDate = defObject.attributes_['camunda:dueDate'].value;
}
if (defObject.attributes_['camunda:followUpDate']) {
currentProcessElement.followUpDate = defObject.attributes_['camunda:followUpDate'].value;
}
if (defObject.attributes_['camunda:priority']) {
currentProcessElement.priority = defObject.attributes_['camunda:priority'].value;
}
if (defObject['bpmn2:extensionElements'] && defObject['bpmn2:extensionElements']['camunda:inputOutput']) {
this.inputOutputParameters = extractInputOutputParameters(defObject['bpmn2:extensionElements']['camunda:inputOutput']);
currentProcessElement.inputOutputParameters = extractInputOutputParameters(defObject['bpmn2:extensionElements']['camunda:inputOutput']);
}

@@ -123,3 +142,3 @@ addUserTaskFormVariables(defObject, currentProcessElement);

if (defObject['bpmn2:extensionElements'] && defObject['bpmn2:extensionElements']['camunda:connector'] &&
defObject['bpmn2:extensionElements']['camunda:inputOutput']) {
defObject['bpmn2:extensionElements']['camunda:inputOutput']) {
this.inputOutputParameters = extractInputOutputParameters(defObject['bpmn2:extensionElements']['camunda:inputOutput']);

@@ -301,62 +320,2 @@ }

/**
* Add Extension Elements to the task object
* @param {BPMNProcessDefinition} defObject ProcessDefinition
* @returns {Object} inputOutputParameters
*/
function extractInputOutputParameters(defObject) {
var inputParametersObj = defObject['camunda:inputParameter'];
var outputParametersObj = defObject['camunda:outputParameter'];
var inputOutputParameters = {'inputParameters': createInputOuputParameters(inputParametersObj),
'outputParameters': createInputOuputParameters(outputParametersObj) };
return inputOutputParameters;
}
/**
* Return the input/output parameters
* @param {Object} inputOutputParameter inputOutputParameter
* @returns {boolean} isServiceTask
*/
function createInputOuputParameters(inputOutputParameter) {
var inputId;
var inputVal;
var objKey;
var inputParameters = {};
if (typeof inputOutputParameter !== 'undefined' && inputOutputParameter.constructor.name === 'Array') {
for (var input of inputOutputParameter) {
if (input.attributes_ && input.attributes_.name) {
inputId = input.attributes_.name.value;
}
if (input.hasOwnProperty('camunda:script')) {
inputVal = input['camunda:script'].text;
}
if (input.hasOwnProperty('camunda:list')) {
var listVals = input['camunda:list']['camunda:value'];
inputVal = [];
for (var val of listVals) {
inputVal.push(val.text);
}
}
if (input.hasOwnProperty('camunda:map')) {
var mapVals = input['camunda:map']['camunda:entry'];
inputVal = {};
objKey = '';
for (var obj of mapVals) {
if (obj.attributes_ && obj.attributes_.key) {
objKey = obj.attributes_.key.value;
}
inputVal[objKey] = obj.text;
}
}
if (input.hasOwnProperty('text')) {
inputVal = input.text;
}
inputParameters[inputId] = inputVal;
}
}
return inputParameters;
}
/**
* Add oe-connector attributes to service task

@@ -368,3 +327,2 @@ * @param {Object} ConnectorObject ConnectorObject

var props = {};
if (typeof ConnectorObject !== 'undefined') {

@@ -377,13 +335,6 @@ if (ConnectorObject.hasOwnProperty('camunda:model')) {

}
if (ConnectorObject.hasOwnProperty('camunda:modelData')) {
props.data = ConnectorObject['camunda:modelData'].text;
if (ConnectorObject.hasOwnProperty('camunda:args')) {
props.data = ConnectorObject['camunda:args'].text;
}
if (ConnectorObject.hasOwnProperty('camunda:modelId')) {
props.modelId = ConnectorObject['camunda:modelId'].text;
}
if (ConnectorObject.hasOwnProperty('camunda:modelVersion')) {
props.modelVersion = ConnectorObject['camunda:modelVersion'].text;
}
}
return props;

@@ -434,4 +385,4 @@ }

}
if (ConnectorObject.hasOwnProperty('camunda:header')) {
formData.header = JSON.parse(ConnectorObject['camunda:header'].text);
if (ConnectorObject.hasOwnProperty('camunda:headers')) {
formData.headers = ConnectorObject['camunda:headers'].text;
}

@@ -438,0 +389,0 @@ if (ConnectorObject.hasOwnProperty('camunda:retries')) {

@@ -71,3 +71,3 @@ /**

for (i in ProcessInstance._processTimerEvents.timerIds) {
if (i === timerToKeep) {
if (Object.prototype.hasOwnProperty.call(ProcessInstance._processTimerEvents.timerIds, i) && i === timerToKeep) {
// TODO : why startTimer is used but not referenced

@@ -74,0 +74,0 @@ var startTimer = ProcessInstance._processTimerEvents.timerIds[i];

@@ -15,3 +15,5 @@ /**

var StateDelta = require('../../process-state-delta.js');
var sandbox = require('../workflow-nodes/sandbox.js');
var recrevaluatePayload = require('../workflow-nodes/businessruletask-node.js').evaluatePayload;
var SUBPROCESS_INTERRUPT_EVENT = 'SUBPROCESS_INTERRUPT_EVENT';

@@ -23,4 +25,4 @@ var TASK_INTERRUPT_EVENT = 'TASK_INTERRUPT_EVENT';

exports._subProcessEndEventHandler = function _subProcessEndEventHandler(options, currentProcess, token, processVariables) {
var mappedVariables = {};
var delta = new StateDelta();
delta.setProcessVariables(processVariables);
currentProcess.processDefinition({}, options, function fetchPD(err, processDefinitionInstance) {

@@ -31,2 +33,36 @@ if (err) {

}
var currentFlowObject = processDefinitionInstance.getFlowObjectByName(token.name);
// Map the required process variables to call activity
if (currentFlowObject.isCallActivity) {
if (currentFlowObject.inOutMappings && currentFlowObject.inOutMappings.outputMappings) {
var outputMappings = currentFlowObject.inOutMappings.outputMappings;
for (var source in outputMappings) {
if (Object.prototype.hasOwnProperty.call(outputMappings, source) && source === 'variables' && outputMappings[source] === 'all') {
Object.assign(mappedVariables, processVariables);
} else if (source in processVariables) {
source = sandbox.evaluate$Expression(options, source, token.message, currentProcess);
var target = outputMappings[source];
if (typeof processVariables[source] === 'object') {
mappedVariables[target] = {};
Object.assign(mappedVariables[target], processVariables[source]);
} else {
mappedVariables[target] = processVariables[source];
}
}
}
} else {
Object.assign(mappedVariables, processVariables);
}
}
if (currentFlowObject.inputOutputParameters && currentFlowObject.inputOutputParameters.outputParameters) {
var outputParameters = currentFlowObject.inputOutputParameters.outputParameters;
var evalInput = recrevaluatePayload(outputParameters, token.message, currentProcess);
Object.assign(mappedVariables, evalInput);
} else if (currentFlowObject.isSubProcess) {
Object.assign(mappedVariables, processVariables);
}
delta.setProcessVariables(mappedVariables);
setImmediate(function setImmediateCb(options) {

@@ -33,0 +69,0 @@ currentProcess._endFlowObject(options, token, processDefinitionInstance, delta);

@@ -17,3 +17,5 @@ /**

var flowObjectEvaluator = require('../workflow-nodes/evaluate-flow-object.js');
var dateUtils = require('../utils/date-utils.js');
var sandbox = require('../workflow-nodes/sandbox.js');
var recrevaluatePayload = require('../workflow-nodes/businessruletask-node.js').evaluatePayload;
var _ = require('lodash');

@@ -29,4 +31,2 @@

var payload;
var code;
var prop;

@@ -60,5 +60,24 @@ if (pDelta) {

var poolInfo = processDefinitionInstance.findPoolInfo(currentFlowObject);
var taskObj = {
'name': currentFlowObject.name,
'processTokenId': token.id
};
var inputParameters;
var evalInput;
if (currentFlowObject.inputOutputParameters && currentFlowObject.inputOutputParameters.inputParameters) {
inputParameters = currentFlowObject.inputOutputParameters.inputParameters;
evalInput = recrevaluatePayload(inputParameters, token.message, currentProcess);
taskObj.stepVariables = {};
Object.assign(taskObj.stepVariables, evalInput);
}
if (taskObj.stepVariables && token.message && typeof token.message === 'object' && typeof taskObj.stepVariables === 'object') {
Object.assign(token.message, taskObj.stepVariables);
}
var evalEntity = function evalEntity(entityList) {
entityList = updateExpBackComp(entityList);
entityList = sandbox.evaluate$Expression(options, entityList, token.message, currentProcess, token);
if (entityList === '') {
return [];
}
return entityList.split(',');

@@ -87,7 +106,2 @@ };

var taskObj = {
'name': currentFlowObject.name,
'processTokenId': token.id
};
if (currentFlowObject.candidateUsers) {

@@ -168,31 +182,9 @@ let evaluatedList = evalEntity(currentFlowObject.candidateUsers);

var evaluatePayload = function evaluatePayload(options, inputData, message, process) {
var self = this;
for (prop in process._processVariables) {
if (Object.prototype.hasOwnProperty.call(process._processVariables, prop)) {
self[prop] = process._processVariables[prop];
}
// evaluating payload
try {
var payload = sandbox.evaluateDirect(options, '`' + inputData + '`', message, process);
} catch (err) {
log.error(options, err);
return;
}
for (prop in message) {
if (Object.prototype.hasOwnProperty.call(message, prop)) {
self[prop] = message[prop];
}
}
var payload = '';
var propVal;
var propExp = 'propVal = `' + inputData + '`';
// TODO : replace eval with sandbox
// eslint-disable-next-line
eval(propExp);
payload = propVal;
for (prop in process._processVariables) {
if (Object.prototype.hasOwnProperty.call(process._processVariables, prop)) {
delete self[prop];
}
}
return payload;

@@ -237,3 +229,22 @@ };

taskObj.workflowInstanceId = currentProcess.workflowInstanceId;
var dateFormat = 'DD-MM-YYYY';
if (currentFlowObject.followUpDate) {
let evaluatedList = evalEntity([currentFlowObject.followUpDate]);
if (evaluatedList !== null) {
taskObj.followUpDate = dateUtils.parse_date(evaluatedList[0], dateFormat);
}
}
if (currentFlowObject.dueDate) {
let evaluatedList = evalEntity([currentFlowObject.dueDate]);
if (evaluatedList !== null) {
taskObj.dueDate = dateUtils.parse_date(evaluatedList[0], dateFormat);
}
}
if (currentFlowObject.priority) {
let evaluatedList = evalEntity([currentFlowObject.priority]);
if (evaluatedList !== null) {
taskObj.priority = evaluatedList[0];
}
}
ProcessInstance.app.models.Task.create(taskObj, options, function createTask(err, task) {

@@ -257,7 +268,9 @@ if (err) {

'workflowInstanceId': currentProcess.workflowInstanceId,
'processVariables': {}
'processVariables': {
'_modelInstance': {}
}
};
if (currentProcess._processVariables._modelInstance) {
Object.assign(subProcessesIns.processVariables, currentProcess._processVariables._modelInstance);
Object.assign(subProcessesIns.processVariables._modelInstance, currentProcess._processVariables._modelInstance);
}

@@ -269,2 +282,32 @@ // additionally pass any local variables as process variables -> step variables/ multi instance variables

// Map the required process variables to call activity
if (currentFlowObject.isCallActivity) {
if (currentFlowObject.inOutMappings && currentFlowObject.inOutMappings.inputMappings) {
var inputMappings = currentFlowObject.inOutMappings.inputMappings;
for (var source in inputMappings) {
if (Object.prototype.hasOwnProperty.call(inputMappings, source) && source === 'variables' && inputMappings[source] === 'all') {
Object.assign(subProcessesIns.processVariables, currentProcess._processVariables);
} else if (source in currentProcess._processVariables) {
source = sandbox.evaluate$Expression(options, source, message, currentProcess);
var target = inputMappings[source];
if (typeof currentProcess._processVariables[source] === 'object') {
subProcessesIns.processVariables[target] = {};
Object.assign(subProcessesIns.processVariables[target], currentProcess._processVariables[source]);
} else {
subProcessesIns.processVariables[target] = currentProcess._processVariables[source];
}
}
}
} else {
Object.assign(subProcessesIns.processVariables, currentProcess._processVariables);
}
}
if (currentFlowObject.inputOutputParameters && currentFlowObject.inputOutputParameters.inputParameters) {
inputParameters = currentFlowObject.inputOutputParameters.inputParameters;
evalInput = recrevaluatePayload(inputParameters, token.message, currentProcess);
Object.assign(subProcessesIns.processVariables, evalInput);
} else if (currentFlowObject.isSubProcess) {
Object.assign(subProcessesIns.processVariables, currentProcess._processVariables);
}
var evaluatedProcessName = currentFlowObject.subProcessId;

@@ -282,2 +325,7 @@ if (currentFlowObject.isCallActivity) {

function fetchCallActivityWD(err, workflowDefinition) {
if (err) {
var errx = new Error('call activity or Subprocess definition fetch error');
log.error(options, errx);
return;
}
var pdfilter = {'and': [{'name': evaluatedProcessName}, {'workflowDefinitionId': workflowDefinition[0].id}]};

@@ -312,2 +360,3 @@ ProcessInstance.app.models.ProcessDefinition.find({'where': pdfilter

} else if (currentFlowObject.isEndEvent || currentFlowObject.isIntermediateThrowEvent) {
let code;
payload = null;

@@ -325,4 +374,6 @@ if (currentFlowObject.isMessageEvent) {

for (key in processDefinition.eventObjectMap) {
if (processDefinition.eventObjectMap[key] === currentFlowObject.escalationId) {
code = key;
if (Object.prototype.hasOwnProperty.call(processDefinition.eventObjectMap, key)) {
if (processDefinition.eventObjectMap[key] === currentFlowObject.escalationId) {
code = key;
}
}

@@ -329,0 +380,0 @@ }

@@ -22,3 +22,3 @@ /**

var model = loopback.getModel(modelName, options);
var evalPayload = evaluatePayload(options, payload, message, process);
var evalPayload = evaluatePayload(payload, message, process);

@@ -43,3 +43,3 @@ model.exec(ruleName, evalPayload, options, function execBR(err, res) {

var evaluatePayload = function evalPayload(options, inputData, message, process) {
var evaluatePayload = function evalPayload(inputData, message, process) {
var self = this;

@@ -46,0 +46,0 @@ var prop;

@@ -35,11 +35,11 @@ /**

if (flowObject.inputOutputParameters && flowObject.inputOutputParameters.inputParameters) {
stepVariables = evaluatePayload(options, flowObject.inputOutputParameters.inputParameters, message, process);
stepVariables = evaluatePayload(flowObject.inputOutputParameters.inputParameters, incomingMsg, process);
_.assign(scriptVariables, stepVariables);
}
var message = sandbox.evaluateScript(options, script, scriptVariables, process, delta, token);
return done(null, message);
var response = sandbox.evaluateScript(options, script, scriptVariables, process, delta, token);
return done(null, response);
} else if (service) {
var serviceVariables = incomingMsg || {};
if (flowObject.inputOutputParameters && flowObject.inputOutputParameters.inputParameters) {
stepVariables = evaluatePayload(options, flowObject.inputOutputParameters.inputParameters, message, process);
stepVariables = evaluatePayload(flowObject.inputOutputParameters.inputParameters, incomingMsg, process);
_.assign(serviceVariables, stepVariables);

@@ -49,3 +49,3 @@ }

} else if (flowObject.businessRuleTask) {
businessRuleTaskHandler(flowObject.ruleName, flowObject.inputOutputParameters.inputParameters, message, process, options, done);
businessRuleTaskHandler(flowObject.ruleName, flowObject.inputOutputParameters.inputParameters, incomingMsg, process, options, done);
} else if (flowObject.type === 'sendTask') {

@@ -102,3 +102,3 @@ process.processDefinition({}, options, function fetchPD(err, processDefinitionInstance) {

for (var i in externalMessageFlows) {
if (externalMessageFlows[i].isExternal) {
if (Object.prototype.hasOwnProperty.call(externalMessageFlows, i) && externalMessageFlows[i].isExternal) {
externalMessageFlowsFilter.push(externalMessageFlows[i]);

@@ -105,0 +105,0 @@ }

@@ -88,4 +88,6 @@ /**

for (var key in obj) {
if (obj[key] === true) {
sandbox._instance.unsetAttribute(key);
if (Object.prototype.hasOwnProperty.call(obj, key)) {
if (obj[key] === true) {
sandbox._instance.unsetAttribute(key);
}
}

@@ -105,3 +107,3 @@ }

for (key in updates.unset) {
if (obj[key]) {
if (Object.prototype.hasOwnProperty.call(updates.unset, key) && obj[key]) {
delete obj[key];

@@ -125,6 +127,6 @@ }

log.error(options, e);
return e;
return { error: e };
}
return message;
return { msg: message };
};

@@ -136,3 +138,16 @@

options: options,
pv: function pv(name) {
if (inVariables && inVariables[name]) {
return inVariables[name];
}
return process._processVariables[name];
},
accessToken: options.accessToken,
access_token: options.accessToken,
msg: msg,
_getPV: function _getPV(name) {
// To be DEPRECATED soon, Please use pv and msg instead of _getPV and _msg in expressions
let depMessage = '[TO BE DEPRECATED SOON]: Please update _getPV and _msg with pv and msg in Expressions.';
// eslint-disable-next-line
console.log(depMessage);
if (inVariables && inVariables[name]) {

@@ -155,3 +170,4 @@ return inVariables[name];

log.error(options, e);
return e;
throw e;
// return e;
}

@@ -161,12 +177,15 @@ return sandbox._output;

module.exports.evaluateAccessExpression = function evalExpression(options, expression, msg, process) {
var sandbox = {
_output: {},
options: options,
pv: function _getPV(name) {
return process._processVariables[name];
},
msg: msg
};
module.exports.evaluateDirect = function evaluateDirect(options, expression, message, process, inVariables) {
var sandbox = {};
// Process Variables will have priority over message
message = message || {};
Object.keys(message).forEach(prop => {
sandbox[prop] = message[prop];
});
process._processVariables = process._processVariables || {};
Object.keys(process._processVariables).forEach(prop => {
sandbox[prop] = process._processVariables[prop];
});
var evalExpression = '_output = ' + expression;

@@ -181,3 +200,4 @@

log.error(options, e);
return e;
throw e;
// return e;
}

@@ -187,3 +207,2 @@ return sandbox._output;

module.exports.evaluate$Expression = function eval$Expression(options, expression, msg, process, token) {

@@ -198,3 +217,3 @@ var prop;

if (Object.prototype.hasOwnProperty.call(process._processVariables, prop)) {
sandbox[prop] = _.cloneDeep(process._processVariables[prop]);
sandbox[prop] = JSON.parse(JSON.stringify(process._processVariables[prop]));
}

@@ -201,0 +220,0 @@ }

@@ -16,2 +16,3 @@ /**

var vm = require('vm');
var sandbox = require('./sandbox.js');

@@ -29,7 +30,6 @@ var logger = require('oe-logger');

* @param {Function} done Callback
* @returns {void}
*/
module.exports.run = function run(options, flowObject, message, process, token, done) {
if (flowObject.isCustom) {
evaluateCustomImplementation(options, flowObject, message, process, done);
} else if (flowObject.connectorType && flowObject.connectorType === 'rest') {
if (flowObject.connectorType && flowObject.connectorType === 'rest') {
evaluateRestConnector(options, flowObject, message, process, token, done);

@@ -41,6 +41,43 @@ } else if (flowObject.connectorType && flowObject.connectorType === 'finalizeTransaction') {

} else {
evaluateCustomImplementation(options, flowObject, message, process, done);
let err = new Error('Invalid connector type found.');
log.error(options, err);
return done(err);
}
};
var evaluateJSON = function evaluateJSON(data, incomingMsg, process, options) {
var sandbox = {
msg: incomingMsg,
pv: function pv(name) {
if (name === 'accessToken') {
return options.accessToken;
}
var val = process._processVariables[name];
if (typeof val === 'undefined' && process._parentProcessVariables) {
val = process._parentProcessVariables[name];
}
return val;
},
data: data,
_output: null
};
if (typeof data !== 'string') {
data = JSON.stringify(data);
}
var script = '_output = ' + data;
// eslint-disable-next-line
var context = new vm.createContext(sandbox);
try {
var compiledScript = new vm.Script(script);
compiledScript.runInContext(context, { timeout: 1000 });
} catch (e) {
log.error(options, e);
return e;
}
return sandbox._output;
};
module.exports.evaluateJSON = evaluateJSON;
/**

@@ -56,3 +93,3 @@ * Evaluates Finalize Transaciton Connector

var variableType = flowObject.variableType;
var status = 'approved';
var status = 'approved';

@@ -81,6 +118,12 @@ if (variableType === 'ProcessVariable' || variableType === 'processvariable') {

if (process._processVariables._maker_checker_impl === 'v2') {
postData.version = 'v2';
}
WorkflowManager.endAttachWfRequest(postData, options, function completeMakerCheckerRequest(err, res) {
if (err) {
log.error(err);
return done(err);
return done(null, {
error: err
});
}

@@ -107,50 +150,24 @@ var msg;

* @param {Function} done Callback
* @returns {void}
*/
function evaluateRestConnector(options, flowObject, message, process, token, done) {
var pv = function pv(name) {
var val = process._processVariables[name];
if (typeof val === 'undefined' && token && token.inVariables) {
var inVariables = token.inVariables;
val = inVariables[name];
var urlOptions = _.cloneDeep(flowObject.formData);
// evaluating url, headers & json
try {
if (urlOptions.url) {
urlOptions.url = sandbox.evaluateExpression(options, '`' + urlOptions.url + '`', message, process);
}
if (typeof val === 'undefined' && process._parentProcessVariables) {
val = process._parentProcessVariables[name];
if (urlOptions.headers) {
urlOptions.headers = sandbox.evaluateExpression(options, urlOptions.headers, message, process);
}
return val;
};
var accessToken = options.accessToken;
// eslint-disable-next-line
var access_token = options.accessToken;
var msg = function msg(name) {
return message[name];
};
log.debug(options, pv, accessToken, msg);
var urlOptions = _.cloneDeep(flowObject.formData);
// evaluating url
// TODO : change eval to sandbox
// eslint-disable-next-line
var _url = eval('`' + urlOptions.url + '`');
urlOptions.url = _url;
// evaluating body
if (urlOptions.json) {
var _json;
var expr = '_json = ' + urlOptions.json;
// TODO : change eval to sandbox
// eslint-disable-next-line
eval(expr);
urlOptions.json = _json;
if (urlOptions.json) {
urlOptions.json = sandbox.evaluateExpression(options, urlOptions.json, message, process);
}
} catch (err) {
return done(null, {
error: err
});
}
var qs = flowObject.queryString;
if (qs) {
urlOptions.qs = qs;
}
// default timeout is now set to 20000 ms

@@ -162,5 +179,11 @@ urlOptions.timeout = flowObject.timeout || 20000;

if (urlOptions.url && urlOptions.url.indexOf('http') !== 0) {
urlOptions.baseUrl = 'http://localhost:3000/';
}
makeRESTCalls(urlOptions, retries, function callback(err, response) {
if (err) {
return done(err);
log.error(options, err);
return done(null, {
error: err
});
}

@@ -179,6 +202,8 @@ done(null, response);

request(urlOptions, function makeRequest(err, response, body) {
if (err) {
callback(err);
}
var message = {
urlOptions: urlOptions
};
message.error = err || 'undefined';
message.body = body || 'undefined';

@@ -190,4 +215,7 @@ if (response && response.statusCode) {

}
if (response && response.statusMessage) {
message.statusMessage = response.statusMessage;
}
if (response && response.statusCode >= 500 && retry > 0) {
if (response && response.statusCode >= 500 && retry > 0 ) {
log.debug(log.defaultContext(), 'making a retry attempt to url : ' + urlOptions.url);

@@ -198,2 +226,14 @@ makeRESTCalls(urlOptions, retry - 1, callback);

// now it will be message.body
if (message.statusCode >= 400) {
let err;
try {
err = JSON.parse(message.body);
if (err.error) {
err = err.error;
}
} catch (ex) {
err = message;
}
return callback(err);
}
callback(null, message);

@@ -203,34 +243,3 @@ }

}
/**
* Custom Function calling EVF Models
* @param {Object} options Options
* @param {Object} flowObject FlowObject
* @param {Object} message Message
* @param {Object} process Process-Instance
* @param {Function} done Callback
*/
function evaluateCustomImplementation(options, flowObject, message, process, done) {
var method = flowObject.formData.method;
var value = flowObject.formData.json;
var attachedModelName = process._processVariables._attachedModelName;
var attachedModel = loopback.getModel(attachedModelName, options);
var attachedInstanceId = process._processVariables._attachedModelInstanceId;
// TODO : separate Id and put try catch to save the server from crashing in case of invalid id
attachedModel.findById(JSON.parse(attachedInstanceId), options, function callback(err, instance) {
if (err) {
return done(err);
}
var data = {};
data[method] = value;
if (instance._version) {
data._version = instance._version;
}
instance.updateAttributes(data, options, function updateMI(err) {
done(err, message);
});
});
}
/**

@@ -243,27 +252,33 @@ * OE Connector for Workflow Engine

* @param {Function} done Callback
* @returns {void}
*/
function evaluateOEConnector(options, flowObject, message, process, done) {
var modelName = evaluateProp(flowObject.props.model, message, process, options);
// var modelName = flowObject.props.model;
var operation = flowObject.props.method;
var model = loopback.getModel(modelName, options);
var id;
var data;
if (operation === 'create') {
data = evaluateJSON(flowObject.props.data, message, process, options);
model.create(data, options, function createMI(err, res) {
if (err) {
log.error(options, err);
return done(null, err);
}
return done(null, res.toObject());
try {
var model = loopback.getModel(modelName, options);
} catch (err) {
log.error(options, err);
return done(null, {
error: err
});
} else if (operation === 'read') {
// id = evaluateProp(flowObject.props.modelId, message, process, options);
var filter = evaluateJSON(flowObject.props.filter, message, process, options);
model.find(filter, options, function fetchMI(err, res) {
}
var data = flowObject.props.data;
if (operation && model) {
data = evaluateJSON(data, message, process, options);
model[operation](data[0], options, function evalCB(err, res) {
if (err) {
log.error(options, err);
return done(null, err);
return done(null, {
error: err
});
}
var result = res;
if (result && typeof result === 'object' && result.constructor.name !== 'Array') {
if (typeof result.toObject !== 'undefined') {
return done(null, result.toObject());
}
return done(null, result);
}
var _res = [];

@@ -275,56 +290,7 @@ for (var i = 0; i < res.length; i++) {

});
} else if (operation === 'update') {
id = evaluateProp(flowObject.props.modelId, message, process, options);
data = evaluateJSON(flowObject.props.data, message, process, options);
data.id = id;
model.upsert(data, options, function updateMI(err, res) {
if (err) {
log.error(options, err);
return done(null, err);
}
return done(null, res.toObject());
});
} else if (operation === 'delete') {
id = evaluateProp(flowObject.props.modelId, message, process, options);
var version = evaluateProp(flowObject.props.modelVersion, message, process, options);
model.deleteWithVersion(id, version, options, function deleteMI(err, res) {
if (err) {
log.error(options, err);
return done(null, err);
}
return done(null, res);
});
}
return;
}
function evaluateJSON(data, incomingMsg, process, options) {
var sandbox = {
msg: incomingMsg,
pv: function pv(name) {
if (name === 'accessToken') {
return options.accessToken;
}
var val = process._processVariables[name];
if (typeof val === 'undefined' && process._parentProcessVariables) {
val = process._parentProcessVariables[name];
}
return val;
},
data: data,
_output: null
};
var script = '_output = ' + data;
// eslint-disable-next-line
var context = new vm.createContext(sandbox);
try {
var compiledScript = new vm.Script(script);
compiledScript.runInContext(context, { timeout: 1000 });
} catch (e) {
log.error(options, e);
return e;
}
return sandbox._output;
}
function evaluateProp(data, incomingMsg, process, options) {

@@ -331,0 +297,0 @@ // check if prop needs to be evaluated

@@ -52,2 +52,5 @@ /**

};
if (processDef.bpmndataId) {
subProcessDef.bpmndataId = processDef.bpmndataId;
}
delete (flowObject.processDefinition);

@@ -54,0 +57,0 @@

@@ -39,2 +39,7 @@

},
"bpmndata": {
"type": "belongsTo",
"model": "bpmndata",
"foreignKey" : "bpmndataId"
},
"workflowDefinition": {

@@ -41,0 +46,0 @@ "type": "belongsTo",

@@ -154,3 +154,3 @@ /**

for (var i in tokens) {
if (tokens[i].name === taskObj.name) {
if (Object.prototype.hasOwnProperty.call(tokens, i) && tokens[i].name === taskObj.name) {
token = tokens[i];

@@ -231,75 +231,84 @@ }

processDefinitionInstance, self, options);
for (var i in nextFlowObjects) {
if (Object.prototype.hasOwnProperty.call(nextFlowObjects, i)) {
var obj = nextFlowObjects[i];
var meta;
if (message && message.error) {
let failure = {};
var props = Object.getOwnPropertyNames(message.error);
for (let i = 0; i < props.length; i++) {
failure[props[i]] = message.error[props[i]];
}
delta.setTokenToFail(flowObjectToken.id, failure);
} else {
for (var i in nextFlowObjects) {
if (Object.prototype.hasOwnProperty.call(nextFlowObjects, i)) {
var obj = nextFlowObjects[i];
var meta;
if (obj.isParallelGateway) {
meta = {
type: 'ParallelGateway',
gwId: obj.bpmnId
};
} else if (obj.isAttachedToEventGateway) {
meta = {
type: 'EventGateway',
tokensToInterrupt: obj.attachedFlowObjects
};
}
if (obj.isParallelGateway) {
meta = {
type: 'ParallelGateway',
gwId: obj.bpmnId
};
} else if (obj.isAttachedToEventGateway) {
meta = {
type: 'EventGateway',
tokensToInterrupt: obj.attachedFlowObjects
};
}
var token = processTokens.createToken(obj.name, obj.bpmnId, message, meta);
var token = processTokens.createToken(obj.name, obj.bpmnId, message, meta);
if (obj.isParallelGateway) {
delta.setPGSeqsToExpect(obj.bpmnId, obj.expectedInFlows);
delta.setPGSeqToFinish(obj.bpmnId, obj.attachedSeqFlow, token.id);
}
if (obj.isParallelGateway) {
delta.setPGSeqsToExpect(obj.bpmnId, obj.expectedInFlows);
delta.setPGSeqToFinish(obj.bpmnId, obj.attachedSeqFlow, token.id);
}
if (obj.isMultiInstanceLoop) {
try {
if (obj.hasCollection) {
var collection = sandbox.evaluateAccessExpression(options, obj.collection, message, self);
if (typeof collection === 'undefined') {
throw new Error('collection in multi instance is undefined.');
if (obj.isMultiInstanceLoop) {
try {
if (obj.hasCollection) {
var collection = sandbox.evaluateExpression(options, obj.collection, message, self);
if (typeof collection === 'undefined') {
throw new Error('collection in multi instance is undefined.');
}
if (collection.constructor.name !== 'Array') {
throw new Error('defined collection in multi instance is not an arary');
}
token.nrOfInstances = collection.length;
token.collection = collection;
token.elementVariable = obj.elementVariable;
} else if (obj.hasLoopCardinality) {
var loopcounter = sandbox.evaluate$Expression(options, obj.loopcounter, message, self);
token.nrOfInstances = Number(loopcounter);
} else {
throw new Error('invalid multi instance specification error');
}
if (collection.constructor.name !== 'Array') {
throw new Error('defined collection in multi instance is not an arary');
}
token.nrOfInstances = collection.length;
token.collection = collection;
token.elementVariable = obj.elementVariable;
} else if (obj.hasLoopCardinality) {
var loopcounter = sandbox.evaluate$Expression(options, obj.loopcounter, message, self);
token.nrOfInstances = Number(loopcounter);
} catch (err) {
log.error(options, err);
return next(err);
}
if (obj.isSequential) {
token.nrOfActiveInstances = 1;
token.isSequential = true;
} else {
throw new Error('invalid multi instance specification error');
token.nrOfActiveInstances = token.nrOfInstances;
token.isParallel = true;
}
} catch (err) {
log.error(options, err);
return next(err);
}
if (obj.isSequential) {
token.nrOfActiveInstances = 1;
token.isSequential = true;
} else {
token.nrOfActiveInstances = token.nrOfInstances;
token.isParallel = true;
if (obj.hasCompletionCondition) {
token.hasCompletionCondition = true;
token.completionCondition = obj.completionCondition;
}
token.nrOfCompleteInstances = 0;
}
if (obj.hasCompletionCondition) {
token.hasCompletionCondition = true;
token.completionCondition = obj.completionCondition;
log.debug(options, token);
if (token === null) {
log.error(options, 'Invalid token');
return next(new Error('Invalid token'));
}
token.nrOfCompleteInstances = 0;
delta.addToken(token);
}
log.debug(options, token);
if (token === null) {
log.error(options, 'Invalid token');
return next(new Error('Invalid token'));
}
delta.addToken(token);
}
delta.setTokenToRemove(flowObjectToken.id);
}
delta.setTokenToRemove(flowObjectToken.id);

@@ -312,3 +321,3 @@ // add boundary event tokens to interrupt for the currentFlowObject that we are completing, if any

var boundaryEventToken = self.getTokenByFlowObject(boundaryEvent);
if (boundaryEventToken && self.isPending(boundaryEventToken)) {
if (boundaryEventToken && boundaryEventToken.status === 'pending') {
delta.setTokenToInterrupt(boundaryEventToken.id);

@@ -453,3 +462,3 @@ }

}).forEach(function continueWorkflow(tokenId) {
self.reemit(tokens[tokenId], options);
self.reemit(tokens[tokenId], options, null);
});

@@ -594,7 +603,7 @@ };

/**
* Finding a processToken if the name of the flow Object is given
* @param {Object} flowObject FlowObject
* @return {Object} Process-Token
*/
/**
* Finding a processToken if the name of the flow Object is given
* @param {Object} flowObject FlowObject
* @return {Object} Process-Token
*/
ProcessInstance.prototype.findToken = function findToken(flowObject) {

@@ -605,3 +614,3 @@ var self = this;

for (var key in self._processTokens) {
if (self._processTokens[key][name] === flowObject[name]) {
if (Object.prototype.hasOwnProperty.call(self._processTokens, key) && self._processTokens[key][name] === flowObject[name]) {
token = self._processTokens[key];

@@ -672,7 +681,7 @@ }

ProcessInstance.prototype.getTokenByFlowObject = function getFlowObjectByToken(flowobject) {
ProcessInstance.prototype.getTokenByFlowObject = function getTokenByFlowObject(flowobject) {
var self = this;
var processTokens = self._processTokens;
for (var i in processTokens) {
if (processTokens[i].bpmnId === flowobject.bpmnId) {
if (Object.prototype.hasOwnProperty.call(processTokens, i) && processTokens[i].bpmnId === flowobject.bpmnId && processTokens[i].status === 'pending') {
return processTokens[i];

@@ -749,2 +758,249 @@ }

};
ProcessInstance.prototype.revertProcessToPending = function revertProcessToPending(tokenId, variables, options, next) {
var self = this;
var delta = new StateDelta();
variables = variables || [];
Object.keys(variables).forEach(function addToDelta(key) {
delta.addProcessVariable(key, variables[key]);
});
delta.setTokenToPending(tokenId);
self.commit(options, delta, function commit(err, instance) {
if (err) {
log.error(options, err);
return next(err);
}
return next(null, instance);
});
};
ProcessInstance.prototype.failureTokens = function failureTokens(options, next) {
var inst = this;
// backward compatibility in ci
Object.values = function values(obj) {
return Object.keys(obj).map( key => {
return obj[key];
});
};
var tokens = Object.values(inst._processTokens).filter( token => {
return token.status === 'failed';
});
return next(null, tokens);
};
ProcessInstance.retryAll = function retryAll(filter, data, options, next) {
filter = filter || {};
data = data || {};
ProcessInstance.find(filter, options, function fetchPDs(err, insts) {
if (err) {
log.error(options, err);
return next(err);
}
// backward compatibility in ci
Object.values = function values(obj) {
return Object.keys(obj).map( key => {
return obj[key];
});
};
var dummyCb = function dummyCb() {};
insts.forEach(inst => {
Object.values(inst._processTokens).filter(token => {
return token.status === 'failed';
}).forEach(token => {
inst.retry(token.id, data, options, dummyCb);
});
});
return next(null, {
emitted: true
});
});
};
ProcessInstance.failures = function failures(filter, options, next) {
filter = filter || {};
if (filter.bpmnData === true) {
filter.include = { 'processDefinition': 'bpmndata' };
}
ProcessInstance.find(filter, options, function fetchPDs(err, insts) {
if (err) {
log.error(options, err);
return next(err);
}
if (filter.bpmnData === true) {
insts = insts.map(inst => {
inst.bpmndata = inst.toObject().processDefinition.bpmndata;
delete inst.processDefinition;
return inst;
});
}
delete filter.bpmndata;
// backward compatibility in ci
Object.values = function values(obj) {
return Object.keys(obj).map( key => {
return obj[key];
});
};
return next(null, insts.filter( inst => {
return Object.values(inst._processTokens).filter( token => {
return token.status === 'failed';
}).length > 0;
}));
});
};
ProcessInstance.prototype.retry = function retry(tokenId, data, options, next) {
var self = this;
var { processVariables } = data;
var tokens = self._processTokens;
// backward compatibility in ci
Object.values = function values(obj) {
return Object.keys(obj).map( key => {
return obj[key];
});
};
var filteredTokens = Object.values(tokens).filter( t => {
return t.id === tokenId;
});
if (filteredTokens.length !== 1) {
let err = new Error('TokenId is incorrect.');
log.error(options, err);
return next(err);
}
var token = filteredTokens[0];
if (token.status !== 'failed') {
let err = new Error('Token is not in failed status.');
// status code 428 for Precondition Required
err.statusCode = 428;
log.error(options, err);
return next(err);
}
return new Promise((resolve, reject) => {
self.revertProcessToPending(token.id, processVariables, options, function cb(err, instance) {
if (err) {
return reject(err);
}
resolve(instance);
});
})
.then(process => {
// updated process is available with latest process variables and pending state
return new Promise((resolve, reject) => {
process.reemit(token, options, function cb(err) {
if (err) {
return reject(err);
}
return resolve({
'emitted': true
});
});
});
})
.then(function done(response) {
return next(null, response);
})
.catch(function errCb(err) {
log.error(options, err);
return next(err);
});
};
ProcessInstance.remoteMethod('failures', {
accessType: 'READ',
accepts: {
arg: 'filter',
type: 'object',
http: {
source: 'query'
},
description: 'Filter defining fields, where, include, order, offset'
},
description: 'Find all failed process instances.',
http: {
verb: 'get'
},
isStatic: true,
returns: {
type: 'object',
root: true
}
});
ProcessInstance.remoteMethod('retryAll', {
accessType: 'WRITE',
accepts: [{
arg: 'filter',
type: 'object',
http: {
source: 'query'
},
description: 'Filter defining fields, where, include, order, offset'
}, {
arg: 'data',
type: 'object',
http: {
source: 'body'
},
description: 'Update Process Variables'
}],
description: 'Retry all failed tokens in fetched Process Instances.',
http: {
verb: 'put',
path: '/retryAll'
},
isStatic: true,
returns: {
type: 'object',
root: true
}
});
ProcessInstance.remoteMethod('failureTokens', {
accessType: 'READ',
description: 'Find failed tokens for a particular process instances',
http: {
verb: 'get',
path: '/failureTokens'
},
isStatic: false,
returns: {
type: 'object',
root: true
}
});
ProcessInstance.remoteMethod('retry', {
accessType: 'WRITE',
accepts: [{
arg: 'tokenId',
type: 'string',
http: {
source: 'path'
},
description: 'Failed token id'
}, {
arg: 'data',
type: 'object',
http: {
source: 'body'
},
description: 'Update Process Variables'
}],
description: 'Retry a failed Task in a failed Process Instance.',
http: {
verb: 'put',
path: '/retry/:tokenId'
},
isStatic: false,
returns: {
type: 'object',
root: true
}
});
};

@@ -69,2 +69,7 @@

},
"passive-wait" : {
"type" : "boolean",
"default" : false,
"required" : false
},
"_status" : {

@@ -71,0 +76,0 @@ "type" : "string",

@@ -30,2 +30,7 @@ /**

Delta.prototype.setTokenToFail = function setTokenToFail(tokenId, error) {
this.tokenToFail = tokenId;
this.error = error;
};
Delta.prototype.addToken = function addToken(token) {

@@ -39,2 +44,6 @@ this.tokens.push(token);

Delta.prototype.setTokenToPending = function setTokenToPending(tokenId) {
this.tokensToPending = [tokenId];
};
Delta.prototype.setTokenToTerminate = function setTokenToTerminate(tokenId) {

@@ -127,3 +136,5 @@ this.tokenToTerminate = tokenId;

Delta.prototype.apply = function apply(zInstance, options) {
var instance = _.cloneDeep(zInstance.toObject(true));
// check why this failes with error items must be an array
// var instance = _.cloneDeep(zInstance.toObject(true));
var instance = JSON.parse(JSON.stringify(zInstance.toObject(true)));
var tokens = instance._processTokens;

@@ -145,4 +156,3 @@ var processVariables = instance._processVariables;

// Instance has been terminated by some event.
if (instance._status !== 'running') {
if (instance._status === 'interrupted') {
log.debug(log.defaultContext(), 'Trying to change state in an interrupted process.');

@@ -206,2 +216,10 @@ return null;

// reverting tokens to pending in case of retry
if (this.tokensToPending) {
this.tokensToPending.forEach( t => {
tokens[t].status = 'pending';
delete tokens[t].error;
});
}
if (setTocomplete) {

@@ -266,5 +284,25 @@ var res = this.applyTokens(tokens, synchronizeFlow);

updates['passive-wait'] = true;
// backward compatibility in ci
Object.values = function values(obj) {
return Object.keys(obj).map( key => {
return obj[key];
});
};
Object.values(updates._processTokens).forEach(token => {
if (token.bpmnId.indexOf('UserTask') !== 0) {
if (token.status === 'pending') {
updates['passive-wait'] = false;
}
}
});
if (processEnded || this.isForceEndToken) {
updates[status] = 'complete';
// passive wait can't be true if process is already complete
updates['passive-wait'] = false;
}
if (this.revertProcessToPending) {
updates[status] = 'pending';
}

@@ -282,2 +320,8 @@ return updates;

if (this.tokenToFail && tokens[this.tokenToFail]) {
var token = tokens[this.tokenToFail];
token.status = 'failed';
token.error = this.error;
token.endTime = new Date();
}
/**

@@ -318,3 +362,3 @@ * If token to remove is Parallel Gateway token, complete other parallel gateway tokens also * * * those which are waiting

// while updating boundary event, we might not be able to interrupt due to some other process, should never come though
log.error(log.defaultContext(), 'unable to interrupt token > ' + tokens[this.tokenToTerminate].name);
log.error(log.defaultContext(), 'unable to interrupt token > ' + tokens[tokenId].name);
continue;

@@ -332,3 +376,3 @@ }

for (var i in tokens) {
if (tokens[i].status === 'pending') {
if (Object.prototype.hasOwnProperty.call(tokens, i) && tokens[i].status === 'pending') {
tokens[i].status = 'interrupted';

@@ -342,3 +386,3 @@ tokens[i].endTime = new Date();

for (var i in tokens) {
if (tokenNames.indexOf(tokens[i].name) > -1) {
if (Object.prototype.hasOwnProperty.call(tokens, i) && tokenNames.indexOf(tokens[i].name) > -1) {
var tokenId = tokens[i].id;

@@ -345,0 +389,0 @@ if (tokens[tokenId] && tokens[tokenId].status !== 'pending') {

@@ -39,3 +39,9 @@ /**

this.status = 'pending';
if (typeof message !== 'undefined') {
if ( message instanceof Error ) {
this.message = {};
var props = Object.getOwnPropertyNames(message);
for (let i = 0; i < props.length; i++) {
this.message[props[i]] = message[props[i]];
}
} else if (typeof message !== 'undefined') {
this.message = message;

@@ -56,8 +62,1 @@ }

};
ProcessToken.prototype.updateMeta = function update(key, value) {
if (typeof this.meta === 'undefined') {
this.meta = {};
}
this.meta[key] = value;
};

@@ -12,2 +12,3 @@ /**

var loopback = require('loopback');
var logger = require('oe-logger');

@@ -65,3 +66,3 @@ var log = logger('Task');

} else if (finalCall === 1) {
// the user was found as a part of candidateUser, won't check for excluded Role [ inconsistencies have to resolved in bpmn itself ]
// the user was found as a part of candidateUser, won't check for excluded Role [ inconsistencies have to resolved in bpmn itself ]
resultData.push(instance);

@@ -74,3 +75,3 @@ continue;

} else if (finalCall === 1) {
// user is part of authorized roles
// user is part of authorized roles
resultData.push(instance);

@@ -83,6 +84,12 @@ continue;

} else if (finalCall === 1) {
// the user was found as a part of candidateUser, won't check for excluded Role [ inconsistencies have to resolved in bpmn itself ]
// the user was found as a part of candidateUser, won't check for excluded Role [ inconsistencies have to resolved in bpmn itself ]
resultData.push(instance);
continue;
} else {
// if the user was not excluded in any way
// and if candidateUsers, candidateRoles, &
// candidateGroups were not defined, assume it be candidate
if (candidateGroups.length === 0 && candidateRoles.length === 0 && candidateUsers.length === 0) {
resultData.push(instance);
}
continue;

@@ -96,9 +103,9 @@ }

if (candidateGroups.indexOf(group) !== -1 ) {
// group found
// group found
return 1;
} else if (excludedGroups.indexOf(group) !== -1) {
// no further check needed for excluded group
// no further check needed for excluded group
return -1;
}
// group match was unsuccessfully, look for role match
// group match was unsuccessfully, look for role match
return 0;

@@ -143,14 +150,13 @@ }

/**
* To be DEPRECATED soon, Please use /complete instead
* REST endpoint for completing User-Task
* @param {Object} message Message
* @param {Object} processVariables Process-Variables
* @param {Object} options Options
* @param {Function} next Callback
* @returns {void}
*/
/**
* To be DEPRECATED soon, Please use /complete instead
* REST endpoint for completing User-Task
* @param {Object} message Message
* @param {Object} processVariables Process-Variables
* @param {Object} options Options
* @param {Function} next Callback
* @returns {void}
*/
Task.prototype.completeTask = function completeTask(message, processVariables, options, next) {
var self = this;
if (self.status !== 'pending') {

@@ -175,5 +181,5 @@ return next(new Error('Task Already Completed'));

}
self.status = status;
self.save(options, function saveTask(saveError, instance) {
// self.status = status;
var updates = { 'status': status, '_version': self._version };
self.updateAttributes(updates, options, function saveTask(saveError, instance) {
if (err || saveError) {

@@ -189,12 +195,256 @@ log.error(options, err, saveError);

/**
* REST endpoint for completing User-Task
* @param {Object} data Process-Variables & Message data
* @param {Object} options Options
* @param {Function} next Callback
* @returns {void}
*/
Task.prototype.complete = function complete(data, options, next) {
var self = this;
var tname = self.name;
self.processInstance({}, options, function fetchProcessDef(err, process) {
if (err) {
log.error(options, err);
return next(err);
}
process.processDefinition({}, options, function fetchProcessDef(err, processDef) {
if (err) {
log.error(options, err);
return next(err);
}
var pdata;
var workflowInstanceId;
var WorkflowManager;
let taskObj = processDef.getFlowObjectByName(tname);
if (taskObj.isMultiMaker) {
// this task is a maker user task, so no need to have pv and msg and directly take obj as update
var updates = data;
pdata = {};
if (typeof data.pv !== 'undefined') {
pdata.pv = data.pv;
delete updates.pv;
}
if (typeof data.msg !== 'undefined') {
pdata.msg = data.msg;
delete updates.msg;
}
var ChangeWorkflowRequest = loopback.getModel('ChangeWorkflowRequest', options);
var modelName = process._processVariables._modelInstance._type;
var Model = loopback.getModel(modelName, options);
var modelId = process._processVariables._modelInstance._modelId;
Model.findById(modelId, options, function fetchCurrentInstance(err, currentInstance) {
if (err) {
log.error(options, err);
return next(err);
}
// if the change request was created on create operation ,
// currentInstance will be null which is fine
ChangeWorkflowRequest.find({
where: {
and: [{
modelName: modelName
}, {
modelId: modelId
}, {
status: 'pending'
}]
}
}, options, function fetchChangeModel(err, inst) {
if (err) {
log.error(options, err);
return next(err);
}
if (inst.length > 1) {
let err = new Error('Multiple instances found with same id in Change Workflow Request');
log.error(options, err);
return next(err);
} else if (inst.length === 0) {
// no instance found in change request model
let err = new Error('change_request_update failed - no instance found');
log.error(options, err);
return next(err);
}
var instObj = inst[0].toObject();
var operation = instObj.operation;
var instx = JSON.parse(JSON.stringify(instObj.data));
for (let key in updates) {
if (Object.prototype.hasOwnProperty.call(updates, key)) {
var val = updates[key];
instx[key] = val;
}
}
var modifiers = inst[0]._modifiers || [];
modifiers.push(options.ctx.username);
instx._modifiedBy = options.ctx.username;
Model._makerValidate(Model, operation, data, currentInstance, options, function _validateCb(err, _data) {
if (err) {
log.error(options, err);
return next(err);
}
log.debug(options, 'Instance has been validated during maker checker creation');
inst[0].updateAttributes({
data: instx,
_modifiers: modifiers
}, options, function updateCM(err, res) {
if (err) {
log.error(options, err);
return next(err);
}
// process._processVariables._modelInstance = instx;
var xdata = {};
xdata.pv = pdata.pv || {};
xdata.pv._modifiers = modifiers;
xdata.pv._modelInstance = instx;
xdata.msg = pdata.msg;
return self.complete_(xdata, options, next);
});
});
});
});
} else if (taskObj.isChecker) {
// do handling of finalize transaction first, only then complete the task
// user task wont complete till finalize transaction is successful
WorkflowManager = loopback.getModel('WorkflowManager', options);
workflowInstanceId = process._processVariables._workflowInstanceId;
if ( typeof data.__action__ === 'undefined' ) {
let err = new Error('__action__ not provided. Checker enabled task requires this field.');
log.error(options, err);
return next(err);
}
let validActArr = [ 'approved', 'rejected' ];
if ( taskObj.stepVariables && taskObj.stepVariables.__action__ ) {
validActArr = validActArr.concat(taskObj.stepVariables.__action__);
}
let isValid = ( validActArr.indexOf(data.__action__) > -1 );
if (!isValid) {
let err = new Error('Provided action is not valid. Possible valid actions : ' + JSON.stringify(validActArr));
log.error(options, err);
return next(err);
}
pdata = {
pv: {}
};
if (typeof data.pv !== 'undefined') {
pdata.pv = data.pv;
}
if (typeof data.msg !== 'undefined') {
pdata.msg = data.msg;
}
pdata.pv.__action__ = data.__action__;
ChangeWorkflowRequest = loopback.getModel('ChangeWorkflowRequest', options);
ChangeWorkflowRequest.find({
where: {
'workflowInstanceId': workflowInstanceId
}
}, options, function fetchRM(err, requests) {
if (err) {
log.error(options, 'unable to find request to end', err);
return next(err);
}
if (requests.length === 0) {
let errInvalidid;
errInvalidid = new Error('No corresponding workflow request found for verification update the Maker-Checker Process.');
log.error(options, errInvalidid);
return next(errInvalidid);
}
if (requests.length > 1) {
let errInvalidid;
errInvalidid = new Error('Multiple workflow requests found for verification update the Maker-Checker Process.');
log.error(options, errInvalidid);
return next(errInvalidid);
}
var request = requests[0];
let _verifiedBy = 'workflow-system';
if (options.ctx && options.ctx.username) {
_verifiedBy = options.ctx.username;
}
let updates = {
_verifiedBy: _verifiedBy
};
request.updateAttributes(updates, options, function updateVerifiedByField(err, inst) {
if (err) {
log.error(options, 'error in updating change workflow instance verifiedBy field', err);
return next(err);
}
log.debug(options, 'updated verified by field in change request by checker');
return self.complete_(pdata, options, next);
});
});
} else if (taskObj.isCheckerAutoFinalize) {
// do handling of finalize transaction first, only then complete the task
// user task wont complete till finalize transaction is successful
WorkflowManager = loopback.getModel('WorkflowManager', options);
workflowInstanceId = process._processVariables._workflowInstanceId;
if ( typeof data.__action__ === 'undefined' ) {
let err = new Error('__action__ not provided. Checker enabled task requires this field.');
log.error(options, err);
return next(err);
}
let validActArr = [ 'approved', 'rejected' ];
if ( self.stepVariables && self.stepVariables.__action__ ) {
validActArr = validActArr.concat(self.stepVariables.__action__);
}
let isValid = ( validActArr.indexOf(data.__action__) > -1 );
if (!isValid) {
let err = new Error('Provided action is not valid. Possible valid actions : ' + JSON.stringify(validActArr));
log.error(options, err);
return next(err);
}
var postData = {
'workflowInstanceId': workflowInstanceId,
'status': data.__action__
};
if (process._processVariables._updates) {
postData.updates = process._processVariables._updates;
}
if (process._processVariables._maker_checker_impl === 'v2') {
postData.version = 'v2';
}
pdata = {
pv: {}
};
if (typeof data.pv !== 'undefined') {
pdata.pv = data.pv;
}
if (typeof data.msg !== 'undefined') {
pdata.msg = data.msg;
}
pdata.pv.__action__ = data.__action__;
if (['approved', 'rejected'].indexOf(data.__action__) > -1 ) {
WorkflowManager.endAttachWfRequest(postData, options, function completeMakerCheckerRequest(err, res) {
if (err) {
log.error(err);
return next(err);
}
return self.complete_(pdata, options, next);
});
} else {
return self.complete_(pdata, options, next);
}
} else {
return self.complete_(data, options, next);
}
});
});
};
/**
* REST endpoint for completing User-Task
* @param {Object} data Process-Variables & Message data
* @param {Object} options Options
* @param {Function} next Callback
* @returns {void}
*/
Task.prototype.complete_ = function complete_(data, options, next) {
var self = this;
var message = {};

@@ -229,5 +479,5 @@ if (data && data.msg) {

}
self.status = status;
self.save(options, function saveTask(saveError, instance) {
// self.status = status;
var updates = {'status': status, '_version': self._version};
self.updateAttributes(updates, options, function saveTask(saveError, instance) {
if (err || saveError) {

@@ -244,9 +494,9 @@ log.error(options, err, saveError);

/**
* REST endpoint for completing User-Task
* @param {Object} data Process-Variables & Message data
* @param {Object} options Options
* @param {Function} next Callback
* @returns {void}
*/
/**
* REST endpoint for completing User-Task
* @param {Object} data Process-Variables & Message data
* @param {Object} options Options
* @param {Function} next Callback
* @returns {void}
*/
Task.prototype.delegate = function delegate(data, options, next) {

@@ -331,3 +581,3 @@ var self = this;

http: {
verb: 'post'
verb: 'put'
},

@@ -334,0 +584,0 @@ isStatic: false,

@@ -50,2 +50,14 @@

},
"dueDate" : {
"type" : "date",
"required" : false
},
"followUpDate" : {
"type" : "date",
"required" : false
},
"priority" : {
"type" : "string",
"required" : false
},
"formKey" : {

@@ -62,2 +74,6 @@ "type" : "string",

"required" : false
},
"stepVariables" : {
"type" : "object",
"required" : false
}

@@ -64,0 +80,0 @@ },

@@ -82,2 +82,3 @@ /**

}
workflowDef.id = workflowDefId;

@@ -109,3 +110,3 @@ // TODO need to check if all the instances for the process definition are ended

if (!collaborationDef) {
return createProcessDefinition(workflowDefId, ctx.options, workflowDef.name, processDefinitions[0], {}, next);
return createProcessDefinition(workflowDef, ctx.options, workflowDef.name, processDefinitions[0], {}, next);
}

@@ -139,4 +140,4 @@

function validateExternalDefinition(options, processDefinitions, participant, callback) {
for (var i in processDefinitions) {
if (participant.processRef === processDefinitions[i].bpmnId) {
for (let i in processDefinitions) {
if (Object.prototype.hasOwnProperty.call(processDefinitions, i) && participant.processRef === processDefinitions[i].bpmnId) {
return callback();

@@ -182,3 +183,3 @@ }

}
createProcessDefinition(workflowDefId, options, name, processDefinition, messageFlowsBySrcProcess, callback);
createProcessDefinition(workflowDef, options, name, processDefinition, messageFlowsBySrcProcess, callback);
}

@@ -188,3 +189,3 @@

* Create Process definition
* @param {Object} workflowDefId WorkflowDefId
* @param {Object} workflowDef WorkflowDef
* @param {Object} options Options

@@ -196,28 +197,11 @@ * @param {String} name Workflow-Definition Name

*/
function createProcessDefinition(workflowDefId, options, name, processDefinition, messageFlowsBySrcProcess, callback) {
// var processDef = {
// 'name': name,
// 'parsedDef': processDefinition,
// 'workflowDefinitionId': workflowDefId
// };
// var ProcessDefinition = WorkflowDefinition.app.models.ProcessDefinition;
// var query = [{'name': name}, {'workflowDefinitionId': workflowDefId}];
// ProcessDefinition.find({'where': {'and': query}}, options, function cb(fetchErr, res) {
// if (!fetchErr) {
// var processDefVersion = res[0]._version;
// processDef._version = processDefVersion;
// processDef.messageFlowsBySrcProcess = messageFlowsBySrcProcess;
// ProcessDefinition.upsert(processDef, options, function createPD(err, def) {
// if (err && err.message === 'Duplicate entry for ' + ProcessDefinition.name) {
// return callback(null, def);
// }
// return callback(err);
// });
// }
// });
function createProcessDefinition(workflowDef, options, name, processDefinition, messageFlowsBySrcProcess, callback) {
var processDef = {
'name': name,
'parsedDef': processDefinition,
'workflowDefinitionId': workflowDefId
'workflowDefinitionId': workflowDef.id
};
if (workflowDef.bpmndataId) {
processDef.bpmndataId = workflowDef.bpmndataId;
}
processDef.messageFlowsBySrcProcess = messageFlowsBySrcProcess;

@@ -224,0 +208,0 @@ var ProcessDefinition = WorkflowDefinition.app.models.ProcessDefinition;

@@ -40,2 +40,7 @@

"model": "ProcessDefinition"
},
"bpmnData": {
"type": "belongsTo",
"model": "bpmndata",
"foreignKey" : "bpmndataId"
}

@@ -42,0 +47,0 @@ },

@@ -23,29 +23,33 @@ /**

WorkflowInstance.observe('before save', function afterSaveWI(ctx, next) {
var workflowDefinitionName = ctx.instance.workflowDefinitionName;
var WorkflowDefinition = loopback.getModel('WorkflowDefinition', ctx.options);
if (ctx.isNewInstance) {
var workflowDefinitionName = ctx.instance.workflowDefinitionName;
var WorkflowDefinition = loopback.getModel('WorkflowDefinition', ctx.options);
WorkflowDefinition.find({
'where': {'and': [
WorkflowDefinition.find({
'where': {'and': [
{'name': workflowDefinitionName},
{'latest': true}
]
}
}, ctx.options, function fetchWD(err, wdefns) {
if (err) {
log.error(ctx.options, err);
return next(err);
} else if (wdefns.length === 0) {
var errx = new Error('No latest workflow definition found.');
log.error(ctx.options, errx);
return next(errx);
} else if (wdefns.length > 1) {
var errxx = new Error('Multiple latest workflow definitions found with the same name.');
log.error(ctx.options, errxx);
return next(errxx);
}
var inst = wdefns[0];
var id = inst.id;
ctx.instance.setAttribute('workflowDefinitionId', id);
]
}
}, ctx.options, function fetchWD(err, wdefns) {
if (err) {
log.error(ctx.options, err);
return next(err);
} else if (wdefns.length === 0) {
var errx = new Error('No latest workflow definition found.');
log.error(ctx.options, errx);
return next(errx);
} else if (wdefns.length > 1) {
var errxx = new Error('Multiple latest workflow definitions found with the same name.');
log.error(ctx.options, errxx);
return next(errxx);
}
var inst = wdefns[0];
var id = inst.id;
ctx.instance.setAttribute('workflowDefinitionId', id);
next();
});
} else {
next();
});
}
});

@@ -258,3 +262,3 @@

for (var i in processes) {
if (processes[i].processDefinitionBpmnId === processDefId) {
if (Object.prototype.hasOwnProperty.call(processes, i) && processes[i].processDefinitionBpmnId === processDefId) {
processes[i]._recieveMessage(options, flowObjectId, message);

@@ -314,4 +318,8 @@ passFlag = true;

}
workflowInstance.setAttribute('status', 'terminated');
workflowInstance.save(options, function saveWI(err, res) {
let updates = {
_version: workflowInstance._version,
status: 'terminated'
};
// workflowInstance.setAttribute('status', 'terminated');
workflowInstance.updateAttributes(updates, options, function saveWI(err, res) {
if (err) {

@@ -318,0 +326,0 @@ log.error(options, 'Unable to update status to terminate');

@@ -17,5 +17,7 @@ /**

var applyMakerCheckerMixin = require('./../mixins/maker-checker-mixin');
var applyMakerCheckerMixinV2 = require('./../mixins/maker-checker-mixin-v2');
var loopback = require('loopback');
var helper = require('./../mixins/lib/maker-checker-helper.js');
var helperv2 = require('./../mixins/lib/maker-checker-helper-v2.js');

@@ -43,11 +45,2 @@ var baseWorkflowCallActivity = 'BaseWorkflowTemplate';

// function WorkflowAttachmentError(message, mappings, attachmentErrors) {
// this.name = 'WorkflowAttachementError';
// this.message = message || '';
// this.mappings = mappings;
// this.attachmentErrors = attachmentErrors;
// }
// WorkflowAttachmentError.prototype = Object.create(Error.prototype);
WorkflowManager.attachWorkflow = function attachWorkflow(data, options, cb) {

@@ -155,3 +148,6 @@ var app = WorkflowManager.app;

var operation = data.operation;
var wfDependent = data.wfDependent;
var wfDependent = true;
if (typeof data === 'object' && typeof data.wfDependent === 'boolean') {
wfDependent = data.wfDependent;
}
var Model = loopback.getModel(modelName, options);

@@ -171,2 +167,6 @@ var actualModelName = Model.modelName;

};
// to make an entry in workflow mapping model for maker-checker v2
if (data.version && data.version === 'v2') {
instance.version = 'v2';
}
if (!workflowBody || typeof workflowBody === 'undefined' || (workflowBody && !workflowBody.workflowDefinitionName)) {

@@ -211,3 +211,7 @@ createMappingscb();

}
applyMakerCheckerMixin(Model);
if (mapping.version === 'v2') {
applyMakerCheckerMixinV2(Model);
} else {
applyMakerCheckerMixin(Model);
}
log.debug(options, 'WorkflowMapping successfully created.');

@@ -269,4 +273,2 @@ mappingsList.push(mapping);

WorkflowManager.detachWorkflow = detachWorkflow;
WorkflowManager.endAttachWfRequest = endAttachWfRequest;

@@ -276,26 +278,2 @@

function detachWorkflow(id, options, cb) {
var app = WorkflowManager.app;
if (!id) {
cb(new Error('id parameter is required to dettachWorkflow'));
return;
}
app.models.WorkflowMapping.findById(id, options, function fetchWM(err, instance) {
if (err) {
log.error(err);
return cb(err);
}
instance.destroy(options, function destoryWM(err, res) {
if (err) {
err = new Error('Unable to dettach Workflow.');
log.error(err);
return cb(err);
}
cb(null, res);
});
});
}
function detachWorkflowWithVersion(id, version, options, cb) {

@@ -351,4 +329,7 @@ var app = WorkflowManager.app;

}
helper._endWorkflowRequest('oe-workflow', data.workflowInstanceId, data.status, updates, app, options, cb);
if (data.version && data.version === 'v2') {
helperv2._endWorkflowRequest('oe-workflow', data.workflowInstanceId, data.status, updates, app, options, cb);
} else {
helper._endWorkflowRequest('oe-workflow', data.workflowInstanceId, data.status, updates, app, options, cb);
}
}

@@ -500,23 +481,2 @@

WorkflowManager.remoteMethod('detachWorkflow', {
http: {
path: '/workflows/:id',
verb: 'delete'
},
description: 'Detach OE workflow from a Model.',
accepts: [{
arg: 'id',
type: 'string',
required: true,
http: {
source: 'path'
}
}],
returns: {
arg: 'response',
type: 'object',
root: true
}
});
WorkflowManager.remoteMethod('detachWorkflowWithVersion', {

@@ -523,0 +483,0 @@ http: {

@@ -33,2 +33,7 @@ {

},
"version" : {
"type": "string",
"required": true,
"default": "v1"
},
"wfDependent" : {

@@ -35,0 +40,0 @@ "type": "boolean",

@@ -67,2 +67,3 @@ /**

*/
/**
WorkflowSignal.send = function send(signalRef, processInstanceId, options, next) {

@@ -108,2 +109,3 @@ if (!signalRef || !processInstanceId) {

};
***/
};
{
"name": "oe-workflow",
"version": "1.0.0",
"version": "1.4.0",
"main": "server/server.js",

@@ -9,3 +9,3 @@ "scripts": {

"precoverage": "npm install --no-optional",
"test": "./node_modules/.bin/mocha"
"test": "./node_modules/.bin/mocha"
},

@@ -21,2 +21,3 @@ "dependencies": {

"chai": "^3.4.1",
"chai-datetime": "^1.5.0",
"chai-things": "^0.2.0",

@@ -23,0 +24,0 @@ "chalk": "^1.1.1",

@@ -13,5 +13,11 @@ /**

var log = logger('workflow-recovery.boot');
var recoveryConfig = require('../wf-recovery-config.json');
module.exports = function attachWorkFlows(app) {
var ProcessInstance = app.models.ProcessInstance;
var workflowMonitor = app.models.WorkflowMonitor;
var BATCH_SIZE = 500;
var BATCH_TIME = 100000;
var updateInterval = recoveryConfig.updateInterval;
var options = {

@@ -22,17 +28,94 @@ ctx: {},

};
ProcessInstance.find({
where: {
'_status': 'running'
}
}, options, function fetchPendingPI(err, processes) {
// Trying to create an entry in the workflow monitor model
// This will ensure that this node will run the boot script and does the
// recovery process of all the process instances.
// If error in creating the entry because it is already existing , we will
// just return and will not continue to the boot recovery process.
workflowMonitor.create({'id': 'node'}, options, function acquireLock(err, inst) {
if (err) {
log.error(options, err);
return;
// Check the error
}
for (var i = 0; i < processes.length; i++) {
var process = processes[i];
process.recover();
}
ProcessInstance.find({
where: {
'and': [{
'_status': 'running'
}, {
'passive-wait': false
}]
},
fields: {
'id': true
}
}, options, function fetchPendingPI(err, processes) {
if (err) {
log.error(options, err);
return;
}
var buildFilter = function buildFilter(start, end) {
let filter = {
where: {
or: []
}
};
for (let idx = start; idx < end; idx++) {
filter.where.or.push({
id: processes[idx].id
});
}
return filter;
};
var NUM_PROCESSES = processes.length;
var iter = 0;
var interval = setInterval(function cb() {
let start = iter * BATCH_SIZE;
let end = (iter + 1) * BATCH_SIZE;
if (end >= NUM_PROCESSES) {
clearInterval(interval);
end = NUM_PROCESSES;
}
let filter = buildFilter(start, end);
ProcessInstance.find(filter, options, function fetchPendingPI(err, processes) {
if (err) {
log.error(options, err);
return;
}
for (var i = 0; i < processes.length; i++) {
var process = processes[i];
var processVersion = process._version;
setTimeout((function setTimeoutCb(process, ProcessInstance, options, processVersion) {
return function wrappedFn() {
ProcessInstance.find({'where': {'id': process.id}}, options, function fetchPI(err, pInstance) {
if (err) {
log.error(options, err);
return;
}
if (processVersion === pInstance[0]._version) {
return pInstance[0].recover();
} else if (processVersion !== pInstance[0]._version) {
// Do nothing some other node is handling the process Instance.
}
});
};
}(process, ProcessInstance, options, processVersion)), updateInterval);
}
});
iter += 1;
}, BATCH_TIME);
});
setTimeout((function setTimeoutCb(inst, workflowMonitor, options) {
return function wrappedFn() {
workflowMonitor.destroyById(inst.id, options, function destroyWMI(err, inst) {
if (err) {
log.error(err);
return;
}
});
};
}(inst, workflowMonitor, options)), 2 * updateInterval);
});
};

@@ -21,2 +21,6 @@ {

},
"WorkflowMonitor": {
"dataSource": "db",
"public": true
},
"ProcessInstance": {

@@ -77,3 +81,7 @@ "dataSource": "db",

"public": false
},
"ChangeWorkflowRequest" :{
"dataSource": "db",
"public":true
}
}

@@ -79,3 +79,3 @@ /**

var ActivitiManager = models.Activiti_Manager;
var url = 'http://' + process.env.ACTIVITI_HOST + '/activiti-rest/service/';
var url = process.env.ACTIVITI_HOST + '/activiti-rest/service/';

@@ -82,0 +82,0 @@ ActivitiManager.enable(url, User1Context, function cb(err, res) {

@@ -133,3 +133,3 @@ /**

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -183,3 +183,3 @@ 'operation': 'create',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -359,3 +359,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -411,3 +411,3 @@ 'operation': 'create',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -810,3 +810,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -861,3 +861,3 @@ 'operation': 'create',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -864,0 +864,0 @@ });

@@ -142,3 +142,3 @@ /**

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -209,3 +209,3 @@ 'operation': 'delete',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -361,3 +361,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -428,3 +428,3 @@ 'operation': 'delete',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -679,3 +679,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -746,3 +746,3 @@ 'operation': 'delete',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -749,0 +749,0 @@ });

@@ -134,3 +134,3 @@ /**

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -209,3 +209,3 @@ 'operation': 'update',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -391,3 +391,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -462,3 +462,3 @@ 'operation': 'update',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -747,3 +747,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -817,3 +817,3 @@ 'operation': 'update',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -1067,3 +1067,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -1140,3 +1140,3 @@ 'operation': 'update',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -1253,3 +1253,3 @@ });

assert.isNotNull(instance.processDefinitionId);
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -1268,3 +1268,3 @@ });

assert.isNotNull(res);
assert.equal(res.processDefinitionId, 'escalationExample:1:36');
assert.equal(res.processDefinitionId, 'escalationExample:1:33');
assert.equal(res.suspended, true);

@@ -1271,0 +1271,0 @@ done();

@@ -136,3 +136,3 @@

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -210,3 +210,3 @@ 'operation': 'update',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -391,3 +391,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -462,3 +462,3 @@ 'operation': 'update',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -746,3 +746,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -816,3 +816,3 @@ 'operation': 'update',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -1066,3 +1066,3 @@ });

'workflowBody': {
'processDefinitionId': 'escalationExample:1:36'
'processDefinitionId': 'escalationExample:1:33'
},

@@ -1139,3 +1139,3 @@ 'operation': 'update',

testVars._workflowRef = instance.id;
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -1252,3 +1252,3 @@ });

assert.isNotNull(instance.processDefinitionId);
assert.equal(instance.processDefinitionId, 'escalationExample:1:36');
assert.equal(instance.processDefinitionId, 'escalationExample:1:33');
done();

@@ -1267,3 +1267,3 @@ });

assert.isNotNull(res);
assert.equal(res.processDefinitionId, 'escalationExample:1:36');
assert.equal(res.processDefinitionId, 'escalationExample:1:33');
assert.equal(res.suspended, true);

@@ -1270,0 +1270,0 @@ done();

@@ -49,3 +49,3 @@ /**

testVars.mainWorkflowInstance = instance;
done();
setTimeout(done, 2000);
});

@@ -124,3 +124,3 @@ });

testVars.mainWorkflowInstance = instance;
done();
setTimeout(done, 2000);
});

@@ -127,0 +127,0 @@ });

@@ -967,2 +967,16 @@ /**

// TODO : create a real scenario around this
it('fetch tasks if any', function CB(done) {
models[modelName].tasks(testVars.instanceId, User1Context,
function cb(err, res) {
if (err) {
log.error(err);
return done(err);
}
log.debug(res);
assert.isNotNull(res);
done();
});
});
it('end create request [ through OE Workflow ]', function CB(done) {

@@ -1396,35 +1410,35 @@ models.WorkflowManager.endAttachWfRequest({

it('remove model instances [clean-up]', function CB(done) {
models[modelName].destroyAll({}, User1Context, function cb(err, res) {
if (err) {
log.error(err);
return done(err);
}
log.debug(res);
done();
});
});
// it('remove model instances [clean-up]', function CB(done) {
// models[modelName].destroyAll({}, User1Context, function cb(err, res) {
// if (err) {
// log.error(err);
// return done(err);
// }
// log.debug(res);
// done();
// });
// });
it('remove model Definition ' + modelName + ' [clean-up]', function CB(done) {
var id = testVars.modelDetails.id;
var version = testVars.modelDetails._version;
models.ModelDefinition.deleteWithVersion(id, version, User1Context, function CB(err) {
if (err) {
done(err);
} else {
done();
}
});
});
// it('remove model Definition ' + modelName + ' [clean-up]', function CB(done) {
// var id = testVars.modelDetails.id;
// var version = testVars.modelDetails._version;
// models.ModelDefinition.deleteWithVersion(id, version, User1Context, function CB(err) {
// if (err) {
// done(err);
// } else {
// done();
// }
// });
// });
it('remove workflow mapping [clean-up]', function CB(done) {
models.WorkflowMapping.destroyAll({}, User1Context, function cb(err, res) {
if (err) {
log.error(err);
return done(err);
}
log.debug(res);
done();
});
});
// it('remove workflow mapping [clean-up]', function CB(done) {
// models.WorkflowMapping.destroyAll({}, User1Context, function cb(err, res) {
// if (err) {
// log.error(err);
// return done(err);
// }
// log.debug(res);
// done();
// });
// });
});

@@ -117,3 +117,2 @@ /**

models.ModelDefinition.create(postData, User1Context, function callback(err, res) {

@@ -136,3 +135,2 @@ if (err) {

it('should create testing model - ' + BaseModel, function callback(done) {

@@ -253,4 +251,4 @@ var postData = {

testVars.instanceId = instance.id;
testVars.relatedInstance01Id = instance.emails[0].id;
testVars.relatedInstance02Id = instance.emails[1].id;
testVars.relatedInstance01Id = instance.__data.emails[0].id;
testVars.relatedInstance02Id = instance.__data.emails[1].id;
setTimeout(done, 3000);

@@ -640,4 +638,4 @@ });

testVars.instanceId = instance.id;
testVars.relatedInstance01Id = instance.emails[0].id;
testVars.relatedInstance02Id = instance.emails[1].id;
testVars.relatedInstance01Id = instance.__data.emails[0].id;
testVars.relatedInstance02Id = instance.__data.emails[1].id;
done();

@@ -1016,4 +1014,4 @@ });

testVars.instanceId = instance.id;
testVars.relatedInstance01Id = instance.emails[0].id;
testVars.relatedInstance02Id = instance.emails[1].id;
testVars.relatedInstance01Id = instance.__data.emails[0].id;
testVars.relatedInstance02Id = instance.__data.emails[1].id;
done();

@@ -1020,0 +1018,0 @@ });

@@ -934,5 +934,7 @@ var fs = require('fs');

for (var index in requests) {
if (requests[index].operation === 'save-update') {
testVars._workflowRef = requests[index].processId;
break;
if (Object.prototype.hasOwnProperty.call(requests, index)) {
if (requests[index].operation === 'save-update') {
testVars._workflowRef = requests[index].processId;
break;
}
}

@@ -1769,5 +1771,7 @@ }

for (var index in requests) {
if (requests[index].operation === 'save-update') {
testVars._workflowRef = requests[index].processId;
break;
if (Object.prototype.hasOwnProperty.call(requests, index)) {
if (requests[index].operation === 'save-update') {
testVars._workflowRef = requests[index].processId;
break;
}
}

@@ -1774,0 +1778,0 @@ }

@@ -105,3 +105,3 @@ /**

it('validate process', function callback(done) {
xit('validate process', function callback(done) {
models.ProcessInstance.findById(testVars.processes[0].id, bootstrap.defaultContext, function callback(err, instance) {

@@ -369,3 +369,3 @@ if (err) {

it('validate process', function callback(done) {
xit('validate process', function callback(done) {
models.ProcessInstance.findById(testVars.processes[0].id, bootstrap.defaultContext, function callback(err, instance) {

@@ -431,3 +431,3 @@ if (err) {

it('validate process', function callback(done) {
xit('validate process', function callback(done) {
models.ProcessInstance.findById(testVars.processes[0].id, bootstrap.defaultContext, function callback(err, instance) {

@@ -434,0 +434,0 @@ if (err) {

@@ -450,5 +450,4 @@ /**

it('fetch task instance', function callback(done) {
testVars.processes[0].tasks({}, ctxUser2, function callback(err, task) {
it('fetch task instance via user1', function callback(done) {
testVars.processes[0].tasks({}, ctxUser1, function callback(err, task) {
if (err) {

@@ -464,2 +463,12 @@ return done(err);

it('delegate task to user2', function callback(done) {
testVars.task.delegate({
assignee: 'user2'
}, ctxUser1, function callback(err, task) {
if (err) {
return done(err);
}
setTimeout(done, 2000);
});
});

@@ -1618,1 +1627,102 @@ it('try to complete task', function callback(done) {

});
describe('Test case for taskManagement [ No Assigned User ]', function callback() {
this.timeout(10000);
var name = 'taskManagement_NoAssignee';
var testVars = {};
it('should login as user : user1', function callback(done) {
BaseUser.login({ username: 'user1', password: 'user1' }, bootstrap.defaultContext, function callback(err, token) {
if (bootstrap.checkDuplicateKeyError(err)) {
done();
} else if (err) {
return done(err);
} else {
assert.isNotNull(token);
testVars.accessToken = token;
done();
}
});
});
it('should read the file', function callback(done) {
fs.readFile(path.resolve('./test/bpmn-files', name + '.bpmn'), 'utf8', (err, data) => {
testVars.xmldata = data;
done(err);
});
});
it('deploy the WorkflowDefinition', function callback(done) {
var defData = { 'name': name, 'xmldata': testVars.xmldata };
models.WorkflowDefinition.create(defData, bootstrap.defaultContext, function callback(err) {
// Code for duplicate keys
if (bootstrap.checkDuplicateKeyError(err)) {done();} else {
done(err);
}
});
});
it('create workflow instance ', function callback(done) {
var data = { 'workflowDefinitionName': name };
models.WorkflowInstance.create(data, bootstrap.defaultContext, function callback(err, instance) {
if (err) {
return done(err);
}
testVars.mainWorkflowInstance = instance;
done();
});
});
it('fetch process instance', function callback(done) {
testVars.mainWorkflowInstance.processes({}, bootstrap.defaultContext, function callback(err, instance) {
if (err) {
return done(err);
}
assert.isNotNull(instance);
assert.lengthOf(instance, 1);
testVars.processes = instance;
setTimeout(done, 2000);
});
});
it('fetch task instance', function callback(done) {
testVars.processes[0].tasks({}, ctxUser2, function callback(err, task) {
if (err) {
return done(err);
}
assert.isNotNull(task);
assert.lengthOf(task, 1);
testVars.task = task[0];
setTimeout(done, 2000);
});
});
it('try to complete task', function callback(done) {
var putURL = 'http://localhost:3000/api/Tasks/' + testVars.task.id + '/completeTask?access_token=' + testVars.accessToken.id;
request({ url: putURL, method: 'PUT', json: {} }, cb);
function cb(err, response) {
if (err) {
done(err);
}
assert.strictEqual(response.statusCode, 200);
setTimeout(done, 2000);
}
});
it('validate process', function callback(done) {
models.ProcessInstance.findById(testVars.processes[0].id, bootstrap.defaultContext, function callback(err, instance) {
if (err) {
return done(err);
}
assert.isNotNull(instance);
assert.equal(instance._status, 'complete');
var expectedTokens = [{ 'name': 'Start', 'status': 'complete' }, { 'name': 'UserTask [No Assignee]', 'status': 'complete' }, { 'name': 'End', 'status': 'complete' }];
stateVerifier.verifyTokens(instance._processTokens, expectedTokens);
setTimeout(done, 2000);
});
});
});

@@ -5,2 +5,8 @@ var chai = require('chai');

module.exports = {
isRunning: function iP(instance) {
assert.strictEqual(instance._status, 'running');
},
isFailed: function iF(instance) {
assert.strictEqual(instance._status, 'failed');
},
isComplete: function iC(instance) {

@@ -7,0 +13,0 @@ assert.strictEqual(instance._status, 'complete');

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc