Skip to content

Commit

Permalink
fix(mongoose): makes sure abilityConditions does not override existin…
Browse files Browse the repository at this point in the history
…g `$and` conditions

Fixes stalniy#272
  • Loading branch information
Matt Weeks authored and stalniy committed Mar 13, 2020
1 parent d471aa0 commit 4a5cbcf
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 10 deletions.
2 changes: 1 addition & 1 deletion packages/casl-mongoose/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"homepage": "https://stalniy.github.io/casl/",
"scripts": {
"build": "BUILD_TYPES=es6,umd:cjs rollup -c ../../tools/rollup.config.js -e @casl/ability/extra",
"build": "BUILD_TYPES=es6,umd:cjs rollup -c ../../tools/rollup.config.js -e @casl/ability/extra,mongoose",
"lint": "eslint src/",
"test": "NODE_ENV=test jest --config ../../tools/jest.config.js --env node",
"prerelease": "npm test && NODE_ENV=production npm run build",
Expand Down
20 changes: 12 additions & 8 deletions packages/casl-mongoose/spec/accessible_records.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ describe('Accessible Records Plugin', () => {
expect(ability.rulesFor).to.have.been.called.with.exactly('delete', Post.modelName)
})

it('calls `where` method of the query', () => {
spy.on(Post, 'where')
Post.accessibleBy(ability)
it('does not change query return type', () => {
const originalType = Post.findById(1).op
const type = Post.findById(1).accessibleBy(ability).op

expect(Post.where).to.be.called()
expect(type).to.equal(originalType)
})

it('wraps `toMongoQuery` result with additional `$and` to prevent collisions when combined with `$or` query', () => {
Expand All @@ -66,11 +66,15 @@ describe('Accessible Records Plugin', () => {
expect(Post.where).to.be.called.with.exactly({ $and: [query] })
})

it('does not change query return type', () => {
const originalType = Post.findById(1).op
const type = Post.findById(1).accessibleBy(ability).op
it('properly merges `toMongoQuery` result with existing in query `$and` conditions', () => {
const existingConditions = [{ prop: true }, { anotherProp: false }]
const query = Post.find({ $and: existingConditions })
const conditions = query.accessibleBy(ability).getQuery()

expect(type).to.equal(originalType)
expect(conditions.$and).to.eql([
...existingConditions,
toMongoQuery(ability, 'Post')
])
})

describe('when ability disallow to perform an action', () => {
Expand Down
7 changes: 6 additions & 1 deletion packages/casl-mongoose/src/accessible_records.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Query } from 'mongoose';
import { toMongoQuery } from './mongo';

const DENY_CONDITION_NAME = '__forbiddenByCasl__';
Expand Down Expand Up @@ -32,7 +33,11 @@ function emptyQuery(query) {
function accessibleBy(ability, action) {
const query = toMongoQuery(ability, this.modelName || this.model.modelName, action);

return query === null ? emptyQuery(this.where()) : this.where({ $and: [query] });
if (query === null) {
return emptyQuery(this.where());
}

return this instanceof Query ? this.and([query]) : this.where({ $and: [query] });
}

export function accessibleRecordsPlugin(schema) {
Expand Down

0 comments on commit 4a5cbcf

Please sign in to comment.