@manyos/smileconnect-api 1.62.0 → 1.63.3
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/app.js +6 -2
- package/conf/clients.json +14 -8
- package/controller/scriptController.js +8 -2
- package/controller/taskController.js +3 -0
- package/controller/ticketController.js +5 -0
- package/docs/_media/architecture-deployment.png +0 -0
- package/docs/_sidebar.md +6 -0
- package/docs/adapter.md +3 -0
- package/docs/architecture.md +8 -1
- package/docs/configuration/config.md +7 -0
- package/docs/getting-started/hands-on.md +59 -0
- package/docs/getting-started/introduction.md +56 -0
- package/docs/getting-started/tips.md +7 -0
- package/docs/openapi.json +42 -1
- package/docs/releases.md +12 -0
- package/docs/scripts.md +25 -15
- package/package.json +5 -2
- package/routes/ticketWorkLogRoutes.js +20 -0
- package/util/config.js +9 -0
- package/util/responsehandler.js +13 -0
- package/util/ticketValidationUtil.js +36 -0
package/app.js
CHANGED
|
@@ -152,6 +152,8 @@ passport.use(
|
|
|
152
152
|
const clientConfig = config.getClientConfig(clientId)
|
|
153
153
|
clientConfig.clientId = clientId
|
|
154
154
|
|
|
155
|
+
req.clientId = clientId;
|
|
156
|
+
|
|
155
157
|
const user = {
|
|
156
158
|
'id': jwt_payload.sub,
|
|
157
159
|
'azp': jwt_payload.azp,
|
|
@@ -196,7 +198,8 @@ const maxFilesize = process.env.MAX_FILESIZE || 5;
|
|
|
196
198
|
|
|
197
199
|
app.use(fileUpload({
|
|
198
200
|
limits: { fileSize: maxFilesize * 1024 * 1024 },
|
|
199
|
-
abortOnLimit: true
|
|
201
|
+
abortOnLimit: true,
|
|
202
|
+
debug: true
|
|
200
203
|
}));
|
|
201
204
|
|
|
202
205
|
//global check for compatibility
|
|
@@ -265,7 +268,8 @@ app.use(function (req, res, next) {
|
|
|
265
268
|
app.use(function (req, res, next) {
|
|
266
269
|
req.globalScriptParams = {
|
|
267
270
|
query: req.query,
|
|
268
|
-
user: req.user
|
|
271
|
+
user: req.user,
|
|
272
|
+
log: log.child({req_id: req.id, clientId:req.clientId}, true)
|
|
269
273
|
}
|
|
270
274
|
// Für Scripte einen globalen parameter bereitstellen, der den org. Body enthält. Damit hat man auch noch in Post Scripten Zugriff auf customAttributes die beim Mapping entfernt werden.
|
|
271
275
|
if (req.body) {
|
package/conf/clients.json
CHANGED
|
@@ -128,6 +128,9 @@
|
|
|
128
128
|
"fields": [],
|
|
129
129
|
"constants": [],
|
|
130
130
|
"scripts": {}
|
|
131
|
+
},
|
|
132
|
+
"options": {
|
|
133
|
+
"translateSelectionFields": true
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
},
|
|
@@ -135,7 +138,8 @@
|
|
|
135
138
|
"name": "smileconnectGui",
|
|
136
139
|
"config": {
|
|
137
140
|
"options": {
|
|
138
|
-
"dateFormati": "dd.MM.yyyy HH:mm.ss"
|
|
141
|
+
"dateFormati": "dd.MM.yyyy HH:mm.ss",
|
|
142
|
+
"translateSelectionFields": true
|
|
139
143
|
},
|
|
140
144
|
"cmdbobject": {
|
|
141
145
|
"basequery": "'Data Set Id' = \"BMC.ASSET\" AND ('Mark As Deleted' = \"No\" OR 'Mark As Deleted' = $NULL$)",
|
|
@@ -600,7 +604,8 @@
|
|
|
600
604
|
"name": "ismsNeu",
|
|
601
605
|
"config": {
|
|
602
606
|
"options": {
|
|
603
|
-
"dateFormati": "dd.MM.yyyy HH:mm.ss"
|
|
607
|
+
"dateFormati": "dd.MM.yyyy HH:mm.ss",
|
|
608
|
+
"translateSelectionFields": true
|
|
604
609
|
},
|
|
605
610
|
"cmdbobject": {
|
|
606
611
|
"basequery": "'Data Set Id' = \"BMC.ASSET\" AND ('Mark As Deleted' = \"No\" OR 'Mark As Deleted' = $NULL$)",
|
|
@@ -1060,7 +1065,8 @@
|
|
|
1060
1065
|
"name": "ismsNeu2",
|
|
1061
1066
|
"config": {
|
|
1062
1067
|
"options": {
|
|
1063
|
-
"dateFormat": "dd.MM.yyyy HH:mm.ss"
|
|
1068
|
+
"dateFormat": "dd.MM.yyyy HH:mm.ss",
|
|
1069
|
+
"translateSelectionFields": true
|
|
1064
1070
|
},
|
|
1065
1071
|
"cmdbobject": {
|
|
1066
1072
|
"basequery": "'Data Set Id' = \"BMC.ASSET\" AND ('Mark As Deleted' = \"No\" OR 'Mark As Deleted' = $NULL$)",
|
|
@@ -1519,7 +1525,8 @@
|
|
|
1519
1525
|
"name": "robert2",
|
|
1520
1526
|
"config": {
|
|
1521
1527
|
"options": {
|
|
1522
|
-
"dateFormati": "dd.MM.yyyy HH:mm.ss"
|
|
1528
|
+
"dateFormati": "dd.MM.yyyy HH:mm.ss",
|
|
1529
|
+
"translateSelectionFields": true
|
|
1523
1530
|
},
|
|
1524
1531
|
"cmdbobject": {
|
|
1525
1532
|
"basequery": "'Data Set Id' = \"BMC.ASSET\" AND ('Mark As Deleted' = \"No\" OR 'Mark As Deleted' = $NULL$)",
|
|
@@ -1982,7 +1989,8 @@
|
|
|
1982
1989
|
"clientLimit": 100000,
|
|
1983
1990
|
"impersonateUser": "rhannemann",
|
|
1984
1991
|
"allowDynamicImpersonate": true,
|
|
1985
|
-
"translateSelectionFieldsX": false
|
|
1992
|
+
"translateSelectionFieldsX": false,
|
|
1993
|
+
"translateSelectionFields": true
|
|
1986
1994
|
},
|
|
1987
1995
|
"custom_Sample:Enrollments": {
|
|
1988
1996
|
"basequery": "1=1",
|
|
@@ -2389,9 +2397,7 @@
|
|
|
2389
2397
|
},
|
|
2390
2398
|
"PUT": {
|
|
2391
2399
|
"preMapping": [],
|
|
2392
|
-
"postMapping": [
|
|
2393
|
-
"notFetchResult"
|
|
2394
|
-
],
|
|
2400
|
+
"postMapping": [],
|
|
2395
2401
|
"afterExecution": []
|
|
2396
2402
|
}
|
|
2397
2403
|
}
|
|
@@ -16,7 +16,13 @@ const {getClients, getClient, setClient} = require('../util/config');
|
|
|
16
16
|
require('dotenv').config();
|
|
17
17
|
const {NodeVM} = require('vm2');
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
//try to read adapterConfig
|
|
20
|
+
let adapterConfigScript = `return {}`;
|
|
21
|
+
try {
|
|
22
|
+
adapterConfigScript = fs.readFileSync('conf/adapterConfig.js',{encoding: 'utf8'});
|
|
23
|
+
} catch (error) {
|
|
24
|
+
log.error(`Can't conf/adapterConfig.js - adapterFoundation not available.`, error);
|
|
25
|
+
}
|
|
20
26
|
|
|
21
27
|
const adapter = adapterFoundation.getAdapter(adapterConfigScript);
|
|
22
28
|
|
|
@@ -80,7 +86,7 @@ async function executeCode(code, requestData, params, logStream, executedByScrip
|
|
|
80
86
|
requestData,
|
|
81
87
|
params,
|
|
82
88
|
adapter,
|
|
83
|
-
log,
|
|
89
|
+
log: globalScriptParams.log.child({script: scriptId}, true),
|
|
84
90
|
clientId,
|
|
85
91
|
xmlParser,
|
|
86
92
|
script:executeScriptByScript,
|
|
@@ -445,6 +445,9 @@ async function updateTask(clientConfig, id, taskData, globalScriptParams) {
|
|
|
445
445
|
await scriptController.runScripts(scripts.postMapping, taskData, clientConfig.clientId, globalScriptParams);
|
|
446
446
|
}
|
|
447
447
|
|
|
448
|
+
//remove ticket id to prevent change
|
|
449
|
+
delete taskData['Task ID'];
|
|
450
|
+
|
|
448
451
|
const result = await arquery.updateEntry('TMS:Task', id, taskData, clientConfig.options);
|
|
449
452
|
|
|
450
453
|
//flow update
|
|
@@ -309,12 +309,17 @@ async function updateTicket(ticketConfig, clientConfig, id, ticketData, globalSc
|
|
|
309
309
|
if (scripts && scripts.postMapping) {
|
|
310
310
|
await scriptController.runScripts(scripts.postMapping, ticketData, clientConfig.clientId, globalScriptParams);
|
|
311
311
|
}
|
|
312
|
+
|
|
312
313
|
const ticket = await getTicket(ticketConfig, myClientConfig, id, myMapping, undefined, globalScriptParams);
|
|
313
314
|
log.debug('Ticket to Update', ticket);
|
|
314
315
|
//keep businessService CI Relation
|
|
315
316
|
if (ticket && ticket.data && ticket.data.serviceReconId && relations) {
|
|
316
317
|
relations.keepCIs = [ticket.data.serviceReconId]
|
|
317
318
|
}
|
|
319
|
+
|
|
320
|
+
//remove ticket id to prevent change
|
|
321
|
+
delete ticketData[ticketConfig.ticketIdField];
|
|
322
|
+
|
|
318
323
|
//todo Abfangen wenn getTicket nichts liefert.
|
|
319
324
|
const update = await arquery.updateEntry(ticketConfig.forms.regular, ticket.data.internalId, ticketData, clientConfig.options);
|
|
320
325
|
relationErrors = await ticketCIRelationController.updateRelations(ticketConfig, clientConfig, id, relations);
|
|
Binary file
|
package/docs/_sidebar.md
CHANGED
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
- [Scripts](scripts)
|
|
19
19
|
- [Adapter](adapter)
|
|
20
20
|
|
|
21
|
+
- Getting started
|
|
22
|
+
|
|
23
|
+
- [Introduction](getting-started/introduction)
|
|
24
|
+
- [Hands on](getting-started/hands-on)
|
|
25
|
+
- [Tips & Tricks](getting-started/tips)
|
|
26
|
+
|
|
21
27
|
- How-Tos
|
|
22
28
|
|
|
23
29
|
- [Authentication](howto/token)
|
package/docs/adapter.md
CHANGED
|
@@ -584,6 +584,7 @@ The SMILEconnect adapter is an open source project.
|
|
|
584
584
|
**secure**: Is secure communication use? True/False
|
|
585
585
|
|
|
586
586
|
**auth.user**: User for SMTP Authentication
|
|
587
|
+
|
|
587
588
|
**auth.pass**: Pass for SMTP Authentication
|
|
588
589
|
|
|
589
590
|
## Functions
|
|
@@ -626,6 +627,8 @@ const mailData = {
|
|
|
626
627
|
text: "Hello world?", // plain text body
|
|
627
628
|
html: "<b>Hello world?</b>", // html body
|
|
628
629
|
}
|
|
630
|
+
|
|
631
|
+
const result = adapter.mail.sendMail(mailData);
|
|
629
632
|
```
|
|
630
633
|
|
|
631
634
|
# DeepL
|
package/docs/architecture.md
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
# Architecture
|
|
2
2
|
|
|
3
|
-
In this guide we will explain the different components of
|
|
3
|
+
In this guide we will explain the different components of SMILEconnect and how you can use them.
|
|
4
|
+
|
|
5
|
+
General logical architecture:
|
|
4
6
|
|
|
5
7
|

|
|
6
8
|
|
|
9
|
+
Deployment architecture in Kubernetes / Docker:
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
Dataflow incl. Authentication:
|
|
7
14
|
|
|
8
15
|

|
|
@@ -156,6 +156,10 @@ Sample:
|
|
|
156
156
|
|
|
157
157
|
Loglevel of the api. Defaults to *error*
|
|
158
158
|
|
|
159
|
+
### LOG_REQUEST
|
|
160
|
+
|
|
161
|
+
If set to true, the incoming request & headers will be written to the JsonValue field in the QueueForm.
|
|
162
|
+
|
|
159
163
|
## Rate Limits
|
|
160
164
|
|
|
161
165
|
### RATE_LIMIT
|
|
@@ -387,6 +391,9 @@ Use REACT_APP_OIDC_TOKEN to choose the token to use. Default is access_token
|
|
|
387
391
|
|
|
388
392
|
Use REACT_APP_OIDC_SCOPE to choose the oidc scope
|
|
389
393
|
|
|
394
|
+
Use REACT_APP_CLIENT_SECRET to use confidential SSO client
|
|
395
|
+
|
|
396
|
+
|
|
390
397
|
## GUI
|
|
391
398
|
|
|
392
399
|
### REACT_APP_GUI_URL
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Hands-on Exercises
|
|
2
|
+
|
|
3
|
+
## Setup Field Mapping
|
|
4
|
+
|
|
5
|
+
In this exercise, participants will learn how to configure the global field mapping for all SMILEconnect interfaces with BMC HELIX ITSM. Global field mapping ensures that BMC field names are translated into valid REST-compatible values, promoting seamless data transfer between systems.
|
|
6
|
+
|
|
7
|
+
SMILEconnect creates new records using the appropriate "Interface Create Forms." Occasionally, field names in BMC may differ between the standard forms and the "Interface Create Forms." To address this, SMILEconnect provides separate mappings for both the standard objects and the creation process. The system attempts to synchronize both mappings automatically to maintain consistency and data accuracy.
|
|
8
|
+
|
|
9
|
+
### Review the mapping
|
|
10
|
+
|
|
11
|
+
### Manage mappings
|
|
12
|
+
|
|
13
|
+
### New vs. Normal Mappings
|
|
14
|
+
|
|
15
|
+
## Configuring Clients
|
|
16
|
+
|
|
17
|
+
In this exercise, participants will learn how to configure client applications to interact with the SMILEconnect integrated REST API with BMC HELIX ITSM. Efficient client configuration is crucial for seamless communication and data exchange between various systems.
|
|
18
|
+
|
|
19
|
+
New clients are created by copying an existing client, which allows for the development of a library of clients. This library facilitates the rapid creation of new clients as needed, streamlining the process and reducing the time it takes to set up new connections.
|
|
20
|
+
|
|
21
|
+
### View the client library
|
|
22
|
+
|
|
23
|
+
### Copy a Client
|
|
24
|
+
|
|
25
|
+
### Modify client configuration
|
|
26
|
+
|
|
27
|
+
For each object in a client, a base query is defined to determine which objects the client can see. For example, a client might only have access to incidents within its own support groups. Then, for each object, the attributes that the client can view are specified.
|
|
28
|
+
|
|
29
|
+
In addition to attribute visibility, constant values can be predefined for specific attributes. These constant values cannot be overwritten by the client. This feature can be used to:
|
|
30
|
+
|
|
31
|
+
* Provide default values for certain attributes, reducing the need for the client to supply them (e.g., a template ID).
|
|
32
|
+
|
|
33
|
+
* Restrict the client from modifying specific attributes, such as the ticket priority, ensuring that only authorized users or systems can make changes.
|
|
34
|
+
|
|
35
|
+
### Setup Base query
|
|
36
|
+
|
|
37
|
+
### Manage fields
|
|
38
|
+
|
|
39
|
+
### Manage constants
|
|
40
|
+
|
|
41
|
+
## Todo
|
|
42
|
+
|
|
43
|
+
* Creating and Updating Tickets
|
|
44
|
+
|
|
45
|
+
* Search for Data
|
|
46
|
+
|
|
47
|
+
* Creating and Reading Worklogs
|
|
48
|
+
|
|
49
|
+
* Handling Attachments
|
|
50
|
+
|
|
51
|
+
* Querying Assets and Configuration Items (CIs)
|
|
52
|
+
|
|
53
|
+
* Creating Outbound Events
|
|
54
|
+
|
|
55
|
+
* Using Scripts for advanced workflows
|
|
56
|
+
|
|
57
|
+
* Understanding Script Timing
|
|
58
|
+
|
|
59
|
+
* Troubleshooting and Debugging
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Introduction to SMILEconnect REST API
|
|
2
|
+
|
|
3
|
+
## Overview of SMILEconnect
|
|
4
|
+
|
|
5
|
+
The primary objective of integrating SMILEconnect with BMC HELIX ITSM is to provide ITSM departments with a powerful and flexible solution for creating and managing new interfaces rapidly. This integration focuses on the following key aspects:
|
|
6
|
+
|
|
7
|
+
* Streamlined Interface Creation: With SMILEconnect, ITSM teams can create new interfaces in minutes, reducing the time and effort required to establish connections between various systems and applications.
|
|
8
|
+
|
|
9
|
+
* Minimal Customization: SMILEconnect integration does not require any customization of the ITSM system, allowing for seamless implementation without altering the existing setup. This approach ensures smooth operation and compatibility with future updates.
|
|
10
|
+
|
|
11
|
+
* Configurable Workflows: Despite the minimal customization requirements, SMILEconnect enables ITSM departments to design and configure complex workflows that cater to their specific needs. This flexibility ensures that organizations can adapt to changing requirements and streamline their processes.
|
|
12
|
+
|
|
13
|
+
* Future-proof ITSM Systems: As interfaces play a crucial role in the evolution of ITSM systems, integrating SMILEconnect with BMC HELIX ITSM helps organizations stay ahead of the curve by providing a scalable and adaptable solution for managing various interfaces.
|
|
14
|
+
|
|
15
|
+
* Enhanced Collaboration: The integration of SMILEconnect facilitates better communication and collaboration between different teams and departments within the organization. By offering a unified platform for managing interfaces, SMILEconnect fosters efficient information exchange and streamlined processes.
|
|
16
|
+
|
|
17
|
+
* Automatic Documentation Generation: SMILEconnect is capable of automatically generating individual documentation for each interface created. This feature ensures that interface partners can quickly and efficiently implement the interface on their end. By providing comprehensive documentation, potential misunderstandings or misconfigurations can be minimized, resulting in faster implementation and a more reliable connection between systems.
|
|
18
|
+
|
|
19
|
+
By addressing these objectives, the SMILEconnect integration with BMC HELIX ITSM aims to enhance the overall efficiency and effectiveness of ITSM departments, ensuring they can meet the ever-evolving needs of their organizations.
|
|
20
|
+
|
|
21
|
+
## What is a REST API?
|
|
22
|
+
|
|
23
|
+
This section provides an overview of the basic concepts and principles of REST APIs to help participants understand the underlying technology used in SMILEconnect and BMC HELIX ITSM integration.
|
|
24
|
+
|
|
25
|
+
### What is a REST API?
|
|
26
|
+
|
|
27
|
+
REST (Representational State Transfer) is an architectural style used for designing networked applications. A REST API (Application Programming Interface) allows communication between different software systems using standard HTTP methods. It is designed to be simple, stateless, and scalable, making it a popular choice for modern web services.
|
|
28
|
+
|
|
29
|
+
### HTTP Methods and Status Codes
|
|
30
|
+
|
|
31
|
+
REST APIs utilize HTTP methods to interact with resources. The most common HTTP methods include:
|
|
32
|
+
|
|
33
|
+
* GET: Retrieves data from a specified resource.
|
|
34
|
+
* POST: Submits new data to a resource, creating a new object.
|
|
35
|
+
* PUT: Updates an existing resource with new data.
|
|
36
|
+
* DELETE: Removes a specified resource.
|
|
37
|
+
|
|
38
|
+
HTTP status codes are three-digit numbers that indicate the outcome of an HTTP request. Some common status codes include:
|
|
39
|
+
|
|
40
|
+
* 200 OK: The request was successful.
|
|
41
|
+
* 201 Created: The request has created a new resource.
|
|
42
|
+
* 400 Bad Request: The request was malformed or invalid.
|
|
43
|
+
* 401 Unauthorized: The request requires authentication.
|
|
44
|
+
* 403 Forbidden: The requester lacks permission to access the resource.
|
|
45
|
+
* 404 Not Found: The requested resource could not be found.
|
|
46
|
+
* 500 Internal Server Error: The server encountered an error while processing the request.
|
|
47
|
+
|
|
48
|
+
### Authentication and Authorization
|
|
49
|
+
|
|
50
|
+
Security is crucial for REST APIs, and SMILEconnect uses OAuth for authentication. OAuth is a standardized method that allows users to grant third-party applications limited access without sharing their credentials. In most organizations, an Identity Provider (IdP) is already in place and can be used for OAuth authentication.
|
|
51
|
+
|
|
52
|
+
### API Endpoints and Resources
|
|
53
|
+
|
|
54
|
+
An API endpoint is a specific address (URL) used to access and interact with resources in an API. Resources are the data objects and services that the API provides access to. In SMILEconnect, automatically provided endpoints cover ITSM objects such as Incident, Problem, Change, Work Order, Task, Assets, and Worklogs. Each endpoint is associated with a specific HTTP method to perform actions such as creating, retrieving, updating, or deleting resources.
|
|
55
|
+
|
|
56
|
+
In summary, understanding the fundamentals of REST APIs helps participants effectively utilize the SMILEconnect integration with BMC HELIX ITSM. Familiarity with these concepts, including OAuth authentication and the automatically provided endpoints, ensures that participants can design, configure, and maintain interfaces, optimizing their ITSM processes and adapting to ever-changing organizational needs.
|
package/docs/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.0.2",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "SMILEconnect",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.63.0",
|
|
6
6
|
"contact": {
|
|
7
7
|
"name": "manyos technology GmbH",
|
|
8
8
|
"url": "https://manyos.it",
|
|
@@ -4536,6 +4536,34 @@
|
|
|
4536
4536
|
"required": true
|
|
4537
4537
|
}
|
|
4538
4538
|
]
|
|
4539
|
+
},
|
|
4540
|
+
"/health": {
|
|
4541
|
+
"get": {
|
|
4542
|
+
"tags": [
|
|
4543
|
+
"AppConfig"
|
|
4544
|
+
],
|
|
4545
|
+
"responses": {
|
|
4546
|
+
"200": {
|
|
4547
|
+
"content": {
|
|
4548
|
+
"application/json": {
|
|
4549
|
+
"schema": {
|
|
4550
|
+
"$ref": "#/components/schemas/HealthStatus"
|
|
4551
|
+
},
|
|
4552
|
+
"examples": {
|
|
4553
|
+
"healthResponse": {
|
|
4554
|
+
"value": {
|
|
4555
|
+
"status": "ok"
|
|
4556
|
+
}
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
},
|
|
4561
|
+
"description": "Returns ok if API is up."
|
|
4562
|
+
}
|
|
4563
|
+
},
|
|
4564
|
+
"summary": "Get API health status",
|
|
4565
|
+
"description": "Responds with 200 if API is ready. No auth needed."
|
|
4566
|
+
}
|
|
4539
4567
|
}
|
|
4540
4568
|
},
|
|
4541
4569
|
"components": {
|
|
@@ -16339,6 +16367,19 @@
|
|
|
16339
16367
|
"description": ""
|
|
16340
16368
|
}
|
|
16341
16369
|
}
|
|
16370
|
+
},
|
|
16371
|
+
"HealthStatus": {
|
|
16372
|
+
"title": "Root Type for HealthStatus",
|
|
16373
|
+
"description": "",
|
|
16374
|
+
"type": "object",
|
|
16375
|
+
"properties": {
|
|
16376
|
+
"status": {
|
|
16377
|
+
"type": "string"
|
|
16378
|
+
}
|
|
16379
|
+
},
|
|
16380
|
+
"example": {
|
|
16381
|
+
"status": "ok"
|
|
16382
|
+
}
|
|
16342
16383
|
}
|
|
16343
16384
|
},
|
|
16344
16385
|
"responses": {
|
package/docs/releases.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
3
|
## API
|
|
4
|
+
### 1.63.0 - 10.01.23
|
|
5
|
+
Security fix for jsonwebtoken https://github.com/advisories/GHSA-27h2-hvpr-p74q
|
|
6
|
+
|
|
4
7
|
### 1.62.0 - 18.11.22
|
|
5
8
|
Add Deepl Translation Adapter
|
|
6
9
|
|
|
@@ -182,6 +185,9 @@ e.g.
|
|
|
182
185
|
*/v1/incidents?impersonateUser=abc123
|
|
183
186
|
|
|
184
187
|
## Event Manager
|
|
188
|
+
### 1.29.1 - 10.01.23
|
|
189
|
+
Security fix for jsonwebtoken https://github.com/advisories/GHSA-27h2-hvpr-p74q
|
|
190
|
+
|
|
185
191
|
### 1.29.0 - 18.11.22
|
|
186
192
|
Add Deepl Translation Adapter
|
|
187
193
|
|
|
@@ -226,6 +232,12 @@ The eventmanager will check all outbound webhooks for an event. If one fails, th
|
|
|
226
232
|
|
|
227
233
|
## GUI
|
|
228
234
|
|
|
235
|
+
### 1.11.0 - 05.04.23
|
|
236
|
+
Feat: Add REACT_APP_CLIENT_SECRET Parameter to allow confidential SSO clients
|
|
237
|
+
|
|
238
|
+
### 1.10.3 - 29.03.23
|
|
239
|
+
Fixed: GUI crash when customForm name contains blank.
|
|
240
|
+
|
|
229
241
|
### 1.10.2 - 30.09.22
|
|
230
242
|
Fixed: openApi page is not loading.
|
|
231
243
|
|
package/docs/scripts.md
CHANGED
|
@@ -266,6 +266,14 @@ const myInstanceId = uid();
|
|
|
266
266
|
requestData['Instance Id'] = myInstanceId;
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
+
## customHeaders
|
|
270
|
+
|
|
271
|
+
Allows custom headers in outbound events.
|
|
272
|
+
|
|
273
|
+
```javascript
|
|
274
|
+
customHeaders['X-API-GATEWAYUSER'] = 'gatewayuser1';
|
|
275
|
+
```
|
|
276
|
+
|
|
269
277
|
# Returning values
|
|
270
278
|
|
|
271
279
|
Values can be returned with the function *resolve()*
|
|
@@ -311,23 +319,25 @@ This script looks up the previous assignment group if an incident is set to "ass
|
|
|
311
319
|
//lookup Previous Assigned Support Group for Incident
|
|
312
320
|
// and assign this group if status is changed to "assigned", and assignedGroup is not set.
|
|
313
321
|
|
|
322
|
+
if ( globalScriptParams && globalScriptParams.id && requestData['status']=="Assigned" && !requestData.hasOwnProperty("assignedGroup") ) {
|
|
314
323
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const data = remedyResult.data;
|
|
320
|
-
let entry = 0;
|
|
321
|
-
if (data.length > 1) {
|
|
322
|
-
entry = data.length - 2;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (data[entry] && data[entry].hasOwnProperty("Assigned Group ID")) {
|
|
326
|
-
requestData['assignedGroup'] = data[entry]['Assigned Group ID'];
|
|
327
|
-
} else {
|
|
328
|
-
reject("could not find previous group. automatic re-ssignement failed. set assigendGroup manually")
|
|
324
|
+
const remedyOptions = {
|
|
325
|
+
limit: 1,
|
|
326
|
+
sort: {
|
|
327
|
+
"Last Date Duration Calculated": -1
|
|
329
328
|
}
|
|
330
|
-
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const remedyResult = await adapter.remedy.search("HPD:Help Desk Assignment Log", `'Incident Number' = "${globalScriptParams.id}"`, "Submit Date, Assigned Support Company, Assigned Support Organization, Assigned Group, Assigned Group ID", remedyOptions);
|
|
332
|
+
|
|
333
|
+
if (remedyResult && remedyResult.data && Array.isArray(remedyResult.data) && remedyResult.data.length > 0) {
|
|
334
|
+
const prevGroupData = remedyResult.data[0];
|
|
335
|
+
requestData.assignedGroup = prevGroupData['Assigned Group ID'];
|
|
336
|
+
requestData.assignedCompany = prevGroupData['Assigned Support Company'];
|
|
337
|
+
requestData.assignedSupportOrg = prevGroupData['Assigned Support Organization'];
|
|
338
|
+
requestData.assignedGroupName = prevGroupData['Assigned Group'];
|
|
339
|
+
} else {
|
|
340
|
+
reject("could not find previous group. automatic re-ssignement failed. set assigendGroup manually")
|
|
331
341
|
}
|
|
332
342
|
}
|
|
333
343
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manyos/smileconnect-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.63.3",
|
|
4
4
|
"description": "A proxy and abstraction layer for BMCs IT Service Management Suite",
|
|
5
5
|
"main": "app.js",
|
|
6
6
|
"scripts": {
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
},
|
|
11
11
|
"author": "Robert Hannemann",
|
|
12
12
|
"license": "ISC",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=0.10.3"
|
|
15
|
+
},
|
|
13
16
|
"dependencies": {
|
|
14
17
|
"@manyos/adapter-foundation": "^1.1.2",
|
|
15
18
|
"@manyos/logger": "^1.3.0",
|
|
@@ -19,7 +22,7 @@
|
|
|
19
22
|
"cors": "^2.8.4",
|
|
20
23
|
"dotenv": "^4.0.0",
|
|
21
24
|
"express": "^4.17.1",
|
|
22
|
-
"express-fileupload": "^1.
|
|
25
|
+
"express-fileupload": "^1.3.1",
|
|
23
26
|
"express-rate-limit": "^5.2.6",
|
|
24
27
|
"express-request-id": "^1.4.1",
|
|
25
28
|
"express-validator": "^6.10.1",
|
|
@@ -2,6 +2,7 @@ const path = require('path');
|
|
|
2
2
|
const log = require('@manyos/logger').setupLog('SMILEconnect_' + path.basename(__filename));
|
|
3
3
|
const {body, validationResult, oneOf} = require('express-validator/check');
|
|
4
4
|
const ticketWorkLogController = require('../controller/ticketWorkLogController');
|
|
5
|
+
const ticketValidationUtil = require('../util/ticketValidationUtil');
|
|
5
6
|
const eventLog = require('../controller/eventLogController');
|
|
6
7
|
const CONSTANTS = require('../util/constants');
|
|
7
8
|
|
|
@@ -13,6 +14,25 @@ module.exports = (function() {
|
|
|
13
14
|
return `${location}[${param}]: ${msg}`;
|
|
14
15
|
};
|
|
15
16
|
|
|
17
|
+
ticketWorkLogRoutes.use(async function (req, res, next) {
|
|
18
|
+
const id = req.parentId;
|
|
19
|
+
log.debug('Check Ticket Access and Id');
|
|
20
|
+
|
|
21
|
+
const ticket = await ticketValidationUtil.checkTicket(req.ticketConfig, id, req.globalScriptParams);
|
|
22
|
+
log.error(ticket);
|
|
23
|
+
|
|
24
|
+
if (ticket && ticket.data) {
|
|
25
|
+
if (ticket.data.id) {
|
|
26
|
+
req.parentId = ticket.data.id;
|
|
27
|
+
}
|
|
28
|
+
log.error(ticket.data.id);
|
|
29
|
+
next();
|
|
30
|
+
} else {
|
|
31
|
+
req.errorStatus = 404;
|
|
32
|
+
next(`Ticket ${id} does not exist`);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
16
36
|
ticketWorkLogRoutes.get('/', function (req, res, next) {
|
|
17
37
|
const id = req.parentId;
|
|
18
38
|
eventLog.setEventData(
|
package/util/config.js
CHANGED
|
@@ -284,6 +284,15 @@ function checkClientConfig(client) {
|
|
|
284
284
|
clientConfig[clientKey] = clientConfigItemTemplate;
|
|
285
285
|
}
|
|
286
286
|
});
|
|
287
|
+
|
|
288
|
+
if (!clientConfig.options) {
|
|
289
|
+
clientConfig.options = {};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (clientConfig.options.translateSelectionFields === undefined) {
|
|
293
|
+
clientConfig.options.translateSelectionFields = true;
|
|
294
|
+
}
|
|
295
|
+
|
|
287
296
|
client.config = clientConfig;
|
|
288
297
|
//save
|
|
289
298
|
setClient(client.name, client);
|
package/util/responsehandler.js
CHANGED
|
@@ -72,6 +72,19 @@ function eventQueueHandler(req, res, next) {
|
|
|
72
72
|
//write to eventQueue if provided
|
|
73
73
|
if (req.eventData) {
|
|
74
74
|
const eventData = req.eventData;
|
|
75
|
+
if (process.env.LOG_REQUEST && (process.env.LOG_REQUEST === true || process.env.LOG_REQUEST.toLowerCase() === 'true')) {
|
|
76
|
+
if (!eventData.jsonData) {
|
|
77
|
+
eventData.jsonData = {};
|
|
78
|
+
}
|
|
79
|
+
eventData.jsonData['req'] = {
|
|
80
|
+
headers: req.headers,
|
|
81
|
+
body: req.body
|
|
82
|
+
}
|
|
83
|
+
// remove auth header
|
|
84
|
+
if (eventData.jsonData.req && eventData.jsonData.req.headers && eventData.jsonData.req.headers.authorization) {
|
|
85
|
+
eventData.jsonData.req.headers.authorization = '*** REMOVED ***';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
75
88
|
eventLog.createSuccessLog(
|
|
76
89
|
req.id,
|
|
77
90
|
req.user.config.clientId,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const ticketController = require("../controller/ticketController");
|
|
3
|
+
const log = require('@manyos/logger').setupLog('SMILEconnect_' + path.basename(__filename));
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
async function checkTicket(ticketConfig, id, globalScriptParams) {
|
|
7
|
+
const myClientConfig = {};
|
|
8
|
+
const fields = [];
|
|
9
|
+
const myMapping = [];
|
|
10
|
+
const requestType = ticketConfig.requestType;
|
|
11
|
+
if (requestType === 'incident') {
|
|
12
|
+
fields.push('Incident Number');
|
|
13
|
+
myMapping.push({"oldName":'Incident Number', "newName" : "id"});
|
|
14
|
+
} else if (requestType === 'change') {
|
|
15
|
+
fields.push('Infrastructure Change ID');
|
|
16
|
+
myMapping.push({"oldName":'Infrastructure Change ID', "newName" : "id"});
|
|
17
|
+
} else if (requestType === 'problem') {
|
|
18
|
+
fields.push('Problem Investigation ID');
|
|
19
|
+
myMapping.push({"oldName":'Problem Investigation ID', "newName" : "id"});
|
|
20
|
+
} else if (requestType === 'workOrder') {
|
|
21
|
+
fields.push('Work Order ID');
|
|
22
|
+
myMapping.push({"oldName":'Work Order ID', "newName" : "id"});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//An dieser Stelle könnte auch die Basequery vom User verwendet werden. Dann gibt es nur noch Zugriff auf Tickets die der User auch sieht. Am besten per Config steuern.
|
|
26
|
+
|
|
27
|
+
myClientConfig[ticketConfig.requestType] = {
|
|
28
|
+
baseQuery: '1=1',
|
|
29
|
+
fields
|
|
30
|
+
};
|
|
31
|
+
return await ticketController.getTicket(ticketConfig, myClientConfig, id, myMapping, undefined, globalScriptParams);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
checkTicket
|
|
36
|
+
};
|