Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 19 additions & 18 deletions src/API/API.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@

import {
IBPMNServer, IEngine, IDefinition, IConfiguration, IDataStore, EXECUTION_EVENT
, IExecution, IInstanceData, IItemData, ISecureUser
, IExecution, IInstanceData, IItemData, ISecureUser,
InstanceQuery, ItemQuery, InputData, AssignmentData, MatchingQuery, FindOption
} from '../';

/**
Expand Down Expand Up @@ -85,46 +86,46 @@ export interface IAPIEngine {
@param {ISecureUser} user - user object {}

*/
start(modelName,
data: {},

start(modelName: string,
data: InputData,
user: ISecureUser,
options?:IEngineOptions): Promise<IExecution>;
/**
continue with the execution of a particular item that is in a wait state, typically a user task
*/
invoke(query, data: {}, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
invoke(query: ItemQuery, data: InputData, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
/**
provide assignment data to a user task
Also, updates item data
*/
assign(query, data, assignment, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
assign(query: ItemQuery, data: InputData, assignment: AssignmentData, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
/**
throw a message with an id, system will identify receiving item
*/
throwMessage(messageId, data, messageMatchingKey, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
throwMessage(messageId: string, data: InputData, messageMatchingKey: MatchingQuery, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
/**
throw a signal with an id, system will identify receiving item(s)
*/
throwSignal(signalId, data, messageMatchingKey, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
throwSignal(signalId: string, data: InputData, messageMatchingKey: MatchingQuery, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
/**
start a second event node (in a subprocess) for a running instance
*/
startEvent(query, elementId, data: {}, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;
startEvent(query: InstanceQuery, elementId: string, data: InputData, user?: ISecureUser, options?:IEngineOptions): Promise<IExecution>;


/**
*
*
* restarting an already completed instance at a particular node
* this function requires `dataStore.enableSavePoints` to be true in configuration.ts
* this add a savePoint for each item, allowing you to select that item to restore it
*
*
*
* @param itemQuery - Query to find a single item
* @param inputData
*
*
*/
restart(itemQuery, data:any,userName, options?) :Promise<IExecution>;
restart(itemQuery: ItemQuery, data: InputData, user: ISecureUser, options?: IEngineOptions) :Promise<IExecution>;

/**
* upgrade running instances with the latest revised bpmn model
Expand Down Expand Up @@ -153,20 +154,20 @@ export interface IAPIData {
```

*/
getPendingUserTasks(query, user: ISecureUser): Promise<IItemData[]>;
getPendingUserTasks(query: InstanceQuery, user: ISecureUser): Promise<IItemData[]>;
/**
returns list of `item`s
*/
findItems(query, user?: ISecureUser): Promise<IItemData[]>;
findItem(query, user?: ISecureUser): Promise<IItemData>;
findItems(query: InstanceQuery, user?: ISecureUser): Promise<IItemData[]>;
findItem(query: InstanceQuery, user?: ISecureUser): Promise<IItemData>;
/**
returns list of `instance`s
*/
findInstances(query, user?: ISecureUser, options?): Promise<IInstanceData[]>;
findInstances(query: InstanceQuery, user?: ISecureUser, options?: FindOption): Promise<IInstanceData[]>;
/**
deletes the `instance`s
*/
deleteInstances(query, user?: ISecureUser);
deleteInstances(query: InstanceQuery, user?: ISecureUser);
}
/**
common parameters:
Expand Down
27 changes: 12 additions & 15 deletions src/API/AccessManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,35 @@ enum USER_ROLE {
DESIGNER = 'DESIGNER'
}

var byPass = false;
class SecureUser implements ISecureUser {
userName;
userGroups;
tenantId?;
modelsOwner?;
constructor(params: IUserInfo) {
Object.assign(this, params);

if (typeof process !=='undefined' && (process.env.REQUIRE_AUTHENTICATION === 'false' || process.env.ENFORCE_SECURITY === 'false')) {
console.log('****Security is disabled as requested in .env****');
byPass = true;
}
else
console.log('Security is enabled as requested in .env');
static isSecurityBypassed(): boolean {
return typeof process !== 'undefined' &&
(process.env.REQUIRE_AUTHENTICATION === 'false' || process.env.ENFORCE_SECURITY === 'false');
}

constructor(params: IUserInfo) {
Object.assign(this, params);
}
static SystemUser() {
return new SecureUser({ userName: 'system', userGroups: [USER_ROLE.SYSTEM], tenantId: null, modelsOwner: null });
}
isAdmin(): boolean {
if (byPass)
if (SecureUser.isSecurityBypassed())
return true;
return (this.userGroups.includes(USER_ROLE.ADMIN) || this.userGroups.includes(USER_ROLE.SYSTEM));
}
isSystem(): boolean {
if (byPass)
if (SecureUser.isSecurityBypassed())
return true;
return (this.userGroups.includes(USER_ROLE.SYSTEM));
}
inGroup(userGroup) :boolean {
if (byPass)
if (SecureUser.isSecurityBypassed())
return true;
return (this.userGroups.includes(userGroup))
}
Expand All @@ -47,7 +44,7 @@ class SecureUser implements ISecureUser {
* @returns query
*/
qualifyInstances(query) {
if (byPass)
if (SecureUser.isSecurityBypassed())
return query;
if (this.tenantId)
query['tenantId'] = this.tenantId;
Expand All @@ -74,7 +71,7 @@ class SecureUser implements ISecureUser {
* @returns query
*/
qualifyItems(query) {
if (byPass)
if (SecureUser.isSecurityBypassed())
return query;
return this.qualifyInstances(query);

Expand Down Expand Up @@ -119,7 +116,7 @@ class SecureUser implements ISecureUser {
* @returns query
*/
qualifyModels(query) {
if (byPass)
if (SecureUser.isSecurityBypassed())
return true;
if (this.modelsOwner)
query['owner'] = this.modelsOwner;
Expand Down
47 changes: 17 additions & 30 deletions src/API/SecureUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,40 @@ enum USER_ROLE {
* Warn the User that instance information has changed since last seen
*
* */
var byPass = false;

class SecureUser implements ISecureUser {
userName;
userGroups;
tenantId?;
modelsOwner?;
constructor(params: IUserInfo) {
Object.assign(this, params);

if (typeof process !=='undefined' && (process.env.REQUIRE_AUTHENTICATION === 'false' || process.env.ENFORCE_SECURITY === 'false')) {
console.log('****Security is disabled as requested in .env****');
byPass = true;
}
// else
// console.log('Security is enabled as requested in .env');

// console.log('new SecureUser', this);
/**
* Returns true when security enforcement is disabled via environment variables.
* Evaluated on every call so toggling the env var takes effect immediately
* without requiring a process restart or leaving a permanent bypass in place.
*/
static isSecurityBypassed(): boolean {
return typeof process !== 'undefined' &&
(process.env.REQUIRE_AUTHENTICATION === 'false' || process.env.ENFORCE_SECURITY === 'false');
}

constructor(params: IUserInfo) {
Object.assign(this, params);
}
static SystemUser() {
return new SecureUser({ userName: 'system', userGroups: [USER_ROLE.SYSTEM], tenantId: null, modelsOwner: null });
}
isAdmin(): boolean {
if (byPass)
if (SecureUser.isSecurityBypassed())
return true;
return (this.userGroups.includes(USER_ROLE.ADMIN) || this.userGroups.includes(USER_ROLE.SYSTEM));
}
isSystem(): boolean {
if (byPass)
if (SecureUser.isSecurityBypassed())
return true;
return (this.userGroups.includes(USER_ROLE.SYSTEM));
}
inGroup(userGroup) :boolean {
if (byPass)
if (SecureUser.isSecurityBypassed())
return true;
return (this.userGroups.includes(userGroup))
}
Expand All @@ -74,25 +73,13 @@ class SecureUser implements ISecureUser {
* @returns query
*/
qualifyInstances(query) {
if (byPass)
if (SecureUser.isSecurityBypassed())
return query;
if (this.tenantId)
query['tenantId'] = this.tenantId;
if (!this.isAdmin()) {

const grpQuery = [];
/* old
grpQuery.push({ 'items.assignee': null, 'items.candidateUsers': null, 'items.candidateGroups': null });

grpQuery.push({ 'items.assignee': this.userName });
grpQuery.push({ 'items.candidateUsers': this.userName, 'items.assignee': null });

this.userGroups.forEach(grp => {
grpQuery.push({ 'items.candidateGroups': grp, 'items.assignee': null });
});

query['$or'] = grpQuery;
*/
grpQuery.push({ 'items.assignee': null, 'items.candidateUsers': null, 'items.candidateGroups': null });

grpQuery.push({ 'items.assignee': this.userName });
Expand All @@ -113,7 +100,7 @@ class SecureUser implements ISecureUser {
* @returns query
*/
qualifyItems(query) {
if (byPass)
if (SecureUser.isSecurityBypassed())
return query;
return this.qualifyInstances(query);

Expand Down Expand Up @@ -158,7 +145,7 @@ class SecureUser implements ISecureUser {
* @returns query
*/
qualifyModels(query) {
if (byPass)
if (SecureUser.isSecurityBypassed())
return true;
if (this.modelsOwner)
query['owner'] = this.modelsOwner;
Expand Down
7 changes: 5 additions & 2 deletions src/common/DefaultConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ export class Configuration implements IConfiguration {
this.templatesPath = templatesPath;
this.timers = timers;
this.database = database;
this.apiKey = apiKey;
this.apiKey = apiKey || process.env.API_KEY;
if (!this.apiKey) {
console.warn('Warning: apiKey is not set. Set the API_KEY environment variable or pass apiKey in configuration.');
}
this.logger = logger;
this.definitions = definitions;
this.appDelegate = appDelegate;
Expand All @@ -78,7 +81,7 @@ export const defaultConfiguration = new Configuration(
db: 'bpmn'
}
},
apiKey: '1234',
apiKey: process.env.API_KEY,
logger: function (server) {
new Logger(server);
},
Expand Down
14 changes: 7 additions & 7 deletions src/datastore/DataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ import { InstanceLocker } from './';
import { QueryTranslator } from './QueryTranslator';
import { Aggregate} from './Aggregate'


/**
* Persistence layer for BPMN process instances.
*
* Manages saving, loading, querying, and deleting instance state in MongoDB.
* Provides locking via {@link InstanceLocker} to prevent concurrent writes,
* and supports optional save-points for instance restart.
*/
class DataStore extends ServerComponent implements IDataStore {

dbConfiguration;
Expand Down Expand Up @@ -63,8 +69,6 @@ class DataStore extends ServerComponent implements IDataStore {
}
const instanceData = recs[0];

// this.logger.log(" instance obj found" + instanceData.id);

return { instance: instanceData, items: this.getItemsFromInstances([instanceData]) };
}
/*
Expand Down Expand Up @@ -106,7 +110,6 @@ class DataStore extends ServerComponent implements IDataStore {
// save instance to DB
static seq = 0;
private async saveInstance(instance,options={}) {
// this.logger.log("Saving...");

let saveObject=
{ version: instance.version,startedAt: instance.startedAt,endedAt: instance.endedAt, status: instance.status, saved: instance.saved,
Expand Down Expand Up @@ -254,15 +257,12 @@ class DataStore extends ServerComponent implements IDataStore {
* @param query
*/
async findItems(query) : Promise<IItemData[]> {
// let us rebuild the query form {status: value} to > "tokens.items.status": "wait"
const trans = new QueryTranslator('items');
const result = trans.translateCriteria(query);
const projection = { id: 1, data: 1, name: 1, version:1, "items": 1 , "tokens":1};
var records = await this.db.find(this.dbConfiguration.db, this.dbConfiguration.Instance_collection, result, projection);
// console.log('...find items for query:', query, " translated to :", JSON.stringify(result), " recs:" , records.length)

const items=this.getItemsFromInstances(records, result,trans);
// this.logger.log('...find items for ' + JSON.stringify(query) + " result :" + JSON.stringify(result) + " instances:" + records.length+ " items: "+items.length);
return items;
}

Expand Down
Loading