scim-patch
Advanced tools
Comparing version 0.6.1 to 0.6.2
@@ -1,1 +0,1 @@ | ||
{"processes":{"b45012dc-f0eb-46be-b7b7-e1a5c483414c":{"parent":null,"children":[]}},"files":{"/home/runner/work/scim-patch/scim-patch/lib/src/scimPatch.js":["b45012dc-f0eb-46be-b7b7-e1a5c483414c"],"/home/runner/work/scim-patch/scim-patch/lib/src/errors/scimErrors.js":["b45012dc-f0eb-46be-b7b7-e1a5c483414c"]},"externalIds":{}} | ||
{"processes":{"1a7f254c-245f-4917-bb0a-a1b0d17f49a7":{"parent":null,"children":[]}},"files":{"/home/runner/work/scim-patch/scim-patch/lib/src/scimPatch.js":["1a7f254c-245f-4917-bb0a-a1b0d17f49a7"],"/home/runner/work/scim-patch/scim-patch/lib/src/errors/scimErrors.js":["1a7f254c-245f-4917-bb0a-a1b0d17f49a7"]},"externalIds":{}} |
@@ -51,2 +51,3 @@ "use strict"; | ||
* @param patchOperations An array of SCIM patch operations we want to apply on the scimResource object. | ||
* @param options Options to customize some behaviour of scimPatch | ||
* @return the scimResource patched. | ||
@@ -89,3 +90,3 @@ * @throws {InvalidScimPatchOp} if the patch could not happen. | ||
throw new scimErrors_1.NoPathInScimPatchOp(); | ||
if (operation.op.toLowerCase() === 'add' && !('value' in operation)) | ||
if (isAddOperation(operation.op) && !('value' in operation)) | ||
throw new scimErrors_1.InvalidScimPatchRequest(`The operation ${operation.op} MUST contain a "value" member whose content specifies the value to be added`); | ||
@@ -170,3 +171,3 @@ if (operation.path && typeof operation.path !== 'string') | ||
const parsedPath = (0, scim2_parse_filter_1.parse)(e.valuePath); | ||
if (patch.op.toLowerCase() === "add" && | ||
if (isAddOperation(patch.op) && | ||
"compValue" in parsedPath && | ||
@@ -196,4 +197,3 @@ parsedPath.compValue !== undefined && | ||
// code 400 and a "scimType" error code of "noTarget". | ||
const isReplace = patch.op.toLowerCase() === 'replace'; | ||
if (isReplace && matchFilter.length === 0) { | ||
if (isReplaceOperation(patch.op) && matchFilter.length === 0) { | ||
throw new scimErrors_1.NoTarget(patch.path); | ||
@@ -274,3 +274,3 @@ } | ||
// if we're adding an array, we need to remove duplicated values from existing array | ||
if (patch.op.toLowerCase() === "add") { | ||
if (isAddOperation(patch.op)) { | ||
const valuesToAdd = patch.value.filter(item => !deepIncludes(property, item)); | ||
@@ -301,3 +301,3 @@ return property.concat(valuesToAdd); | ||
if (typeof patch.value !== 'object') { | ||
if (patch.op.toLowerCase() === 'add' && !multiValuedPathFilter) | ||
if (isAddOperation(patch.op) && !multiValuedPathFilter) | ||
throw new scimErrors_1.InvalidScimPatchOp('Invalid patch query.'); | ||
@@ -308,3 +308,3 @@ return patch.value; | ||
for (const [key, value] of Object.entries(patch.value)) { | ||
assign(property, resolvePaths(key), value); | ||
assign(property, resolvePaths(key), value, patch.op); | ||
} | ||
@@ -318,4 +318,5 @@ return property; | ||
* @param value value to assign | ||
* @param op patch operation | ||
*/ | ||
function assign(obj, keyPath, value) { | ||
function assign(obj, keyPath, value, op) { | ||
const lastKeyIndex = keyPath.length - 1; | ||
@@ -329,2 +330,15 @@ for (let i = 0; i < lastKeyIndex; ++i) { | ||
} | ||
// If the attribute is an array and the operation is "add", | ||
// then the value should be added to the array | ||
const attribute = obj[keyPath[lastKeyIndex]]; | ||
if (isAddOperation(op) && Array.isArray(attribute)) { | ||
// If the value is also an array, append all values of the array to the attribute | ||
if (Array.isArray(value)) { | ||
obj[keyPath[lastKeyIndex]] = [...attribute, ...value]; | ||
return; | ||
} | ||
// If value is not an array, simply append it as a whole to end of attribute | ||
obj[keyPath[lastKeyIndex]] = [...attribute, value]; | ||
return; | ||
} | ||
obj[keyPath[lastKeyIndex]] = value; | ||
@@ -382,2 +396,18 @@ } | ||
} | ||
/** | ||
* isAddOperation check if the operation is an ADD | ||
* @param operation the name of the SCIM Patch operation | ||
* @return true if this is an add operation | ||
*/ | ||
function isAddOperation(operation) { | ||
return operation !== undefined && operation.toLowerCase() === 'add'; | ||
} | ||
/** | ||
* isReplaceOperation check if the operation is an REPACE | ||
* @param operation the name of the SCIM Patch operation | ||
* @return true if this is a replace operation | ||
*/ | ||
function isReplaceOperation(operation) { | ||
return operation !== undefined && operation.toLowerCase() === 'replace'; | ||
} | ||
class ScimSearchQuery { | ||
@@ -384,0 +414,0 @@ constructor(attrName, valuePath, array) { |
@@ -688,2 +688,36 @@ "use strict"; | ||
}); | ||
// see https://github.com/thomaspoignant/scim-patch/issues/220 | ||
it("ADD: on array attribute when 'path' is absent & value is array should append all values", done => { | ||
const patch = { | ||
op: "add", | ||
value: { | ||
emails: [ | ||
{ | ||
value: "batman@superheroes.com", | ||
primary: true | ||
}, { | ||
value: "superman@superheroes.com", | ||
primary: true | ||
} | ||
] | ||
} | ||
}; | ||
const afterPatch = (0, scimPatch_1.scimPatch)(scimUser, [patch]); | ||
(0, chai_1.expect)(afterPatch.emails.length).to.be.eq(3); | ||
return done(); | ||
}); | ||
it("ADD: on array attribute when 'path' is absent & value is non-array should append the value", done => { | ||
const patch = { | ||
op: "add", | ||
value: { | ||
emails: { | ||
value: "batman@superheroes.com", | ||
primary: true | ||
} | ||
} | ||
}; | ||
const afterPatch = (0, scimPatch_1.scimPatch)(scimUser, [patch]); | ||
(0, chai_1.expect)(afterPatch.emails.length).to.be.eq(2); | ||
return done(); | ||
}); | ||
}); | ||
@@ -690,0 +724,0 @@ describe('remove', () => { |
{ | ||
"name": "scim-patch", | ||
"version": "0.6.1", | ||
"version": "0.6.2", | ||
"description": "SCIM Patch operation (rfc7644).", | ||
@@ -5,0 +5,0 @@ "main": "lib/src/scimPatch.js", |
@@ -94,2 +94,3 @@ import { | ||
* @param patchOperations An array of SCIM patch operations we want to apply on the scimResource object. | ||
* @param options Options to customize some behaviour of scimPatch | ||
* @return the scimResource patched. | ||
@@ -136,3 +137,3 @@ * @throws {InvalidScimPatchOp} if the patch could not happen. | ||
if (operation.op.toLowerCase() === 'add' && !('value' in operation)) | ||
if (isAddOperation(operation.op) && !('value' in operation)) | ||
throw new InvalidScimPatchRequest(`The operation ${operation.op} MUST contain a "value" member whose content specifies the value to be added`); | ||
@@ -174,3 +175,3 @@ | ||
const paths = resolvePaths(patch.path); | ||
try { | ||
@@ -234,3 +235,3 @@ resource = navigate(resource, paths, {isRemoveOp: true}); | ||
const parsedPath = parse(e.valuePath); | ||
if (patch.op.toLowerCase() === "add" && | ||
if (isAddOperation(patch.op) && | ||
"compValue" in parsedPath && | ||
@@ -265,4 +266,3 @@ parsedPath.compValue !== undefined && | ||
// code 400 and a "scimType" error code of "noTarget". | ||
const isReplace = patch.op.toLowerCase() === 'replace'; | ||
if (isReplace && matchFilter.length === 0) { | ||
if (isReplaceOperation(patch.op) && matchFilter.length === 0) { | ||
throw new NoTarget(patch.path); | ||
@@ -333,3 +333,3 @@ } | ||
throw new InvalidRemoveOpPath(); | ||
schema = schema[subPath] || (schema[subPath] = {}); | ||
@@ -352,3 +352,3 @@ } | ||
// if we're adding an array, we need to remove duplicated values from existing array | ||
if (patch.op.toLowerCase() === "add") { | ||
if (isAddOperation(patch.op)) { | ||
const valuesToAdd = patch.value.filter(item => !deepIncludes(property, item)); | ||
@@ -383,3 +383,3 @@ return property.concat(valuesToAdd); | ||
if (typeof patch.value !== 'object') { | ||
if (patch.op.toLowerCase() === 'add' && !multiValuedPathFilter) | ||
if (isAddOperation(patch.op) && !multiValuedPathFilter) | ||
throw new InvalidScimPatchOp('Invalid patch query.'); | ||
@@ -392,3 +392,3 @@ | ||
for (const [key, value] of Object.entries(patch.value)) { | ||
assign(property, resolvePaths(key), value); | ||
assign(property, resolvePaths(key), value, patch.op); | ||
} | ||
@@ -403,4 +403,5 @@ return property; | ||
* @param value value to assign | ||
* @param op patch operation | ||
*/ | ||
function assign(obj:any, keyPath:Array<string>, value:any) { | ||
function assign(obj:any, keyPath:Array<string>, value:any, op: string) { | ||
const lastKeyIndex = keyPath.length-1; | ||
@@ -414,2 +415,17 @@ for (let i = 0; i < lastKeyIndex; ++ i) { | ||
} | ||
// If the attribute is an array and the operation is "add", | ||
// then the value should be added to the array | ||
const attribute = obj[keyPath[lastKeyIndex]]; | ||
if (isAddOperation(op) && Array.isArray(attribute)) { | ||
// If the value is also an array, append all values of the array to the attribute | ||
if (Array.isArray(value)) { | ||
obj[keyPath[lastKeyIndex]] = [...attribute, ...value]; | ||
return; | ||
} | ||
// If value is not an array, simply append it as a whole to end of attribute | ||
obj[keyPath[lastKeyIndex]] = [...attribute, value]; | ||
return; | ||
} | ||
obj[keyPath[lastKeyIndex]] = value; | ||
@@ -476,2 +492,20 @@ } | ||
/** | ||
* isAddOperation check if the operation is an ADD | ||
* @param operation the name of the SCIM Patch operation | ||
* @return true if this is an add operation | ||
*/ | ||
function isAddOperation(operation: string): boolean { | ||
return operation !== undefined && operation.toLowerCase() === 'add'; | ||
} | ||
/** | ||
* isReplaceOperation check if the operation is an REPACE | ||
* @param operation the name of the SCIM Patch operation | ||
* @return true if this is a replace operation | ||
*/ | ||
function isReplaceOperation(operation: string): boolean { | ||
return operation !== undefined && operation.toLowerCase() === 'replace'; | ||
} | ||
class ScimSearchQuery { | ||
@@ -478,0 +512,0 @@ constructor( |
@@ -753,2 +753,39 @@ import { | ||
}); | ||
// see https://github.com/thomaspoignant/scim-patch/issues/220 | ||
it("ADD: on array attribute when 'path' is absent & value is array should append all values", done => { | ||
const patch: ScimPatchAddReplaceOperation = { | ||
op: "add", | ||
value: { | ||
emails: [ | ||
{ | ||
value: "batman@superheroes.com", | ||
primary: true | ||
},{ | ||
value: "superman@superheroes.com", | ||
primary: true | ||
}] | ||
} | ||
}; | ||
const afterPatch = scimPatch(scimUser, [patch]); | ||
expect(afterPatch.emails.length).to.be.eq(3); | ||
return done(); | ||
}); | ||
it("ADD: on array attribute when 'path' is absent & value is non-array should append the value", done => { | ||
const patch: ScimPatchAddReplaceOperation = { | ||
op: "add", | ||
value: { | ||
emails: { | ||
value: "batman@superheroes.com", | ||
primary: true | ||
} | ||
} | ||
}; | ||
const afterPatch = scimPatch(scimUser, [patch]); | ||
expect(afterPatch.emails.length).to.be.eq(2); | ||
return done(); | ||
}); | ||
}); | ||
@@ -755,0 +792,0 @@ describe('remove', () => { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
300892
3552