Skip to content

Commit 2c573b1

Browse files
committed
feat(policy-resolver): use an LRU cache instead of a map
1 parent 97355b5 commit 2c573b1

File tree

3 files changed

+122
-26
lines changed

3 files changed

+122
-26
lines changed

lib/policy-resolver.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import jsonLogic from "json-logic-js";
21
import pathExists from "just-has";
2+
import jsonLogic from "json-logic-js";
3+
import LRUCache from "lru-cache";
34
import { PolicyStatementStore } from "./store/types";
45
import { JsonLogicParser, PolicyDocument, PolicyStatement } from "./types";
56
import {
@@ -9,8 +10,15 @@ import {
910
import { PolicyDocumentValidator } from "./validator";
1011
import { CachedStatementsStore } from "./store/cached-statements-store";
1112

12-
interface ResourceActionResolverOptions {
13+
interface PolicyResolverOptions {
14+
/** restrict valid actions to only this list */
15+
allowedActions?: string[];
1316
parser?: JsonLogicParser;
17+
cache?: LRUCache.Options<string, CompiledFns<unknown>>;
18+
}
19+
20+
const DEFAULT_CACHE_OPTIONS: LRUCache.Options<string, CompiledFns<unknown>> = {
21+
max: 1000
1422
}
1523

1624
type CompiledFns<TContext> = {
@@ -31,7 +39,7 @@ function hasAllPaths(statement: ParsedPolicyStatement, ctx: unknown) {
3139
}
3240

3341
export class PolicyResolver {
34-
static fromDocuments(docs: PolicyDocument[]): PolicyResolver {
42+
static fromDocuments(docs: PolicyDocument[], opts: PolicyResolverOptions = {}): PolicyResolver {
3543
const validator = new PolicyDocumentValidator();
3644

3745
const statements = docs.flatMap((doc) => {
@@ -40,31 +48,33 @@ export class PolicyResolver {
4048
return doc.statement;
4149
});
4250

43-
return this.fromStatements(statements);
51+
return this.fromStatements(statements, opts);
4452
}
4553

46-
static fromStatements(statements: PolicyStatement[]): PolicyResolver {
54+
static fromStatements(statements: PolicyStatement[], opts: PolicyResolverOptions = {}): PolicyResolver {
4755
const parsed = statements.map((statement) =>
4856
parsePolicyStatement(statement)
4957
);
5058

5159
const store = new CachedStatementsStore();
5260
store.addAll(parsed);
5361

54-
return new PolicyResolver(store);
62+
return new PolicyResolver(store, opts);
5563
}
5664

65+
#allowedActions: string[] | null;
5766
#policyStore: PolicyStatementStore;
5867
#parser: JsonLogicParser;
59-
#cache: Map<string, CompiledFns<unknown>>;
68+
#cache: LRUCache<string, CompiledFns<unknown>>;
6069

6170
constructor(
6271
policyStore: PolicyStatementStore,
63-
opts: ResourceActionResolverOptions = {}
72+
opts: PolicyResolverOptions = {}
6473
) {
6574
this.#policyStore = policyStore;
75+
this.#allowedActions = opts.allowedActions ?? null;
6676
this.#parser = opts.parser ?? jsonLogic;
67-
this.#cache = new Map();
77+
this.#cache = new LRUCache({ ...DEFAULT_CACHE_OPTIONS, ...opts.cache });
6878
}
6979

7080
/**
@@ -73,6 +83,10 @@ export class PolicyResolver {
7383
* @param context extra data that can be referenced with { "var": "path.to.resource" }
7484
*/
7585
can<TContext = unknown>(action: string, context?: TContext): boolean {
86+
if (this.#allowedActions && !this.#allowedActions.includes(action)) {
87+
return false;
88+
}
89+
7690
if (!this.#cache.has(action)) {
7791
this.#cache.set(action, this.#compileAction(action));
7892
}
@@ -89,6 +103,10 @@ export class PolicyResolver {
89103
action: string,
90104
context?: TContext
91105
): ParsedPolicyStatement[] {
106+
if (this.#allowedActions && !this.#allowedActions.includes(action)) {
107+
return [];
108+
}
109+
92110
if (!this.#cache.has(action)) {
93111
this.#cache.set(action, this.#compileAction(action));
94112
}

package-lock.json

Lines changed: 93 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"dependencies": {
1919
"ajv": "^8.11.0",
2020
"json-logic-js": "^2.0.2",
21-
"just-has": "^2.3.0"
21+
"just-has": "^2.3.0",
22+
"lru-cache": "^7.18.1"
2223
},
2324
"devDependencies": {
2425
"@babel/preset-env": "^7.16.11",

0 commit comments

Comments
 (0)