Skip to content

Commit

Permalink
feat: enforceSync
Browse files Browse the repository at this point in the history
Signed-off-by: Xiaotian Lu <xtlu000@gmail.com>
  • Loading branch information
17bit committed Jan 26, 2021
1 parent 713ab1e commit ff41f0a
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 11 deletions.
23 changes: 15 additions & 8 deletions src/coreEnforcer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { DefaultEffector, Effect, Effector } from './effect';
import { FunctionMap, Model, newModel, PolicyOp } from './model';
import { Adapter, FilteredAdapter, Watcher, BatchAdapter } from './persist';
import { DefaultRoleManager, RoleManager } from './rbac';
import { escapeAssertion, generateGFunction, getEvalValue, hasEval, replaceEval } from './util';
import { escapeAssertion, generateGFunction, getEvalValue, hasEval, replaceEval, generatorRunSync, generatorRunAsync } from './util';
import { getLogger, logPrint } from './log';

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

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

const context = { ...parameters, ...functions };
const result = asyncCompile ? await expression(context) : expression(context);
const result = asyncCompile ? yield expression(context) : expression(context);

let eftRes: Effect;
switch (typeof result) {
Expand Down Expand Up @@ -395,7 +395,7 @@ export class CoreEnforcer {

expression = this.getExpression(asyncCompile, expString);
const context = { ...parameters, ...functions };
const result = asyncCompile ? await expression(context) : expression(context);
const result = asyncCompile ? yield expression(context) : expression(context);

if (result) {
effectStream.pushEffect(Effect.Allow);
Expand Down Expand Up @@ -427,15 +427,22 @@ export class CoreEnforcer {
/**
* If the matchers does not contain an asynchronous method, call it faster.
*
* enforceWithSyncCompile decides whether a "subject" can access a "object" with
* enforceSync decides whether a "subject" can access a "object" with
* the operation "action", input parameters are usually: (sub, obj, act).
*
* @param rvals the request needs to be mediated, usually an array
* of strings, can be class instances if ABAC is used.
* @return whether to allow the request.
*/
public async enforceWithSyncCompile(...rvals: any[]): Promise<boolean> {
return this.privateEnforce(false, ...rvals);
public enforceSync(...rvals: any[]): boolean {
return generatorRunSync(this.privateEnforce(false, ...rvals));
}

/**
* Same as enforceSync. To be removed.
*/
public enforceWithSyncCompile(...rvals: any[]): boolean {
return this.enforceSync(...rvals);
}

/**
Expand All @@ -447,6 +454,6 @@ export class CoreEnforcer {
* @return whether to allow the request.
*/
public async enforce(...rvals: any[]): Promise<boolean> {
return this.privateEnforce(true, ...rvals);
return generatorRunAsync(this.privateEnforce(true, ...rvals));
}
}
5 changes: 2 additions & 3 deletions src/syncedEnforcer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,8 @@ export class SyncedEnforcer extends Enforcer {
* of strings, can be class instances if ABAC is used.
* @return whether to allow the request.
*/
public async enforceWithSyncCompile(...rvals: any[]): Promise<boolean> {
await this.lock.acquireAsync();
return super.enforceWithSyncCompile(...rvals).finally(() => this.lock.release());
public enforceWithSyncCompile(...rvals: any[]): boolean {
return super.enforceWithSyncCompile(...rvals);
}

/**
Expand Down
31 changes: 31 additions & 0 deletions src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,35 @@ function getEvalValue(s: string): string[] {
return rules;
}

// generatorRunSync handle generator function in Sync model and return value which is not Promise
function generatorRunSync(iterator: Generator<any>): any {
let { value, done } = iterator.next();
while (true) {
if (value instanceof Promise) {
throw new Error('cannot handle Promise in generatorRunSync, Please use generatorRunAsync');
}
if (!done) {
const temp = value;
({ value, done } = iterator.next(temp));
} else {
return value;
}
}
}

// generatorRunAsync handle generator function in Async model and return Promise
async function generatorRunAsync(iterator: Generator<any>): Promise<any> {
let { value, done } = iterator.next();
while (true) {
if (!done) {
const temp = await value;
({ value, done } = iterator.next(temp));
} else {
return value;
}
}
}

export {
escapeAssertion,
removeComments,
Expand All @@ -144,4 +173,6 @@ export {
hasEval,
replaceEval,
getEvalValue,
generatorRunSync,
generatorRunAsync,
};
19 changes: 19 additions & 0 deletions test/enforcer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ async function testEnforce(e: Enforcer, sub: any, obj: string, act: string, res:
await expect(e.enforce(sub, obj, act)).resolves.toBe(res);
}

function testEnforceSync(e: Enforcer, sub: any, obj: string, act: string, res: boolean): void {
expect(e.enforceSync(sub, obj, act)).toBe(res);
}

async function testGetPolicy(e: Enforcer, res: string[][]): Promise<void> {
const myRes = await e.getPolicy();
console.log('Policy: ', myRes);
Expand Down Expand Up @@ -566,3 +570,18 @@ test('test ABAC Scaling', async () => {
await testEnforce(e, sub3, '/data1', 'write', false);
await testEnforce(e, sub3, '/data2', 'write', false);
});

test('TestEnforceSync', async () => {
const m = newModel();
m.addDef('r', 'r', 'sub, obj, act');
m.addDef('p', 'p', 'sub, obj, act');
m.addDef('g', 'g', '_, _');
m.addDef('e', 'e', 'some(where (p.eft == allow))');
m.addDef('m', 'm', 'g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act');

const e = await newEnforcer(m);

await e.addPermissionForUser('alice', 'data1', 'invalid');

testEnforceSync(e, 'alice', 'data1', 'read', false);
});

0 comments on commit ff41f0a

Please sign in to comment.