Skip to content

Commit

Permalink
feat(policies): adding addStatement function
Browse files Browse the repository at this point in the history
this new function provides a way to add a new statement in each Policy instance

re #35
  • Loading branch information
roggervalf committed Dec 5, 2020
1 parent 6d9135e commit fc2697f
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 25 deletions.
17 changes: 9 additions & 8 deletions dist/main.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,22 +189,23 @@ declare class ResourceBased<T extends object> extends Statement<T> {
private matchNotResources;
}

declare class Policy<T extends object> {
declare abstract class Policy<T extends object, U> {
protected context?: T;
protected conditionResolver?: ConditionResolver;
constructor({ context, conditionResolver }: MatchConditionInterface<T>);
setContext(this: Policy<T>, context: T): void;
getContext(this: Policy<T>): T | undefined;
setConditionResolver(this: Policy<T>, conditionResolver: ConditionResolver): void;
getConditionResolver(this: Policy<T>): ConditionResolver | undefined;
setContext(this: Policy<T, U>, context: T): void;
getContext(this: Policy<T, U>): T | undefined;
setConditionResolver(this: Policy<T, U>, conditionResolver: ConditionResolver): void;
getConditionResolver(this: Policy<T, U>): ConditionResolver | undefined;
abstract getStatements(this: Policy<T, U>): U[];
}

interface ActionBasedPolicyInterface<T extends object> {
statements: ActionBasedType[];
conditionResolver?: ConditionResolver;
context?: T;
}
declare class ActionBasedPolicy<T extends object> extends Policy<T> {
declare class ActionBasedPolicy<T extends object> extends Policy<T, ActionBasedType> {
private denyStatements;
private allowStatements;
private statements;
Expand All @@ -221,7 +222,7 @@ interface IdentityBasedPolicyInterface<T extends object> {
conditionResolver?: ConditionResolver;
context?: T;
}
declare class IdentityBasedPolicy<T extends object> extends Policy<T> {
declare class IdentityBasedPolicy<T extends object> extends Policy<T, IdentityBasedType> {
private denyStatements;
private allowStatements;
private statements;
Expand All @@ -237,7 +238,7 @@ interface ResourceBasedPolicyInterface<T extends object> {
conditionResolver?: ConditionResolver;
context?: T;
}
declare class ResourceBasedPolicy<T extends object> extends Policy<T> {
declare class ResourceBasedPolicy<T extends object> extends Policy<T, ResourceBasedType> {
private denyStatements;
private allowStatements;
private statements;
Expand Down
2 changes: 1 addition & 1 deletion dist/main.es.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/main.js.map

Large diffs are not rendered by default.

43 changes: 42 additions & 1 deletion src/ActionBasedPolicy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,48 @@ describe('ActionBasedPolicy Class', () => {
});
});

describe('when get statements', () => {
describe('when addStatement is called', () => {
describe('when adding an statement with effect as allow', () => {
it('adds a new ActionBased statement', () => {
const statements = [
{
action: 'read'
}
];
const newStatement = {
action: 'write'
};

const policy = new ActionBasedPolicy({ statements });
policy.addStatement(newStatement);
const exportedStatements = policy.getStatements();

expect(exportedStatements).toMatchObject([...statements, newStatement]);
});
});

describe('when adding an statement with effect as deny', () => {
it('adds a new ActionBased statement', () => {
const statements = [
{
action: 'read'
}
];
const newStatement = {
effect: 'deny' as const,
action: 'write'
};

const policy = new ActionBasedPolicy({ statements });
policy.addStatement(newStatement);
const exportedStatements = policy.getStatements();

expect(exportedStatements).toMatchObject([...statements, newStatement]);
});
});
});

describe('when getStatements is called', () => {
it('returns those statements', () => {
const statements = [
{
Expand Down
15 changes: 14 additions & 1 deletion src/ActionBasedPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ export interface ActionBasedPolicyInterface<T extends object> {
context?: T;
}

export class ActionBasedPolicy<T extends object> extends Policy<T> {
export class ActionBasedPolicy<T extends object> extends Policy<
T,
ActionBasedType
> {
private denyStatements: ActionBased<T>[];
private allowStatements: ActionBased<T>[];
private statements: ActionBasedType[];
Expand All @@ -36,6 +39,16 @@ export class ActionBasedPolicy<T extends object> extends Policy<T> {
);
}

addStatement(this: ActionBasedPolicy<T>, statement: ActionBasedType): void {
const statementInstance = new ActionBased(statement);
if (statementInstance.effect === 'allow') {
this.allowStatements.push(statementInstance);
} else {
this.denyStatements.push(statementInstance);
}
this.statements.push(statementInstance.getStatement());
}

getStatements(this: ActionBasedPolicy<T>): ActionBasedType[] {
return this.statements;
}
Expand Down
52 changes: 49 additions & 3 deletions src/IdentityBasedPolicy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,53 @@ describe('IdentityBasedPolicy Class', () => {
});
});

describe('when get statements', () => {
describe('when addStatement is called', () => {
describe('when adding an statement with effect as allow', () => {
it('adds a new IdentityBased statement', () => {
const statements = [
{
resource: ['books:horror:*'],
action: ['read']
}
];
const newStatement = {
effect: 'allow' as const,
resource: ['books:horror:*'],
action: 'write'
};

const policy = new IdentityBasedPolicy({ statements });
policy.addStatement(newStatement);
const exportedStatements = policy.getStatements();

expect(exportedStatements).toMatchObject([...statements, newStatement]);
});
});

describe('when adding an statement with effect as deny', () => {
it('adds a new IdentityBased statement', () => {
const statements = [
{
resource: ['books:horror:*'],
action: ['read']
}
];
const newStatement = {
effect: 'deny' as const,
resource: ['books:horror:*'],
action: 'write'
};

const policy = new IdentityBasedPolicy({ statements });
policy.addStatement(newStatement);
const exportedStatements = policy.getStatements();

expect(exportedStatements).toMatchObject([...statements, newStatement]);
});
});
});

describe('when getStatements is called', () => {
it('returns those statements', () => {
const statements = [
{
Expand All @@ -46,7 +92,7 @@ describe('IdentityBasedPolicy Class', () => {
});
});

describe('when getContext', () => {
describe('when getContext is called', () => {
it('returns context attribute', () => {
const context = { user: { age: 31 } };
const statements = [
Expand All @@ -61,7 +107,7 @@ describe('IdentityBasedPolicy Class', () => {
});
});

describe('when setContext', () => {
describe('when setContext is called', () => {
it('sets context attribute', () => {
const context = { user: { age: 31 } };
const statements = [
Expand Down
18 changes: 17 additions & 1 deletion src/IdentityBasedPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ interface IdentityBasedPolicyInterface<T extends object> {
context?: T;
}

export class IdentityBasedPolicy<T extends object> extends Policy<T> {
export class IdentityBasedPolicy<T extends object> extends Policy<
T,
IdentityBasedType
> {
private denyStatements: IdentityBased<T>[];
private allowStatements: IdentityBased<T>[];
private statements: IdentityBasedType[];
Expand All @@ -35,6 +38,19 @@ export class IdentityBasedPolicy<T extends object> extends Policy<T> {
);
}

addStatement(
this: IdentityBasedPolicy<T>,
statement: IdentityBasedType
): void {
const statementInstance = new IdentityBased(statement);
if (statementInstance.effect === 'allow') {
this.allowStatements.push(statementInstance);
} else {
this.denyStatements.push(statementInstance);
}
this.statements.push(statementInstance.getStatement());
}

getStatements(this: IdentityBasedPolicy<T>): IdentityBasedType[] {
return this.statements;
}
Expand Down
12 changes: 7 additions & 5 deletions src/Policy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MatchConditionInterface, ConditionResolver } from './types';

abstract class Policy<T extends object> {
abstract class Policy<T extends object, U> {
protected context?: T;
protected conditionResolver?: ConditionResolver;

Expand All @@ -9,24 +9,26 @@ abstract class Policy<T extends object> {
this.conditionResolver = conditionResolver;
}

setContext(this: Policy<T>, context: T): void {
setContext(this: Policy<T, U>, context: T): void {
this.context = context;
}

getContext(this: Policy<T>): T | undefined {
getContext(this: Policy<T, U>): T | undefined {
return this.context;
}

setConditionResolver(
this: Policy<T>,
this: Policy<T, U>,
conditionResolver: ConditionResolver
): void {
this.conditionResolver = conditionResolver;
}

getConditionResolver(this: Policy<T>): ConditionResolver | undefined {
getConditionResolver(this: Policy<T, U>): ConditionResolver | undefined {
return this.conditionResolver;
}

abstract getStatements(this: Policy<T, U>): U[];
}

export { Policy };
54 changes: 51 additions & 3 deletions src/ResourceBasedPolicy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,55 @@ describe('ResourceBasedPolicy Class', () => {
});
});

describe('when get statements', () => {
describe('when addStatement is called', () => {
describe('when adding an statement with effect as allow', () => {
it('adds a new ResourceBased statement', () => {
const statements = [
{
principal: 'andre',
resource: ['books:horror:*'],
action: ['read']
}
];
const newStatement = {
effect: 'allow' as const,
resource: ['books:horror:*'],
action: 'write'
};

const policy = new ResourceBasedPolicy({ statements });
policy.addStatement(newStatement);
const exportedStatements = policy.getStatements();

expect(exportedStatements).toMatchObject([...statements, newStatement]);
});
});

describe('when adding an statement with effect as deny', () => {
it('adds a new ResourceBased statement', () => {
const statements = [
{
principal: 'andre',
resource: ['books:horror:*'],
action: ['read']
}
];
const newStatement = {
effect: 'deny' as const,
resource: ['books:horror:*'],
action: 'write'
};

const policy = new ResourceBasedPolicy({ statements });
policy.addStatement(newStatement);
const exportedStatements = policy.getStatements();

expect(exportedStatements).toMatchObject([...statements, newStatement]);
});
});
});

describe('when getStatements is called', () => {
it('returns those statements', () => {
const statements = [
{
Expand All @@ -48,7 +96,7 @@ describe('ResourceBasedPolicy Class', () => {
});
});

describe('when getConditionResolver', () => {
describe('when getConditionResolver is called', () => {
it('returns conditionResolver attribute', () => {
const conditionResolver = {
greaterThan: (data: number, expected: number): boolean => {
Expand All @@ -68,7 +116,7 @@ describe('ResourceBasedPolicy Class', () => {
});
});

describe('when setConditionResolver', () => {
describe('when setConditionResolver is called', () => {
it('sets conditionResolver attribute', () => {
const conditionResolver = {
greaterThan: (data: number, expected: number): boolean => {
Expand Down
18 changes: 17 additions & 1 deletion src/ResourceBasedPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ interface ResourceBasedPolicyInterface<T extends object> {
context?: T;
}

export class ResourceBasedPolicy<T extends object> extends Policy<T> {
export class ResourceBasedPolicy<T extends object> extends Policy<
T,
ResourceBasedType
> {
private denyStatements: ResourceBased<T>[];
private allowStatements: ResourceBased<T>[];
private statements: ResourceBasedType[];
Expand All @@ -35,6 +38,19 @@ export class ResourceBasedPolicy<T extends object> extends Policy<T> {
);
}

addStatement(
this: ResourceBasedPolicy<T>,
statement: ResourceBasedType
): void {
const statementInstance = new ResourceBased(statement);
if (statementInstance.effect === 'allow') {
this.allowStatements.push(statementInstance);
} else {
this.denyStatements.push(statementInstance);
}
this.statements.push(statementInstance.getStatement());
}

getStatements(this: ResourceBasedPolicy<T>): ResourceBasedType[] {
return this.statements;
}
Expand Down

0 comments on commit fc2697f

Please sign in to comment.