Skip to content

Commit

Permalink
fix(actionbasedstatement): throw TypeError when action and notAction …
Browse files Browse the repository at this point in the history
…are present
  • Loading branch information
roggervalf committed Oct 18, 2020
1 parent f78553e commit 2e4409d
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 12 deletions.
32 changes: 32 additions & 0 deletions src/ActionBasedStatement.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ActionBased } from './ActionBasedStatement';

describe('ActionBased Class', () => {
describe('when creating action based statement', () => {
it("doesn't throw an error", () => {
expect(
() =>
new ActionBased({
action: ['read', 'write']
})
).not.toThrow();
expect(
() =>
new ActionBased({
notAction: ['write']
})
).not.toThrow();
});

it('throws a TypeError', () => {
const expectedError = new TypeError(
'ActionBased statement should have an action or a notAction attribute, no both'
);
expect(() => {
new ActionBased({
action: ['read', 'write'],
notAction: 'delete'
});
}).toThrow(expectedError);
});
});
});
22 changes: 16 additions & 6 deletions src/ActionBasedStatement.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Context, ActionBasedType, MatchActionBasedInterface } from './types';
import { instanceOfActionBlock } from './utils/instanceOfInterfaces';
import { ActionBasedType, Context, MatchActionBasedInterface } from './types';
import {
instanceOfActionBlock,
instanceOfNotActionBlock
} from './utils/instanceOfInterfaces';
import { Matcher } from './Matcher';
import { Statement, applyContext } from './Statement';
import { applyContext, Statement } from './Statement';

class ActionBased extends Statement {
private action?: string[];
Expand All @@ -10,7 +13,14 @@ class ActionBased extends Statement {

constructor(action: ActionBasedType) {
super(action);
if (instanceOfActionBlock(action)) {
const hasAction = instanceOfActionBlock(action);
const hasNotAction = instanceOfNotActionBlock(action);
if (hasAction && hasNotAction) {
throw new TypeError(
'ActionBased statement should have an action or a notAction attribute, no both'
);
}
if (hasAction) {
this.action =
typeof action.action === 'string' ? [action.action] : action.action;
} else {
Expand Down Expand Up @@ -40,15 +50,15 @@ class ActionBased extends Statement {

private matchActions(action: string, context?: Context): boolean {
return this.action
? this.action.some(a =>
? this.action.some((a) =>
new Matcher(applyContext(a, context)).match(action)
)
: true;
}

private matchNotActions(action: string, context?: Context): boolean {
return this.notAction
? !this.notAction.some(a =>
? !this.notAction.some((a) =>
new Matcher(applyContext(a, context)).match(action)
)
: true;
Expand Down
11 changes: 6 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,15 @@ type ResourceBasedType = StatementInterface &

export {
ActionBasedType,
ActionBlock,
IdentityBasedType,
ResourceBasedType,
PrincipalMap,
Patterns,
PrincipalBlock,
PrincipalMap,
ResourceBasedType,
ResourceBlock,
NotResourceBlock,
ActionBlock,
PrincipalBlock
NotActionBlock,
NotResourceBlock
};

/*
Expand Down
15 changes: 14 additions & 1 deletion src/utils/instanceOfInterfaces.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
instanceOfActionBlock,
instanceOfPrincipalBlock,
instanceOfResourceBlock,
instanceOfActionBlock,
instanceOfNotActionBlock,
instanceOfNotResourceBlock
} from './instanceOfInterfaces';

Expand Down Expand Up @@ -44,6 +45,18 @@ describe('Util functions', () => {
});
});

describe('instanceOfNotActionBlock', () => {
it("doesn't throw an error", () => {
expect(() =>
instanceOfNotActionBlock({
notAction: 'something'
})
).not.toThrow();
expect(instanceOfNotActionBlock({ notAction: 'something' })).toBe(true);
expect(instanceOfNotActionBlock({ action: 'something' })).toBe(false);
});
});

describe('instanceOfNotResourceBlock', () => {
it("doesn't throw an error", () => {
expect(() =>
Expand Down
23 changes: 23 additions & 0 deletions src/utils/instanceOfInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ActionBlock,
NotActionBlock,
PrincipalBlock,
NotResourceBlock,
ResourceBlock
Expand All @@ -13,12 +14,34 @@ import {
* ```javascript
* instanceOfActionBlock({ action: 'something' })
* // => true
*
* instanceOfActionBlock({ notAction: 'something' })
* // => false
* ```
*/
export function instanceOfActionBlock(object: object): object is ActionBlock {
return 'action' in object;
}

/**
* Validate if an `object` is an instance of `NotActionBlock`.
* @param {Object} object Object to validate
* @returns {boolean} Returns true if `object` has `notAction` attribute.
* @example
* ```javascript
* instanceOfNotActionBlock({ notAction: 'something' })
* // => true
*
* instanceOfNotActionBlock({ action: 'something' })
* // => false
* ```
*/
export function instanceOfNotActionBlock(
object: object
): object is NotActionBlock {
return 'notAction' in object;
}

/**
* Validate if an `object` is an instance of `PrincipalBlock`.
* @param {Object} object Object to validate
Expand Down

0 comments on commit 2e4409d

Please sign in to comment.