diff --git a/src/coreEnforcer.ts b/src/coreEnforcer.ts index e46c870..894fcc9 100644 --- a/src/coreEnforcer.ts +++ b/src/coreEnforcer.ts @@ -61,6 +61,7 @@ export class CoreEnforcer { protected autoSave = true; protected autoBuildRoleLinks = true; protected autoNotifyWatcher = true; + protected acceptJsonRequest = false; protected fs?: FileSystem; /** @@ -351,6 +352,15 @@ export class CoreEnforcer { this.autoNotifyWatcher = enable; } + /** + * enableAcceptJsonRequest determines whether to attempt parsing request args as JSON + * + * @param enable whether to attempt parsing request args as JSON + */ + public enableAcceptJsonRequest(enable: boolean): void { + this.acceptJsonRequest = enable; + } + /** * enableAutoBuildRoleLinks controls whether to save a policy rule * automatically to the adapter when it is added or removed. @@ -477,9 +487,20 @@ export class CoreEnforcer { throw new Error(`invalid request size: expected ${rTokensLen}, got ${rvals.length}, rvals: ${rvals}"`); } - rTokens.forEach((token, j) => { - parameters[token] = rvals[j]; - }); + if (this.acceptJsonRequest) { + // Attempt to parse each request parameter as JSON; continue with string if failed + rTokens.forEach((token, j) => { + try { + parameters[token] = JSON.parse(rvals[j]); + } catch { + parameters[token] = rvals[j]; + } + }); + } else { + rTokens.forEach((token, j) => { + parameters[token] = rvals[j]; + }); + } p?.tokens.forEach((token, j) => { parameters[token] = p?.policy[i][j]; diff --git a/test/enforcer.test.ts b/test/enforcer.test.ts index a09c863..06f88d8 100644 --- a/test/enforcer.test.ts +++ b/test/enforcer.test.ts @@ -560,6 +560,10 @@ class TestSub { this.Name = name; this.Age = age; } + + toJSONString(): string { + return JSON.stringify(this); + } } test('test ABAC Scaling', async () => { @@ -837,3 +841,31 @@ test('TestEnforceWithMatcher', async () => { expect(await e.enforceWithMatcher(m2, 'data2_admin', 'data1', 'read')).toBe(true); expect(await e.enforceWithMatcher(m2, 'data2_admin', 'data1', 'write')).toBe(true); }); + +test('TestEnforceWithEnableAcceptJsonRequest', async () => { + const e = await newEnforcer('examples/abac_rule_model.conf', 'examples/abac_rule_policy.csv'); + e.enableAcceptJsonRequest(true); + + const sub1 = new TestSub('alice', 16).toJSONString(); + const sub2 = new TestSub('alice', 20).toJSONString(); + const sub3 = new TestSub('alice', 65).toJSONString(); + + await testEnforce(e, sub1, '/data1', 'read', false); + await testEnforce(e, sub1, '/data2', 'read', false); + await testEnforce(e, sub1, '/data1', 'write', false); + await testEnforce(e, sub1, '/data2', 'write', true); + await testEnforce(e, sub2, '/data1', 'read', true); + await testEnforce(e, sub2, '/data2', 'read', false); + await testEnforce(e, sub2, '/data1', 'write', false); + await testEnforce(e, sub2, '/data2', 'write', true); + await testEnforce(e, sub3, '/data1', 'read', true); + await testEnforce(e, sub3, '/data2', 'read', false); + await testEnforce(e, sub3, '/data1', 'write', false); + await testEnforce(e, sub3, '/data2', 'write', false); + + e.enableAcceptJsonRequest(false); + await testEnforce(e, sub1, '/data2', 'write', false); + await testEnforce(e, sub2, '/data1', 'read', false); + await testEnforce(e, sub2, '/data2', 'write', false); + await testEnforce(e, sub3, '/data1', 'read', false); +});