@manyos/smileconnect-api 1.39.0 → 1.39.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/app.js CHANGED
@@ -236,8 +236,7 @@ app.use(passport.authenticate('jwt', {session: false}), responseHandler.logReque
236
236
  //set globalscript params
237
237
  app.use(function (req, res, next) {
238
238
  req.globalScriptParams = {
239
- query: req.query,
240
- params: req.params
239
+ query: req.query
241
240
  }
242
241
  next()
243
242
  });
package/docs/_config.yml CHANGED
@@ -24,6 +24,8 @@ navbar-links:
24
24
  Resources:
25
25
  - Architecture: "general/architecture"
26
26
  - Configuration: "general/config"
27
+ - Scripts: "configuration/scripts"
28
+ - Adapter: "configuration/adapter"
27
29
  - Specification: "spec/index.html"
28
30
  How-Tos:
29
31
  - Authenticate: "howto/token"
@@ -0,0 +1,317 @@
1
+ ---
2
+ layout: page
3
+ title: Adapter
4
+ subtitle: Talk to the outside world
5
+ use-site-title: true
6
+ bigimg: /img/gb-isapi.jpg
7
+ toc: true
8
+ ---
9
+
10
+ # Introduction
11
+
12
+ Adapter are used to integrate with different systems. SMILEconnect comes with a flexible adapter architecture. Multiple types of adapters can be used and also multiple adapters of the same type can be configured. This can be useful if you need to interact e.g. with two different LDAP Systems.
13
+
14
+ # Adapter Configuration
15
+
16
+ Adapter are configured in the file *adapterConfig.js* in the root of the conf folder. Within the configuration file the variable *env* can be used to access system environment variables. E.g. *env.AR_USER* reflects the value of the system variable *AR_USER*.
17
+
18
+ For security, it is advised to store confidential information, like passwords, in the environment variables and not in the configuration file itself.
19
+
20
+ Configuration example:
21
+ ```javascript
22
+ const adapterParams = {
23
+ remedy: {
24
+ type: "remedy",
25
+ arServer: env.AR_SERVER,
26
+ arUser: env.AR_USER,
27
+ arPassword: env.AR_PASSWORD,
28
+ arPort: env.AR_PORT,
29
+ rapiUri: env.RAPI_URL,
30
+ cacheTime: env.AR_CACHE_TTL,
31
+ limitDefault: env.LIMIT_DEFAULT || 100,
32
+ limitMax: env.LIMIT_MAX
33
+ },
34
+ ldap: {
35
+ type: "ldap",
36
+ ldapUrl: env.LDAP_URL,
37
+ ldapBind: env.LDAP_BIND,
38
+ ldapSecret: env.LDAP_SECRET
39
+ },
40
+ ldapIDM: {
41
+ type: "ldap",
42
+ ldapUrl: env.LDAP_IDM_URL,
43
+ ldapBind: env.LDAP_IDM_BIND,
44
+ ldapSecret: env.LDAP_IDM_SECRET
45
+ },
46
+ smileconnect: {
47
+ type: "SMILEconnect",
48
+ clientId: env.SC_CLIENT,
49
+ secret: env.SC_SECRET,
50
+ ssoUrl: env.SC_SSO_URL,
51
+ smileConnectUrl: env.SC_SMILECONNECT_URL
52
+ }
53
+ };
54
+
55
+ // noinspection JSAnnotator
56
+ return adapterParams;
57
+ ```
58
+
59
+ The different Adapter and their configuration values are described in detail below.
60
+
61
+ ## Remedy
62
+
63
+ The Remedy Adapter is used to connect to BMC Remedy Action Request Servers. It allows you to create, query and update records.
64
+
65
+ ### Configuration values
66
+
67
+ **arServer**: The name of the arsystem server. e.g. ars1.mydomain.com
68
+
69
+ **arUser**: The user which is used to connect to the remedy server. E.g. Allen
70
+
71
+ **arPassword**: The password of the ar user.
72
+
73
+ **arPort**: The port of the arsystem server. e.g. 5142. Use 0 if you want to a portmapper.
74
+
75
+ **rapiUri**: The URL of the RAPI Server wich is used as middleware to connect to the arsystem server. e.g. https://rapi.mydomain.com
76
+
77
+ **cacheTime**: The default time in seconds in which the result of queries is stored in a cache. This is used to increase performance dramatically. Defaults to 300s.
78
+
79
+ **limitDefault**: The default limit of records retrieved in a query. This value is used whenever no value is specified. Can be overwritten in queries.
80
+
81
+ **limitMax**: The maximum number of records retrieved in a query. This parameter can be used to enforce a limit. The limit can not be overwritten by queries.
82
+
83
+ ### Functions
84
+
85
+ #### Search
86
+
87
+ ```javascript
88
+ async function search(form, query, fields, options)
89
+ ```
90
+
91
+ Parameter:
92
+
93
+ * form (string):
94
+
95
+ The form used to query data. e.g. CTM:People
96
+
97
+ * query (string):
98
+
99
+ The query used in the form. e.g. 'Remedy Login ID' = "Allen"
100
+
101
+ * fields (comma separated list):
102
+
103
+ The fields to be returned by the query. e.g. "Full Name, Remedy Login ID, First Name, Last Name, Department"
104
+
105
+ Full example:
106
+ ```javascript
107
+ const result = await adapter.remedy.search(
108
+ "CTM:People",
109
+ "'Remedy Login ID' = \"Allen\"",
110
+ "Full Name, Remedy Login ID, First Name, Last Name, Department");
111
+ ```
112
+
113
+ Will return an object with a data array and some meta data.
114
+
115
+ ```javascript
116
+ {
117
+ "status": "success",
118
+ "query": "'Remedy Login ID' = \"Allen\"",
119
+ "server": "arserver:51423",
120
+ "form": "CTM:People",
121
+ "runtime": 106,
122
+ "dataSize": 1,
123
+ "data": [
124
+ {
125
+ "Person ID": "PPL000000000013",
126
+ "Remedy Login ID": "Allen",
127
+ "Department": "Customer Service",
128
+ "Full Name": "Allen Allbrook",
129
+ "Last Name": "Allbrook",
130
+ "First Name": "Allen"
131
+ }
132
+ ]
133
+ }
134
+ ```
135
+
136
+
137
+ #### Create
138
+
139
+ ```javascript
140
+ async function create(form, entry, options)
141
+ ```
142
+
143
+ Parameter:
144
+
145
+ * form (string):
146
+
147
+ The form in which a new record is created. e.g. CTM:People
148
+
149
+ * entry (object):
150
+
151
+ The entry object that is ceated.
152
+
153
+ e.g.
154
+
155
+ ```javascript
156
+ {
157
+ "Source Keyword": "SMILEcatalog",
158
+ "Company": "Calbro Services",
159
+ "AppRequestSummary": "New Request from SMILEcatalog",
160
+ "TitleInstanceID": "SRGAA5V0GEfds7LO5YL6Q945Z",
161
+ "Login ID": "Allen"
162
+ }
163
+ ```
164
+
165
+ Full example:
166
+
167
+ ```javascript
168
+ const settings = {
169
+ "createForm":"SRM:RequestInterface_Create",
170
+ "entry": {
171
+ "Source Keyword": "SMILEcatalog",
172
+ "Company": "Calbro Services",
173
+ "AppRequestSummary": "New Request from SMILEcatalog",
174
+ "TitleInstanceID": "SRGAA5V0GEfds7LO5YL6Q945Z",
175
+ "Login ID": "Allen"
176
+ }
177
+ };
178
+ //Create Service Request
179
+ const resultCreate = await adapter.remedy.create(settings.createForm, settings.entry);
180
+ ```
181
+
182
+ Will return return the id of the created record. e.g. REQ00000002893
183
+
184
+ #### Options
185
+
186
+ * limit
187
+
188
+ The maximum number of records that should be returned by this query. e.g. 5. Use this value to increase performance or to overwrite a default limit.
189
+
190
+ * offset
191
+
192
+ Use together with limit to allow pagination. e.g. limit=10 & offset=10
193
+
194
+ * dateFormat
195
+
196
+ The format in which dates are returned.
197
+
198
+ * sort
199
+
200
+ The fields that are to sort the result on the remedy server. Use 1 for ascending and -1 for descending order.
201
+
202
+ e.g.
203
+ ```javascript
204
+ {
205
+ "Name": 1,
206
+ "Status": -1
207
+ }
208
+ ```
209
+
210
+ * countOnly (only search)
211
+
212
+ Can be used to retrieve only the size of the results without any payload. This improves performance.
213
+
214
+ Full example:
215
+
216
+ ```javascript
217
+ const options = {
218
+ limit: 100,
219
+ offset: 100,
220
+ dafeFormat: "yyyy-MM-dd HH:mm:ss.SSSZ",
221
+ sort: {
222
+ "Name": 1,
223
+ "Status": -1
224
+ }
225
+ }
226
+ ```
227
+
228
+ ## LDAP
229
+
230
+
231
+ ### Configuration values
232
+
233
+ * ldapUrl
234
+
235
+ The connection URL of the LDAP Server. e.g. ldap://ldap.forumsys.com:389
236
+
237
+ * ldapBind
238
+
239
+ The Bind DN to authenticate with. e.g. cn=smilecatalog-user,dc=example,dc=com
240
+
241
+ * ldapSecret
242
+
243
+ The secret to use with the Bind DN. e.g. password
244
+
245
+ ### Functions
246
+
247
+
248
+ #### Search
249
+
250
+ ```javascript
251
+ async search(base, options)
252
+ ```
253
+ Runs a query against the ldap Server.
254
+
255
+ Parameter:
256
+
257
+ * base
258
+
259
+ A DN string to start.
260
+
261
+ * options
262
+
263
+ Options for the search. Like filters and returned attributes. See http://ldapjs.org/client.html for more details.
264
+
265
+ ```javascript
266
+ const opts = {
267
+ filter: '(&(l=Seattle)(email=*@foo.com))',
268
+ scope: 'sub',
269
+ attributes: ['dn', 'sn', 'cn']
270
+ };
271
+ ```
272
+
273
+ Full example:
274
+
275
+ ```javascript
276
+ const base = "dc=example,dc=com";
277
+ const options = {
278
+ attributes: ['dn', 'sn', 'cn'],
279
+ scope: "sub",
280
+ filter: "sn=Riemann"
281
+ }
282
+ const result = await adapter.ldap.search(base, options);
283
+ resolve(result);
284
+ ```
285
+
286
+ Returns an array of records. e.g.
287
+
288
+ ```javascript
289
+ [
290
+ {
291
+ "dn": "uid=riemann,dc=example,dc=com",
292
+ "controls": [],
293
+ "cn": "Bernhard Riemann",
294
+ "sn": "Riemann"
295
+ }
296
+ ]
297
+ ```
298
+
299
+ ## SMILEconnect
300
+
301
+ The SMILEconnect Adapter can be used to do calls against SMILEconnect. It will act as it is called externally.
302
+
303
+ ### Configuration values
304
+
305
+ **smileConnectUrl**: The url of your SMILEconnect installation e.g. https://smileconnect.mydomain.io
306
+
307
+ **ssoUrl**: The url of the oidc identity provider. e.g. https://sso.mydomain.io/auth/realms/smileconnect
308
+
309
+ **clientId**: The name of the client that is used to connect to SMILEconnect
310
+
311
+ **secret**: The secret of the client. e.g. jd92hd-03283d-2293s-232
312
+
313
+ ### Functions
314
+
315
+ The SMILEconnect adapter is an open source project.
316
+
317
+ [Visit the project homepage for details]https://github.com/manyosit/smileconnect-client
@@ -0,0 +1,207 @@
1
+ ---
2
+ layout: page
3
+ title: Scripts
4
+ subtitle: How-to modify data
5
+ use-site-title: true
6
+ bigimg: /img/gb-isapi.jpg
7
+ ---
8
+
9
+ # Introduction
10
+
11
+ Scripts are used to modify requests, gather data or to drive external actions.
12
+
13
+ Scripts can call adapter to interact with other systems and they can be reused.
14
+
15
+ #### **`workOrder_lookupSericeNameByReconId`**
16
+ ```javascript
17
+ //lookup service ci name if reconId is given
18
+
19
+ if (requestData['ReconciliationIdentity']) {
20
+ const remedyResult = await adapter.remedy.search("BMC.CORE:BMC_BusinessService", `'ReconciliationIdentity' = "${requestData['ReconciliationIdentity']}" AND 'DatasetId' = "BMC.ASSET"`, "Name")
21
+
22
+ if (remedyResult && remedyResult.data && remedyResult.data[0]) {
23
+ const data = remedyResult.data[0];
24
+ requestData['CI Name'] = data['Name'];
25
+ }
26
+
27
+ }
28
+ resolve()
29
+ ```
30
+
31
+ The above script will lookup the service name for a given reconciliation id.
32
+
33
+ # Accessible Variables
34
+
35
+ Within scripts the following variables are available.
36
+
37
+ ## params
38
+
39
+ The parameter params can be defined in a script and used when another script is called. This is useful to reuse scripts.
40
+
41
+ e.g.
42
+ ```javascript
43
+ const returnValue = await script('ars101', {}, params);
44
+ ```
45
+
46
+ ## globalScriptParams
47
+
48
+ Global script params are set by the application and handed over to the script. They include the following parameter:
49
+
50
+ * query: This property is an object containing a property for each query string parameter in the route.
51
+ * id: the id of the ticket. Only set in GET & PUT actions
52
+ * id2: the id of child ticket. e.g. Tasks or Worklogs. Only set in GET & PUT actions
53
+ * id2: the id of child worklogs. e.g. Tasksworklog. Only set in GET & PUT actions
54
+ * classId: the classId of cmdbobjects. Only set in POST & PUT actions
55
+
56
+ ```json
57
+ {
58
+ "query": {
59
+ "includeObjects": "true",
60
+ "limit": "3",
61
+ "include": "supportGroupRelations,persons"
62
+ },
63
+ "id": "INC000000001507"
64
+ }
65
+ ```
66
+
67
+ ## requestData
68
+
69
+ This parameter holds the complete request data.
70
+
71
+ ## clientId
72
+
73
+ This id of the client who executes the script.
74
+
75
+ ## executedByScript
76
+
77
+ This parameter will be set to *true* if the script is executed by another script.
78
+
79
+ ## env
80
+
81
+ This parameter allows access to the environment variables.
82
+
83
+ ## log
84
+
85
+ Can be used to write data to the applications log stream.
86
+
87
+ The following log level can be used:
88
+
89
+ * trace
90
+ * debug
91
+ * info
92
+ * warn
93
+ * error
94
+ * fatal
95
+
96
+ e.g.
97
+
98
+ ```javascript
99
+ log.debug('log text', variable);
100
+ log.info('log text', variable);
101
+ log.error('error text', variable);
102
+ ```
103
+
104
+ ## script
105
+
106
+ Can be used to execute a script within a script.
107
+
108
+ script(scriptId, requestData, params, scope)
109
+
110
+ e.g.
111
+ ```javascript
112
+ const returnValue = await script('ars101', {}, params);
113
+ ```
114
+
115
+ For more information see subscripts.
116
+
117
+ ## fetch
118
+
119
+ Allows access to external webservices via the package *node-fetch*
120
+
121
+ See https://www.npmjs.com/package/node-fetch for details.
122
+
123
+ ## adapter
124
+
125
+ Allows to make adapter calls. [See details](../configuration/adapter.md)
126
+
127
+ # Returning values
128
+
129
+ Values can be returned with the fuction *resolve()*
130
+
131
+ e.g.
132
+
133
+ ```javascript
134
+ const values = [
135
+ "value1",
136
+ "value2",
137
+ "value3"
138
+ ]
139
+ resolve (values)
140
+ ```
141
+
142
+ # Error handling
143
+
144
+ Values can be returned with the fuction *reject()*
145
+
146
+ e.g.
147
+
148
+ ```javascript
149
+ if (!params.form) {
150
+ reject("The parameter form is required")
151
+ }
152
+ ```
153
+
154
+ # Async calls
155
+
156
+ Within scripts *await* can be used to make async calls.
157
+
158
+ ```javascript
159
+ const returnValue = await script('ars101', {}, params);
160
+ ```
161
+
162
+ # Samples
163
+
164
+ ## Simple Static Menu
165
+
166
+ This script creates the data for a simple static menu in a Selection (Drop Down) field.
167
+
168
+ ```javascript
169
+ const data = [
170
+ {
171
+ "value": "Menu Item 1",
172
+ "label": "internalVal1"
173
+ },
174
+ {
175
+ "value": "Menu Item 2",
176
+ "label": "internalVal2"
177
+ },
178
+ {
179
+ "value": "Menu Item 3",
180
+ "label": "internalVal3"
181
+ },
182
+ {
183
+ "value": "Menu Item 4",
184
+ "label": "internalVal4"
185
+ }
186
+ ];
187
+ resolve(data);
188
+
189
+ ```
190
+
191
+ ## Simple Query Menu
192
+
193
+ This script calls another script query data for a menu.
194
+
195
+ ```javascript
196
+ //prepare params
197
+ const params = {
198
+ "query": "'Remedy Login ID'=\"astern\"",
199
+ "form": "CTM:People",
200
+ "labelField": "Full Name",
201
+ "valueField": "Remedy Login ID"
202
+ };
203
+ //execute script
204
+ const personResult = await script('remedy/ars101', {}, params, "global");
205
+ //return parameter
206
+ resolve(personResult);
207
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manyos/smileconnect-api",
3
- "version": "1.39.0",
3
+ "version": "1.39.1",
4
4
  "description": "A proxy and abstraction layer for BMCs IT Service Management Suite",
5
5
  "main": "app.js",
6
6
  "scripts": {
@@ -107,6 +107,7 @@ module.exports = (function () {
107
107
  cmdbObjectRoutes.get('/:id', passport.authenticate('jwt', {session: false}),
108
108
  function (req, res, next) {
109
109
  const id = req.params.id;
110
+ req.globalScriptParams.id = id
110
111
  const includeString = req.query.include;
111
112
  eventLog.setEventData(
112
113
  req,
@@ -165,6 +166,8 @@ module.exports = (function () {
165
166
  const id = req.params.id;
166
167
  const classId = req.body.classId;
167
168
  const includeString = req.query.include;
169
+ req.globalScriptParams.id = id
170
+ req.globalScriptParams.classId = classId
168
171
  eventLog.setEventData(
169
172
  req,
170
173
  CONSTANTS.EVENT_BASE_AST,
@@ -200,6 +203,7 @@ module.exports = (function () {
200
203
  cmdbObjectRoutes.post('/', checkSchema(fieldMappingSchemas.CMDBCreateDataSchema), async function (req, res, next) {
201
204
  const classId = req.body.classId;
202
205
  const includeString = req.query.include;
206
+ req.globalScriptParams.classId = classId
203
207
  eventLog.setEventData(
204
208
  req,
205
209
  CONSTANTS.EVENT_BASE_AST,
@@ -215,6 +219,7 @@ module.exports = (function () {
215
219
  const result = [];
216
220
  try {
217
221
  const ciInstanceId = await cmdbobjects.createCmdbObject(req.ticketConfig, req.user.config, classId, req.body.data, req.globalScriptParams);
222
+ req.globalScriptParams.id = ciInstanceId
218
223
  const ci = await cmdbobjects.getCmdbObject(req.user.config, ciInstanceId, includeString, undefined, req.globalScriptParams);
219
224
  req.result = ci;
220
225
  next();
@@ -130,6 +130,7 @@ module.exports = (function() {
130
130
  });
131
131
 
132
132
  function getRecord(req, res, next, clientConfig, id, mapping, includeString) {
133
+ req.globalScriptParams.id = id
133
134
  customFormController.getRecord(req.formConfig, clientConfig, id, mapping, includeString, globalScriptParams).then(function (result) {
134
135
  log.debug('result', result);
135
136
  req.includeObjectsList = result.included;
@@ -145,6 +146,7 @@ module.exports = (function() {
145
146
 
146
147
  routes.put('/:id', function (req, res, next) {
147
148
  const id = req.params.id;
149
+ req.globalScriptParams.id = id
148
150
  const origData = JSON.parse(JSON.stringify(req.body));
149
151
  const includeString = req.query.include;
150
152
  eventLog.setEventData(
@@ -85,6 +85,8 @@ module.exports = (function () {
85
85
  taskRoutes.get('/:taskId', async function (req, res, next) {
86
86
  const parentId = req.parentId;
87
87
  const taskId = req.params.taskId;
88
+ req.globalScriptParams.id = parentId
89
+ req.globalScriptParams.id2 = taskId
88
90
  eventLog.setEventData(
89
91
  req,
90
92
  req.parentEventBase + '_' + CONSTANTS.EVENT_BASE_TAS,
@@ -103,6 +105,8 @@ module.exports = (function () {
103
105
 
104
106
  taskRoutes.put('/:taskId', function (req, res, next) {
105
107
  const taskId = req.params.taskId;
108
+ req.globalScriptParams.id = req.parentId;
109
+ req.globalScriptParams.id2 = taskId
106
110
  const origData = JSON.parse(JSON.stringify(req.body));
107
111
  eventLog.setEventData(
108
112
  req,
@@ -134,6 +138,8 @@ module.exports = (function () {
134
138
 
135
139
  taskRoutes.get('/:taskId/worklogs', async function (req, res, next) {
136
140
  const taskId = req.params.taskId;
141
+ req.globalScriptParams.id = req.parentId;
142
+ req.globalScriptParams.id2 = taskId
137
143
  eventLog.setEventData(
138
144
  req,
139
145
  req.parentEventBase + '_' + CONSTANTS.EVENT_BASE_TAS,
@@ -158,6 +164,8 @@ module.exports = (function () {
158
164
 
159
165
  const origData = JSON.parse(JSON.stringify(req.body));
160
166
  const taskId = req.params.taskId;
167
+ req.globalScriptParams.id = req.parentId;
168
+ req.globalScriptParams.id2 = taskId
161
169
  eventLog.setEventData(
162
170
  req,
163
171
  req.parentEventBase + '_' + CONSTANTS.EVENT_BASE_TAS,
@@ -199,6 +207,9 @@ module.exports = (function () {
199
207
  taskRoutes.get('/:taskId/worklogs/:worklogId', async function (req, res, next) {
200
208
  const taskId = req.params.taskId;
201
209
  const worklogId = req.params.worklogId;
210
+ req.globalScriptParams.id = req.parentId;
211
+ req.globalScriptParams.id2 = taskId
212
+ req.globalScriptParams.id3 = worklogId
202
213
  eventLog.setEventData(
203
214
  req,
204
215
  req.parentEventBase + '_' + CONSTANTS.EVENT_BASE_TAS,
@@ -136,6 +136,7 @@ module.exports = (function() {
136
136
  });
137
137
 
138
138
  function getTicket(req, res, next, clientConfig, id, mapping, includeString) {
139
+ req.globalScriptParams.id = id
139
140
  ticketController.getTicket(req.ticketConfig, clientConfig, id, mapping, includeString, req.globalScriptParams).then(function (result) {
140
141
  log.debug('result', result);
141
142
  req.includeObjectsList = result.included;
@@ -151,6 +152,7 @@ module.exports = (function() {
151
152
 
152
153
  ticketRoutes.put('/:id', function (req, res, next) {
153
154
  const id = req.params.id;
155
+ req.globalScriptParams.id = id
154
156
  const origData = JSON.parse(JSON.stringify(req.body));
155
157
  const includeString = req.query.include;
156
158
  eventLog.setEventData(
@@ -36,6 +36,8 @@ module.exports = (function() {
36
36
  ticketWorkLogRoutes.get('/:worklogId', function (req, res, next) {
37
37
  const ticketId = req.parentId;
38
38
  const worklogId = req.params.worklogId;
39
+ req.globalScriptParams.id = ticketId
40
+ req.globalScriptParams.id2 = worklogId
39
41
  eventLog.setEventData(
40
42
  req,
41
43
  req.parentEventBase,
@@ -167,6 +169,8 @@ module.exports = (function() {
167
169
  .then(result => {
168
170
  const worklogId = result['0'];
169
171
  req.eventData.ticketNumber2 = worklogId;
172
+ req.globalScriptParams.id = ticketId
173
+ req.globalScriptParams.id2 = worklogId
170
174
  log.debug('WorkLog created', worklogId);
171
175
  ticketWorkLogController.getWorklog(req.ticketConfig, req.user.config, ticketId, worklogId, undefined, req.globalScriptParams).then(worklogResult => {
172
176
  req.result = worklogResult;