scimgateway 4.2.2 → 4.2.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/README.md +6 -0
- package/lib/plugin-loki.js +27 -18
- package/lib/plugin-mongodb.js +27 -18
- package/lib/scimgateway.js +12 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1165,6 +1165,12 @@ MIT © [Jarle Elshaug](https://www.elshaug.xyz)
|
|
|
1165
1165
|
|
|
1166
1166
|
## Change log
|
|
1167
1167
|
|
|
1168
|
+
### v4.2.3
|
|
1169
|
+
|
|
1170
|
+
[Fixed]
|
|
1171
|
+
|
|
1172
|
+
- plugin-loki and plugin-mongodb, for multi-value attributes like emails,phoneNumbers,... that includes primary attribute, only one is allowed having primary value set to true in the multi-value set.
|
|
1173
|
+
|
|
1168
1174
|
### v4.2.2
|
|
1169
1175
|
|
|
1170
1176
|
[Fixed]
|
package/lib/plugin-loki.js
CHANGED
|
@@ -267,27 +267,27 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
|
|
|
267
267
|
const userObj = res[0]
|
|
268
268
|
|
|
269
269
|
for (const key in attrObj) {
|
|
270
|
-
if (Array.isArray(attrObj[key])) { // standard, not using type (e.g roles/groups)
|
|
271
|
-
attrObj[key].
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
270
|
+
if (Array.isArray(attrObj[key])) { // standard, not using type (e.g roles/groups) or skipTypeConvert=true
|
|
271
|
+
const delArr = attrObj[key].filter(el => el.operation === 'delete')
|
|
272
|
+
const addArr = attrObj[key].filter(el => (!el.operation || el.operation !== 'delete'))
|
|
273
|
+
if (!userObj[key]) userObj[key] = []
|
|
274
|
+
// delete
|
|
275
|
+
userObj[key] = userObj[key].filter(el => {
|
|
276
|
+
if (delArr.findIndex(e => e.value === el.value) >= 0) return false
|
|
277
|
+
return true
|
|
278
|
+
})
|
|
279
|
+
// add
|
|
280
|
+
addArr.forEach(el => {
|
|
281
|
+
if (Object.prototype.hasOwnProperty.call(el, 'primary')) {
|
|
282
|
+
if (el.primary === true || (typeof el.primary === 'string' && el.primary.toLowerCase() === 'true')) {
|
|
283
|
+
const index = userObj[key].findIndex(e => e.primary === el.primary)
|
|
284
|
+
if (index >= 0) {
|
|
285
|
+
if (key === 'roles') userObj[key].splice(index, 1) // roles, delete existing role having primary attribute true (new role with primary will be added)
|
|
286
|
+
else userObj[key][index].primary = undefined // remove primary attribute, only one primary
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
|
-
userObj[key].push(el)
|
|
290
289
|
}
|
|
290
|
+
userObj[key].push(el)
|
|
291
291
|
})
|
|
292
292
|
} else if (scimgateway.isMultiValueTypes(key)) { // "type converted object" logic and original blank type having type "undefined"
|
|
293
293
|
if (!attrObj[key]) delete userObj[key] // blank or null
|
|
@@ -300,6 +300,15 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
|
|
|
300
300
|
if (userObj[key].length < 1) delete userObj[key]
|
|
301
301
|
} else { // modify/create multivalue
|
|
302
302
|
if (!userObj[key]) userObj[key] = []
|
|
303
|
+
if (attrObj[key][el].primary) { // remove any existing primary attribute, should only have one primary set
|
|
304
|
+
const primVal = attrObj[key][el].primary
|
|
305
|
+
if (primVal === true || (typeof primVal === 'string' && primVal.toLowerCase() === 'true')) {
|
|
306
|
+
const index = userObj[key].findIndex(e => e.primary === primVal)
|
|
307
|
+
if (index >= 0) {
|
|
308
|
+
userObj[key][index].primary = undefined
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
303
312
|
const found = userObj[key].find((e, i) => {
|
|
304
313
|
if (e.type === el || (!e.type && el === 'undefined')) {
|
|
305
314
|
for (const k in attrObj[key][el]) {
|
package/lib/plugin-mongodb.js
CHANGED
|
@@ -353,27 +353,27 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
|
|
|
353
353
|
let userObj = decodeDotDate(res[0])
|
|
354
354
|
|
|
355
355
|
for (const key in attrObj) {
|
|
356
|
-
if (Array.isArray(attrObj[key])) { // standard, not using type (e.g roles/groups)
|
|
357
|
-
attrObj[key].
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if (
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
356
|
+
if (Array.isArray(attrObj[key])) { // standard, not using type (e.g roles/groups) or skipTypeConvert=true
|
|
357
|
+
const delArr = attrObj[key].filter(el => el.operation === 'delete')
|
|
358
|
+
const addArr = attrObj[key].filter(el => (!el.operation || el.operation !== 'delete'))
|
|
359
|
+
if (!userObj[key]) userObj[key] = []
|
|
360
|
+
// delete
|
|
361
|
+
userObj[key] = userObj[key].filter(el => {
|
|
362
|
+
if (delArr.findIndex(e => e.value === el.value) >= 0) return false
|
|
363
|
+
return true
|
|
364
|
+
})
|
|
365
|
+
// add
|
|
366
|
+
addArr.forEach(el => {
|
|
367
|
+
if (Object.prototype.hasOwnProperty.call(el, 'primary')) {
|
|
368
|
+
if (el.primary === true || (typeof el.primary === 'string' && el.primary.toLowerCase() === 'true')) {
|
|
369
|
+
const index = userObj[key].findIndex(e => e.primary === el.primary)
|
|
370
|
+
if (index >= 0) {
|
|
371
|
+
if (key === 'roles') userObj[key].splice(index, 1) // roles, delete existing role having primary attribute true (new role with primary will be added)
|
|
372
|
+
else userObj[key][index].primary = undefined // remove primary attribute, only one primary
|
|
373
373
|
}
|
|
374
374
|
}
|
|
375
|
-
userObj[key].push(el)
|
|
376
375
|
}
|
|
376
|
+
userObj[key].push(el)
|
|
377
377
|
})
|
|
378
378
|
} else if (scimgateway.isMultiValueTypes(key)) { // "type converted object" logic and original blank type having type "undefined"
|
|
379
379
|
if (!attrObj[key]) delete userObj[key] // blank or null
|
|
@@ -386,6 +386,15 @@ scimgateway.modifyUser = async (baseEntity, id, attrObj, ctx) => {
|
|
|
386
386
|
if (userObj[key].length < 1) delete userObj[key]
|
|
387
387
|
} else { // modify/create multivalue
|
|
388
388
|
if (!userObj[key]) userObj[key] = []
|
|
389
|
+
if (attrObj[key][el].primary) { // remove any existing primary attribute, should only have one primary set
|
|
390
|
+
const primVal = attrObj[key][el].primary
|
|
391
|
+
if (primVal === true || (typeof primVal === 'string' && primVal.toLowerCase() === 'true')) {
|
|
392
|
+
const index = userObj[key].findIndex(e => e.primary === primVal)
|
|
393
|
+
if (index >= 0) {
|
|
394
|
+
userObj[key][index].primary = undefined
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
389
398
|
const found = userObj[key].find((e, i) => {
|
|
390
399
|
if (e.type === el || (!e.type && el === 'undefined')) {
|
|
391
400
|
for (const k in attrObj[key][el]) {
|
package/lib/scimgateway.js
CHANGED
|
@@ -2604,7 +2604,7 @@ const addSchemas = (data, type, isScimv2, location) => {
|
|
|
2604
2604
|
return data
|
|
2605
2605
|
}
|
|
2606
2606
|
|
|
2607
|
-
// addPrimaryAttrs cheks for primary attributes and add them as standalone attributes
|
|
2607
|
+
// addPrimaryAttrs cheks for primary attributes (only for roles) and add them as standalone attributes
|
|
2608
2608
|
// some IdP's may check for these e.g. Azure
|
|
2609
2609
|
// e.g. {roles: [{value: "val1", primary: "True"}]}
|
|
2610
2610
|
// gives:
|
|
@@ -2613,33 +2613,19 @@ const addSchemas = (data, type, isScimv2, location) => {
|
|
|
2613
2613
|
// roles[primary eq "True"].primary: "True"}]
|
|
2614
2614
|
// }
|
|
2615
2615
|
const addPrimaryAttrs = (obj) => {
|
|
2616
|
+
const key = 'roles'
|
|
2616
2617
|
if (!obj || typeof obj !== 'object') return obj
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
const o = utils.copyObj(obj)
|
|
2626
|
-
for (const key in o) {
|
|
2627
|
-
if (Array.isArray(o[key]) && key !== 'groups' && key !== 'members') {
|
|
2628
|
-
// check for primary attribute
|
|
2629
|
-
const index = o[key].findIndex(el => (el.primary === true || (typeof el.primary === 'string' && el.primary.toLowerCase() === 'true')))
|
|
2630
|
-
if (index >= 0) {
|
|
2631
|
-
const prim = o[key][index]
|
|
2632
|
-
for (const k in prim) {
|
|
2633
|
-
const primKey = `${key}[primary eq ${typeof prim.primary === 'string' ? `"${prim.primary}"` : prim.primary}].${k}` // roles[primary eq true].value / roles[primary eq "True"].value``
|
|
2634
|
-
o[primKey] = prim[k] // { roles[primary eq true].value : "some-value" }
|
|
2635
|
-
}
|
|
2636
|
-
}
|
|
2637
|
-
}
|
|
2618
|
+
if (!obj[key] || !Array.isArray(obj[key])) return obj
|
|
2619
|
+
const o = utils.copyObj(obj)
|
|
2620
|
+
const index = o[key].findIndex(el => (el.primary === true || (typeof el.primary === 'string' && el.primary.toLowerCase() === 'true')))
|
|
2621
|
+
if (index >= 0) {
|
|
2622
|
+
const prim = o[key][index]
|
|
2623
|
+
for (const k in prim) {
|
|
2624
|
+
const primKey = `${key}[primary eq ${typeof prim.primary === 'string' ? `"${prim.primary}"` : prim.primary}].${k}` // roles[primary eq true].value / roles[primary eq "True"].value``
|
|
2625
|
+
o[primKey] = prim[k] // { roles[primary eq true].value : "some-value" }
|
|
2638
2626
|
}
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
if (!Array.isArray(obj)) return arrRet[0]
|
|
2642
|
-
return arrRet
|
|
2627
|
+
}
|
|
2628
|
+
return o
|
|
2643
2629
|
}
|
|
2644
2630
|
|
|
2645
2631
|
//
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scimgateway",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.3",
|
|
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",
|