diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..bccdcf9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "endOfLine": "lf", + "semi": true, + "camelcase": false, + "new-cap": false, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "none", + "printWidth": 100 +} diff --git a/src/adapter.ts b/src/adapter.ts index c2c0239..686bedc 100644 --- a/src/adapter.ts +++ b/src/adapter.ts @@ -12,24 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { - BatchAdapter, - FilteredAdapter, - Helper, - logPrint, - Model, - UpdatableAdapter, -} from "casbin"; +import { BatchAdapter, FilteredAdapter, Helper, logPrint, Model, UpdatableAdapter } from 'casbin'; import { ClientSession, Connection, ConnectOptions, createConnection, FilterQuery, - Model as MongooseModel, -} from "mongoose"; -import { AdapterError, InvalidAdapterTypeError } from "./errors"; -import { collectionName, IModel, modelName, schema } from "./model"; + Model as MongooseModel +} from 'mongoose'; +import { AdapterError, InvalidAdapterTypeError } from './errors'; +import { collectionName, IModel, modelName, schema } from './model'; export interface MongooseAdapterOptions { filtered?: boolean; @@ -58,9 +51,7 @@ export interface sessionOption { * * @class */ -export class MongooseAdapter - implements BatchAdapter, FilteredAdapter, UpdatableAdapter -{ +export class MongooseAdapter implements BatchAdapter, FilteredAdapter, UpdatableAdapter { public connection?: Connection; private filtered: boolean; @@ -85,13 +76,9 @@ export class MongooseAdapter * const adapter = new MongooseAdapter('MONGO_URI'); * const adapter = new MongooseAdapter('MONGO_URI', { mongoose_options: 'here' }) */ - constructor( - uri: string, - options?: ConnectOptions, - adapterOptions?: MongooseAdapterOptions - ) { + constructor(uri: string, options?: ConnectOptions, adapterOptions?: MongooseAdapterOptions) { if (!uri) { - throw new AdapterError("You must provide Mongo URI to connect to!"); + throw new AdapterError('You must provide Mongo URI to connect to!'); } // by default, adapter is not filtered @@ -131,7 +118,7 @@ export class MongooseAdapter filtered = false, synced = false, autoAbort = false, - autoCommit = false, + autoCommit = false } = adapterOptions; adapter.setFiltered(filtered); adapter.setSynced(synced); @@ -154,7 +141,7 @@ export class MongooseAdapter */ static async newFilteredAdapter(uri: string, options?: ConnectOptions) { const adapter = await MongooseAdapter.newAdapter(uri, options, { - filtered: true, + filtered: true }); return adapter; } @@ -177,13 +164,13 @@ export class MongooseAdapter static async newSyncedAdapter( uri: string, options?: ConnectOptions, - autoAbort = true, + autoAbort: boolean = true, autoCommit = true ) { return await MongooseAdapter.newAdapter(uri, options, { synced: true, autoAbort, - autoCommit, + autoCommit }); } @@ -245,7 +232,7 @@ export class MongooseAdapter : this.connection!.startSession(); } else throw new InvalidAdapterTypeError( - "Transactions are only supported by SyncedAdapter. See newSyncedAdapter" + 'Transactions are only supported by SyncedAdapter. See newSyncedAdapter' ); } @@ -257,7 +244,7 @@ export class MongooseAdapter this.session = session; } else { throw new InvalidAdapterTypeError( - "Sessions are only supported by SyncedAdapter. See newSyncedAdapter" + 'Sessions are only supported by SyncedAdapter. See newSyncedAdapter' ); } } @@ -274,13 +261,13 @@ export class MongooseAdapter await this.casbinRule.createCollection(); await session.startTransaction(); logPrint( - "Transaction started. To commit changes use adapter.commitTransaction() or to abort use adapter.abortTransaction()" + 'Transaction started. To commit changes use adapter.commitTransaction() or to abort use adapter.abortTransaction()' ); } return session; } else throw new InvalidAdapterTypeError( - "Transactions are only supported by SyncedAdapter. See newSyncedAdapter" + 'Transactions are only supported by SyncedAdapter. See newSyncedAdapter' ); } @@ -295,7 +282,7 @@ export class MongooseAdapter await session.commitTransaction(); } else throw new InvalidAdapterTypeError( - "Transactions are only supported by SyncedAdapter. See newSyncedAdapter" + 'Transactions are only supported by SyncedAdapter. See newSyncedAdapter' ); } @@ -308,10 +295,10 @@ export class MongooseAdapter if (this.isSynced) { const session = await this.getSession(); await session.abortTransaction(); - logPrint("Transaction aborted"); + logPrint('Transaction aborted'); } else throw new InvalidAdapterTypeError( - "Transactions are only supported by SyncedAdapter. See newSyncedAdapter" + 'Transactions are only supported by SyncedAdapter. See newSyncedAdapter' ); } @@ -366,13 +353,9 @@ export class MongooseAdapter const options: sessionOption = {}; if (this.isSynced) options.session = await this.getTransaction(); - const lines = await this.casbinRule - .find(filter || {}, null, options) - .lean(); + const lines = await this.casbinRule.find(filter || {}, null, options).lean(); - this.autoCommit && - options.session && - (await options.session.commitTransaction()); + this.autoCommit && options.session && (await options.session.commitTransaction()); for (const line of lines) { this.loadPolicyLine(line, model); } @@ -433,10 +416,9 @@ export class MongooseAdapter try { const lines: IModel[] = []; - const policyRuleAST = - model.model.get("p") instanceof Map ? model.model.get("p")! : new Map(); + const policyRuleAST = model.model.get('p') instanceof Map ? model.model.get('p')! : new Map(); const groupingPolicyAST = - model.model.get("g") instanceof Map ? model.model.get("g")! : new Map(); + model.model.get('g') instanceof Map ? model.model.get('g')! : new Map(); for (const [ptype, ast] of policyRuleAST) { for (const rule of ast.policy) { @@ -452,13 +434,9 @@ export class MongooseAdapter await this.casbinRule.collection.insertMany(lines, options); - this.autoCommit && - options.session && - (await options.session.commitTransaction()); + this.autoCommit && options.session && (await options.session.commitTransaction()); } catch (err) { - this.autoAbort && - options.session && - (await options.session.abortTransaction()); + this.autoAbort && options.session && (await options.session.abortTransaction()); console.error(err); return false; } @@ -483,13 +461,9 @@ export class MongooseAdapter const line = this.savePolicyLine(pType, rule); await line.save(options); - this.autoCommit && - options.session && - (await options.session.commitTransaction()); + this.autoCommit && options.session && (await options.session.commitTransaction()); } catch (err) { - this.autoAbort && - options.session && - (await options.session.abortTransaction()); + this.autoAbort && options.session && (await options.session.abortTransaction()); throw err; } } @@ -503,30 +477,20 @@ export class MongooseAdapter * @param {Array} rules Policy rule to add into enforcer * @returns {Promise} */ - async addPolicies( - sec: string, - pType: string, - rules: Array - ): Promise { + async addPolicies(sec: string, pType: string, rules: Array): Promise { const options: sessionOption = {}; if (this.isSynced) options.session = await this.getTransaction(); else throw new InvalidAdapterTypeError( - "addPolicies is only supported by SyncedAdapter. See newSyncedAdapter" + 'addPolicies is only supported by SyncedAdapter. See newSyncedAdapter' ); try { - const promises = rules.map(async (rule) => - this.addPolicy(sec, pType, rule) - ); + const promises = rules.map(async (rule) => this.addPolicy(sec, pType, rule)); await Promise.all(promises); - this.autoCommit && - options.session && - (await options.session.commitTransaction()); + this.autoCommit && options.session && (await options.session.commitTransaction()); } catch (err) { - this.autoAbort && - options.session && - (await options.session.abortTransaction()); + this.autoAbort && options.session && (await options.session.abortTransaction()); throw err; } } @@ -550,10 +514,7 @@ export class MongooseAdapter const options: sessionOption = {}; try { if (this.isSynced) options.session = await this.getTransaction(); - const { ptype, v0, v1, v2, v3, v4, v5 } = this.savePolicyLine( - pType, - oldRule - ); + const { ptype, v0, v1, v2, v3, v4, v5 } = this.savePolicyLine(pType, oldRule); const newRuleLine = this.savePolicyLine(pType, newRule); const newModel = { ptype: newRuleLine.ptype, @@ -562,22 +523,14 @@ export class MongooseAdapter v2: newRuleLine.v2, v3: newRuleLine.v3, v4: newRuleLine.v4, - v5: newRuleLine.v5, + v5: newRuleLine.v5 }; - await this.casbinRule.updateOne( - { ptype, v0, v1, v2, v3, v4, v5 }, - newModel, - options - ); + await this.casbinRule.updateOne({ ptype, v0, v1, v2, v3, v4, v5 }, newModel, options); - this.autoCommit && - options.session && - (await options.session.commitTransaction()); + this.autoCommit && options.session && (await options.session.commitTransaction()); } catch (err) { - this.autoAbort && - options.session && - (await options.session.abortTransaction()); + this.autoAbort && options.session && (await options.session.abortTransaction()); throw err; } } @@ -591,32 +544,18 @@ export class MongooseAdapter * @param {Array} rule Policy rule to remove from enforcer * @returns {Promise} */ - async removePolicy( - sec: string, - pType: string, - rule: string[] - ): Promise { + async removePolicy(sec: string, pType: string, rule: string[]): Promise { const options: sessionOption = {}; try { if (this.isSynced) options.session = await this.getTransaction(); - const { ptype, v0, v1, v2, v3, v4, v5 } = this.savePolicyLine( - pType, - rule - ); + const { ptype, v0, v1, v2, v3, v4, v5 } = this.savePolicyLine(pType, rule); - await this.casbinRule.deleteMany( - { ptype, v0, v1, v2, v3, v4, v5 }, - options - ); + await this.casbinRule.deleteMany({ ptype, v0, v1, v2, v3, v4, v5 }, options); - this.autoCommit && - options.session && - (await options.session.commitTransaction()); + this.autoCommit && options.session && (await options.session.commitTransaction()); } catch (err) { - this.autoAbort && - options.session && - (await options.session.abortTransaction()); + this.autoAbort && options.session && (await options.session.abortTransaction()); throw err; } } @@ -630,31 +569,21 @@ export class MongooseAdapter * @param {Array} rules Policy rule to remove from enforcer * @returns {Promise} */ - async removePolicies( - sec: string, - pType: string, - rules: Array - ): Promise { + async removePolicies(sec: string, pType: string, rules: Array): Promise { const options: sessionOption = {}; try { if (this.isSynced) options.session = await this.getTransaction(); else throw new InvalidAdapterTypeError( - "removePolicies is only supported by SyncedAdapter. See newSyncedAdapter" + 'removePolicies is only supported by SyncedAdapter. See newSyncedAdapter' ); - const promises = rules.map(async (rule) => - this.removePolicy(sec, pType, rule) - ); + const promises = rules.map(async (rule) => this.removePolicy(sec, pType, rule)); await Promise.all(promises); - this.autoCommit && - options.session && - (await options.session.commitTransaction()); + this.autoCommit && options.session && (await options.session.commitTransaction()); } catch (err) { - this.autoAbort && - options.session && - (await options.session.abortTransaction()); + this.autoAbort && options.session && (await options.session.abortTransaction()); throw err; } } @@ -678,64 +607,41 @@ export class MongooseAdapter const options: sessionOption = {}; try { if (this.isSynced) options.session = await this.getTransaction(); - const where: policyLine = pType ? { ptype: pType } : {}; - - if ( - fieldIndex <= 0 && - fieldIndex + fieldValues.length > 0 && - fieldValues[0 - fieldIndex] - ) { - where.v0 = fieldValues[0 - fieldIndex]; + const where: any = pType ? { ptype: pType } : {}; + + if (fieldIndex <= 0 && fieldIndex + fieldValues.length > 0 && fieldValues[0 - fieldIndex]) { + if (pType === 'g') { + where.$or = [{ v0: fieldValues[0 - fieldIndex] }, { v1: fieldValues[0 - fieldIndex] }]; + } else { + where.v0 = fieldValues[0 - fieldIndex]; + } } - if ( - fieldIndex <= 1 && - fieldIndex + fieldValues.length > 1 && - fieldValues[1 - fieldIndex] - ) { + if (fieldIndex <= 1 && fieldIndex + fieldValues.length > 1 && fieldValues[1 - fieldIndex]) { where.v1 = fieldValues[1 - fieldIndex]; } - if ( - fieldIndex <= 2 && - fieldIndex + fieldValues.length > 2 && - fieldValues[2 - fieldIndex] - ) { + if (fieldIndex <= 2 && fieldIndex + fieldValues.length > 2 && fieldValues[2 - fieldIndex]) { where.v2 = fieldValues[2 - fieldIndex]; } - if ( - fieldIndex <= 3 && - fieldIndex + fieldValues.length > 3 && - fieldValues[3 - fieldIndex] - ) { + if (fieldIndex <= 3 && fieldIndex + fieldValues.length > 3 && fieldValues[3 - fieldIndex]) { where.v3 = fieldValues[3 - fieldIndex]; } - if ( - fieldIndex <= 4 && - fieldIndex + fieldValues.length > 4 && - fieldValues[4 - fieldIndex] - ) { + if (fieldIndex <= 4 && fieldIndex + fieldValues.length > 4 && fieldValues[4 - fieldIndex]) { where.v4 = fieldValues[4 - fieldIndex]; } - if ( - fieldIndex <= 5 && - fieldIndex + fieldValues.length > 5 && - fieldValues[5 - fieldIndex] - ) { + if (fieldIndex <= 5 && fieldIndex + fieldValues.length > 5 && fieldValues[5 - fieldIndex]) { where.v5 = fieldValues[5 - fieldIndex]; } + await this.casbinRule.deleteMany(where, options); - this.autoCommit && - options.session && - (await options.session.commitTransaction()); + this.autoCommit && options.session && (await options.session.commitTransaction()); } catch (err) { - this.autoAbort && - options.session && - (await options.session.abortTransaction()); + this.autoAbort && options.session && (await options.session.abortTransaction()); throw err; } } diff --git a/test/fixtures/basic_model.conf b/test/fixtures/basic_model.conf index cee2566..dc6da81 100644 --- a/test/fixtures/basic_model.conf +++ b/test/fixtures/basic_model.conf @@ -8,4 +8,4 @@ p = sub, obj, act e = some(where (p.eft == allow)) [matchers] -m = r.sub == p.sub && r.obj == p.obj && r.act == p.act +m = r.sub == p.sub && r.obj == p.obj && r.act == p.act \ No newline at end of file diff --git a/test/integration/adapter.test.js b/test/integration/adapter.test.js index 57c2d7b..032b81a 100644 --- a/test/integration/adapter.test.js +++ b/test/integration/adapter.test.js @@ -24,12 +24,10 @@ const { rbacModel, rbacPolicy, rbacDenyDomainModel, - rbacDenyDomainPolicy, createAdapterWithDBName + rbacDenyDomainPolicy, + createAdapterWithDBName } = require('../helpers/helpers'); -const { - newEnforcer, - Model -} = require('casbin'); +const { newEnforcer, Model } = require('casbin'); const { InvalidAdapterTypeError } = require('../../lib/cjs/errors'); // These tests are just smoke tests for get/set policy rules @@ -85,12 +83,16 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(await e.getModel()); const rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write'], - ['p', 'data2_admin', 'data2', 'read'], - ['p', 'data2_admin', 'data2', 'write'], - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'], + ['p', 'data2_admin', 'data2', 'read'], + ['p', 'data2_admin', 'data2', 'write'], + ['g', 'alice', 'data2_admin', undefined] + ] + ); // Add a single policy to Database await a.addPolicy('', 'p', ['role', 'res', 'action']); @@ -100,10 +102,14 @@ describe('MongooseAdapter', () => { ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], ['data2_admin', 'data2', 'write'], - ['role', 'res', 'action']]); + ['role', 'res', 'action'] + ]); // Add a policyList to Database - await a.addPolicies('', 'p', [['role', 'res', 'GET'], ['role', 'res', 'POST']]); + await a.addPolicies('', 'p', [ + ['role', 'res', 'GET'], + ['role', 'res', 'POST'] + ]); e = await newEnforcer(rbacModel, a); // Clear the current policy. @@ -119,7 +125,8 @@ describe('MongooseAdapter', () => { ['data2_admin', 'data2', 'write'], ['role', 'res', 'action'], ['role', 'res', 'GET'], - ['role', 'res', 'POST']]); + ['role', 'res', 'POST'] + ]); // Remove a single policy from Database await a.removePolicy('', 'p', ['role', 'res', 'action']); @@ -130,17 +137,22 @@ describe('MongooseAdapter', () => { ['data2_admin', 'data2', 'read'], ['data2_admin', 'data2', 'write'], ['role', 'res', 'GET'], - ['role', 'res', 'POST']]); + ['role', 'res', 'POST'] + ]); // Remove a policylist from Database - await a.removePolicies('', 'p', [['role', 'res', 'GET'], ['role', 'res', 'POST']]); + await a.removePolicies('', 'p', [ + ['role', 'res', 'GET'], + ['role', 'res', 'POST'] + ]); e = await newEnforcer(rbacModel, a); assert.includeDeepMembers(await e.getPolicy(), [ ['alice', 'data1', 'read'], ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], - ['data2_admin', 'data2', 'write']]); + ['data2_admin', 'data2', 'write'] + ]); }); it('Add Policies and Remove Policies should not work on normal adapter', async () => { @@ -158,12 +170,16 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(await e.getModel()); const rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write'], - ['p', 'data2_admin', 'data2', 'read'], - ['p', 'data2_admin', 'data2', 'write'], - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'], + ['p', 'data2_admin', 'data2', 'read'], + ['p', 'data2_admin', 'data2', 'write'], + ['g', 'alice', 'data2_admin', undefined] + ] + ); // Add a single policy to Database await a.addPolicy('', 'p', ['role', 'res', 'action']); @@ -173,14 +189,21 @@ describe('MongooseAdapter', () => { ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], ['data2_admin', 'data2', 'write'], - ['role', 'res', 'action']]); + ['role', 'res', 'action'] + ]); // Add policyList to Database try { - await a.addPolicies('', 'p', [['role', 'res', 'GET'], ['role', 'res', 'POST']]); + await a.addPolicies('', 'p', [ + ['role', 'res', 'GET'], + ['role', 'res', 'POST'] + ]); } catch (error) { assert(error instanceof InvalidAdapterTypeError); - assert.equal(error.message, 'addPolicies is only supported by SyncedAdapter. See newSyncedAdapter'); + assert.equal( + error.message, + 'addPolicies is only supported by SyncedAdapter. See newSyncedAdapter' + ); } e = await newEnforcer(rbacModel, a); @@ -196,7 +219,8 @@ describe('MongooseAdapter', () => { ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], ['data2_admin', 'data2', 'write'], - ['role', 'res', 'action']]); + ['role', 'res', 'action'] + ]); // Remove a single policy from Database await a.removePolicy('', 'p', ['role', 'res', 'action']); @@ -205,15 +229,22 @@ describe('MongooseAdapter', () => { ['alice', 'data1', 'read'], ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], - ['data2_admin', 'data2', 'write']]); + ['data2_admin', 'data2', 'write'] + ]); // Remove a policylist from Database try { - await a.removePolicies('', 'p', [['data2_admin', 'datag1712', 'read'], ['data2_admin', 'data2', 'write']]); + await a.removePolicies('', 'p', [ + ['data2_admin', 'datag1712', 'read'], + ['data2_admin', 'data2', 'write'] + ]); } catch (error) { assert(error instanceof InvalidAdapterTypeError); - assert.equal(error.message, 'removePolicies is only supported by SyncedAdapter. See newSyncedAdapter'); + assert.equal( + error.message, + 'removePolicies is only supported by SyncedAdapter. See newSyncedAdapter' + ); } e = await newEnforcer(rbacModel, a); @@ -221,7 +252,8 @@ describe('MongooseAdapter', () => { ['alice', 'data1', 'read'], ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], - ['data2_admin', 'data2', 'write']]); + ['data2_admin', 'data2', 'write'] + ]); }); it('Should properly store new policy rules from a file', async () => { @@ -240,12 +272,16 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(await e.getModel()); const rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write'], - ['p', 'data2_admin', 'data2', 'read'], - ['p', 'data2_admin', 'data2', 'write'], - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'], + ['p', 'data2_admin', 'data2', 'read'], + ['p', 'data2_admin', 'data2', 'write'], + ['g', 'alice', 'data2_admin', undefined] + ] + ); // Clear the current policy. await e.clearPolicy(); @@ -257,7 +293,8 @@ describe('MongooseAdapter', () => { ['alice', 'data1', 'read'], ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], - ['data2_admin', 'data2', 'write']]); + ['data2_admin', 'data2', 'write'] + ]); // Note: you don't need to look at the above code // if you already have a working DB with policy inside. @@ -270,7 +307,8 @@ describe('MongooseAdapter', () => { ['alice', 'data1', 'read'], ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], - ['data2_admin', 'data2', 'write']]); + ['data2_admin', 'data2', 'write'] + ]); // Add policy to DB await a.addPolicy('', 'p', ['role', 'res', 'action']); @@ -280,7 +318,8 @@ describe('MongooseAdapter', () => { ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], ['data2_admin', 'data2', 'write'], - ['role', 'res', 'action']]); + ['role', 'res', 'action'] + ]); // Remove policy from DB await a.removePolicy('', 'p', ['role', 'res', 'action']); e = await newEnforcer(rbacModel, a); @@ -288,7 +327,8 @@ describe('MongooseAdapter', () => { ['alice', 'data1', 'read'], ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], - ['data2_admin', 'data2', 'write']]); + ['data2_admin', 'data2', 'write'] + ]); }); it('Empty Role Definition should not raise an error', async () => { @@ -307,10 +347,13 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(e.getModel()); const rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write'] - ]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'] + ] + ); // Clear the current policy. e.clearPolicy(); @@ -341,7 +384,8 @@ describe('MongooseAdapter', () => { assert.deepEqual(await e.getPolicy(), [ ['alice', 'data1', 'read'], ['bob', 'data2', 'write'], - ['role', 'res', 'action']]); + ['role', 'res', 'action'] + ]); // Remove policy from DB await a.removePolicy('', 'p', ['role', 'res', 'action']); e = await newEnforcer(basicModel, a); @@ -466,31 +510,46 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(e.getModel()); let rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write'], - ['p', 'data2_admin', 'data2', 'read'], - ['p', 'data2_admin', 'data2', 'write'], - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'], + ['p', 'data2_admin', 'data2', 'read'], + ['p', 'data2_admin', 'data2', 'write'], + ['g', 'alice', 'data2_admin', undefined] + ] + ); // Remove 'data2_admin' related policy rules via a filter. // Two rules: {'data2_admin', 'data2', 'read'}, {'data2_admin', 'data2', 'write'} are deleted. await a.removeFilteredPolicy(undefined, undefined, 0, 'data2_admin'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write'], - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'], + ['g', 'alice', 'data2_admin', undefined] + ] + ); e = await newEnforcer(rbacModel, a); - assert.deepEqual(await e.getPolicy(), [['alice', 'data1', 'read'], ['bob', 'data2', 'write']]); + assert.deepEqual(await e.getPolicy(), [ + ['alice', 'data1', 'read'], + ['bob', 'data2', 'write'] + ]); // Remove 'data1' related policy rules via a filter. // One rule: {'alice', 'data1', 'read'} is deleted. await a.removeFilteredPolicy(undefined, undefined, 1, 'data1'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'bob', 'data2', 'write'], - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'bob', 'data2', 'write'], + ['g', 'alice', 'data2_admin', undefined] + ] + ); e = await newEnforcer(rbacModel, a); assert.deepEqual(await e.getPolicy(), [['bob', 'data2', 'write']]); @@ -498,13 +557,15 @@ describe('MongooseAdapter', () => { // One rule: {'bob', 'data2', 'write'} is deleted. await a.removeFilteredPolicy(undefined, undefined, 2, 'write'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [['g', 'alice', 'data2_admin', undefined]] + ); e = await newEnforcer(rbacModel, a); assert.deepEqual(await e.getPolicy(), []); }); - it('Should remove user\'s policies and groups when using deleteUser', async () => { + it("Should remove user's policies and groups when using deleteUser", async () => { const a = await createAdapter(); const CasbinRule = a.getCasbinRule(); // Because the DB is empty at first, @@ -519,42 +580,56 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(e.getModel()); let rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write'], - ['p', 'data2_admin', 'data2', 'read'], - ['p', 'data2_admin', 'data2', 'write'], - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'], + ['p', 'data2_admin', 'data2', 'read'], + ['p', 'data2_admin', 'data2', 'write'], + ['g', 'alice', 'data2_admin', undefined] + ] + ); e = await newEnforcer(rbacModel, a); // Remove 'alice' related policy rules via a RBAC deleteUser-function. // One policy: {'alice', 'data2', 'read'} and One Grouping Policy {'alice', 'data2_admin'} are deleted. await e.deleteUser('alice'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'bob', 'data2', 'write'], - ['p', 'data2_admin', 'data2', 'read'], - ['p', 'data2_admin', 'data2', 'write']]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'bob', 'data2', 'write'], + ['p', 'data2_admin', 'data2', 'read'], + ['p', 'data2_admin', 'data2', 'write'] + ] + ); e = await newEnforcer(rbacModel, a); assert.deepEqual(await e.getPolicy(), [ ['bob', 'data2', 'write'], ['data2_admin', 'data2', 'read'], - ['data2_admin', 'data2', 'write']]); + ['data2_admin', 'data2', 'write'] + ]); // Remove 'data1' related policy rules via a filter. // One rule: {'bob', 'data2', 'write'} is deleted. await e.deleteUser('bob'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'data2_admin', 'data2', 'read'], - ['p', 'data2_admin', 'data2', 'write']]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'data2_admin', 'data2', 'read'], + ['p', 'data2_admin', 'data2', 'write'] + ] + ); e = await newEnforcer(rbacModel, a); assert.deepEqual(await e.getPolicy(), [ ['data2_admin', 'data2', 'read'], - ['data2_admin', 'data2', 'write']]); + ['data2_admin', 'data2', 'write'] + ]); }); - it('Should remove user\'s policies and groups when using deleteRole', async () => { + it("Should remove user's policies and groups when using deleteRole", async () => { const a = await createAdapter(); const CasbinRule = a.getCasbinRule(); // Because the DB is empty at first, @@ -569,24 +644,33 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(e.getModel()); let rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write'], - ['p', 'data2_admin', 'data2', 'read'], - ['p', 'data2_admin', 'data2', 'write'], - ['g', 'alice', 'data2_admin', undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'], + ['p', 'data2_admin', 'data2', 'read'], + ['p', 'data2_admin', 'data2', 'write'], + ['g', 'alice', 'data2_admin', undefined] + ] + ); e = await newEnforcer(rbacModel, a); // Remove 'data2_admin' related policy rules via a RBAC deleteRole-function. - // One policy: {'alice', 'data2', 'read'} and One Grouping Policy {'alice', 'data2_admin'} are deleted. + // One policy: {'data2_admin', 'data2', 'read'} and One Grouping Policy {'alice', 'data2_admin'} are deleted. await e.deleteRole('data2_admin'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2]), [ - ['p', 'alice', 'data1', 'read'], - ['p', 'bob', 'data2', 'write']]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2]), + [ + ['p', 'alice', 'data1', 'read'], + ['p', 'bob', 'data2', 'write'] + ] + ); assert.deepEqual(await e.getPolicy(), [ ['alice', 'data1', 'read'], - ['bob', 'data2', 'write']]); + ['bob', 'data2', 'write'] + ]); }); it('Should properly store new complex policy rules from a file', async () => { @@ -604,13 +688,17 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(await e.getModel()); const rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), [ - ['p', 'admin', 'domain1', 'data1', 'read', 'allow'], - ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], - ['p', 'admin', 'domain2', 'data2', 'read', 'allow'], - ['p', 'admin', 'domain2', 'data2', 'write', 'allow'], - ['p', 'alice', 'domain2', 'data2', 'write', 'deny'], - ['g', 'alice', 'admin', 'domain2', undefined, undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [ + ['p', 'admin', 'domain1', 'data1', 'read', 'allow'], + ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], + ['p', 'admin', 'domain2', 'data2', 'read', 'allow'], + ['p', 'admin', 'domain2', 'data2', 'write', 'allow'], + ['p', 'alice', 'domain2', 'data2', 'write', 'deny'], + ['g', 'alice', 'admin', 'domain2', undefined, undefined] + ] + ); // Clear the current policy. await e.clearPolicy(); @@ -623,7 +711,8 @@ describe('MongooseAdapter', () => { ['admin', 'domain1', 'data1', 'write', 'allow'], ['admin', 'domain2', 'data2', 'read', 'allow'], ['admin', 'domain2', 'data2', 'write', 'allow'], - ['alice', 'domain2', 'data2', 'write', 'deny']]); + ['alice', 'domain2', 'data2', 'write', 'deny'] + ]); // Note: you don't need to look at the above code // if you already have a working DB with policy inside. @@ -637,7 +726,8 @@ describe('MongooseAdapter', () => { ['admin', 'domain1', 'data1', 'write', 'allow'], ['admin', 'domain2', 'data2', 'read', 'allow'], ['admin', 'domain2', 'data2', 'write', 'allow'], - ['alice', 'domain2', 'data2', 'write', 'deny']]); + ['alice', 'domain2', 'data2', 'write', 'deny'] + ]); // Add policy to DB await a.addPolicy('', 'p', ['role', 'domain', 'res', 'action', 'allow']); @@ -648,7 +738,8 @@ describe('MongooseAdapter', () => { ['admin', 'domain2', 'data2', 'read', 'allow'], ['admin', 'domain2', 'data2', 'write', 'allow'], ['alice', 'domain2', 'data2', 'write', 'deny'], - ['role', 'domain', 'res', 'action', 'allow']]); + ['role', 'domain', 'res', 'action', 'allow'] + ]); // Remove policy from DB await a.removePolicy('', 'p', ['role', 'domain', 'res', 'action', 'allow']); e = await newEnforcer(rbacDenyDomainModel, a); @@ -657,7 +748,8 @@ describe('MongooseAdapter', () => { ['admin', 'domain1', 'data1', 'write', 'allow'], ['admin', 'domain2', 'data2', 'read', 'allow'], ['admin', 'domain2', 'data2', 'write', 'allow'], - ['alice', 'domain2', 'data2', 'write', 'deny']]); + ['alice', 'domain2', 'data2', 'write', 'deny'] + ]); // Enforce a rule assert.notOk(await e.enforce('alice', 'domain2', 'data2', 'write')); assert.ok(await e.enforce('admin', 'domain2', 'data2', 'write')); @@ -683,19 +775,25 @@ describe('MongooseAdapter', () => { // The current policy means the policy in the Node-Casbin enforcer (aka in memory). await a.savePolicy(e.getModel()); let rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), [ - ['p', 'admin', 'domain1', 'data1', 'read', 'allow'], - ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], - ['p', 'admin', 'domain2', 'data2', 'read', 'allow'], - ['p', 'admin', 'domain2', 'data2', 'write', 'allow'], - ['p', 'alice', 'domain2', 'data2', 'write', 'deny'], - ['g', 'alice', 'admin', 'domain2', undefined, undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [ + ['p', 'admin', 'domain1', 'data1', 'read', 'allow'], + ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], + ['p', 'admin', 'domain2', 'data2', 'read', 'allow'], + ['p', 'admin', 'domain2', 'data2', 'write', 'allow'], + ['p', 'alice', 'domain2', 'data2', 'write', 'deny'], + ['g', 'alice', 'admin', 'domain2', undefined, undefined] + ] + ); e = await newEnforcer(rbacDenyDomainModel, a); - assert.deepEqual(await e.getPolicy(), [['admin', 'domain1', 'data1', 'read', 'allow'], + assert.deepEqual(await e.getPolicy(), [ + ['admin', 'domain1', 'data1', 'read', 'allow'], ['admin', 'domain1', 'data1', 'write', 'allow'], ['admin', 'domain2', 'data2', 'read', 'allow'], ['admin', 'domain2', 'data2', 'write', 'allow'], - ['alice', 'domain2', 'data2', 'write', 'deny']]); + ['alice', 'domain2', 'data2', 'write', 'deny'] + ]); // Remove 'data2_admin' related policy rules via a filter. // Four rules: @@ -706,18 +804,27 @@ describe('MongooseAdapter', () => { // are deleted. await a.removeFilteredPolicy(undefined, undefined, 0, 'admin'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), [ - ['p', 'alice', 'domain2', 'data2', 'write', 'deny'], - ['g', 'alice', 'admin', 'domain2', undefined, undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [ + ['p', 'alice', 'domain2', 'data2', 'write', 'deny'], + ['g', 'alice', 'admin', 'domain2', undefined, undefined] + ] + ); e = await newEnforcer(rbacDenyDomainModel, a); assert.deepEqual(await e.getPolicy(), [['alice', 'domain2', 'data2', 'write', 'deny']]); await a.removeFilteredPolicy(undefined, 'g'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), [ - ['p', 'alice', 'domain2', 'data2', 'write', 'deny']]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [['p', 'alice', 'domain2', 'data2', 'write', 'deny']] + ); await a.removeFilteredPolicy(undefined, 'p'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), []); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [] + ); // Reload the mode + policy e = await newEnforcer(rbacDenyDomainModel, rbacDenyDomainPolicy); @@ -730,14 +837,19 @@ describe('MongooseAdapter', () => { // are deleted. await a.removeFilteredPolicy(undefined, undefined, 1, 'domain2'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), [ - ['p', 'admin', 'domain1', 'data1', 'read', 'allow'], - ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], - ['g', 'alice', 'admin', 'domain2', undefined, undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [ + ['p', 'admin', 'domain1', 'data1', 'read', 'allow'], + ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], + ['g', 'alice', 'admin', 'domain2', undefined, undefined] + ] + ); e = await newEnforcer(rbacModel, a); assert.deepEqual(await e.getPolicy(), [ ['admin', 'domain1', 'data1', 'read', 'allow'], - ['admin', 'domain1', 'data1', 'write', 'allow']]); + ['admin', 'domain1', 'data1', 'write', 'allow'] + ]); // Remove 'data1' related policy rules via a filter. // Two rules: @@ -746,15 +858,20 @@ describe('MongooseAdapter', () => { // are deleted. await a.removeFilteredPolicy(undefined, undefined, 2, 'data1'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), [ - ['g', 'alice', 'admin', 'domain2', undefined, undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [['g', 'alice', 'admin', 'domain2', undefined, undefined]] + ); e = await newEnforcer(rbacDenyDomainModel, a); assert.deepEqual(await e.getPolicy(), []); await a.removeFilteredPolicy(undefined, 'g'); await a.removeFilteredPolicy(undefined, 'p'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), []); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [] + ); e = await newEnforcer(rbacDenyDomainModel, rbacDenyDomainPolicy); await a.savePolicy(e.getModel()); @@ -766,16 +883,21 @@ describe('MongooseAdapter', () => { // are deleted. await a.removeFilteredPolicy(undefined, undefined, 3, 'read'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), [ - ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], - ['p', 'admin', 'domain2', 'data2', 'write', 'allow'], - ['p', 'alice', 'domain2', 'data2', 'write', 'deny'], - ['g', 'alice', 'admin', 'domain2', undefined, undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [ + ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], + ['p', 'admin', 'domain2', 'data2', 'write', 'allow'], + ['p', 'alice', 'domain2', 'data2', 'write', 'deny'], + ['g', 'alice', 'admin', 'domain2', undefined, undefined] + ] + ); e = await newEnforcer(rbacDenyDomainModel, a); assert.deepEqual(await e.getPolicy(), [ ['admin', 'domain1', 'data1', 'write', 'allow'], ['admin', 'domain2', 'data2', 'write', 'allow'], - ['alice', 'domain2', 'data2', 'write', 'deny']]); + ['alice', 'domain2', 'data2', 'write', 'deny'] + ]); // Remove 'read' related policy rules via a filter. // One rule: @@ -783,14 +905,19 @@ describe('MongooseAdapter', () => { // is deleted. await a.removeFilteredPolicy(undefined, undefined, 4, 'deny'); rulesAfter = await CasbinRule.find({}); - assert.deepEqual(rulesAfter.map(rule => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), [ - ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], - ['p', 'admin', 'domain2', 'data2', 'write', 'allow'], - ['g', 'alice', 'admin', 'domain2', undefined, undefined]]); + assert.deepEqual( + rulesAfter.map((rule) => [rule.ptype, rule.v0, rule.v1, rule.v2, rule.v3, rule.v4]), + [ + ['p', 'admin', 'domain1', 'data1', 'write', 'allow'], + ['p', 'admin', 'domain2', 'data2', 'write', 'allow'], + ['g', 'alice', 'admin', 'domain2', undefined, undefined] + ] + ); e = await newEnforcer(rbacDenyDomainModel, a); assert.deepEqual(await e.getPolicy(), [ ['admin', 'domain1', 'data1', 'write', 'allow'], - ['admin', 'domain2', 'data2', 'write', 'allow']]); + ['admin', 'domain2', 'data2', 'write', 'allow'] + ]); }); it('SetSynced should fail in non-replicaset connection', async () => {