Skip to content

Commit ff41f0a

Browse files
committed
feat: enforceSync
Signed-off-by: Xiaotian Lu <xtlu000@gmail.com>
1 parent 713ab1e commit ff41f0a

File tree

4 files changed

+67
-11
lines changed

4 files changed

+67
-11
lines changed

src/coreEnforcer.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { DefaultEffector, Effect, Effector } from './effect';
1818
import { FunctionMap, Model, newModel, PolicyOp } from './model';
1919
import { Adapter, FilteredAdapter, Watcher, BatchAdapter } from './persist';
2020
import { DefaultRoleManager, RoleManager } from './rbac';
21-
import { escapeAssertion, generateGFunction, getEvalValue, hasEval, replaceEval } from './util';
21+
import { escapeAssertion, generateGFunction, getEvalValue, hasEval, replaceEval, generatorRunSync, generatorRunAsync } from './util';
2222
import { getLogger, logPrint } from './log';
2323

2424
type Matcher = ((context: any) => Promise<any>) | ((context: any) => any);
@@ -274,7 +274,7 @@ export class CoreEnforcer {
274274
await this.model.buildRoleLinks(this.rm);
275275
}
276276

277-
private async privateEnforce(asyncCompile = true, ...rvals: any[]): Promise<boolean> {
277+
private *privateEnforce(asyncCompile = true, ...rvals: any[]): Generator<boolean | Promise<boolean>> {
278278
if (!this.enabled) {
279279
return true;
280280
}
@@ -347,7 +347,7 @@ export class CoreEnforcer {
347347
}
348348

349349
const context = { ...parameters, ...functions };
350-
const result = asyncCompile ? await expression(context) : expression(context);
350+
const result = asyncCompile ? yield expression(context) : expression(context);
351351

352352
let eftRes: Effect;
353353
switch (typeof result) {
@@ -395,7 +395,7 @@ export class CoreEnforcer {
395395

396396
expression = this.getExpression(asyncCompile, expString);
397397
const context = { ...parameters, ...functions };
398-
const result = asyncCompile ? await expression(context) : expression(context);
398+
const result = asyncCompile ? yield expression(context) : expression(context);
399399

400400
if (result) {
401401
effectStream.pushEffect(Effect.Allow);
@@ -427,15 +427,22 @@ export class CoreEnforcer {
427427
/**
428428
* If the matchers does not contain an asynchronous method, call it faster.
429429
*
430-
* enforceWithSyncCompile decides whether a "subject" can access a "object" with
430+
* enforceSync decides whether a "subject" can access a "object" with
431431
* the operation "action", input parameters are usually: (sub, obj, act).
432432
*
433433
* @param rvals the request needs to be mediated, usually an array
434434
* of strings, can be class instances if ABAC is used.
435435
* @return whether to allow the request.
436436
*/
437-
public async enforceWithSyncCompile(...rvals: any[]): Promise<boolean> {
438-
return this.privateEnforce(false, ...rvals);
437+
public enforceSync(...rvals: any[]): boolean {
438+
return generatorRunSync(this.privateEnforce(false, ...rvals));
439+
}
440+
441+
/**
442+
* Same as enforceSync. To be removed.
443+
*/
444+
public enforceWithSyncCompile(...rvals: any[]): boolean {
445+
return this.enforceSync(...rvals);
439446
}
440447

441448
/**
@@ -447,6 +454,6 @@ export class CoreEnforcer {
447454
* @return whether to allow the request.
448455
*/
449456
public async enforce(...rvals: any[]): Promise<boolean> {
450-
return this.privateEnforce(true, ...rvals);
457+
return generatorRunAsync(this.privateEnforce(true, ...rvals));
451458
}
452459
}

src/syncedEnforcer.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,8 @@ export class SyncedEnforcer extends Enforcer {
7575
* of strings, can be class instances if ABAC is used.
7676
* @return whether to allow the request.
7777
*/
78-
public async enforceWithSyncCompile(...rvals: any[]): Promise<boolean> {
79-
await this.lock.acquireAsync();
80-
return super.enforceWithSyncCompile(...rvals).finally(() => this.lock.release());
78+
public enforceWithSyncCompile(...rvals: any[]): boolean {
79+
return super.enforceWithSyncCompile(...rvals);
8180
}
8281

8382
/**

src/util/util.ts

+31
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,35 @@ function getEvalValue(s: string): string[] {
130130
return rules;
131131
}
132132

133+
// generatorRunSync handle generator function in Sync model and return value which is not Promise
134+
function generatorRunSync(iterator: Generator<any>): any {
135+
let { value, done } = iterator.next();
136+
while (true) {
137+
if (value instanceof Promise) {
138+
throw new Error('cannot handle Promise in generatorRunSync, Please use generatorRunAsync');
139+
}
140+
if (!done) {
141+
const temp = value;
142+
({ value, done } = iterator.next(temp));
143+
} else {
144+
return value;
145+
}
146+
}
147+
}
148+
149+
// generatorRunAsync handle generator function in Async model and return Promise
150+
async function generatorRunAsync(iterator: Generator<any>): Promise<any> {
151+
let { value, done } = iterator.next();
152+
while (true) {
153+
if (!done) {
154+
const temp = await value;
155+
({ value, done } = iterator.next(temp));
156+
} else {
157+
return value;
158+
}
159+
}
160+
}
161+
133162
export {
134163
escapeAssertion,
135164
removeComments,
@@ -144,4 +173,6 @@ export {
144173
hasEval,
145174
replaceEval,
146175
getEvalValue,
176+
generatorRunSync,
177+
generatorRunAsync,
147178
};

test/enforcer.test.ts

+19
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ async function testEnforce(e: Enforcer, sub: any, obj: string, act: string, res:
2020
await expect(e.enforce(sub, obj, act)).resolves.toBe(res);
2121
}
2222

23+
function testEnforceSync(e: Enforcer, sub: any, obj: string, act: string, res: boolean): void {
24+
expect(e.enforceSync(sub, obj, act)).toBe(res);
25+
}
26+
2327
async function testGetPolicy(e: Enforcer, res: string[][]): Promise<void> {
2428
const myRes = await e.getPolicy();
2529
console.log('Policy: ', myRes);
@@ -566,3 +570,18 @@ test('test ABAC Scaling', async () => {
566570
await testEnforce(e, sub3, '/data1', 'write', false);
567571
await testEnforce(e, sub3, '/data2', 'write', false);
568572
});
573+
574+
test('TestEnforceSync', async () => {
575+
const m = newModel();
576+
m.addDef('r', 'r', 'sub, obj, act');
577+
m.addDef('p', 'p', 'sub, obj, act');
578+
m.addDef('g', 'g', '_, _');
579+
m.addDef('e', 'e', 'some(where (p.eft == allow))');
580+
m.addDef('m', 'm', 'g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act');
581+
582+
const e = await newEnforcer(m);
583+
584+
await e.addPermissionForUser('alice', 'data1', 'invalid');
585+
586+
testEnforceSync(e, 'alice', 'data1', 'read', false);
587+
});

0 commit comments

Comments
 (0)