scimgateway 4.5.1 → 4.5.4

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/README.md CHANGED
@@ -321,6 +321,19 @@ Below shows an example of config\plugin-saphana.json
321
321
  "replaceDomains": []
322
322
  }
323
323
  }
324
+ },
325
+ "publisher": {
326
+ "enabled": false,
327
+ "entity": {
328
+ "undefined": {
329
+ "nats": {
330
+ "tenant": null,
331
+ "subject": null,
332
+ "jwt": null,
333
+ "secret": null
334
+ }
335
+ }
336
+ }
324
337
  }
325
338
  }
326
339
  },
@@ -1150,6 +1163,36 @@ MIT © [Jarle Elshaug](https://www.elshaug.xyz)
1150
1163
 
1151
1164
  ## Change log
1152
1165
 
1166
+ ### v4.5.4
1167
+
1168
+ [Fixed]
1169
+
1170
+ - Delete User missing url-decoding of id e.g. using ldap-dn as id
1171
+
1172
+ ### v4.5.3
1173
+
1174
+ [Fixed]
1175
+
1176
+ - plugin-api configuration file having new credentials for dummy-json testing
1177
+
1178
+ [Improved]
1179
+
1180
+ - Dependencies bump
1181
+ - plugin-loki and plugin-mongodb, minor improvements for handling raw mulitivalue updates when not using default skipTypeConvert=false
1182
+ - endpointMapper supporting comma separated string to be converted to array, e.g.:
1183
+ SCIM otherMails = "myAlias1@company.com,myAlias2@company.com,myAlias3@company.com"
1184
+
1185
+ endpointMapper configuration for endpoint attribute emails of type array:
1186
+
1187
+ "map": {
1188
+ "user": {
1189
+ "emails": {
1190
+ "mapTo": "otherMails",
1191
+ "type": "array",
1192
+ "typeInbound": "string"
1193
+ },
1194
+ ...
1195
+
1153
1196
  ### v4.5.1
1154
1197
 
1155
1198
  [Improved]
@@ -141,8 +141,8 @@
141
141
  "oauth": null,
142
142
  "tokenAuth": {
143
143
  "tokenUrl": "https://dummyjson.com/auth/login",
144
- "username": "jissetts",
145
- "password": "ePawWgrnZR8L"
144
+ "username": "emilys",
145
+ "password": "emilyspass"
146
146
  },
147
147
  "bearerAuth": null,
148
148
  "basicAuth": null,
@@ -471,6 +471,8 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
471
471
  const guid = Buffer.from(id, 'base64').toString('hex')
472
472
  base = `<GUID=${guid}>`
473
473
  } else base = id // dn
474
+
475
+ if (Object.keys(endpointObj).length < 1) return null
474
476
  const ldapOptions = {
475
477
  operation: 'replace',
476
478
  modification: endpointObj
@@ -289,8 +289,20 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
289
289
  if (!userObj[key] || !Array.isArray(userObj[key])) userObj[key] = []
290
290
  // delete
291
291
  userObj[key] = userObj[key].filter(el => {
292
- if (delArr.findIndex(e => e.value === el.value) >= 0) return false
293
- return true
292
+ const index = delArr.findIndex(e => {
293
+ let elExist = false
294
+ for (const k in el) {
295
+ if (k === 'primary') continue
296
+ if (el[k] !== e[k]) {
297
+ elExist = false
298
+ break
299
+ }
300
+ elExist = true
301
+ }
302
+ return elExist
303
+ })
304
+ if (index >= 0) return false
305
+ else return true
294
306
  })
295
307
  // add
296
308
  addArr.forEach(el => {
@@ -303,7 +315,18 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
303
315
  }
304
316
  }
305
317
  }
306
- userObj[key].push(el)
318
+ const index = userObj[key].findIndex(e => { // avoid adding existing
319
+ let elExist = false
320
+ for (const k in el) {
321
+ if (el[k] !== e[k]) {
322
+ elExist = false
323
+ break
324
+ }
325
+ elExist = true
326
+ }
327
+ return elExist
328
+ })
329
+ if (index < 0) userObj[key].push(el)
307
330
  })
308
331
  } else if (scimgateway.isMultiValueTypes(key)) { // "type converted object" logic and original blank type having type "undefined"
309
332
  if (!attrObj[key]) delete userObj[key] // blank or null
@@ -375,8 +375,20 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
375
375
  if (!userObj[key] || !Array.isArray(userObj[key])) userObj[key] = []
376
376
  // delete
377
377
  userObj[key] = userObj[key].filter(el => {
378
- if (delArr.findIndex(e => e.value === el.value) >= 0) return false
379
- return true
378
+ const index = delArr.findIndex(e => {
379
+ let elExist = false
380
+ for (const k in el) {
381
+ if (k === 'primary') continue
382
+ if (el[k] !== e[k]) {
383
+ elExist = false
384
+ break
385
+ }
386
+ elExist = true
387
+ }
388
+ return elExist
389
+ })
390
+ if (index >= 0) return false
391
+ else return true
380
392
  })
381
393
  // add
382
394
  addArr.forEach(el => {
@@ -389,7 +401,18 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
389
401
  }
390
402
  }
391
403
  }
392
- userObj[key].push(el)
404
+ const index = userObj[key].findIndex(e => { // avoid adding existing
405
+ let elExist = false
406
+ for (const k in el) {
407
+ if (el[k] !== e[k]) {
408
+ elExist = false
409
+ break
410
+ }
411
+ elExist = true
412
+ }
413
+ return elExist
414
+ })
415
+ if (index < 0) userObj[key].push(el)
393
416
  })
