scimgateway 4.5.4 → 4.5.6

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
@@ -1163,6 +1163,19 @@ MIT © [Jarle Elshaug](https://www.elshaug.xyz)
1163
1163
 
1164
1164
  ## Change log
1165
1165
 
1166
+ ### v4.5.6
1167
+
1168
+ [Improved]
1169
+
1170
+ - plugin-ldap preserve multivalue-attribute order on modify. Do not apply to groups/members.
1171
+
1172
+ ### v4.5.5
1173
+
1174
+ [Fixed]
1175
+
1176
+ - PUT /Groups/xxx failed on final group lookup and returned error
1177
+ - endpointMapper failed to correctly map customExtensions in certain use cases
1178
+
1166
1179
  ### v4.5.4
1167
1180
 
1168
1181
  [Fixed]
@@ -1110,7 +1110,15 @@ const doRequest = async (baseEntity, method, base, ldapOptions, ctx) => {
1110
1110
  for (const key in options.modification) {
1111
1111
  const mod = {}
1112
1112
  mod.type = key
1113
- if (Array.isArray(options.modification[key])) mod.values = options.modification[key]
1113
+ if (Array.isArray(options.modification[key])) {
1114
+ mod.values = options.modification[key]
1115
+ if (mod.values.length > 1) { // delete before replace to keep inbound order
1116
+ changes.push({
1117
+ operation: 'delete',
1118
+ modification: {type: key, values: []}
1119
+ })
1120
+ }
1121
+ }
1114
1122
  else {
1115
1123
  if (typeof options.modification[key] === 'string') mod.values = [options.modification[key]]
1116
1124
  else mod.values = [options.modification[key].toString()]
@@ -1686,7 +1686,8 @@ const ScimGateway = function () {
1686
1686
  this.replaceUsrGrp = replaceUsrGrp
1687
1687
 
1688
1688
  router.put([`/(|scim/)(!${undefined}|Users|Groups|servicePlans)/:id`,
1689
- `/:baseEntity/(|scim/)(!${undefined}|Users|Groups|servicePlans)/:id`], async (ctx) => {
1689
+ `/:baseEntity/(|scim/)(!${undefined}|Users|Groups|servicePlans)/:id`], async (ctx) => {
1690
+ const originalUrl = ctx.request.originalUrl
1690
1691
  if (config.stream.publisher.enabled) {
1691
1692
  const streamObj = {
1692
1693
  handle: 'replaceUsrGrp',
@@ -1700,7 +1701,7 @@ const ScimGateway = function () {
1700
1701
  } else {
1701
1702
  await replaceUsrGrp(ctx)
1702
1703
  }
1703
- ctx.request.originalUrl = ctx.params.baseEntity ? `/${ctx.params.baseEntity}/Users/${ctx.params.id}` : `/Users/${ctx.params.id}`
1704
+ ctx.request.originalUrl = originalUrl
1704
1705
  return await getById(ctx)
1705
1706
  })
1706
1707
 
@@ -2542,18 +2543,20 @@ ScimGateway.prototype.endpointMapper = function endpointMapper (direction, parse
2542
2543
  let arrIndex = null
2543
2544
  const arr = key.split('.') // multivalue/array - servicePlan.0.value
2544
2545
  const keyOrg = key
2545
- if (arr[arr.length - 1] === 'value') {
2546
- if (!isNaN(arr[arr.length - 2])) { // servicePlan.0.value => servicePlan.0
2547
- for (let i = 0; i < (arr.length - 2); i++) {
2546
+ if (arr.length > 1 && arr[arr.length - 1] === 'value') {
2547
+ const secondLast = arr.length - 2
2548
+ if (!isNaN(arr[secondLast])) { // servicePlan.0.value => servicePlan.0
2549
+ for (let i = 0; i < (secondLast); i++) {
2548
2550
  if (i === 0) key = arr[i]
2549
2551
  else key += `.${arr[i]}`
2550
2552
  }
2551
- arrIndex = arr[arr.length - 2]
2552
- } else if (arr[arr.length - 2].slice(-1) === ']' && arr.length - 2 === 0) { // groups[0].value => groups.value
2553
- const startPos = arr[0].indexOf('[')
2553
+ arrIndex = arr[secondLast]
2554
+ } else if (arr[secondLast].slice(-1) === ']') { // groups[0].value => groups.value
2555
+ const prefix = arr.slice(0, -1).join('.')
2556
+ const startPos = prefix.indexOf('[')
2554
2557
  if (startPos > 0) {
2555
- key = arr[0].substring(0, startPos) + '.value' // groups.value
2556
- arrIndex = arr[0].substring(startPos + 1, arr[0].length - 1) // 1
2558
+ key = prefix.substring(0, startPos) + '.value' // groups.value
2559
+ arrIndex = prefix.substring(startPos + 1, prefix.length - 1) // 1
2557
2560
  }
2558
2561
  }
2559
2562
  }
@@ -2643,10 +2646,15 @@ ScimGateway.prototype.endpointMapper = function endpointMapper (direction, parse
2643
2646
  dotArrIndex = keyArr[1]
2644
2647
  }
2645
2648
 
2646
- if (!dotMap[`${key}.mapTo`]) continue
2649
+ let mapTo = dotMap[`${key}.mapTo`]
2650
+ if (mapTo.startsWith('urn:')) { // dot workaround for none core (e.g. enterprise and custom schema attributes) having dot in key e.g "2.0": urn:ietf:params:scim:schemas:extension:enterprise:2.0:User.department
2651
+ mapTo = mapTo.replace('.', '##') // only first occurence
2652
+ noneCore = true
2653
+ }
2654
+ if (!mapTo) continue
2647
2655
 
2648
2656
  if (dotMap[`${key}.type`] === 'array') {
2649
- let newStr = dotMap[`${key}.mapTo`]
2657
+ let newStr = mapTo
2650
2658
  if (newStr === 'roles') { // {"mapTo": "roles"} should be {"mapTo": "roles.value"}
2651
2659
  arrUnsupported.push('roles.value')
2652
2660
  }
@@ -2669,23 +2677,11 @@ ScimGateway.prototype.endpointMapper = function endpointMapper (direction, parse
2669
2677
  }
2670
2678
  }
2671
2679
  } else { // none array
2672
- // let mapTo = mapObj[key].mapTo
2673
- let mapTo = dotMap[`${key}.mapTo`]
2674
- if (mapTo.startsWith('urn:')) { // dot workaround for none core (e.g. enterprise and custom schema attributes) having dot in key e.g "2.0": urn:ietf:params:scim:schemas:extension:enterprise:2.0:User.department
2675
- mapTo = mapTo.replace('.', '##') // only first occurence
2676
- noneCore = true
2677
- }
2678
2680
  const arrMapTo = mapTo.split(',').map(item => item.trim()) // supports {"mapTo": "id,userName"}
2679
2681
  for (let i = 0; i < arrMapTo.length; i++) {
2680
2682
  dotNewObj[arrMapTo[i]] = dotParse[key] // {"active": {"mapTo": "accountEnabled"} => str.replace("accountEnabled", "active")
2681
2683
  }
2682
2684
  }
2683
- // let mapTo = mapObj[key].mapTo
2684
- let mapTo = dotMap[`${key}.mapTo`]
2685
- if (mapTo.startsWith('urn:')) {
2686
- mapTo = mapTo.replace('.', '##')
2687
- noneCore = true
2688
- }
2689
2685
  const arr = mapTo.split('.') // addresses.work.postalCode
2690
2686
  if (arr.length > 2 && complexObj[arr[0]]) complexArr.push(arr[0]) // addresses
2691
2687
  }
@@ -2718,7 +2714,7 @@ ScimGateway.prototype.endpointMapper = function endpointMapper (direction, parse
2718
2714
  if (noneCore) { // revert back dot workaround
2719
2715
  const tmpObj = {}
2720
2716
  for (const key in newObj) {
2721
- if (key.includes('##')) {
2717
+ if (key.startsWith('urn:') && key.includes('##')) {
2722
2718
  const newKey = key.replace('##', '.')
2723
2719
  tmpObj[newKey] = newObj[key]
2724
2720
  } else tmpObj[key] = newObj[key]
package/package.json CHANGED
@@ -1,59 +1,59 @@
1
- {
2
- "name": "scimgateway",
3
- "version": "4.5.4",
4
- "description": "Using SCIM protocol as a gateway for user provisioning to other endpoints",
5
- "author": "Jarle Elshaug <jarle.elshaug@gmail.com> (https://elshaug.xyz)",
6
- "homepage": "https://elshaug.xyz",
7
- "license": "MIT",
8
- "main": "lib/scimgateway.js",
9
- "scripts": {
10
- "postinstall": "node lib/postinstall.js",
11
- "start": "node index.js",
12
- "test": "mocha -R spec ./test"
13
- },
14
- "bin": {
15
- "scimgateway": "./index.js"
16
- },
17
- "repository": {
18
- "type": "git",
19
- "url": "https://github.com/jelhub/scimgateway.git"
20
- },
21
- "keywords": [
22
- "scim",
23
- "gateway",
24
- "stream",
25
- "iga",
26
- "provisioning",
27
- "entra"
28
- ],
29
- "engines": {
30
- "node": ">=16.0.0"
31
- },
32
- "dependencies": {
33
- "@godaddy/terminus": "^4.12.1",
34
- "callsite": "^1.0.0",
35
- "dot-object": "^2.1.5",
36
- "fold-to-ascii": "^5.0.1",
37
- "https-proxy-agent": "^7.0.4",
38
- "is-in-subnet": "^4.0.1",
39
- "jsonwebtoken": "^9.0.2",
40
- "koa": "^2.15.3",
41
- "koa-bodyparser": "^4.4.1",
42
- "koa-router": "^12.0.1",
43
- "ldapjs": "^3.0.7",
44
- "lokijs": "^1.5.12",
45
- "mongodb": "^6.6.2",
46
- "nats": "^2.26.0",
47
- "node-machine-id": "1.1.9",
48
- "nodemailer": "^6.9.13",
49
- "passport": "^0.7.0",
50
- "passport-azure-ad": "^4.3.5",
51
- "tedious": "^18.2.0",
52
- "winston": "^3.13.0"
53
- },
54
- "devDependencies": {
55
- "chai": "^4.2.0",
56
- "mocha": "^9.2.0",
57
- "supertest": "^6.3.3"
58
- }
59
- }
1
+ {
2
+ "name": "scimgateway",
3
+ "version": "4.5.6",
4
+ "description": "Using SCIM protocol as a gateway for user provisioning to other endpoints",
5
+ "author": "Jarle Elshaug <jarle.elshaug@gmail.com> (https://elshaug.xyz)",
6
+ "homepage": "https://elshaug.xyz",
7
+ "license": "MIT",
8
+ "main": "lib/scimgateway.js",
9
+ "scripts": {
10
+ "postinstall": "node lib/postinstall.js",
11
+ "start": "node index.js",
12
+ "test": "mocha -R spec ./test"
13
+ },
14
+ "bin": {
15
+ "scimgateway": "./index.js"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/jelhub/scimgateway.git"
20
+ },
21
+ "keywords": [
22
+ "scim",
23
+ "gateway",
24
+ "stream",
25
+ "iga",
26
+ "provisioning",
27
+ "entra"
28
+ ],
29
+ "engines": {
30
+ "node": ">=16.0.0"
31
+ },
32
+ "dependencies": {
33
+ "@godaddy/terminus": "^4.12.1",
34
+ "callsite": "^1.0.0",
35
+ "dot-object": "^2.1.5",
36
+ "fold-to-ascii": "^5.0.1",
37
+ "https-proxy-agent": "^7.0.4",
38
+ "is-in-subnet": "^4.0.1",
39
+ "jsonwebtoken": "^9.0.2",
40
+ "koa": "^2.15.3",
41
+ "koa-bodyparser": "^4.4.1",
42
+ "koa-router": "^12.0.1",
43
+ "ldapjs": "^3.0.7",
44
+ "lokijs": "^1.5.12",
45
+ "mongodb": "^6.6.2",
46
+ "nats": "^2.26.0",
47
+ "node-machine-id": "1.1.9",
48
+ "nodemailer": "^6.9.13",
49
+ "passport": "^0.7.0",
50
+ "passport-azure-ad": "^4.3.5",
51
+ "tedious": "^18.2.0",
52
+ "winston": "^3.13.0"
53
+ },
54
+ "devDependencies": {
55
+ "chai": "^4.2.0",
56
+ "mocha": "^9.2.0",
57
+ "supertest": "^6.3.3"
58
+ }
59
+ }