-
Notifications
You must be signed in to change notification settings - Fork 7
/
IdentityBasedPolicy.ts
111 lines (102 loc) · 3 KB
/
IdentityBasedPolicy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import {
ConditionResolver,
EvaluateIdentityBasedInterface,
IdentityBasedType
} from './types';
import { IdentityBased } from './IdentityBasedStatement';
import { Policy } from './Policy';
interface IdentityBasedPolicyInterface<T extends object> {
statements: IdentityBasedType[];
conditionResolver?: ConditionResolver;
context?: T;
}
export class IdentityBasedPolicy<T extends object> extends Policy<
T,
IdentityBasedType
> {
private denyStatements: IdentityBased<T>[];
private allowStatements: IdentityBased<T>[];
private statements: IdentityBasedType[];
constructor({
statements,
conditionResolver,
context
}: IdentityBasedPolicyInterface<T>) {
super({ context, conditionResolver });
const statementInstances = statements.map(
(statement) => new IdentityBased(statement)
);
this.allowStatements = statementInstances.filter(
(s) => s.effect === 'allow'
);
this.denyStatements = statementInstances.filter((s) => s.effect === 'deny');
this.statements = statementInstances.map((statement) =>
statement.getStatement()
);
}
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;
}
evaluate(
this: IdentityBasedPolicy<T>,
{ action, resource, context }: EvaluateIdentityBasedInterface<T>
): boolean {
const args = { action, resource, context };
return !this.cannot(args) && this.can(args);
}
can(
this: IdentityBasedPolicy<T>,
{ action, resource, context }: EvaluateIdentityBasedInterface<T>
): boolean {
return this.allowStatements.some((s) =>
s.matches({
action,
resource,
context: context || this.context,
conditionResolver: this.conditionResolver
})
);
}
whyCan(
this: IdentityBasedPolicy<T>,
{ action, resource, context }: EvaluateIdentityBasedInterface<T>
): IdentityBasedType[] {
return this.allowStatements.reduce((statements, currentStatement) => {
const matches = currentStatement.matches({
action,
resource,
context: context || this.context,
conditionResolver: this.conditionResolver
});
if (matches) {
return [...statements, currentStatement.getStatement()];
}
return statements;
}, [] as IdentityBasedType[]);
}
cannot(
this: IdentityBasedPolicy<T>,
{ action, resource, context }: EvaluateIdentityBasedInterface<T>
): boolean {
return this.denyStatements.some((s) =>
s.matches({
action,
resource,
context: context || this.context,
conditionResolver: this.conditionResolver
})
);
}
}