394
417
  } else if (scimgateway.isMultiValueTypes(key)) { // "type converted object" logic and original blank type having type "undefined"
395
418
  if (!attrObj[key]) delete userObj[key] // blank or null
@@ -1353,7 +1353,7 @@ const ScimGateway = function () {
1353
1353
  let u = ctx.request.originalUrl.substr(0, ctx.request.originalUrl.lastIndexOf('/'))
1354
1354
  u = u.substr(u.lastIndexOf('/') + 1) // u = Users, Groups
1355
1355
  const handle = handler[u]
1356
- const id = ctx.params.id
1356
+ const id = decodeURIComponent(ctx.params.id)
1357
1357
  logger.debug(`${gwName}[${pluginName}] [Delete ${handle.description}] id=${id}`)
1358
1358
 
1359
1359
  try {
@@ -2658,13 +2658,15 @@ ScimGateway.prototype.endpointMapper = function endpointMapper (direction, parse
2658
2658
  else {
2659
2659
  if (dotMap[`${key}.typeInbound`] && dotMap[`${key}.typeInbound`] === 'string') {
2660
2660
  if (!dotNewObj[newStr]) dotNewObj[newStr] = dotParse[`${key}.${dotArrIndex}`]
2661
- else dotNewObj[newStr] = `${dotNewObj[newStr]}, ${dotParse[`${key}.${dotArrIndex}`]}`
2661
+ else dotNewObj[newStr] = `${dotParse[`${key}.${dotArrIndex}`]},${dotNewObj[newStr]}`
2662
2662
  } else dotNewObj[`${newStr}.${dotArrIndex}`] = dotParse[`${key}.${dotArrIndex}`]
2663
2663
  }
2664
2664
  } else { // type=array but element is not array
2665
2665
  if (multiValue) dotNewObj[`${newStr}.0.value`] = dotParse[key]
2666
2666
  else dotNewObj[newStr] = dotParse[key]
2667
- if (!inboundArrCheck.includes(newStr)) inboundArrCheck.push(newStr) // will be checked
2667
+ if (!dotMap[`${key}.typeInbound`] || dotMap[`${key}.typeInbound`] !== 'string') {
2668
+ if (!inboundArrCheck.includes(newStr)) inboundArrCheck.push(newStr) // will be checked
2669
+ }
2668
2670
  }
2669
2671
  } else { // none array
2670
2672
  // let mapTo = mapObj[key].mapTo
@@ -2748,7 +2750,6 @@ ScimGateway.prototype.endpointMapper = function endpointMapper (direction, parse
2748
2750
  if (!dotPath) dotKey = key
2749
2751
  else dotKey = `${dotPath}.${key}`
2750
2752
  if (direction === 'outbound') { // outbound
2751
- if (obj[key] === '') obj[key] = null
2752
2753
  if (dotMap[`${dotKey}.type`]) {
2753
2754
  const type = dotMap[`${dotKey}.type`].toLowerCase()
2754
2755
  if (type === 'boolean' && obj[key].constructor === String) {
@@ -2757,7 +2758,7 @@ ScimGateway.prototype.endpointMapper = function endpointMapper (direction, parse
2757
2758
  } else if (type === 'array') {
2758
2759
  if (!Array.isArray(obj[key])) {
2759
2760
  if (!obj[key]) obj[key] = []
2760
- else obj[key] = [obj[key]]
2761
+ else obj[key] = obj[key].split(',').map(item => item.trim())
2761
2762
  }
2762
2763
  } else if (dotMap.sAMAccountName) { // Active Directory
2763
2764
  if (dotMap[`${dotKey}.mapTo`].startsWith('addresses.') && dotMap[`${dotKey}.mapTo`].endsWith('.country')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scimgateway",
3
- "version": "4.5.1",
3
+ "version": "4.5.4",
4
4
  "description": "Using SCIM protocol as a gateway for user provisioning to other endpoints",
5
5
  "author": "Jarle Elshaug <jarle.elshaug@gmail.com> (https://elshaug.xyz)",
6
6
  "homepage": "https://elshaug.xyz",
@@ -32,24 +32,24 @@
32
32
  "dependencies": {
33
33
  "@godaddy/terminus": "^4.12.1",
34
34
  "callsite": "^1.0.0",
35
- "dot-object": "^2.1.4",
35
+ "dot-object": "^2.1.5",
36
36
  "fold-to-ascii": "^5.0.1",
37
37
  "https-proxy-agent": "^7.0.4",
38
38
  "is-in-subnet": "^4.0.1",
39
39
  "jsonwebtoken": "^9.0.2",
40
- "koa": "^2.15.2",
40
+ "koa": "^2.15.3",
41
41
  "koa-bodyparser": "^4.4.1",
42
42
  "koa-router": "^12.0.1",
43
43
  "ldapjs": "^3.0.7",
44
44
  "lokijs": "^1.5.12",
45
- "mongodb": "^6.5.0",
46
- "nats": "^2.19.0",
45
+ "mongodb": "^6.6.2",
46
+ "nats": "^2.26.0",
47
47
  "node-machine-id": "1.1.9",
48
48
  "nodemailer": "^6.9.13",
49
49
  "passport": "^0.7.0",
50
50
  "passport-azure-ad": "^4.3.5",
51
- "tedious": "^18.1.0",
52
- "winston": "^3.12.0"
51
+ "tedious": "^18.2.0",
52
+ "winston": "^3.13.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "chai": "^4.2.0",