scim-patch
Advanced tools
Comparing version 0.4.5 to 0.5.0
@@ -1,1 +0,1 @@ | ||
{"processes":{"5ad3b032-0623-4f30-b48c-a64c66463e7d":{"parent":null,"children":[]}},"files":{"/home/runner/work/scim-patch/scim-patch/lib/src/scimPatch.js":["5ad3b032-0623-4f30-b48c-a64c66463e7d"],"/home/runner/work/scim-patch/scim-patch/lib/src/errors/scimErrors.js":["5ad3b032-0623-4f30-b48c-a64c66463e7d"]},"externalIds":{}} | ||
{"processes":{"3d38ea8c-d461-4599-bd54-618ddf2a998b":{"parent":null,"children":[]}},"files":{"/home/runner/work/scim-patch/scim-patch/lib/src/scimPatch.js":["3d38ea8c-d461-4599-bd54-618ddf2a998b"],"/home/runner/work/scim-patch/scim-patch/lib/src/errors/scimErrors.js":["3d38ea8c-d461-4599-bd54-618ddf2a998b"]},"externalIds":{}} |
@@ -20,2 +20,8 @@ export declare abstract class ScimError extends Error { | ||
} | ||
export declare class FilterOnEmptyArray extends InvalidScimPatchOp { | ||
schema: any; | ||
attrName: string; | ||
valuePath: string; | ||
constructor(message: string, attrName: string, valuePath: string); | ||
} | ||
export declare class NoPathInScimPatchOp extends InvalidScimPatch { | ||
@@ -22,0 +28,0 @@ constructor(); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.NoTarget = exports.InvalidScimPatchRequest = exports.NoPathInScimPatchOp = exports.InvalidScimPatchOp = exports.RemoveValueNotArray = exports.RemoveValueNestedArrayNotSupported = exports.InvalidScimRemoveValue = exports.InvalidScimPatch = exports.ScimError = void 0; | ||
exports.NoTarget = exports.InvalidScimPatchRequest = exports.NoPathInScimPatchOp = exports.FilterOnEmptyArray = exports.InvalidScimPatchOp = exports.RemoveValueNotArray = exports.RemoveValueNestedArrayNotSupported = exports.InvalidScimRemoveValue = exports.InvalidScimPatch = exports.ScimError = void 0; | ||
class ScimError extends Error { | ||
@@ -43,2 +43,10 @@ constructor(scimCode) { | ||
exports.InvalidScimPatchOp = InvalidScimPatchOp; | ||
class FilterOnEmptyArray extends InvalidScimPatchOp { | ||
constructor(message, attrName, valuePath) { | ||
super(`${message}`); | ||
this.attrName = attrName; | ||
this.valuePath = valuePath; | ||
} | ||
} | ||
exports.FilterOnEmptyArray = FilterOnEmptyArray; | ||
class NoPathInScimPatchOp extends InvalidScimPatch { | ||
@@ -45,0 +53,0 @@ constructor() { |
@@ -123,4 +123,24 @@ "use strict"; | ||
const paths = patch.path.split(SPLIT_PERIOD); | ||
resource = navigate(resource, paths); | ||
const lastSubPath = paths[paths.length - 1]; | ||
try { | ||
resource = navigate(resource, paths); | ||
} | ||
catch (e) { | ||
if (e instanceof scimErrors_1.FilterOnEmptyArray) { | ||
resource = e.schema; | ||
// check issue https://github.com/thomaspoignant/scim-patch/issues/42 to see why we should add this | ||
const parsedPath = (scim2_parse_filter_1.parse(e.valuePath)); | ||
if (patch.op.toLowerCase() === "add" && | ||
"compValue" in parsedPath && | ||
parsedPath.compValue !== undefined && | ||
parsedPath.op === "eq") { | ||
const result = {}; | ||
result[parsedPath.attrPath] = parsedPath.compValue; | ||
result[lastSubPath] = addOrReplaceAttribute(resource, patch); | ||
resource[e.attrName] = [result]; | ||
return scimResource; | ||
} | ||
} | ||
throw e; | ||
} | ||
if (!IS_ARRAY_SEARCH.test(lastSubPath)) { | ||
@@ -163,3 +183,3 @@ if (resource === undefined) { | ||
if (!Array.isArray(element)) | ||
throw new scimErrors_1.InvalidScimPatchOp('Impossible to search on a mono valued attribute.'); | ||
throw new scimErrors_1.FilterOnEmptyArray('Impossible to search on a mono valued attribute.', attrName, valuePath); | ||
return new ScimSearchQuery(attrName, valuePath, element); | ||
@@ -179,4 +199,4 @@ } | ||
if (IS_ARRAY_SEARCH.test(subPath)) { | ||
const { valuePath, array } = extractArray(subPath, schema); | ||
try { | ||
const { valuePath, array } = extractArray(subPath, schema); | ||
// Get the item who is successful for the search query. | ||
@@ -189,3 +209,6 @@ const matchFilter = filterWithQuery(array, valuePath); | ||
catch (error) { | ||
throw new scimErrors_1.InvalidScimPatchOp(error); | ||
if (error instanceof scimErrors_1.FilterOnEmptyArray) { | ||
error.schema = schema; | ||
} | ||
throw error; | ||
} | ||
@@ -192,0 +215,0 @@ } |
@@ -235,2 +235,11 @@ "use strict"; | ||
}); | ||
it("REPLACE: empty array add filter type + field (Azure AD)", (done) => { | ||
const patch = { | ||
op: "Replace", | ||
value: "1111 Street Rd", | ||
path: "addresses[type eq \"work\"].formatted" | ||
}; | ||
chai_1.expect(() => scimPatch_1.scimPatch(scimUser, [patch])).to.throw(scimPatch_1.InvalidScimPatchOp); | ||
return done(); | ||
}); | ||
}); | ||
@@ -452,2 +461,58 @@ describe('add', () => { | ||
}); | ||
// Check issue https://github.com/thomaspoignant/scim-patch/issues/42 to understand this usecase | ||
it("ADD: empty array add filter type + field (Azure AD)", (done) => { | ||
var _a; | ||
const patch = { | ||
op: "Add", | ||
value: "1111 Street Rd", | ||
path: "addresses[type eq \"work\"].formatted" | ||
}; | ||
chai_1.expect(scimUser.addresses).to.be.undefined; | ||
const afterPatch = scimPatch_1.scimPatch(scimUser, [patch]); | ||
chai_1.expect(afterPatch.addresses).to.not.be.undefined; | ||
chai_1.expect((_a = afterPatch.addresses) === null || _a === void 0 ? void 0 : _a.length).to.be.eq(1); | ||
if (afterPatch.addresses !== undefined) { | ||
const address = afterPatch.addresses[0]; | ||
chai_1.expect(address.type).to.be.eq("work"); | ||
chai_1.expect(address.formatted).to.be.eq("1111 Street Rd"); | ||
} | ||
return done(); | ||
}); | ||
it("ADD: empty array multiple filter should throw an error", (done) => { | ||
const patch = { | ||
op: "Add", | ||
value: "1111 Street Rd", | ||
path: "addresses[type eq \"work\" or type eq \"home\"].formatted" | ||
}; | ||
chai_1.expect(() => scimPatch_1.scimPatch(scimUser, [patch])).to.throw(scimPatch_1.InvalidScimPatchOp); | ||
return done(); | ||
}); | ||
it("ADD: Invalid filter operation", (done) => { | ||
const patch = { | ||
op: "Add", | ||
value: "1111 Street Rd", | ||
path: "addresses[type eq \"work.formatted" | ||
}; | ||
chai_1.expect(() => scimPatch_1.scimPatch(scimUser, [patch])).to.throw(scimPatch_1.InvalidScimPatchOp); | ||
return done(); | ||
}); | ||
// Check issue https://github.com/thomaspoignant/scim-patch/issues/42 to understand this usecase | ||
it("ADD: empty array add filter type + field 2nd level", (done) => { | ||
var _a; | ||
const patch = { | ||
op: "Add", | ||
value: "1111 Street Rd", | ||
path: "name.nestedArray[primary eq true].newProperty1" | ||
}; | ||
chai_1.expect(scimUser.name.nestedArray).to.be.undefined; | ||
const afterPatch = scimPatch_1.scimPatch(scimUser, [patch]); | ||
chai_1.expect(afterPatch.name.nestedArray).to.not.be.undefined; | ||
chai_1.expect((_a = afterPatch.name.nestedArray) === null || _a === void 0 ? void 0 : _a.length).to.be.eq(1); | ||
if (afterPatch.name.nestedArray !== undefined) { | ||
const address = afterPatch.name.nestedArray[0]; | ||
chai_1.expect(address.primary).to.be.eq(true); | ||
chai_1.expect(address.newProperty1).to.be.eq("1111 Street Rd"); | ||
} | ||
return done(); | ||
}); | ||
}); | ||
@@ -454,0 +519,0 @@ describe('remove', () => { |
@@ -34,2 +34,6 @@ import { ScimResource, ScimMeta } from '../../src/types/types'; | ||
}>; | ||
addresses?: Array<{ | ||
type: string; | ||
formatted: string; | ||
}>; | ||
roles?: Array<{ | ||
@@ -36,0 +40,0 @@ value: string; |
{ | ||
"name": "scim-patch", | ||
"version": "0.4.5", | ||
"version": "0.5.0", | ||
"description": "SCIM Patch operation (rfc7644).", | ||
@@ -5,0 +5,0 @@ "main": "lib/src/scimPatch.js", |
@@ -41,2 +41,14 @@ export abstract class ScimError extends Error { | ||
export class FilterOnEmptyArray extends InvalidScimPatchOp { | ||
schema: any; | ||
attrName: string; | ||
valuePath: string; | ||
constructor(message: string, attrName: string, valuePath: string) { | ||
super(`${message}`); | ||
this.attrName = attrName; | ||
this.valuePath = valuePath; | ||
} | ||
} | ||
export class NoPathInScimPatchOp extends InvalidScimPatch { | ||
@@ -43,0 +55,0 @@ constructor() { |
@@ -10,3 +10,3 @@ import { | ||
RemoveValueNotArray, | ||
InvalidScimRemoveValue | ||
InvalidScimRemoveValue, FilterOnEmptyArray | ||
} from './errors/scimErrors'; | ||
@@ -165,2 +165,3 @@ import { | ||
function applyAddOrReplaceOperation<T extends ScimResource>(scimResource: T, patch: ScimPatchAddReplaceOperation): T { | ||
@@ -176,5 +177,26 @@ // We manipulate the object directly without knowing his property, that's why we use any. | ||
const paths = patch.path.split(SPLIT_PERIOD); | ||
resource = navigate(resource, paths); | ||
const lastSubPath = paths[paths.length - 1]; | ||
try { | ||
resource = navigate(resource, paths); | ||
} catch(e) { | ||
if (e instanceof FilterOnEmptyArray) { | ||
resource = e.schema; | ||
// check issue https://github.com/thomaspoignant/scim-patch/issues/42 to see why we should add this | ||
const parsedPath = (parse(e.valuePath)) | ||
if (patch.op.toLowerCase() === "add" && | ||
"compValue" in parsedPath && | ||
parsedPath.compValue !== undefined && | ||
parsedPath.op === "eq" | ||
) { | ||
const result: any = {} | ||
result[parsedPath.attrPath] = parsedPath.compValue; | ||
result[lastSubPath] = addOrReplaceAttribute(resource, patch); | ||
resource[e.attrName] = [result]; | ||
return scimResource; | ||
} | ||
} | ||
throw e; | ||
} | ||
if (!IS_ARRAY_SEARCH.test(lastSubPath)) { | ||
@@ -225,3 +247,3 @@ if (resource === undefined) { | ||
if (!Array.isArray(element)) | ||
throw new InvalidScimPatchOp('Impossible to search on a mono valued attribute.'); | ||
throw new FilterOnEmptyArray('Impossible to search on a mono valued attribute.', attrName, valuePath); | ||
@@ -244,5 +266,4 @@ return new ScimSearchQuery(attrName, valuePath, element); | ||
if (IS_ARRAY_SEARCH.test(subPath)) { | ||
const {valuePath, array} = extractArray(subPath, schema); | ||
try { | ||
const {valuePath, array} = extractArray(subPath, schema); | ||
// Get the item who is successful for the search query. | ||
@@ -254,3 +275,6 @@ const matchFilter = filterWithQuery<any>(array, valuePath); | ||
} catch (error) { | ||
throw new InvalidScimPatchOp(error); | ||
if(error instanceof FilterOnEmptyArray){ | ||
error.schema = schema; | ||
} | ||
throw error; | ||
} | ||
@@ -257,0 +281,0 @@ } else { |
@@ -262,2 +262,12 @@ import { | ||
}); | ||
it("REPLACE: empty array add filter type + field (Azure AD)", (done) => { | ||
const patch: ScimPatchAddReplaceOperation = { | ||
op: "Replace", | ||
value: "1111 Street Rd", | ||
path: "addresses[type eq \"work\"].formatted" | ||
}; | ||
expect(() => scimPatch(scimUser, [patch])).to.throw(InvalidScimPatchOp); | ||
return done(); | ||
}); | ||
}); | ||
@@ -502,2 +512,60 @@ | ||
}); | ||
// Check issue https://github.com/thomaspoignant/scim-patch/issues/42 to understand this usecase | ||
it("ADD: empty array add filter type + field (Azure AD)", (done) => { | ||
const patch: ScimPatchAddReplaceOperation = { | ||
op: "Add", | ||
value: "1111 Street Rd", | ||
path: "addresses[type eq \"work\"].formatted" | ||
}; | ||
expect(scimUser.addresses).to.be.undefined; | ||
const afterPatch = scimPatch(scimUser, [patch]); | ||
expect(afterPatch.addresses).to.not.be.undefined; | ||
expect(afterPatch.addresses?.length).to.be.eq(1); | ||
if (afterPatch.addresses !== undefined){ | ||
const address = afterPatch.addresses[0]; | ||
expect(address.type).to.be.eq("work") | ||
expect(address.formatted).to.be.eq("1111 Street Rd") | ||
} | ||
return done(); | ||
}); | ||
it("ADD: empty array multiple filter should throw an error", (done) => { | ||
const patch: ScimPatchAddReplaceOperation = { | ||
op: "Add", | ||
value: "1111 Street Rd", | ||
path: "addresses[type eq \"work\" or type eq \"home\"].formatted" | ||
}; | ||
expect(() => scimPatch(scimUser, [patch])).to.throw(InvalidScimPatchOp); | ||
return done(); | ||
}); | ||
it("ADD: Invalid filter operation", (done) => { | ||
const patch: ScimPatchAddReplaceOperation = { | ||
op: "Add", | ||
value: "1111 Street Rd", | ||
path: "addresses[type eq \"work.formatted" | ||
}; | ||
expect(() => scimPatch(scimUser, [patch])).to.throw(InvalidScimPatchOp); | ||
return done(); | ||
}); | ||
// Check issue https://github.com/thomaspoignant/scim-patch/issues/42 to understand this usecase | ||
it("ADD: empty array add filter type + field 2nd level", (done) => { | ||
const patch: ScimPatchAddReplaceOperation = { | ||
op: "Add", | ||
value: "1111 Street Rd", | ||
path: "name.nestedArray[primary eq true].newProperty1" | ||
}; | ||
expect(scimUser.name.nestedArray).to.be.undefined; | ||
const afterPatch = scimPatch(scimUser, [patch]); | ||
expect(afterPatch.name.nestedArray).to.not.be.undefined; | ||
expect(afterPatch.name.nestedArray?.length).to.be.eq(1); | ||
if (afterPatch.name.nestedArray !== undefined){ | ||
const address = afterPatch.name.nestedArray[0]; | ||
expect(address.primary).to.be.eq(true) | ||
expect(address.newProperty1).to.be.eq("1111 Street Rd") | ||
} | ||
return done(); | ||
}); | ||
}); | ||
@@ -504,0 +572,0 @@ describe('remove', () => { |
@@ -36,2 +36,6 @@ import {ScimResource, ScimMeta} from '../../src/types/types'; | ||
}>; | ||
addresses?: Array<{ | ||
type: string; | ||
formatted: string; | ||
}>; | ||
roles?: Array<{ | ||
@@ -38,0 +42,0 @@ value: string; |
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
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
243672
2763