UNPKG

@5minds/processcube_engine

Version:

The ProcessCube Engine. Stores and executes BPMNs.

243 lines • 13.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProcessModelApiServiceProxyConfiguration = exports.ProcessModelApiService = void 0; const inversify_1 = require("inversify"); const processcube_engine_sdk_1 = require("@5minds/processcube_engine_sdk"); const index_1 = require("../../Contracts/InternalMessages/index"); const index_2 = require("../../Contracts/index"); const index_3 = require("../../Core/index"); const Configurator_1 = __importDefault(require("../../Tools/Configurator")); const index_4 = require("../../Tools/DatabaseAdaptersSequelize/index"); const EventAggregator_1 = __importDefault(require("../../Tools/EventAggregator")); const index_5 = require("../../Tools/Iam/index"); const ProcessDefinitionMediator_1 = require("../../Tools/ProcessDefinitionMediator"); const NotificationService_1 = require("./NotificationService"); const Paginator_1 = __importDefault(require("./lib/Paginator")); const ProcessDefinitionMapper_1 = require("./lib/ProcessDefinitionMapper"); let ProcessModelApiService = class ProcessModelApiService { coreAccess; executeProcessService; iamService; logger; notificationService; processDefinitionMediator; processInstanceDatabaseAdapter; identityService; internalIdentity; config; constructor(coreAccess, executeProcessService, iamService, notificationService, processDefinitionMediator, processInstanceDatabaseAdapter, identityService) { this.coreAccess = coreAccess; this.executeProcessService = executeProcessService; this.iamService = iamService; this.logger = new processcube_engine_sdk_1.Logger('api:process_model_service'); this.notificationService = notificationService; this.processDefinitionMediator = processDefinitionMediator; this.processInstanceDatabaseAdapter = processInstanceDatabaseAdapter; this.identityService = identityService; this.config = Configurator_1.default.application(); } initialize() { this.internalIdentity = this.identityService.getInternalIdentity(); } async getAll(identity, includeCount = true, offset, limit) { if (!limit || limit <= 0) { limit = this.config.defaultResponseLimit; } const processDefinitionList = await this.processDefinitionMediator.getAll(identity, undefined, undefined, includeCount); const processModels = processDefinitionList.flatMap((processDefinition) => processDefinition.processes.map((processModel) => (0, ProcessDefinitionMapper_1.mapProcessModelToPublicType)(processModel, processDefinition))); const subset = (0, Paginator_1.default)(processModels, offset, limit); return { processModels: subset, totalCount: processModels.length, }; } async getById(identity, processModelId) { const processDefinition = await this.processDefinitionMediator.getByProcessModelId(identity, processModelId); const processModel = processDefinition.processes.find((process) => process.id === processModelId); const publicProcessModel = (0, ProcessDefinitionMapper_1.mapProcessModelToPublicType)(processModel, processDefinition); return publicProcessModel; } async start(identity, request) { this.validateProcessStartRequest(request); this.logger.info(`Starting new Instance for Process Model ${request.processModelId}`, { processModelId: request.processModelId, startEventId: request.startEventId, correlationId: request.correlationId, returnOn: request.returnOn, endEventId: request.endEventId, }); if (request.returnOn === processcube_engine_sdk_1.StartCallbackType.CallbackOnEndEventReached || request.returnOn === processcube_engine_sdk_1.StartCallbackType.CallbackOnProcessInstanceFinished) { return this.startProcessInstanceAndAwaitEndEvent(identity, request); } return this.startProcessInstance(identity, request); } async setIsExecutableFlagForProcessModel(identity, processModelId, isExecutable) { this.ensureHasClaim(identity, processcube_engine_sdk_1.claims.canWriteProcessModel); this.logger.trace(`Setting 'executable' flag for Process Model ${processModelId} to '${isExecutable}'`, { processModelId: processModelId, isExecutable: isExecutable, }); await this.processDefinitionMediator.setIsExecutableFlagForProcessModel(processModelId, isExecutable); const executableChangedNotification = { processModelId: processModelId, isExecutable: isExecutable, }; EventAggregator_1.default.publish(index_1.eventAggregatorSettings.messagePaths.processExecutableChanged, executableChangedNotification); this.logger.info(`Set 'executable' flag for Process Model ${processModelId} to '${isExecutable}'`, { processModelId: processModelId, isExecutable: isExecutable, }); } async deleteDefinitionByProcessModelId(identity, processModelId, deleteAllRelatedData, force) { this.ensureHasClaim(identity, processcube_engine_sdk_1.claims.canDeleteProcessModel); try { this.logger.trace(`Retrieving Process Definition for Process Model ${processModelId}`); const processDefinition = await this.processDefinitionMediator.getByProcessModelId(identity, processModelId); if (processDefinition.processes.length > 1 && !force) { const errorMsg = `Cannot delete Process Definition \`${processDefinition.id}\` for Process Model \`${processModelId}\`, because it contains multiple processes. Set \`force\` to true, to delete the Process Definition anyway.`; throw new processcube_engine_sdk_1.BadRequestError(errorMsg); } if (deleteAllRelatedData) { await this.stopRunningProcessInstancesForProcessDefinition(identity, processDefinition.id); } this.logger.trace(`Deleting process definition ${processDefinition.id}`); await this.processDefinitionMediator.deleteById(processDefinition.id, deleteAllRelatedData); this.logger.info(`Deleted process definition ${processDefinition.id}`); } catch (error) { // Note: Trying to delete non-existing Process Definitions doesn't cause errors, so trying to delete non-existing models shouldn't either. if (error.message === `Process definition for ProcessModel \`${processModelId}\` not found!`) { return; } throw error; } } async stopRunningProcessInstancesForProcessDefinition(identity, processDefinitionId) { this.logger.trace(`Retrieving list of running process instances for definition ${processDefinitionId}`); const processInstances = await this.processInstanceDatabaseAdapter.getProcessInstancesByProcessDefinitionIdAndState(processDefinitionId, processcube_engine_sdk_1.ProcessInstanceState.running); this.logger.trace(`Ensure that user can stop running process instances for definition ${processDefinitionId}`); this.ensureProcessDefinitionIsNotInUse(identity, processDefinitionId, processInstances); this.logger.trace(`Terminating all running process instances for definition ${processDefinitionId}`); for (const processInstance of processInstances) { await this.terminateProcessInstance(processInstance.processInstanceId); } this.logger.info(`Terminated all running process instances for definition ${processDefinitionId}`); } validateProcessStartRequest(request) { if (request.returnOn === processcube_engine_sdk_1.StartCallbackType.CallbackOnEndEventReached && !request.endEventId) { throw new processcube_engine_sdk_1.BadRequestError('Must provide an EndEventId, since returnOn is set to `CallbackOnEndEventReached`!'); } const errors = []; if (request.processModelId && typeof request.processModelId !== 'string') { errors.push('processModelId must be a string'); } if (request.correlationId && typeof request.correlationId !== 'string') { errors.push('correlationId must be a string'); } if (request.startEventId && typeof request.startEventId !== 'string') { errors.push('startEventId must be a string'); } if (request.endEventId && typeof request.endEventId !== 'string') { errors.push('endEventId must be a string'); } if (request.initialToken && typeof request.initialToken !== 'object') { errors.push('initialToken must be a valid JSON'); } if (errors.length > 0) { const validationError = new processcube_engine_sdk_1.BadRequestError('Request body is invalid'); validationError.additionalInformation = { validationErrors: errors, }; throw validationError; } } async startProcessInstance(identity, request) { const result = await this.executeProcessService.start(identity, request); return { processInstanceId: result.processInstanceId, correlationId: result.correlationId, }; } async startProcessInstanceAndAwaitEndEvent(identity, request) { const result = await this.executeProcessService.startAndAwaitEndEvent(identity, request); return { processInstanceId: result.processInstanceId, correlationId: result.correlationId, endEventId: result.flowNodeId, tokenPayload: result.currentToken, }; } ensureProcessDefinitionIsNotInUse(identity, processDefinitionId, processInstances) { const isSuperAdmin = this.iamService.checkIfUserIsSuperAdmin(identity); if (isSuperAdmin) { return; } const processIsInUse = processInstances.some((processInstance) => processInstance.ownerId !== identity.userId); if (processIsInUse) { throw new processcube_engine_sdk_1.ForbiddenError(`Cannot delete Process \`${processDefinitionId}\`, because it is currently being executed by another user.`); } } async terminateProcessInstance(processInstanceId) { await new Promise(async (resolve) => { this.notificationService.onProcessTerminated(async (message) => { if (message.processInstanceId === processInstanceId) { resolve(); } }, true, this.internalIdentity); await this.coreAccess.killProcessInstance(this.internalIdentity, processInstanceId); }); } ensureHasClaim(identity, claimName) { const isSuperAdmin = this.iamService.checkIfUserIsSuperAdmin(identity); if (isSuperAdmin) { return; } this.iamService.ensureHasClaim(identity, claimName); } }; exports.ProcessModelApiService = ProcessModelApiService; __decorate([ (0, inversify_1.postConstruct)(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ProcessModelApiService.prototype, "initialize", null); exports.ProcessModelApiService = ProcessModelApiService = __decorate([ (0, inversify_1.injectable)(), __param(0, (0, inversify_1.inject)(index_2.IocRegistrationKeys.core.services.CoreAccess)), __param(1, (0, inversify_1.inject)(index_2.IocRegistrationKeys.core.services.ExecuteProcessService)), __param(2, (0, inversify_1.inject)(index_2.IocRegistrationKeys.internal.IamService)), __param(3, (0, inversify_1.inject)(index_2.IocRegistrationKeys.api.services.NotificationService)), __param(4, (0, inversify_1.inject)(index_2.IocRegistrationKeys.internal.ProcessDefinitionMediator)), __param(5, (0, inversify_1.inject)(index_2.IocRegistrationKeys.internal.ProcessInstanceDatabaseAdapter)), __param(6, (0, inversify_1.inject)(index_2.IocRegistrationKeys.internal.IdentityService)), __metadata("design:paramtypes", [index_3.CoreAccessService, index_3.ExecuteProcessService, index_5.IamService, NotificationService_1.NotificationService, ProcessDefinitionMediator_1.ProcessDefinitionMediator, index_4.ProcessInstanceDatabaseAdapter, index_5.IdentityService]) ], ProcessModelApiService); exports.ProcessModelApiServiceProxyConfiguration = { proxyKey: index_2.IocRegistrationKeys.api.services.ProcessModelServiceProxy, targetKey: index_2.IocRegistrationKeys.api.services.ProcessModelService, target: ProcessModelApiService, }; //# sourceMappingURL=ProcessModelService.js.map