diff --git a/src/frontend.ts b/src/frontend.ts index 7798a08..adc72d1 100644 --- a/src/frontend.ts +++ b/src/frontend.ts @@ -13,6 +13,7 @@ // limitations under the License. import { Enforcer } from './enforcer'; +import { deepCopy } from './util'; /** * Experiment! @@ -41,7 +42,7 @@ export async function casbinJsGetPermissionForUser(e: Enforcer, user: string): P s += '[matchers]\n'; s += `m = ${m.get('m')?.get('m')?.value.replace(/_/g, '.')}`; obj['m'] = s; - obj['p'] = await e.getPolicy(); + obj['p'] = deepCopy(await e.getPolicy()); for (const arr of obj['p']) { arr.splice(0, 0, 'p'); } diff --git a/src/util/util.ts b/src/util/util.ts index 42c7380..2d55149 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -159,6 +159,17 @@ async function generatorRunAsync(iterator: Generator): Promise { } } +function deepCopy(obj: Array | any): any { + if (typeof obj !== 'object') return; + const newObj: any = obj instanceof Array ? [] : {}; + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]; + } + } + return newObj; +} + export { escapeAssertion, removeComments, @@ -175,4 +186,5 @@ export { getEvalValue, generatorRunSync, generatorRunAsync, + deepCopy, }; diff --git a/test/frontend.test.ts b/test/frontend.test.ts index 54c82d0..3d2bc9a 100644 --- a/test/frontend.test.ts +++ b/test/frontend.test.ts @@ -18,6 +18,11 @@ import { casbinJsGetPermissionForUser } from '../src/frontend'; test('TestCasbinJsGetPermissionForUser', async () => { const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv'); + const a = await casbinJsGetPermissionForUser(e, 'alice'); + const b = await casbinJsGetPermissionForUser(e, 'alice'); + if (a !== b) { + throw new Error('Unexpected side affect.'); + } const received = JSON.parse(await casbinJsGetPermissionForUser(e, 'alice')); const expectedModelStr = readFileSync('examples/rbac_model.conf').toString(); expect(received['m']).toBe(expectedModelStr.replace(/\n\n/g, '\n'));