diff --git a/src/internalEnforcer.ts b/src/internalEnforcer.ts index 569d9c9..49c73e4 100644 --- a/src/internalEnforcer.ts +++ b/src/internalEnforcer.ts @@ -24,12 +24,18 @@ export class InternalEnforcer extends CoreEnforcer { /** * addPolicyInternal adds a rule to the current policy. */ - protected async addPolicyInternal(sec: string, ptype: string, rule: string[], useWatcher: boolean): Promise { + protected async addPolicyInternal( + sec: string, + ptype: string, + rule: string[], + useWatcher: boolean, + useAdapter: boolean + ): Promise { if (this.model.hasPolicy(sec, ptype, rule)) { return false; } - if (this.adapter && this.autoSave) { + if (this.adapter && this.autoSave && useAdapter) { try { await this.adapter.addPolicy(sec, ptype, rule); } catch (e) { @@ -60,14 +66,20 @@ export class InternalEnforcer extends CoreEnforcer { // addPolicies adds rules to the current policy. // removePolicies removes rules from the current policy. - protected async addPoliciesInternal(sec: string, ptype: string, rules: string[][], useWatcher: boolean): Promise { + protected async addPoliciesInternal( + sec: string, + ptype: string, + rules: string[][], + useWatcher: boolean, + useAdapter: boolean + ): Promise { for (const rule of rules) { if (this.model.hasPolicy(sec, ptype, rule)) { return false; } } - if (this.autoSave) { + if (this.autoSave && useAdapter) { if ('addPolicies' in this.adapter) { try { await this.adapter.addPolicies(sec, ptype, rules); @@ -107,13 +119,14 @@ export class InternalEnforcer extends CoreEnforcer { ptype: string, oldRule: string[], newRule: string[], - useWatcher: boolean + useWatcher: boolean, + useAdapter: boolean ): Promise { if (!this.model.hasPolicy(sec, ptype, oldRule)) { return false; } - if (this.autoSave) { + if (this.autoSave && useAdapter) { if ('updatePolicy' in this.adapter) { try { await this.adapter.updatePolicy(sec, ptype, oldRule, newRule); @@ -149,12 +162,18 @@ export class InternalEnforcer extends CoreEnforcer { /** * removePolicyInternal removes a rule from the current policy. */ - protected async removePolicyInternal(sec: string, ptype: string, rule: string[], useWatcher: boolean): Promise { + protected async removePolicyInternal( + sec: string, + ptype: string, + rule: string[], + useWatcher: boolean, + useAdapter: boolean + ): Promise { if (!this.model.hasPolicy(sec, ptype, rule)) { return false; } - if (this.adapter && this.autoSave) { + if (this.adapter && this.autoSave && useAdapter) { try { await this.adapter.removePolicy(sec, ptype, rule); } catch (e) { @@ -183,14 +202,20 @@ export class InternalEnforcer extends CoreEnforcer { } // removePolicies removes rules from the current policy. - protected async removePoliciesInternal(sec: string, ptype: string, rules: string[][], useWatcher: boolean): Promise { + protected async removePoliciesInternal( + sec: string, + ptype: string, + rules: string[][], + useWatcher: boolean, + useAdapter: boolean + ): Promise { for (const rule of rules) { if (!this.model.hasPolicy(sec, ptype, rule)) { return false; } } - if (this.autoSave) { + if (this.autoSave && useAdapter) { if ('removePolicies' in this.adapter) { try { await this.adapter.removePolicies(sec, ptype, rules); @@ -230,9 +255,10 @@ export class InternalEnforcer extends CoreEnforcer { ptype: string, fieldIndex: number, fieldValues: string[], - useWatcher: boolean + useWatcher: boolean, + useAdapter: boolean ): Promise { - if (this.adapter && this.autoSave) { + if (this.adapter && this.autoSave && useAdapter) { try { await this.adapter.removeFilteredPolicy(sec, ptype, fieldIndex, ...fieldValues); } catch (e) { diff --git a/src/managementEnforcer.ts b/src/managementEnforcer.ts index 1393c0d..ce2f76b 100644 --- a/src/managementEnforcer.ts +++ b/src/managementEnforcer.ts @@ -260,7 +260,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async addNamedPolicy(ptype: string, ...params: string[]): Promise { - return this.addPolicyInternal('p', ptype, params, true); + return this.addPolicyInternal('p', ptype, params, true, true); } /** @@ -273,7 +273,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async addNamedPolicies(ptype: string, rules: string[][]): Promise { - return this.addPoliciesInternal('p', ptype, rules, true); + return this.addPoliciesInternal('p', ptype, rules, true, true); } /** @@ -300,7 +300,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async updateNamedPolicy(ptype: string, oldRule: string[], newRule: string[]): Promise { - return this.updatePolicyInternal('p', ptype, oldRule, newRule, true); + return this.updatePolicyInternal('p', ptype, oldRule, newRule, true, true); } /** @@ -343,7 +343,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async removeNamedPolicy(ptype: string, ...params: string[]): Promise { - return this.removePolicyInternal('p', ptype, params, true); + return this.removePolicyInternal('p', ptype, params, true, true); } /** @@ -354,7 +354,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async removeNamedPolicies(ptype: string, rules: string[][]): Promise { - return this.removePoliciesInternal('p', ptype, rules, true); + return this.removePoliciesInternal('p', ptype, rules, true, true); } /** @@ -367,7 +367,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async removeFilteredNamedPolicy(ptype: string, fieldIndex: number, ...fieldValues: string[]): Promise { - return this.removeFilteredPolicyInternal('p', ptype, fieldIndex, fieldValues, true); + return this.removeFilteredPolicyInternal('p', ptype, fieldIndex, fieldValues, true, true); } /** @@ -425,7 +425,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async addNamedGroupingPolicy(ptype: string, ...params: string[]): Promise { - return this.addPolicyInternal('g', ptype, params, true); + return this.addPolicyInternal('g', ptype, params, true, true); } /** @@ -438,7 +438,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async addNamedGroupingPolicies(ptype: string, rules: string[][]): Promise { - return this.addPoliciesInternal('g', ptype, rules, true); + return this.addPoliciesInternal('g', ptype, rules, true, true); } /** @@ -481,7 +481,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async removeNamedGroupingPolicy(ptype: string, ...params: string[]): Promise { - return this.removePolicyInternal('g', ptype, params, true); + return this.removePolicyInternal('g', ptype, params, true, true); } /** @@ -492,7 +492,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async removeNamedGroupingPolicies(ptype: string, rules: string[][]): Promise { - return this.removePoliciesInternal('g', ptype, rules, true); + return this.removePoliciesInternal('g', ptype, rules, true, true); } /** @@ -505,7 +505,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async removeFilteredNamedGroupingPolicy(ptype: string, fieldIndex: number, ...fieldValues: string[]): Promise { - return this.removeFilteredPolicyInternal('g', ptype, fieldIndex, fieldValues, true); + return this.removeFilteredPolicyInternal('g', ptype, fieldIndex, fieldValues, true, true); } /** @@ -528,7 +528,7 @@ export class ManagementEnforcer extends InternalEnforcer { * @return succeeds or not. */ public async updateNamedGroupingPolicy(ptype: string, oldRule: string[], newRule: string[]): Promise { - return this.updatePolicyInternal('g', ptype, oldRule, newRule, true); + return this.updatePolicyInternal('g', ptype, oldRule, newRule, true, true); } /** @@ -541,26 +541,336 @@ export class ManagementEnforcer extends InternalEnforcer { } public async selfAddPolicy(sec: string, ptype: string, rule: string[]): Promise { - return this.addPolicyInternal(sec, ptype, rule, false); + return this.addPolicyInternal(sec, ptype, rule, false, true); } public async selfRemovePolicy(sec: string, ptype: string, rule: string[]): Promise { - return this.removePolicyInternal(sec, ptype, rule, false); + return this.removePolicyInternal(sec, ptype, rule, false, true); } public async selfRemoveFilteredPolicy(sec: string, ptype: string, fieldIndex: number, fieldValues: string[]): Promise { - return this.removeFilteredPolicyInternal(sec, ptype, fieldIndex, fieldValues, false); + return this.removeFilteredPolicyInternal(sec, ptype, fieldIndex, fieldValues, false, true); } public async selfUpdatePolicy(sec: string, ptype: string, oldRule: string[], newRule: string[]): Promise { - return this.updatePolicyInternal(sec, ptype, oldRule, newRule, false); + return this.updatePolicyInternal(sec, ptype, oldRule, newRule, false, true); } public async selfAddPolicies(sec: string, ptype: string, rule: string[][]): Promise { - return this.addPoliciesInternal(sec, ptype, rule, false); + return this.addPoliciesInternal(sec, ptype, rule, false, true); } public async selfRemovePolicies(sec: string, ptype: string, rule: string[][]): Promise { - return this.removePoliciesInternal(sec, ptype, rule, false); + return this.removePoliciesInternal(sec, ptype, rule, false, true); + } + + /** + * selfAddPolicyLocally adds an authorization rule to the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule already exists, the function returns false and the rule will not be added. + * Otherwise the function returns true by adding the new rule. + * + * @param params the "p" policy rule, ptype "p" is implicitly used. + * @return succeeds or not. + */ + public async selfAddPolicyLocally(...params: string[]): Promise { + return this.selfAddNamedPolicyLocally('p', ...params); + } + + /** + * selfAddPoliciesLocally adds authorization rules to the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule already exists, the function returns false and the rules will not be added. + * Otherwise the function returns true by adding the new rules. + * + * @param rules the "p" policy rules, ptype "p" is implicitly used. + * @return succeeds or not. + */ + public async selfAddPoliciesLocally(rules: string[][]): Promise { + return this.selfAddNamedPoliciesLocally('p', rules); + } + + /** + * selfAddNamedPolicyLocally adds an authorization rule to the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule already exists, the function returns false and the rule will not be added. + * Otherwise the function returns true by adding the new rule. + * + * @param ptype the policy type, can be "p", "p2", "p3", .. + * @param params the "p" policy rule. + * @return succeeds or not. + */ + public async selfAddNamedPolicyLocally(ptype: string, ...params: string[]): Promise { + return this.addPolicyInternal('p', ptype, params, false, false); + } + + /** + * selfAddNamedPoliciesLocally adds authorization rules to the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule already exists, the function returns false and the rules will not be added. + * Otherwise the function returns true by adding the new rules. + * + * @param ptype the policy type, can be "p", "p2", "p3", .. + * @param rules the "p" policy rules. + * @return succeeds or not. + */ + public async selfAddNamedPoliciesLocally(ptype: string, rules: string[][]): Promise { + return this.addPoliciesInternal('p', ptype, rules, false, false); + } + + /** + * selfUpdatePolicyLocally updates an authorization rule from the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule not exists, the function returns false. + * Otherwise the function returns true by changing it to the new rule. + * + * @return succeeds or not. + * @param oldRule the policy will be remove + * @param newRule the policy will be added + */ + public async selfUpdatePolicyLocally(oldRule: string[], newRule: string[]): Promise { + return this.selfUpdateNamedPolicyLocally('p', oldRule, newRule); + } + + /** + * selfUpdateNamedPolicyLocally updates an authorization rule from the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule not exists, the function returns false. + * Otherwise the function returns true by changing it to the new rule. + * + * @param ptype the policy type, can be "p", "p2", "p3", .. + * @param oldRule the policy rule will be remove + * @param newRule the policy rule will be added + * @return succeeds or not. + */ + public async selfUpdateNamedPolicyLocally(ptype: string, oldRule: string[], newRule: string[]): Promise { + return this.updatePolicyInternal('p', ptype, oldRule, newRule, false, false); + } + + /** + * selfRemovePolicyLocally removes an authorization rule from the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param params the "p" policy rule, ptype "p" is implicitly used. + * @return succeeds or not. + */ + public async selfRemovePolicyLocally(...params: string[]): Promise { + return this.selfRemoveNamedPolicyLocally('p', ...params); + } + + /** + * selfRemovePoliciesLocally removes authorization rules from the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param rules the "p" policy rules, ptype "p" is implicitly used. + * @return succeeds or not. + */ + public async selfRemovePoliciesLocally(rules: string[][]): Promise { + return this.selfRemoveNamedPoliciesLocally('p', rules); + } + + /** + * selfRemoveFilteredPolicyLocally removes an authorization rule from the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * Field filters can be specified. + * + * @param fieldIndex the policy rule's start index to be matched. + * @param fieldValues the field values to be matched, value "" + * means not to match this field. + * @return succeeds or not. + */ + public async selfRemoveFilteredPolicyLocally(fieldIndex: number, ...fieldValues: string[]): Promise { + return this.selfRemoveFilteredNamedPolicyLocally('p', fieldIndex, ...fieldValues); + } + + /** + * selfRemoveNamedPolicyLocally removes an authorization rule from the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param ptype the policy type, can be "p", "p2", "p3", .. + * @param params the "p" policy rule. + * @return succeeds or not. + */ + public async selfRemoveNamedPolicyLocally(ptype: string, ...params: string[]): Promise { + return this.removePolicyInternal('p', ptype, params, false, false); + } + + /** + * selfRemoveNamedPoliciesLocally removes authorization rules from the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param ptype the policy type, can be "p", "p2", "p3", .. + * @param rules the "p" policy rules. + * @return succeeds or not. + */ + public async selfRemoveNamedPoliciesLocally(ptype: string, rules: string[][]): Promise { + return this.removePoliciesInternal('p', ptype, rules, false, false); + } + + /** + * selfRemoveFilteredNamedPolicyLocally removes an authorization rule from the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * Field filters can be specified. + * + * @param ptype the policy type, can be "p", "p2", "p3", .. + * @param fieldIndex the policy rule's start index to be matched. + * @param fieldValues the field values to be matched, value "" + * means not to match this field. + * @return succeeds or not. + */ + public async selfRemoveFilteredNamedPolicyLocally(ptype: string, fieldIndex: number, ...fieldValues: string[]): Promise { + return this.removeFilteredPolicyInternal('p', ptype, fieldIndex, fieldValues, false, false); + } + + /** + * selfAddGroupingPolicyLocally adds a role inheritance rule to the current policy. + * If the rule already exists, the function returns false and the rule will not be added. + * Otherwise the function returns true by adding the new rule. + * + * @param params the "g" policy rule, ptype "g" is implicitly used. + * @return succeeds or not. + */ + public async selfAddGroupingPolicyLocally(...params: string[]): Promise { + return this.selfAddNamedGroupingPolicyLocally('g', ...params); + } + + /** + * selfAddGroupingPoliciesLocally adds a role inheritance rules to the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule already exists, the function returns false and the rules will not be added. + * Otherwise the function returns true by adding the new rules. + * + * @param rules the "g" policy rules, ptype "g" is implicitly used. + * @return succeeds or not. + */ + public async selfAddGroupingPoliciesLocally(rules: string[][]): Promise { + return this.selfAddNamedGroupingPoliciesLocally('g', rules); + } + + /** + * selfAddNamedGroupingPolicyLocally adds a named role inheritance rule to the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule already exists, the function returns false and the rule will not be added. + * Otherwise the function returns true by adding the new rule. + * + * @param ptype the policy type, can be "g", "g2", "g3", .. + * @param params the "g" policy rule. + * @return succeeds or not. + */ + public async selfAddNamedGroupingPolicyLocally(ptype: string, ...params: string[]): Promise { + return this.addPolicyInternal('g', ptype, params, false, false); + } + + /** + * selfAddNamedGroupingPoliciesLocally adds named role inheritance rules to the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * If the rule already exists, the function returns false and the rules will not be added. + * Otherwise the function returns true by adding the new rules. + * + * @param ptype the policy type, can be "g", "g2", "g3", .. + * @param rules the "g" policy rule. + * @return succeeds or not. + */ + public async selfAddNamedGroupingPoliciesLocally(ptype: string, rules: string[][]): Promise { + return this.addPoliciesInternal('g', ptype, rules, false, false); + } + + /** + * selfRemoveGroupingPolicyLocally removes a role inheritance rule from the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param params the "g" policy rule, ptype "g" is implicitly used. + * @return succeeds or not. + */ + public async selfRemoveGroupingPolicyLocally(...params: string[]): Promise { + return this.selfRemoveNamedGroupingPolicyLocally('g', ...params); + } + + /** + * selfRemoveGroupingPoliciesLocally removes role inheritance rules from the current policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param rules the "g" policy rules, ptype "g" is implicitly used. + * @return succeeds or not. + */ + public async selfRemoveGroupingPoliciesLocally(rules: string[][]): Promise { + return this.selfRemoveNamedGroupingPoliciesLocally('g', rules); + } + + /** + * selfRemoveFilteredGroupingPolicyLocally removes a role inheritance rule from the current policy, field filters can be specified without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param fieldIndex the policy rule's start index to be matched. + * @param fieldValues the field values to be matched, value "" + * means not to match this field. + * @return succeeds or not. + */ + public async selfRemoveFilteredGroupingPolicyLocally(fieldIndex: number, ...fieldValues: string[]): Promise { + return this.selfRemoveFilteredNamedGroupingPolicyLocally('g', fieldIndex, ...fieldValues); + } + + /** + * selfRemoveNamedGroupingPolicyLocally removes a role inheritance rule from the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param ptype the policy type, can be "g", "g2", "g3", .. + * @param params the "g" policy rule. + * @return succeeds or not. + */ + public async selfRemoveNamedGroupingPolicyLocally(ptype: string, ...params: string[]): Promise { + return this.removePolicyInternal('g', ptype, params, false, false); + } + + /** + * selfRemoveNamedGroupingPoliciesLocally removes role inheritance rules from the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param ptype the policy type, can be "g", "g2", "g3", .. + * @param rules the "g" policy rules. + * @return succeeds or not. + */ + public async selfRemoveNamedGroupingPoliciesLocally(ptype: string, rules: string[][]): Promise { + return this.removePoliciesInternal('g', ptype, rules, false, false); + } + + /** + * selfRemoveFilteredNamedGroupingPolicyLocally removes a role inheritance rule from the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * Field filters can be specified. + * + * @param ptype the policy type, can be "g", "g2", "g3", .. + * @param fieldIndex the policy rule's start index to be matched. + * @param fieldValues the field values to be matched, value "" + * means not to match this field. + * @return succeeds or not. + */ + public async selfRemoveFilteredNamedGroupingPolicyLocally(ptype: string, fieldIndex: number, ...fieldValues: string[]): Promise { + return this.removeFilteredPolicyInternal('g', ptype, fieldIndex, fieldValues, false, false); + } + + /** + * selfUpdateGroupingPolicyLocally updates an rule to the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param oldRule the old rule. + * @param newRule the new rule. + * @return succeeds or not. + */ + public async selfUpdateGroupingPolicyLocally(oldRule: string[], newRule: string[]): Promise { + return this.selfUpdateNamedGroupingPolicyLocally('g', oldRule, newRule); + } + + /** + * selfUpdateNamedGroupingPolicyLocally updates an rule to the current named policy without + * persistence via the adapter and without calling the update() function of the watcher. + * + * @param ptype the policy type, can be "g", "g2", "g3", .. + * @param oldRule the old rule. + * @param newRule the new rule. + * @return succeeds or not. + */ + public async selfUpdateNamedGroupingPolicyLocally(ptype: string, oldRule: string[], newRule: string[]): Promise { + return this.updatePolicyInternal('g', ptype, oldRule, newRule, false, false); } } diff --git a/src/syncedEnforcer.ts b/src/syncedEnforcer.ts index bbc1146..aaec212 100644 --- a/src/syncedEnforcer.ts +++ b/src/syncedEnforcer.ts @@ -366,7 +366,7 @@ export class SyncedEnforcer extends Enforcer { */ public async removeNamedPolicy(ptype: string, ...params: string[]): Promise { await this.lock.acquireAsync(); - return this.removePolicyInternal('p', ptype, params, true).finally(() => this.lock.release()); + return this.removePolicyInternal('p', ptype, params, true, true).finally(() => this.lock.release()); } /** diff --git a/test/managementAPI.test.ts b/test/managementAPI.test.ts index 2afc92e..abbb0cd 100644 --- a/test/managementAPI.test.ts +++ b/test/managementAPI.test.ts @@ -377,3 +377,232 @@ test('updateNamedGroupingPolicy', async () => { groupingPolicy = await e.getGroupingPolicy(); testArray2DEquals(groupingPolicy, [['alice', 'update_test']]); }); + +test('selfAddPolicyLocally', async () => { + const p = ['eve', 'data3', 'read']; + const added = await e.selfAddPolicyLocally(...p); + expect(added).toBe(true); + expect(await e.hasPolicy(...p)).toBe(true); +}); + +test('selfAddPoliciesLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const rules = [ + ['jack', 'data4', 'read'], + ['katy', 'data4', 'write'], + ['leyo', 'data4', 'read'], + ['ham', 'data4', 'write'], + ]; + const added = await e.selfAddPoliciesLocally(rules); + expect(added).toBe(true); + for (const rule of rules) { + expect(await e.hasPolicy(...rule)).toBe(true); + } +}); + +test('selfAddNamedPolicyLocally', async () => { + const p = ['eve', 'data3', 'read']; + const added = await e.selfAddNamedPolicyLocally('p', ...p); + expect(added).toBe(true); + expect(await e.hasPolicy(...p)).toBe(true); +}); + +test('selfAddNamedPoliciesLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const rules = [ + ['jack', 'data4', 'read'], + ['katy', 'data4', 'write'], + ['leyo', 'data4', 'read'], + ['ham', 'data4', 'write'], + ]; + const added = await e.selfAddNamedPoliciesLocally('p', rules); + expect(added).toBe(true); + for (const rule of rules) { + expect(await e.hasPolicy(...rule)).toBe(true); + } +}); + +test('selfUpdatePolicyLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const p = ['alice', 'data1', 'read']; + const q = ['alice', 'data2', 'read']; + const updated = await e.selfUpdatePolicyLocally(p, q); + expect(updated).toBe(true); + expect(await e.hasPolicy(...p)).toBe(false); + expect(await e.hasPolicy(...q)).toBe(true); +}); + +test('selfUpdateNamedPolicyLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const p = ['alice', 'data1', 'read']; + const q = ['alice', 'data2', 'read']; + const updated = await e.selfUpdateNamedPolicyLocally('p', p, q); + expect(updated).toBe(true); + expect(await e.hasPolicy(...p)).toBe(false); + expect(await e.hasPolicy(...q)).toBe(true); +}); + +test('selfRemovePolicyLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const p = ['alice', 'data1', 'read']; + const removed = await e.selfRemovePolicyLocally(...p); + expect(removed).toBe(true); + expect(await e.hasPolicy(...p)).toBe(false); +}); + +test('selfRemovePoliciesLocally', async () => { + const rules = [ + ['jack', 'data4', 'read'], + ['katy', 'data4', 'write'], + ['leyo', 'data4', 'read'], + ['ham', 'data4', 'write'], + ]; + const added = await e.selfAddPoliciesLocally(rules); + expect(added).toBe(true); + const removed = await e.selfRemovePoliciesLocally(rules); + expect(removed).toBe(true); + for (const rule of rules) { + expect(await e.hasPolicy(...rule)).toBe(false); + } +}); + +test('selfRemoveFilteredPolicyLocally', async () => { + const p = ['alice', 'data1', 'read']; + const removed = await e.selfRemoveFilteredPolicyLocally(0, ...p); + expect(removed).toBe(true); + expect(await e.hasPolicy(...p)).toBe(false); +}); + +test('selfRemoveNamedPolicyLocally', async () => { + const p = ['alice', 'data1', 'read']; + const removed = await e.selfRemoveNamedPolicyLocally('p', ...p); + expect(removed).toBe(true); + expect(await e.hasPolicy(...p)).toBe(false); +}); + +test('selfRemoveNamedPoliciesLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const rules = [ + ['jack', 'data4', 'read'], + ['katy', 'data4', 'write'], + ['leyo', 'data4', 'read'], + ['ham', 'data4', 'write'], + ]; + const added = await e.selfAddPoliciesLocally(rules); + expect(added).toBe(true); + const removed = await e.selfRemoveNamedPoliciesLocally('p', rules); + expect(removed).toBe(true); + for (const rule of rules) { + expect(await e.hasPolicy(...rule)).toBe(false); + } +}); + +test('selfRemoveFilteredNamedPolicyLocally', async () => { + const p = ['alice', 'data1', 'read']; + const removed = await e.selfRemoveFilteredNamedPolicyLocally('p', 0, ...p); + expect(removed).toBe(true); + expect(await e.hasPolicy(...p)).toBe(false); +}); + +test('selfAddGroupingPolicyLocally', async () => { + const added = await e.selfAddGroupingPolicyLocally('group1', 'data2_admin'); + expect(added).toBe(true); +}); + +test('selfAddGroupingPoliciesLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const groupingRules = [ + ['ham', 'data4_admin'], + ['jack', 'data5_admin'], + ]; + const added = await e.selfAddGroupingPoliciesLocally(groupingRules); + expect(added).toBe(true); +}); + +test('selfAddNamedGroupingPolicyLocally', async () => { + const added = await e.selfAddNamedGroupingPolicyLocally('g', 'group1', 'data2_admin'); + expect(added).toBe(true); +}); + +test('selfAddNamedGroupingPoliciesLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const groupingRules = [ + ['ham', 'data4_admin'], + ['jack', 'data5_admin'], + ]; + const added = await e.selfAddNamedGroupingPoliciesLocally('g', groupingRules); + expect(added).toBe(true); +}); + +test('selfRemoveGroupingPolicyLocally', async () => { + const removed = await e.selfRemoveGroupingPolicyLocally('alice', 'data2_admin'); + expect(removed).toBe(true); +}); + +test('selfRemoveGroupingPoliciesLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const groupingRules = [ + ['ham', 'data4_admin'], + ['jack', 'data5_admin'], + ]; + const added = await e.selfAddGroupingPoliciesLocally(groupingRules); + expect(added).toBe(true); + const removed = await e.selfRemoveGroupingPoliciesLocally(groupingRules); + expect(removed).toBe(true); +}); + +test('selfRemoveFilteredGroupingPolicyLocally', async () => { + const removed = await e.selfRemoveFilteredGroupingPolicyLocally(0, 'alice'); + expect(removed).toBe(true); +}); + +test('selfRemoveFilteredNamedGroupingPolicyLocally', async () => { + const removed = await e.selfRemoveFilteredNamedGroupingPolicyLocally('g', 0, 'alice'); + expect(removed).toBe(true); +}); + +test('selfRemoveNamedGroupingPoliciesLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + const groupingRules = [ + ['ham', 'data4_admin'], + ['jack', 'data5_admin'], + ]; + const added = await e.selfAddGroupingPoliciesLocally(groupingRules); + expect(added).toBe(true); + const removed = await e.selfRemoveNamedGroupingPoliciesLocally('g', groupingRules); + expect(removed).toBe(true); +}); + +test('selfUpdateGroupingPolicyLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + + let groupingPolicy = await e.getGroupingPolicy(); + testArray2DEquals(groupingPolicy, [['alice', 'data2_admin']]); + + const updated = e.selfUpdateGroupingPolicyLocally(['alice', 'data2_admin'], ['alice', 'update_test']); + groupingPolicy = await e.getGroupingPolicy(); + testArray2DEquals(groupingPolicy, [['alice', 'update_test']]); +}); + +test('selfUpdateNamedGroupingPolicyLocally', async () => { + const a = new FileAdapter('examples/rbac_policy.csv'); + e.setAdapter(a); + + let groupingPolicy = await e.getGroupingPolicy(); + testArray2DEquals(groupingPolicy, [['alice', 'data2_admin']]); + + const updated = e.selfUpdateNamedGroupingPolicyLocally('g', ['alice', 'data2_admin'], ['alice', 'update_test']); + groupingPolicy = await e.getGroupingPolicy(); + testArray2DEquals(groupingPolicy, [['alice', 'update_test']]); +});