Skip to content

Commit

Permalink
feat: implement UpdatableAdapter interface (#49)
Browse files Browse the repository at this point in the history
Signed-off-by: Zxilly <[email protected]>
  • Loading branch information
Zxilly authored Aug 3, 2021
1 parent d2f6241 commit 131a446
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 27 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.21.0",
"casbin": "^5.1.0",
"casbin": "^5.11.1",
"chai": "^4.3.0",
"coveralls": "^3.0.9",
"cz-conventional-changelog": "^3.3.0",
Expand Down
49 changes: 42 additions & 7 deletions src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {Helper, logPrint, Model} from "casbin";
import {BatchAdapter, FilteredAdapter, Helper, logPrint, Model, UpdatableAdapter} from "casbin";
import {ConnectOptions, Mongoose, connect, FilterQuery} from "mongoose";
import CasbinRule, {IModel} from './model'
import {AdapterError, InvalidAdapterTypeError} from "./errors";
Expand Down Expand Up @@ -44,12 +44,12 @@ export interface sessionOption {
*
* @class
*/
export class MongooseAdapter {
export class MongooseAdapter implements BatchAdapter, FilteredAdapter, UpdatableAdapter {
private filtered: boolean;
private isSynced: boolean;
private uri: string;
private options: ConnectOptions;
private mongoseInstance: Mongoose;
private mongooseInstance: Mongoose;
private autoAbort: boolean;
private autoCommit: boolean;
private session: ClientSession;
Expand Down Expand Up @@ -86,7 +86,7 @@ export class MongooseAdapter {
async _open() {
await connect(this.uri, this.options)
.then(instance => {
this.mongoseInstance = instance;
this.mongooseInstance = instance;
});
}

Expand Down Expand Up @@ -206,7 +206,7 @@ export class MongooseAdapter {
*/
async getSession() {
if (this.isSynced) {
return this.session && this.session.inTransaction() ? this.session : this.mongoseInstance.startSession();
return this.session && this.session.inTransaction() ? this.session : this.mongooseInstance.startSession();
} else throw new InvalidAdapterTypeError('Transactions are only supported by SyncedAdapter. See newSyncedAdapter');
}

Expand Down Expand Up @@ -469,6 +469,41 @@ export class MongooseAdapter {
}
}

/**
* Implements the process of updating policy rule.
* This method is used by casbin and should not be called by user.
*
* @param {String} sec Section of the policy
* @param {String} ptype Type of the policy (e.g. "p" or "g")
* @param {Array<String>} oldRule Policy rule to remove from enforcer
* @param {Array<String>} newRule Policy rule to add into enforcer
* @returns {Promise<void>}
*/
async updatePolicy(sec: string, ptype: string, oldRule: string[], newRule: string[]) {
const options: sessionOption = {};
try {
if (this.isSynced) options.session = await this.getTransaction();
const {p_type, v0, v1, v2, v3, v4, v5} = this.savePolicyLine(ptype, oldRule);
const newRuleLine = this.savePolicyLine(ptype, newRule);
const newModel = {
p_type: newRuleLine.p_type,
v0: newRuleLine.v0,
v1: newRuleLine.v1,
v2: newRuleLine.v2,
v3: newRuleLine.v3,
v4: newRuleLine.v4,
v5: newRuleLine.v5
}

await CasbinRule.updateOne({p_type, v0, v1, v2, v3, v4, v5}, newModel, options);

this.autoCommit && options.session && await options.session.commitTransaction();
} catch (err) {
this.autoAbort && options.session && await options.session.abortTransaction();
throw err;
}
}

/**
* Implements the process of removing a list of policy rules.
* This method is used by casbin and should not be called by user.
Expand Down Expand Up @@ -568,9 +603,9 @@ export class MongooseAdapter {
}

async close() {
if (this.mongoseInstance && this.mongoseInstance.connection) {
if (this.mongooseInstance && this.mongooseInstance.connection) {
if (this.session) await this.session.endSession();
await this.mongoseInstance.connection.close();
await this.mongooseInstance.connection.close();
}
}
}
33 changes: 30 additions & 3 deletions test/integration/adapter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,33 @@ describe('MongooseAdapter', () => {
}
});

it('Should properly update existing policy rules', async () => {
const enforcer = await createEnforcer();

const rulesBefore = await CasbinRule.find();
assert.deepEqual(rulesBefore, []);
assert.isTrue(await enforcer.addPolicy('sub', 'obj', 'act'));
assert.deepEqual(await enforcer.getPolicy(), [['sub', 'obj', 'act']]);

const rulesAfter = await CasbinRule.find({
p_type: 'p',
v0: 'sub',
v1: 'obj',
v2: 'act'
});
assert.equal(rulesAfter.length, 1);
assert.isTrue(await enforcer.updatePolicy(['sub', 'obj', 'act'], ['sub1', 'obj1', 'act1']));
assert.deepEqual(await enforcer.getPolicy(), [['sub1', 'obj1', 'act1']]);

const rulesAfterUpdate = await CasbinRule.find({
p_type: 'p',
v0: 'sub1',
v1: 'obj1',
v2: 'act1'
});
assert.equal(rulesAfterUpdate.length, 1);
});

it('Should properly delete existing policy rules', async () => {
const enforcer = await createEnforcer();

Expand Down Expand Up @@ -808,18 +835,18 @@ describe('MongooseAdapter', () => {
// Create mongoAdapter
const enforcer = await createEnforcer();
const adapter = enforcer.getAdapter();
assert.equal(adapter.mongoseInstance.connection.readyState, 1, 'Connection should be open');
assert.equal(adapter.mongooseInstance.connection.readyState, 1, 'Connection should be open');

// Connection should close
await adapter.close();
assert.equal(adapter.mongoseInstance.connection.readyState, 0, 'Connection should be closed');
assert.equal(adapter.mongooseInstance.connection.readyState, 0, 'Connection should be closed');
});

it('Closing a closed/undefined connection should not raise an error', async () => {
// Create mongoAdapter
const adapter = await createDisconnectedAdapter();
// Closing a closed connection should not raise an error
await adapter.close();
assert.equal(adapter.mongoseInstance, undefined, 'mongoseInstance should be undefined');
assert.equal(adapter.mongooseInstance, undefined, 'mongoseInstance should be undefined');
});
});
31 changes: 15 additions & 16 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -825,16 +825,15 @@ caniuse-lite@^1.0.30001219:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71"
integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==

casbin@^5.1.0:
version "5.6.1"
resolved "https://registry.npmjs.org/casbin/-/casbin-5.6.1.tgz#d4aced0a0023021355646947558f6a11bde96c86"
integrity sha512-WFroyV4dkEoA3YwzFThefK2zbMpJUqf+gO6ReG0BVanOd/Du/CWUy0VAQvz1WO2JNHo5Lgr8jtEYpj4/Hvk/7g==
casbin@^5.11.1:
version "5.11.1"
resolved "https://registry.npmjs.org/casbin/-/casbin-5.11.1.tgz#763ed69105a57ce0e2356684dd60cbeeb6db5b7a"
integrity sha512-/6eDOFyv3sgjJRVKTTDN0V4jTPXiTPNwsqoI5Bge/UkIGnl6gdV6yOpKEbTDXgsQWW5vfSfOfsoA/xwqqNNuOg==
dependencies:
await-lock "^2.0.1"
csv-parse "^4.15.3"
expression-eval "^2.0.0"
ip "^1.1.5"
micromatch "^4.0.2"
expression-eval "^4.0.0"
picomatch "^2.2.3"

caseless@~0.12.0:
version "0.12.0"
Expand Down Expand Up @@ -1644,10 +1643,10 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
dependencies:
homedir-polyfill "^1.0.1"

expression-eval@^2.0.0:
version "2.1.0"
resolved "https://registry.npmjs.org/expression-eval/-/expression-eval-2.1.0.tgz#422915caa46140a7c5b5f248650dea8bf8236e62"
integrity sha512-FUJO/Akvl/JOWkvlqZaqbkhsEWlCJWDeZG4tzX96UH68D9FeRgYgtb55C2qtqbORC0Q6x5419EDjWu4IT9kQfg==
expression-eval@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/expression-eval/-/expression-eval-4.0.0.tgz#d6a07c93e8b33e635710419d4a595d9208b9cc5e"
integrity sha512-YHSnLTyIb9IKaho2IdQbvlei/pElxnGm48UgaXJ1Fe5au95Ck0R9ftm6rHJQuKw3FguZZ4eXVllJFFFc7LX0WQ==
dependencies:
jsep "^0.3.0"

Expand Down Expand Up @@ -2269,11 +2268,6 @@ [email protected]:
strip-ansi "^5.1.0"
through "^2.3.6"

ip@^1.1.5:
version "1.1.5"
resolved "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=

is-accessor-descriptor@^0.1.6:
version "0.1.6"
resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
Expand Down Expand Up @@ -3573,6 +3567,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==

picomatch@^2.2.3:
version "2.3.0"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==

pidtree@^0.3.0:
version "0.3.1"
resolved "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a"
Expand Down

0 comments on commit 131a446

Please sign in to comment.