@red-hat-developer-hub/backstage-plugin-orchestrator-backend 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +740 -0
- package/README.md +5 -0
- package/app-config.yaml +3 -0
- package/dist/helpers/errorBuilder.cjs.js +36 -0
- package/dist/helpers/errorBuilder.cjs.js.map +1 -0
- package/dist/helpers/filterBuilder.cjs.js +197 -0
- package/dist/helpers/filterBuilder.cjs.js.map +1 -0
- package/dist/helpers/queryBuilder.cjs.js +40 -0
- package/dist/helpers/queryBuilder.cjs.js.map +1 -0
- package/dist/index.cjs.js +10 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/package.json.cjs.js +6 -0
- package/dist/package.json.cjs.js.map +1 -0
- package/dist/plugin.cjs.js +45 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/routerWrapper/index.cjs.js +31 -0
- package/dist/routerWrapper/index.cjs.js.map +1 -0
- package/dist/service/DataIndexService.cjs.js +405 -0
- package/dist/service/DataIndexService.cjs.js.map +1 -0
- package/dist/service/DataInputSchemaService.cjs.js +12 -0
- package/dist/service/DataInputSchemaService.cjs.js.map +1 -0
- package/dist/service/DevModeService.cjs.js +144 -0
- package/dist/service/DevModeService.cjs.js.map +1 -0
- package/dist/service/GitService.cjs.js +72 -0
- package/dist/service/GitService.cjs.js.map +1 -0
- package/dist/service/GitWrapper/git.cjs.js +219 -0
- package/dist/service/GitWrapper/git.cjs.js.map +1 -0
- package/dist/service/Helper.cjs.js +66 -0
- package/dist/service/Helper.cjs.js.map +1 -0
- package/dist/service/OrchestratorService.cjs.js +119 -0
- package/dist/service/OrchestratorService.cjs.js.map +1 -0
- package/dist/service/ScaffolderService.cjs.js +94 -0
- package/dist/service/ScaffolderService.cjs.js.map +1 -0
- package/dist/service/SonataFlowService.cjs.js +188 -0
- package/dist/service/SonataFlowService.cjs.js.map +1 -0
- package/dist/service/WorkflowCacheService.cjs.js +91 -0
- package/dist/service/WorkflowCacheService.cjs.js.map +1 -0
- package/dist/service/api/mapping/V2Mappings.cjs.js +150 -0
- package/dist/service/api/mapping/V2Mappings.cjs.js.map +1 -0
- package/dist/service/api/v2.cjs.js +187 -0
- package/dist/service/api/v2.cjs.js.map +1 -0
- package/dist/service/constants.cjs.js +10 -0
- package/dist/service/constants.cjs.js.map +1 -0
- package/dist/service/router.cjs.js +626 -0
- package/dist/service/router.cjs.js.map +1 -0
- package/dist/types/pagination.cjs.js +30 -0
- package/dist/types/pagination.cjs.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var rootHttpRouter = require('@backstage/backend-defaults/rootHttpRouter');
|
|
4
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
5
|
+
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
6
|
+
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
7
|
+
var pluginRbacCommon = require('@backstage-community/plugin-rbac-common');
|
|
8
|
+
var backstagePluginAuditLogNode = require('@janus-idp/backstage-plugin-audit-log-node');
|
|
9
|
+
var formats = require('ajv-formats/dist/formats');
|
|
10
|
+
var express = require('express');
|
|
11
|
+
var openapiBackend = require('openapi-backend');
|
|
12
|
+
var backstagePluginOrchestratorCommon = require('@red-hat-developer-hub/backstage-plugin-orchestrator-common');
|
|
13
|
+
var _package = require('../package.json.cjs.js');
|
|
14
|
+
var pagination = require('../types/pagination.cjs.js');
|
|
15
|
+
var v2 = require('./api/v2.cjs.js');
|
|
16
|
+
var constants = require('./constants.cjs.js');
|
|
17
|
+
var DataIndexService = require('./DataIndexService.cjs.js');
|
|
18
|
+
var DataInputSchemaService = require('./DataInputSchemaService.cjs.js');
|
|
19
|
+
var OrchestratorService = require('./OrchestratorService.cjs.js');
|
|
20
|
+
var ScaffolderService = require('./ScaffolderService.cjs.js');
|
|
21
|
+
var SonataFlowService = require('./SonataFlowService.cjs.js');
|
|
22
|
+
var WorkflowCacheService = require('./WorkflowCacheService.cjs.js');
|
|
23
|
+
|
|
24
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
25
|
+
|
|
26
|
+
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
27
|
+
|
|
28
|
+
const authorize = async (request, permission, permissionsSvc, httpAuth) => {
|
|
29
|
+
const decision = (await permissionsSvc.authorize([{ permission }], {
|
|
30
|
+
credentials: await httpAuth.credentials(request)
|
|
31
|
+
}))[0];
|
|
32
|
+
return decision;
|
|
33
|
+
};
|
|
34
|
+
async function createBackendRouter(options) {
|
|
35
|
+
const {
|
|
36
|
+
config,
|
|
37
|
+
logger,
|
|
38
|
+
discovery,
|
|
39
|
+
catalogApi,
|
|
40
|
+
urlReader,
|
|
41
|
+
scheduler,
|
|
42
|
+
permissions,
|
|
43
|
+
auth,
|
|
44
|
+
httpAuth
|
|
45
|
+
} = options;
|
|
46
|
+
const publicServices = initPublicServices(logger, config, scheduler);
|
|
47
|
+
const routerApi = await initRouterApi(publicServices.orchestratorService);
|
|
48
|
+
const auditLogger = new backstagePluginAuditLogNode.DefaultAuditLogger({
|
|
49
|
+
logger,
|
|
50
|
+
authService: auth,
|
|
51
|
+
httpAuthService: httpAuth
|
|
52
|
+
});
|
|
53
|
+
const router = express.Router();
|
|
54
|
+
const permissionsIntegrationRouter = pluginPermissionNode.createPermissionIntegrationRouter({
|
|
55
|
+
permissions: backstagePluginOrchestratorCommon.orchestratorPermissions
|
|
56
|
+
});
|
|
57
|
+
router.use(express__default.default.json());
|
|
58
|
+
router.use(permissionsIntegrationRouter);
|
|
59
|
+
router.use("/workflows", express__default.default.text());
|
|
60
|
+
router.use("/static", express__default.default.static(backendPluginApi.resolvePackagePath(_package.name, "static")));
|
|
61
|
+
router.get("/health", (_, response) => {
|
|
62
|
+
logger.info("PONG!");
|
|
63
|
+
response.json({ status: "ok" });
|
|
64
|
+
});
|
|
65
|
+
const scaffolderService = new ScaffolderService.ScaffolderService(
|
|
66
|
+
logger,
|
|
67
|
+
config,
|
|
68
|
+
catalogApi,
|
|
69
|
+
urlReader
|
|
70
|
+
);
|
|
71
|
+
setupInternalRoutes(
|
|
72
|
+
publicServices,
|
|
73
|
+
routerApi,
|
|
74
|
+
permissions,
|
|
75
|
+
httpAuth,
|
|
76
|
+
auditLogger
|
|
77
|
+
);
|
|
78
|
+
setupExternalRoutes(router, discovery, scaffolderService, auditLogger);
|
|
79
|
+
router.use((req, res, next) => {
|
|
80
|
+
if (!next) {
|
|
81
|
+
throw new Error("next is undefined");
|
|
82
|
+
}
|
|
83
|
+
return routerApi.openApiBackend.handleRequest(
|
|
84
|
+
req,
|
|
85
|
+
req,
|
|
86
|
+
res,
|
|
87
|
+
next
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
const middleware = rootHttpRouter.MiddlewareFactory.create({ logger, config });
|
|
91
|
+
router.use(middleware.error());
|
|
92
|
+
return router;
|
|
93
|
+
}
|
|
94
|
+
function initPublicServices(logger, config, scheduler) {
|
|
95
|
+
const dataIndexUrl = config.getString("orchestrator.dataIndexService.url");
|
|
96
|
+
const dataIndexService = new DataIndexService.DataIndexService(dataIndexUrl, logger);
|
|
97
|
+
const sonataFlowService = new SonataFlowService.SonataFlowService(dataIndexService, logger);
|
|
98
|
+
const workflowCacheService = new WorkflowCacheService.WorkflowCacheService(
|
|
99
|
+
logger,
|
|
100
|
+
dataIndexService,
|
|
101
|
+
sonataFlowService
|
|
102
|
+
);
|
|
103
|
+
workflowCacheService.schedule({ scheduler });
|
|
104
|
+
const orchestratorService = new OrchestratorService.OrchestratorService(
|
|
105
|
+
sonataFlowService,
|
|
106
|
+
dataIndexService,
|
|
107
|
+
workflowCacheService
|
|
108
|
+
);
|
|
109
|
+
const dataInputSchemaService = new DataInputSchemaService.DataInputSchemaService();
|
|
110
|
+
return {
|
|
111
|
+
orchestratorService,
|
|
112
|
+
dataInputSchemaService
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async function initRouterApi(orchestratorService) {
|
|
116
|
+
const openApiBackend = new openapiBackend.OpenAPIBackend({
|
|
117
|
+
definition: backstagePluginOrchestratorCommon.openApiDocument,
|
|
118
|
+
strict: false,
|
|
119
|
+
ajvOpts: {
|
|
120
|
+
strict: false,
|
|
121
|
+
strictSchema: false,
|
|
122
|
+
verbose: true,
|
|
123
|
+
addUsedSchema: false,
|
|
124
|
+
formats: formats.fullFormats
|
|
125
|
+
// open issue: https://github.com/openapistack/openapi-backend/issues/280
|
|
126
|
+
},
|
|
127
|
+
handlers: {
|
|
128
|
+
validationFail: async (c, _req, res) => {
|
|
129
|
+
console.log("validationFail", c.operation);
|
|
130
|
+
res.status(400).json({ err: c.validation.errors });
|
|
131
|
+
},
|
|
132
|
+
notFound: async (_c, req, res) => {
|
|
133
|
+
res.status(404).json({ err: `${req.path} path not found` });
|
|
134
|
+
},
|
|
135
|
+
notImplemented: async (_c, req, res) => res.status(500).json({ err: `${req.path} not implemented` })
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
await openApiBackend.init();
|
|
139
|
+
const v2$1 = new v2.V2(orchestratorService);
|
|
140
|
+
return { v2: v2$1, openApiBackend };
|
|
141
|
+
}
|
|
142
|
+
function setupInternalRoutes(services, routerApi, permissions, httpAuth, auditLogger) {
|
|
143
|
+
function manageDenyAuthorization(endpointName, endpoint, req) {
|
|
144
|
+
const error = new pluginRbacCommon.UnauthorizedError();
|
|
145
|
+
auditLogger.auditLog({
|
|
146
|
+
eventName: `${endpointName}EndpointHit`,
|
|
147
|
+
stage: "authorization",
|
|
148
|
+
status: "failed",
|
|
149
|
+
level: "error",
|
|
150
|
+
request: req,
|
|
151
|
+
response: {
|
|
152
|
+
status: 403,
|
|
153
|
+
body: {
|
|
154
|
+
errors: [
|
|
155
|
+
{
|
|
156
|
+
name: error.name,
|
|
157
|
+
message: error.message
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
errors: [error],
|
|
163
|
+
message: `Not authorize to request the ${endpoint} endpoint`
|
|
164
|
+
});
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
function auditLogRequestError(error, endpointName, endpoint, req) {
|
|
168
|
+
auditLogger.auditLog({
|
|
169
|
+
eventName: `${endpointName}EndpointHit`,
|
|
170
|
+
stage: "completion",
|
|
171
|
+
status: "failed",
|
|
172
|
+
level: "error",
|
|
173
|
+
request: req,
|
|
174
|
+
response: {
|
|
175
|
+
status: 500,
|
|
176
|
+
body: {
|
|
177
|
+
errors: [
|
|
178
|
+
{
|
|
179
|
+
name: error.name,
|
|
180
|
+
message: error.message || constants.INTERNAL_SERVER_ERROR_MESSAGE
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
errors: [error],
|
|
186
|
+
message: `Error occured while requesting the '${endpoint}' endpoint`
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
routerApi.openApiBackend.register(
|
|
190
|
+
"getWorkflowsOverview",
|
|
191
|
+
async (_c, req, res, next) => {
|
|
192
|
+
const endpointName = "getWorkflowsOverview";
|
|
193
|
+
const endpoint = "/v2/workflows/overview";
|
|
194
|
+
auditLogger.auditLog({
|
|
195
|
+
eventName: "getWorkflowsOverview",
|
|
196
|
+
stage: "start",
|
|
197
|
+
status: "succeeded",
|
|
198
|
+
level: "debug",
|
|
199
|
+
request: req,
|
|
200
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
201
|
+
});
|
|
202
|
+
const decision = await authorize(
|
|
203
|
+
req,
|
|
204
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowInstancesReadPermission,
|
|
205
|
+
permissions,
|
|
206
|
+
httpAuth
|
|
207
|
+
);
|
|
208
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
209
|
+
manageDenyAuthorization(endpointName, endpoint, req);
|
|
210
|
+
}
|
|
211
|
+
return routerApi.v2.getWorkflowsOverview(pagination.buildPagination(req), getRequestFilters(req)).then((result) => res.json(result)).catch((error) => {
|
|
212
|
+
auditLogRequestError(error, endpointName, endpoint, req);
|
|
213
|
+
next(error);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
routerApi.openApiBackend.register(
|
|
218
|
+
"getWorkflowSourceById",
|
|
219
|
+
async (c, _req, res, next) => {
|
|
220
|
+
const workflowId = c.request.params.workflowId;
|
|
221
|
+
const endpointName = "getWorkflowSourceById";
|
|
222
|
+
const endpoint = `/v2/workflows/${workflowId}/source`;
|
|
223
|
+
auditLogger.auditLog({
|
|
224
|
+
eventName: endpointName,
|
|
225
|
+
stage: "start",
|
|
226
|
+
status: "succeeded",
|
|
227
|
+
level: "debug",
|
|
228
|
+
request: _req,
|
|
229
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
230
|
+
});
|
|
231
|
+
const decision = await authorize(
|
|
232
|
+
_req,
|
|
233
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowReadPermission,
|
|
234
|
+
permissions,
|
|
235
|
+
httpAuth
|
|
236
|
+
);
|
|
237
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
238
|
+
manageDenyAuthorization(endpointName, endpoint, _req);
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
const result = await routerApi.v2.getWorkflowSourceById(workflowId);
|
|
242
|
+
res.status(200).contentType("text/plain").send(result);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
auditLogRequestError(error, endpointName, endpoint, _req);
|
|
245
|
+
next(error);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
routerApi.openApiBackend.register(
|
|
250
|
+
"executeWorkflow",
|
|
251
|
+
async (c, req, res, next) => {
|
|
252
|
+
const workflowId = c.request.params.workflowId;
|
|
253
|
+
const endpointName = "executeWorkflow";
|
|
254
|
+
const endpoint = `/v2/workflows/${workflowId}/execute`;
|
|
255
|
+
auditLogger.auditLog({
|
|
256
|
+
eventName: endpointName,
|
|
257
|
+
stage: "start",
|
|
258
|
+
status: "succeeded",
|
|
259
|
+
level: "debug",
|
|
260
|
+
request: req,
|
|
261
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
262
|
+
});
|
|
263
|
+
const decision = await authorize(
|
|
264
|
+
req,
|
|
265
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowExecutePermission,
|
|
266
|
+
permissions,
|
|
267
|
+
httpAuth
|
|
268
|
+
);
|
|
269
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
270
|
+
manageDenyAuthorization(endpointName, endpoint, req);
|
|
271
|
+
}
|
|
272
|
+
const businessKey = routerApi.v2.extractQueryParam(
|
|
273
|
+
c.request,
|
|
274
|
+
backstagePluginOrchestratorCommon.QUERY_PARAM_BUSINESS_KEY
|
|
275
|
+
);
|
|
276
|
+
const executeWorkflowRequestDTO = req.body;
|
|
277
|
+
return routerApi.v2.executeWorkflow(executeWorkflowRequestDTO, workflowId, businessKey).then((result) => res.status(200).json(result)).catch((error) => {
|
|
278
|
+
auditLogRequestError(error, endpointName, endpoint, req);
|
|
279
|
+
next(error);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
routerApi.openApiBackend.register(
|
|
284
|
+
"retriggerInstance",
|
|
285
|
+
async (c, req, res, next) => {
|
|
286
|
+
const workflowId = c.request.params.workflowId;
|
|
287
|
+
const instanceId = c.request.params.instanceId;
|
|
288
|
+
const endpointName = "retriggerInstance";
|
|
289
|
+
const endpoint = `/v2/workflows/${workflowId}/${instanceId}/retrigger`;
|
|
290
|
+
auditLogger.auditLog({
|
|
291
|
+
eventName: endpointName,
|
|
292
|
+
stage: "start",
|
|
293
|
+
status: "succeeded",
|
|
294
|
+
level: "debug",
|
|
295
|
+
request: req,
|
|
296
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
297
|
+
});
|
|
298
|
+
const decision = await authorize(
|
|
299
|
+
req,
|
|
300
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowExecutePermission,
|
|
301
|
+
permissions,
|
|
302
|
+
httpAuth
|
|
303
|
+
);
|
|
304
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
305
|
+
manageDenyAuthorization(endpointName, endpoint, req);
|
|
306
|
+
}
|
|
307
|
+
await routerApi.v2.retriggerInstance(workflowId, instanceId).then((result) => res.status(200).json(result)).catch((error) => {
|
|
308
|
+
auditLogRequestError(error, endpointName, endpoint, req);
|
|
309
|
+
next(error);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
routerApi.openApiBackend.register(
|
|
314
|
+
"getWorkflowOverviewById",
|
|
315
|
+
async (c, _req, res, next) => {
|
|
316
|
+
const workflowId = c.request.params.workflowId;
|
|
317
|
+
const endpointName = "getWorkflowOverviewById";
|
|
318
|
+
const endpoint = `/v2/workflows/${workflowId}/overview`;
|
|
319
|
+
auditLogger.auditLog({
|
|
320
|
+
eventName: endpointName,
|
|
321
|
+
stage: "start",
|
|
322
|
+
status: "succeeded",
|
|
323
|
+
level: "debug",
|
|
324
|
+
request: _req,
|
|
325
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
326
|
+
});
|
|
327
|
+
const decision = await authorize(
|
|
328
|
+
_req,
|
|
329
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowReadPermission,
|
|
330
|
+
permissions,
|
|
331
|
+
httpAuth
|
|
332
|
+
);
|
|
333
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
334
|
+
manageDenyAuthorization(endpointName, endpoint, _req);
|
|
335
|
+
}
|
|
336
|
+
return routerApi.v2.getWorkflowOverviewById(workflowId).then((result) => res.json(result)).catch((error) => {
|
|
337
|
+
auditLogRequestError(error, endpointName, endpoint, _req);
|
|
338
|
+
next(error);
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
routerApi.openApiBackend.register(
|
|
343
|
+
"getWorkflowStatuses",
|
|
344
|
+
async (_c, _req, res, next) => {
|
|
345
|
+
const endpointName = "getWorkflowStatuses";
|
|
346
|
+
const endpoint = "/v2/workflows/instances/statuses";
|
|
347
|
+
auditLogger.auditLog({
|
|
348
|
+
eventName: endpointName,
|
|
349
|
+
stage: "start",
|
|
350
|
+
status: "succeeded",
|
|
351
|
+
level: "debug",
|
|
352
|
+
request: _req,
|
|
353
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
354
|
+
});
|
|
355
|
+
const decision = await authorize(
|
|
356
|
+
_req,
|
|
357
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowInstanceReadPermission,
|
|
358
|
+
permissions,
|
|
359
|
+
httpAuth
|
|
360
|
+
);
|
|
361
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
362
|
+
manageDenyAuthorization(endpointName, endpoint, _req);
|
|
363
|
+
}
|
|
364
|
+
return routerApi.v2.getWorkflowStatuses().then((result) => res.status(200).json(result)).catch((error) => {
|
|
365
|
+
auditLogRequestError(error, endpointName, endpoint, _req);
|
|
366
|
+
next(error);
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
);
|
|
370
|
+
routerApi.openApiBackend.register(
|
|
371
|
+
"getWorkflowInputSchemaById",
|
|
372
|
+
async (c, req, res, next) => {
|
|
373
|
+
const workflowId = c.request.params.workflowId;
|
|
374
|
+
const instanceId = c.request.query.instanceId;
|
|
375
|
+
const endpointName = "getWorkflowInputSchemaById";
|
|
376
|
+
const endpoint = `/v2/workflows/${workflowId}/inputSchema`;
|
|
377
|
+
try {
|
|
378
|
+
auditLogger.auditLog({
|
|
379
|
+
eventName: endpointName,
|
|
380
|
+
stage: "start",
|
|
381
|
+
status: "succeeded",
|
|
382
|
+
level: "debug",
|
|
383
|
+
request: req,
|
|
384
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
385
|
+
});
|
|
386
|
+
const decision = await authorize(
|
|
387
|
+
req,
|
|
388
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowInstanceReadPermission,
|
|
389
|
+
permissions,
|
|
390
|
+
httpAuth
|
|
391
|
+
);
|
|
392
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
393
|
+
manageDenyAuthorization(endpointName, endpoint, req);
|
|
394
|
+
}
|
|
395
|
+
const workflowDefinition = await services.orchestratorService.fetchWorkflowInfo({
|
|
396
|
+
definitionId: workflowId,
|
|
397
|
+
cacheHandler: "throw"
|
|
398
|
+
});
|
|
399
|
+
if (!workflowDefinition) {
|
|
400
|
+
throw new Error(
|
|
401
|
+
`Failed to fetch workflow info for workflow ${workflowId}`
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
const serviceUrl = workflowDefinition.serviceUrl;
|
|
405
|
+
if (!serviceUrl) {
|
|
406
|
+
throw new Error(
|
|
407
|
+
`Service URL is not defined for workflow ${workflowId}`
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
const definition = await services.orchestratorService.fetchWorkflowDefinition({
|
|
411
|
+
definitionId: workflowId,
|
|
412
|
+
cacheHandler: "throw"
|
|
413
|
+
});
|
|
414
|
+
if (!definition) {
|
|
415
|
+
throw new Error(
|
|
416
|
+
"Failed to fetch workflow definition for workflow ${workflowId}"
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
if (!definition.dataInputSchema) {
|
|
420
|
+
res.status(200).json({});
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
const instanceVariables = instanceId ? await services.orchestratorService.fetchInstanceVariables({
|
|
424
|
+
instanceId,
|
|
425
|
+
cacheHandler: "throw"
|
|
426
|
+
}) : void 0;
|
|
427
|
+
const workflowData = instanceVariables ? services.dataInputSchemaService.extractWorkflowData(
|
|
428
|
+
instanceVariables
|
|
429
|
+
) : void 0;
|
|
430
|
+
const workflowInfo = await routerApi.v2.getWorkflowInputSchemaById(workflowId, serviceUrl).catch((error) => {
|
|
431
|
+
auditLogRequestError(error, endpointName, endpoint, req);
|
|
432
|
+
res.status(500).json({
|
|
433
|
+
message: error.message || constants.INTERNAL_SERVER_ERROR_MESSAGE
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
if (!workflowInfo || !workflowInfo.inputSchema || !workflowInfo.inputSchema.properties) {
|
|
437
|
+
res.status(200).json({});
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const inputSchemaProps = workflowInfo.inputSchema.properties;
|
|
441
|
+
let inputData;
|
|
442
|
+
if (workflowData) {
|
|
443
|
+
inputData = Object.keys(inputSchemaProps).filter((k) => k in workflowData).reduce((result, k) => {
|
|
444
|
+
if (!workflowData[k]) {
|
|
445
|
+
return result;
|
|
446
|
+
}
|
|
447
|
+
result[k] = workflowData[k];
|
|
448
|
+
return result;
|
|
449
|
+
}, {});
|
|
450
|
+
}
|
|
451
|
+
res.status(200).json({
|
|
452
|
+
inputSchema: workflowInfo.inputSchema,
|
|
453
|
+
data: inputData
|
|
454
|
+
});
|
|
455
|
+
} catch (err) {
|
|
456
|
+
auditLogRequestError(err, endpointName, endpoint, req);
|
|
457
|
+
next(err);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
);
|
|
461
|
+
routerApi.openApiBackend.register(
|
|
462
|
+
"getWorkflowInstances",
|
|
463
|
+
async (c, req, res, next) => {
|
|
464
|
+
const endpointName = "getWorkflowInstances";
|
|
465
|
+
const workflowId = c.request.params.workflowId;
|
|
466
|
+
const endpoint = `/v2/workflows/${workflowId}/instances`;
|
|
467
|
+
auditLogger.auditLog({
|
|
468
|
+
eventName: endpointName,
|
|
469
|
+
stage: "start",
|
|
470
|
+
status: "succeeded",
|
|
471
|
+
level: "debug",
|
|
472
|
+
request: req,
|
|
473
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
474
|
+
});
|
|
475
|
+
const decision = await authorize(
|
|
476
|
+
req,
|
|
477
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowInstancesReadPermission,
|
|
478
|
+
permissions,
|
|
479
|
+
httpAuth
|
|
480
|
+
);
|
|
481
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
482
|
+
manageDenyAuthorization(endpointName, endpoint, req);
|
|
483
|
+
}
|
|
484
|
+
return routerApi.v2.getInstances(pagination.buildPagination(req), getRequestFilters(req), workflowId).then((result) => res.json(result)).catch((error) => {
|
|
485
|
+
auditLogRequestError(error, endpointName, endpoint, req);
|
|
486
|
+
next(error);
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
);
|
|
490
|
+
routerApi.openApiBackend.register(
|
|
491
|
+
"getInstances",
|
|
492
|
+
async (_c, req, res, next) => {
|
|
493
|
+
const endpointName = "getInstances";
|
|
494
|
+
const endpoint = `/v2/workflows/instances`;
|
|
495
|
+
auditLogger.auditLog({
|
|
496
|
+
eventName: endpointName,
|
|
497
|
+
stage: "start",
|
|
498
|
+
status: "succeeded",
|
|
499
|
+
level: "debug",
|
|
500
|
+
request: req,
|
|
501
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
502
|
+
});
|
|
503
|
+
const decision = await authorize(
|
|
504
|
+
req,
|
|
505
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowInstancesReadPermission,
|
|
506
|
+
permissions,
|
|
507
|
+
httpAuth
|
|
508
|
+
);
|
|
509
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
510
|
+
manageDenyAuthorization(endpointName, endpoint, req);
|
|
511
|
+
}
|
|
512
|
+
return routerApi.v2.getInstances(pagination.buildPagination(req), getRequestFilters(req)).then((result) => res.json(result)).catch((error) => {
|
|
513
|
+
auditLogRequestError(error, endpointName, endpoint, req);
|
|
514
|
+
next(error);
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
);
|
|
518
|
+
routerApi.openApiBackend.register(
|
|
519
|
+
"getInstanceById",
|
|
520
|
+
async (c, _req, res, next) => {
|
|
521
|
+
const instanceId = c.request.params.instanceId;
|
|
522
|
+
const endpointName = "getInstanceById";
|
|
523
|
+
const endpoint = `/v2/workflows/instances/${instanceId}`;
|
|
524
|
+
auditLogger.auditLog({
|
|
525
|
+
eventName: endpointName,
|
|
526
|
+
stage: "start",
|
|
527
|
+
status: "succeeded",
|
|
528
|
+
level: "debug",
|
|
529
|
+
request: _req,
|
|
530
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
531
|
+
});
|
|
532
|
+
const decision = await authorize(
|
|
533
|
+
_req,
|
|
534
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowInstanceReadPermission,
|
|
535
|
+
permissions,
|
|
536
|
+
httpAuth
|
|
537
|
+
);
|
|
538
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
539
|
+
manageDenyAuthorization(endpointName, endpoint, _req);
|
|
540
|
+
}
|
|
541
|
+
const includeAssessment = routerApi.v2.extractQueryParam(
|
|
542
|
+
c.request,
|
|
543
|
+
backstagePluginOrchestratorCommon.QUERY_PARAM_INCLUDE_ASSESSMENT
|
|
544
|
+
);
|
|
545
|
+
return routerApi.v2.getInstanceById(instanceId, !!includeAssessment).then((result) => res.status(200).json(result)).catch((error) => {
|
|
546
|
+
auditLogRequestError(error, endpointName, endpoint, _req);
|
|
547
|
+
next(error);
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
);
|
|
551
|
+
routerApi.openApiBackend.register(
|
|
552
|
+
"abortWorkflow",
|
|
553
|
+
async (c, _req, res, next) => {
|
|
554
|
+
const instanceId = c.request.params.instanceId;
|
|
555
|
+
const endpointName = "abortWorkflow";
|
|
556
|
+
const endpoint = `/v2/workflows/instances/${instanceId}/abort`;
|
|
557
|
+
auditLogger.auditLog({
|
|
558
|
+
eventName: endpointName,
|
|
559
|
+
stage: "start",
|
|
560
|
+
status: "succeeded",
|
|
561
|
+
level: "debug",
|
|
562
|
+
request: _req,
|
|
563
|
+
message: `Received request to '${endpoint}' endpoint`
|
|
564
|
+
});
|
|
565
|
+
const decision = await authorize(
|
|
566
|
+
_req,
|
|
567
|
+
backstagePluginOrchestratorCommon.orchestratorWorkflowInstanceAbortPermission,
|
|
568
|
+
permissions,
|
|
569
|
+
httpAuth
|
|
570
|
+
);
|
|
571
|
+
if (decision.result === pluginPermissionCommon.AuthorizeResult.DENY) {
|
|
572
|
+
manageDenyAuthorization(endpointName, endpoint, _req);
|
|
573
|
+
}
|
|
574
|
+
return routerApi.v2.abortWorkflow(instanceId).then((result) => res.json(result)).catch((error) => {
|
|
575
|
+
auditLogRequestError(error, endpointName, endpoint, _req);
|
|
576
|
+
next(error);
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
function setupExternalRoutes(router, discovery, scaffolderService, auditLogger) {
|
|
582
|
+
router.get("/actions", async (req, res) => {
|
|
583
|
+
auditLogger.auditLog({
|
|
584
|
+
eventName: "ActionsEndpointHit",
|
|
585
|
+
stage: "start",
|
|
586
|
+
status: "succeeded",
|
|
587
|
+
level: "debug",
|
|
588
|
+
request: req,
|
|
589
|
+
message: `Received request to '/actions' endpoint`
|
|
590
|
+
});
|
|
591
|
+
const scaffolderUrl = await discovery.getBaseUrl("scaffolder");
|
|
592
|
+
const response = await fetch(`${scaffolderUrl}/v2/actions`);
|
|
593
|
+
const json = await response.json();
|
|
594
|
+
res.status(response.status).json(json);
|
|
595
|
+
});
|
|
596
|
+
router.post("/actions/:actionId", async (req, res) => {
|
|
597
|
+
const { actionId } = req.params;
|
|
598
|
+
auditLogger.auditLog({
|
|
599
|
+
eventName: "ActionsActionIdEndpointHit",
|
|
600
|
+
stage: "start",
|
|
601
|
+
status: "succeeded",
|
|
602
|
+
level: "debug",
|
|
603
|
+
request: req,
|
|
604
|
+
message: `Received request to '/actions/${actionId}' endpoint`
|
|
605
|
+
});
|
|
606
|
+
const instanceId = req.header("kogitoprocinstanceid");
|
|
607
|
+
const body = await req.body;
|
|
608
|
+
const filteredBody = Object.fromEntries(
|
|
609
|
+
Object.entries(body).filter(
|
|
610
|
+
([, value]) => value !== void 0 && value !== null
|
|
611
|
+
)
|
|
612
|
+
);
|
|
613
|
+
const result = await scaffolderService.executeAction({
|
|
614
|
+
actionId,
|
|
615
|
+
instanceId,
|
|
616
|
+
input: filteredBody
|
|
617
|
+
});
|
|
618
|
+
res.status(200).json(result);
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
function getRequestFilters(req) {
|
|
622
|
+
return req.body.filters ? req.body.filters : void 0;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
exports.createBackendRouter = createBackendRouter;
|
|
626
|
+
//# sourceMappingURL=router.cjs.js.map
|