Skip to content

Commit

Permalink
feat: add flag to filterData, not only fields
Browse files Browse the repository at this point in the history
  • Loading branch information
0xfede committed Oct 21, 2020
1 parent 0ebae3f commit 5acb38e
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,11 @@ export abstract class Operation {

abstract handler(req: APIRequest, res: APIResponse, next?: NextFunction);

checkAbility(ability: Ability, data?: any, filter?: boolean): any {
checkAbility(ability: Ability, data?: any, filterFields?: boolean, filterData?: boolean): any {
if (this.scopes) {
for (let resource in this.scopes) {
for (let action in this.scopes[resource]) {
checkAbility(ability, resource, action, data, filter);
checkAbility(ability, resource, action, data, filterFields, filterData);
}
}
}
Expand Down
16 changes: 10 additions & 6 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Ability, ForbiddenError } from '@casl/ability';
import { Ability, ForbiddenError, subject } from '@casl/ability';
import * as dot from 'dot-prop';
import * as _ from 'lodash';
import { OpenAPIV3 } from 'openapi-police';
Expand Down Expand Up @@ -270,9 +270,10 @@ function deleteUnreferencedParameters(occurrences: any, spec: OpenAPIV3.Document
return spec;
}

export function checkAbility(ability: Ability, resource: string, action: string, data?: any, filter?: boolean): any {
export function checkAbility(ability: Ability, resource: string, action: string, data?: any, filterFields?: boolean, filterData?: boolean): any {
if (!data) {
ForbiddenError.from(ability).throwUnlessCan(action, resource);
return undefined;
} else {
function innerCheckAbility(data: any, path?: string[]): any {
let foundOne = false;
Expand All @@ -283,7 +284,7 @@ export function checkAbility(ability: Ability, resource: string, action: string,
innerCheckAbility(i, path);
return true;
} catch (err) {
if (filter) {
if (filterFields) {
return false;
} else {
API.fireError(403, 'insufficient privileges', undefined, err);
Expand All @@ -297,7 +298,7 @@ export function checkAbility(ability: Ability, resource: string, action: string,
data[key] = innerCheckAbility(value, (path || []).concat(key));
foundOne = true;
} catch (err) {
if (filter) {
if (filterFields) {
delete data[key];
} else {
API.fireError(403, 'insufficient privileges', undefined, err);
Expand All @@ -313,7 +314,10 @@ export function checkAbility(ability: Ability, resource: string, action: string,
}
return data;
}
innerCheckAbility(data);
if (filterData && !ability.can(action, subject(resource, data))) {
return undefined;
} else {
return innerCheckAbility(data);
}
}
return data;
}
1 change: 0 additions & 1 deletion test/ts/operation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,6 @@ describe('Operation', function () {
api.addResource(r);

before(function () {
debugger;
return api.router().then((router) => {
app.use(router);
server = app.listen(port);
Expand Down
17 changes: 15 additions & 2 deletions test/ts/util.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineAbility } from '@casl/ability';
import * as chai from 'chai';
import { rebaseOASDefinitions, refsRebaser, removeSchemaDeclaration, removeUnusedSchemas } from '../../dist/util';
import { checkAbility, rebaseOASDefinitions, refsRebaser, removeSchemaDeclaration, removeUnusedSchemas } from '../../dist/util';
import {
complexSpec,
jsonSchema,
Expand All @@ -18,7 +19,7 @@ import {
specWithUnreferencedSchemasButWrongRef,
specWithWrongComplexRef,
specWithWrongParamRef,
wrongSpec,
wrongSpec
} from './specs';

const should = chai.should();
Expand Down Expand Up @@ -4736,4 +4737,16 @@ describe('util', function () {
);
});
});

describe('checkAbility', function() {
it('should return undefined if data does not fulfill the conditions', function() {
const ability = defineAbility((can) => {
can('doSomething', 'Resource', { x: { $gt: 2 }});
});
const ok = checkAbility(ability, 'Resource', 'doSomething', { x: 3 }, false, true);
const nok = checkAbility(ability, 'Resource', 'doSomething', { x: 2 }, false, true);
ok.should.deep.equal({x: 3});
should.not.exist(nok);
})
});
});

0 comments on commit 5acb38e

Please sign in to comment.