@manyos/smileconnect-api 1.52.4 → 1.53.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/Dockerfile +1 -1
- package/app.js +6 -2
- package/controller/taskController.js +27 -2
- package/docs/releases.md +10 -4
- package/package.json +1 -1
- package/util/config.js +76 -25
package/Dockerfile
CHANGED
package/app.js
CHANGED
|
@@ -184,8 +184,12 @@ app.use('/v1/health', function (req, res, next) {
|
|
|
184
184
|
//health check
|
|
185
185
|
app.use('/v1/openapi/:clientId', async function (req, res, next) {
|
|
186
186
|
const clientId = req.params.clientId;
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
try {
|
|
188
|
+
const spec = await config.getDesignPackage(clientId)
|
|
189
|
+
res.json(spec)
|
|
190
|
+
} catch (error) {
|
|
191
|
+
next(error)
|
|
192
|
+
}
|
|
189
193
|
})
|
|
190
194
|
|
|
191
195
|
const maxFilesize = process.env.MAX_FILESIZE || 5;
|
|
@@ -129,6 +129,20 @@ async function updateTaskFlow(clientConfig, rootForm, rootRequestId, rootRequest
|
|
|
129
129
|
"RootRequestInstanceID" : rootRequestInstanceId
|
|
130
130
|
};
|
|
131
131
|
|
|
132
|
+
/*let flowReq2 = {
|
|
133
|
+
"10000000" : "AGGarserver000RD23DCRC3JB8TC9E",
|
|
134
|
+
"10000001" : "PBI000000001807",
|
|
135
|
+
"10000005" : "PBM:Problem Investigation",
|
|
136
|
+
"10001735" : "CREATE_TASK_FLOW",
|
|
137
|
+
"10001751" : "TMGarserver000RD2334RC3J1UTD55",
|
|
138
|
+
"10001753" : "0",
|
|
139
|
+
"10001756" : "AGGarserver000RD23DCRC3JB8TC9E",
|
|
140
|
+
"10002025" : "1",
|
|
141
|
+
"10007302" : "TMGarserver000RD233CRC3J18TD4L",
|
|
142
|
+
"10010305" : "PBI000000001807",
|
|
143
|
+
"1000000001" : "Calbro Services"
|
|
144
|
+
}*/
|
|
145
|
+
|
|
132
146
|
const mappingflow = config.getMapping('flowBuilder');
|
|
133
147
|
|
|
134
148
|
flowBuilderRequest = mappingUtil.applyMapping2Remedy(flowBuilderRequest, mappingflow, clientConfig.flowBuilder.constants);
|
|
@@ -171,10 +185,17 @@ async function checkFlowActivation(clientConfig, rootRequestInstanceId, rootRequ
|
|
|
171
185
|
|
|
172
186
|
const phaseRecords = await arquery.executeARQuery(form, undefined,
|
|
173
187
|
configQuery, 'InstanceId')
|
|
188
|
+
|
|
189
|
+
//Todo: Handle records without phases
|
|
174
190
|
if (phaseRecords && phaseRecords.data && phaseRecords.data.length > 0) {
|
|
175
191
|
const phaseRecord = phaseRecords.data[0]
|
|
176
192
|
const phaseGuid = phaseRecord['InstanceId']
|
|
177
193
|
await activateTaskFlow(clientConfig, rootRequestInstanceId, phaseGuid)
|
|
194
|
+
} else {
|
|
195
|
+
// nur bei Problem sofort aktivieren
|
|
196
|
+
if (rootForm === CONSTANTS.FORM_PROBLEM) {
|
|
197
|
+
activateTaskFlow(clientConfig, rootRequestInstanceId)
|
|
198
|
+
}
|
|
178
199
|
}
|
|
179
200
|
}
|
|
180
201
|
|
|
@@ -191,8 +212,12 @@ async function activateTaskFlow(clientConfig, rootRequestInstanceId, phaseGuid)
|
|
|
191
212
|
"zTmpInternal" : "True"
|
|
192
213
|
};
|
|
193
214
|
|
|
194
|
-
|
|
195
|
-
|
|
215
|
+
let query = `'RootRequestInstanceID'="${rootRequestInstanceId}" AND 'ParentID' = "${rootRequestInstanceId}" AND 'Predecessor Link' = "Start" AND 'Status' = "Pending" AND 'Sequence Mode' = "Yes"`
|
|
216
|
+
if (phaseGuid) {
|
|
217
|
+
query += ` AND 'Phase GUID' = "${phaseGuid}"`
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const records = await arquery.executeARQuery(form, undefined, query, idField)
|
|
196
221
|
if (records && records.data) {
|
|
197
222
|
for (let x=0; x<records.data.length; x++) {
|
|
198
223
|
const record = records.data[x]
|
package/docs/releases.md
CHANGED
|
@@ -2,16 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## API
|
|
4
4
|
|
|
5
|
-
### 1.
|
|
5
|
+
### 1.53.1 - 01.02.22
|
|
6
|
+
Fix Task Flow Activation for Problems
|
|
7
|
+
|
|
8
|
+
### 1.53.0 - 17.11.21
|
|
9
|
+
Update NodeJs to v16
|
|
10
|
+
|
|
11
|
+
### 1.52.4 - 17.11.21
|
|
6
12
|
Fix issue: Keep invisible ServiceCi Relation in Tickets during CI Relation Update
|
|
7
13
|
|
|
8
|
-
### 1.52.3 - 16.11.
|
|
14
|
+
### 1.52.3 - 16.11.21
|
|
9
15
|
Fix issue: Add globalParams to update ticket
|
|
10
16
|
|
|
11
|
-
### 1.52.2 - 16.11.
|
|
17
|
+
### 1.52.2 - 16.11.21
|
|
12
18
|
Fix issue: Inbound Events Names missed 'Worklog' for Task Worklogs
|
|
13
19
|
|
|
14
|
-
### 1.52.1 - 12.11.
|
|
20
|
+
### 1.52.1 - 12.11.21
|
|
15
21
|
Fix issue: Task CI relations might be removed on duplicate updates
|
|
16
22
|
|
|
17
23
|
### 1.52.0 - 09.11.21
|
package/package.json
CHANGED
package/util/config.js
CHANGED
|
@@ -330,28 +330,34 @@ async function getDesignPackage(clientId) {
|
|
|
330
330
|
const clientConfig = await getClientConfig(clientId)
|
|
331
331
|
const schemas = {}
|
|
332
332
|
let paths = {}
|
|
333
|
+
|
|
334
|
+
//generate docs for normal tickets
|
|
333
335
|
const keys = Object.keys(ticketConfig)
|
|
336
|
+
|
|
334
337
|
for (let x=0; x<keys.length; x++) {
|
|
335
338
|
const key = keys[x]
|
|
336
339
|
const config = ticketConfig[key]
|
|
337
340
|
const clientObjectConfig = clientConfig[config.requestType]
|
|
338
341
|
if (clientObjectConfig) {
|
|
339
|
-
{
|
|
342
|
+
if (clientObjectConfig.fields && clientObjectConfig.fields.length > 0){
|
|
340
343
|
const mapping = getDeprecatedMappingAsCustom(config.requestType)
|
|
341
|
-
schemas[config.requestType] = await getObjectSchema(clientObjectConfig, mapping, config.forms.regular)
|
|
344
|
+
schemas[config.requestType] = await getObjectSchema(clientObjectConfig.fields, mapping, config.forms.regular)
|
|
342
345
|
paths = {...paths, ... await getPathDef(config.assocTicketType, config.baseURI, config.requestType)}
|
|
343
346
|
}
|
|
344
|
-
if (config.requestTypeWorkLog) {
|
|
347
|
+
if (config.requestTypeWorkLog && clientConfig[config.requestTypeWorkLog].fields && clientConfig[config.requestTypeWorkLog].fields.length > 0) {
|
|
345
348
|
const mapping = getDeprecatedMappingAsCustom(config.requestTypeWorkLog)
|
|
346
|
-
schemas[config.requestTypeWorkLog] = await getObjectSchema(clientConfig[config.requestTypeWorkLog], mapping, config.forms.workLog)
|
|
349
|
+
schemas[config.requestTypeWorkLog] = await getObjectSchema(clientConfig[config.requestTypeWorkLog].fields, mapping, config.forms.workLog)
|
|
347
350
|
paths = {...paths, ... await getPathDef(config.assocTicketType, config.baseURI + '/{ticketId}/worklogs', config.requestTypeWorkLog, true, true)}
|
|
348
351
|
}
|
|
349
|
-
if (config.requestTemplate) {
|
|
352
|
+
if (config.requestTemplate && clientConfig[config.requestTemplate].fields && clientConfig[config.requestTemplate].fields.length > 0) {
|
|
350
353
|
const mapping = getDeprecatedMappingAsCustom(config.requestTemplate)
|
|
351
|
-
schemas[config.requestTemplate] = await getObjectSchema(clientConfig[config.requestTemplate], mapping, config.forms.template)
|
|
354
|
+
schemas[config.requestTemplate] = await getObjectSchema(clientConfig[config.requestTemplate].fields, mapping, config.forms.template)
|
|
352
355
|
}
|
|
353
356
|
}
|
|
354
357
|
}
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
//generate docs for custom Forms
|
|
355
361
|
const customFormMappings = await getCustomFormMapping()
|
|
356
362
|
const customKeys = Object.keys(customFormMappings)
|
|
357
363
|
for (let x=0; x<customKeys.length; x++) {
|
|
@@ -360,14 +366,51 @@ async function getDesignPackage(clientId) {
|
|
|
360
366
|
const clientObjectConfig = clientConfig[`custom_${formName}`]
|
|
361
367
|
log.debug('key', key, clientObjectConfig)
|
|
362
368
|
if (clientObjectConfig) {
|
|
363
|
-
schemas[key] = await getObjectSchema(clientObjectConfig, customFormMappings[key].mapping, formName)
|
|
369
|
+
schemas[key] = await getObjectSchema(clientObjectConfig.fields, customFormMappings[key].mapping, formName)
|
|
364
370
|
paths = {...paths, ... await getPathDef(key, '/v1/customForms/' + key, key)}
|
|
365
371
|
}
|
|
366
372
|
}
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
//generate docs for cmdb
|
|
376
|
+
const cmdbMapping = getDeprecatedMappingAsCustom('cmdbobject')
|
|
377
|
+
|
|
378
|
+
if (clientConfig.cmdbobject && clientConfig.cmdbobject.fields) {
|
|
379
|
+
schemas['cmdbobject'] = await getObjectSchema(clientConfig.cmdbobject.fields, cmdbMapping, 'AST:BaseElement')
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
const cmdbdef = Object.keys(clientConfig.cmdbobject)
|
|
383
|
+
const classConfigs = cmdbdef.filter(item => item.startsWith('fields_'))
|
|
384
|
+
const cmdbSchemaList = ['cmdbobject']
|
|
385
|
+
for (let x=0; x<classConfigs.length; x++) {
|
|
386
|
+
const classConfig = classConfigs[x]
|
|
387
|
+
const formName = classConfig.replace('fields_', '')
|
|
388
|
+
const fields = clientConfig.cmdbobject[classConfig]
|
|
389
|
+
const classMapping = getDeprecatedMappingAsCustom(`cmdbobject_${formName}`)
|
|
390
|
+
const classSchema = await getObjectSchema(fields, classMapping, formName)
|
|
391
|
+
let schemaName = `cmdbobject_${formName}`
|
|
392
|
+
schemaName = schemaName.replaceAll(':','_')
|
|
393
|
+
schemaName = schemaName.replaceAll(' ','_')
|
|
394
|
+
cmdbSchemaList.push(schemaName)
|
|
395
|
+
schemas[schemaName] = {
|
|
396
|
+
required: schemas['cmdbobject'].required.concat(classSchema.required),
|
|
397
|
+
properties: {...schemas['cmdbobject'].properties, ...classSchema.properties}
|
|
398
|
+
}
|
|
399
|
+
log.debug('customForm', formName, fields, classMapping, classSchema)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
paths = {...paths, ... await getPathDef('cmdbobject', '/v1/cmdbobjects', cmdbSchemaList)}
|
|
403
|
+
}
|
|
404
|
+
|
|
367
405
|
return {openapi: "3.0.1", info, servers, paths, components: {schemas}}
|
|
368
406
|
}
|
|
369
407
|
|
|
370
|
-
async function getPathDef(objectName, baseUri,
|
|
408
|
+
async function getPathDef(objectName, baseUri, schema, isSubTicket, suppressUpdate, suppressCreate) {
|
|
409
|
+
let tag = [schema]
|
|
410
|
+
if (Array.isArray(schema)) {
|
|
411
|
+
tag = schema
|
|
412
|
+
}
|
|
413
|
+
|
|
371
414
|
const ticketIdParam = {
|
|
372
415
|
name: "ticketId",
|
|
373
416
|
description: "id of the parent object to retrieve",
|
|
@@ -396,39 +439,39 @@ async function getPathDef(objectName, baseUri, tag, isSubTicket, suppressUpdate,
|
|
|
396
439
|
pathDef[`${baseUri}/{id}`] = {
|
|
397
440
|
parameters,
|
|
398
441
|
get: {
|
|
399
|
-
tags:
|
|
442
|
+
tags: tag,
|
|
400
443
|
summary: `Get a single ${objectName} object by id`,
|
|
401
444
|
description: "A single object is returned in the data attribute",
|
|
402
445
|
parameters: [],
|
|
403
|
-
responses: await getApiResponse(
|
|
446
|
+
responses: await getApiResponse(schema, true)
|
|
404
447
|
}
|
|
405
448
|
}
|
|
406
449
|
if (!suppressUpdate) {
|
|
407
450
|
pathDef[`${baseUri}/{id}`].put = {
|
|
408
|
-
tags:
|
|
451
|
+
tags: tag,
|
|
409
452
|
summary: `Update an object of type ${objectName}`,
|
|
410
453
|
description: "A single object is returned in the data attribute",
|
|
411
454
|
parameters: [],
|
|
412
|
-
responses: await getApiResponse(
|
|
455
|
+
responses: await getApiResponse(schema, false)
|
|
413
456
|
}
|
|
414
457
|
}
|
|
415
458
|
|
|
416
459
|
pathDef[`${baseUri}`] = {
|
|
417
460
|
get: {
|
|
418
|
-
tags:
|
|
461
|
+
tags: tag,
|
|
419
462
|
summary: `Get a list of object of type ${objectName}`,
|
|
420
463
|
description: "An array ob objects is returned in the data attribute",
|
|
421
464
|
parameters: [],
|
|
422
|
-
responses: await getApiResponse(
|
|
465
|
+
responses: await getApiResponse(schema, false)
|
|
423
466
|
}
|
|
424
467
|
}
|
|
425
468
|
if (!suppressCreate) {
|
|
426
469
|
pathDef[`${baseUri}`].post = {
|
|
427
|
-
tags:
|
|
470
|
+
tags: tag,
|
|
428
471
|
summary: `Create a new object of type ${objectName}`,
|
|
429
472
|
description: "A single object is returned in the data attribute",
|
|
430
473
|
parameters: [],
|
|
431
|
-
responses: await getApiResponse(
|
|
474
|
+
responses: await getApiResponse(schema, false)
|
|
432
475
|
}
|
|
433
476
|
}
|
|
434
477
|
if (isSubTicket) {
|
|
@@ -438,6 +481,18 @@ async function getPathDef(objectName, baseUri, tag, isSubTicket, suppressUpdate,
|
|
|
438
481
|
}
|
|
439
482
|
|
|
440
483
|
async function getApiResponse(schema, single) {
|
|
484
|
+
let dataValue = {
|
|
485
|
+
"$ref": `#/components/schemas/${schema}`
|
|
486
|
+
}
|
|
487
|
+
if (Array.isArray(schema)) {
|
|
488
|
+
dataValue = {
|
|
489
|
+
oneOf: schema.map(item => {
|
|
490
|
+
return {
|
|
491
|
+
"$ref": `#/components/schemas/${item}`
|
|
492
|
+
}
|
|
493
|
+
})
|
|
494
|
+
}
|
|
495
|
+
}
|
|
441
496
|
responses = {
|
|
442
497
|
"200": {
|
|
443
498
|
description: "successful operation",
|
|
@@ -456,24 +511,20 @@ async function getApiResponse(schema, single) {
|
|
|
456
511
|
if (!single) {
|
|
457
512
|
responses["200"].content["application/json"].schema.properties.data = {
|
|
458
513
|
type: "array",
|
|
459
|
-
items:
|
|
460
|
-
"$ref": `#/components/schemas/${schema}`
|
|
461
|
-
}
|
|
514
|
+
items: dataValue
|
|
462
515
|
}
|
|
463
516
|
} else {
|
|
464
|
-
responses["200"].content["application/json"].schema.properties.data =
|
|
465
|
-
"$ref": `#/components/schemas/${schema}`
|
|
466
|
-
}
|
|
517
|
+
responses["200"].content["application/json"].schema.properties.data = dataValue
|
|
467
518
|
}
|
|
468
519
|
return responses
|
|
469
520
|
}
|
|
470
521
|
|
|
471
|
-
async function getObjectSchema(
|
|
522
|
+
async function getObjectSchema(clientFields, mapping, formName) {
|
|
472
523
|
const fields = await getFields(formName)
|
|
473
524
|
const required = []
|
|
474
525
|
const properties = {}
|
|
475
|
-
log.debug('
|
|
476
|
-
|
|
526
|
+
log.debug('clientFields', clientFields, mapping, formName)
|
|
527
|
+
clientFields.forEach(field => {
|
|
477
528
|
const mappedName = mapping[field]
|
|
478
529
|
const fieldDef = {}
|
|
479
530
|
const fieldDetails = fields.find(item => item.name === field)
|