Skip to content

Commit 2bf4299

Browse files
authored
feat: support RBAC for syncedEnforcer (#150)
* feat: add full support for sync Enforcer Signed-off-by: Zxilly <zhouxinyu1001@gmail.com> * refactor: add override sync function Signed-off-by: Zxilly <zhouxinyu1001@gmail.com> * refactor: remove sync role manager interface Signed-off-by: Zxilly <zhouxinyu1001@gmail.com> * fix: remove non-existent type Signed-off-by: Zxilly <zhouxinyu1001@gmail.com> * feat: add setNamedRoleManager Signed-off-by: Zxilly <zhouxinyu1001@gmail.com> * style: remove comment Signed-off-by: Zxilly <zhouxinyu1001@gmail.com> * fix: fix functions Signed-off-by: Zxilly <zhouxinyu1001@gmail.com> * fix: fix synced undefined Signed-off-by: Zxilly <zhouxinyu1001@gmail.com>
1 parent 135f8df commit 2bf4299

19 files changed

+637
-359
lines changed

src/coreEnforcer.ts

+35-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,17 @@ import { DefaultEffector, Effect, Effector } from './effect';
1818
import { FunctionMap, Model, newModel, PolicyOp } from './model';
1919
import { Adapter, FilteredAdapter, Watcher } from './persist';
2020
import { DefaultRoleManager, RoleManager } from './rbac';
21-
import { escapeAssertion, generateGFunction, getEvalValue, hasEval, replaceEval, generatorRunSync, generatorRunAsync } from './util';
21+
import {
22+
escapeAssertion,
23+
generateGFunction,
24+
getEvalValue,
25+
hasEval,
26+
replaceEval,
27+
generatorRunSync,
28+
generatorRunAsync,
29+
generateSyncGFunction,
30+
isRoleManagerSync,
31+
} from './util';
2232
import { getLogger, logPrint } from './log';
2333
import { MatchingFunc } from './rbac';
2434

@@ -38,7 +48,7 @@ export class CoreEnforcer {
3848

3949
protected adapter: Adapter;
4050
protected watcher: Watcher | null = null;
41-
protected rmMap: Map<string, RoleManager> = new Map<string, RoleManager>([['g', new DefaultRoleManager(10)]]);
51+
protected rmMap: Map<string, RoleManager>;
4252

4353
protected enabled = true;
4454
protected autoSave = true;
@@ -69,10 +79,18 @@ export class CoreEnforcer {
6979
*/
7080
public loadModel(): void {
7181
this.model = newModel();
82+
this.model.synced = false;
7283
this.model.loadModel(this.modelPath);
7384
this.model.printModel();
7485
}
7586

87+
/**
88+
* get a new RoleManager based on the type of current Enforcer
89+
*/
90+
public newRoleManager(): RoleManager {
91+
return new DefaultRoleManager(10);
92+
}
93+
7694
/**
7795
* getModel gets the current model.
7896
*
@@ -128,11 +146,21 @@ export class CoreEnforcer {
128146
this.rmMap.set('g', rm);
129147
}
130148

149+
/**
150+
* setRoleManager sets the current role manager.
151+
*
152+
* @param name
153+
* @param rm the role manager.
154+
*/
155+
public setNamedRoleManager(name: string, rm: RoleManager): void {
156+
this.rmMap.set(name, rm);
157+
}
158+
131159
/**
132160
* getRoleManager gets the current role manager.
133161
*/
134-
public getRoleManager(): RoleManager {
135-
return <RoleManager>this.rmMap.get('g');
162+
public getRoleManager(): RoleManager | undefined {
163+
return this.rmMap.get('g');
136164
}
137165

138166
/**
@@ -163,7 +191,7 @@ export class CoreEnforcer {
163191
const rm = this.model.model.get('g');
164192
if (rm) {
165193
for (const ptype of rm.keys()) {
166-
this.rmMap.set(ptype, new DefaultRoleManager(10));
194+
this.rmMap.set(ptype, this.newRoleManager());
167195
}
168196
}
169197
}
@@ -352,7 +380,7 @@ export class CoreEnforcer {
352380
public async buildIncrementalRoleLinks(op: PolicyOp, ptype: string, rules: string[][]): Promise<void> {
353381
let rm = this.rmMap.get(ptype);
354382
if (!rm) {
355-
rm = new DefaultRoleManager(10);
383+
rm = this.newRoleManager();
356384
this.rmMap.set(ptype, rm);
357385
}
358386
await this.model.buildIncrementalRoleLinks(rm, op, 'g', ptype, rules);
@@ -381,7 +409,7 @@ export class CoreEnforcer {
381409

382410
astMap?.forEach((value, key) => {
383411
const rm = value.rm;
384-
functions[key] = generateGFunction(rm);
412+
functions[key] = isRoleManagerSync(rm) ? generateSyncGFunction(rm) : generateGFunction(rm);
385413
});
386414

387415
const expString = this.model.model.get('m')?.get('m')?.value;

src/enforcer.ts

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { Model, newModel } from './model';
1717
import { Adapter, StringAdapter } from './persist';
1818
import { getLogger } from './log';
1919
import { arrayRemoveDuplicates } from './util';
20+
import { RoleManager } from './rbac';
2021

2122
/**
2223
* Enforcer = ManagementEnforcer + RBAC API.
@@ -60,6 +61,8 @@ export class Enforcer extends ManagementEnforcer {
6061
this.model = m;
6162
this.model.printModel();
6263

64+
this.rmMap = new Map<string, RoleManager>([['g', this.newRoleManager()]]);
65+
6366
if (!lazyLoad && this.adapter) {
6467
await this.loadPolicy();
6568
}

src/internalEnforcer.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export class InternalEnforcer extends CoreEnforcer {
8080
this.watcher.update();
8181
}
8282

83-
const [ok, effects] = await this.model.addPolicies(sec, ptype, rules);
83+
const [ok, effects] = this.model.addPolicies(sec, ptype, rules);
8484
if (sec === 'g' && ok && effects?.length) {
8585
await this.buildIncrementalRoleLinks(PolicyOp.PolicyAdd, ptype, effects);
8686
}
@@ -147,7 +147,7 @@ export class InternalEnforcer extends CoreEnforcer {
147147
this.watcher.update();
148148
}
149149

150-
const ok = await this.model.removePolicy(sec, ptype, rule);
150+
const ok = this.model.removePolicy(sec, ptype, rule);
151151
if (sec === 'g' && ok) {
152152
await this.buildIncrementalRoleLinks(PolicyOp.PolicyRemove, ptype, [rule]);
153153
}

src/model/assertion.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import * as rbac from '../rbac';
1616
import { logPrint } from '../log';
1717
import { PolicyOp } from './model';
18+
import { RoleManager } from '../rbac';
1819

1920
// Assertion represents an expression in a section of the model.
2021
// For example: r = sub, obj, act
@@ -23,17 +24,17 @@ export class Assertion {
2324
public value: string;
2425
public tokens: string[];
2526
public policy: string[][];
26-
public rm: rbac.RoleManager;
27+
public rm: RoleManager;
2728

2829
/**
2930
* constructor is the constructor for Assertion.
3031
*/
31-
constructor() {
32+
constructor(synced = false) {
3233
this.key = '';
3334
this.value = '';
3435
this.tokens = [];
3536
this.policy = [];
36-
this.rm = new rbac.DefaultRoleManager(10);
37+
this.rm = synced ? new rbac.DefaultSyncedRoleManager(10) : new rbac.DefaultRoleManager(10);
3738
}
3839

3940
public async buildIncrementalRoleLinks(rm: rbac.RoleManager, op: PolicyOp, rules: string[][]): Promise<void> {

src/model/functionMap.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export type MatchingFunction = (...arg: any[]) => boolean | number | Promise<boo
1818

1919
// FunctionMap represents the collection of Function.
2020
export class FunctionMap {
21-
private functions: Map<string, any>;
21+
private readonly functions: Map<string, any>;
2222

2323
/**
2424
* constructor is the constructor for FunctionMap.

src/model/model.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import * as util from '../util';
1717
import { Config, ConfigInterface } from '../config';
1818
import { Assertion } from './assertion';
1919
import { getLogger, logPrint } from '../log';
20-
import { DefaultRoleManager } from '../rbac';
20+
import { RoleManager } from '../rbac';
2121

2222
export const sectionNameMap: { [index: string]: string } = {
2323
r: 'request_definition',
@@ -38,6 +38,7 @@ export class Model {
3838
// Model represents the whole access control model.
3939
// Mest-map is the collection of assertions, can be "r", "p", "g", "e", "m".
4040
public model: Map<string, Map<string, Assertion>>;
41+
public synced = false;
4142

4243
/**
4344
* constructor is the constructor for Model.
@@ -77,7 +78,7 @@ export class Model {
7778
return false;
7879
}
7980

80-
const ast = new Assertion();
81+
const ast = new Assertion(this.synced);
8182
ast.key = key;
8283
ast.value = value;
8384

@@ -173,17 +174,16 @@ export class Model {
173174
}
174175

175176
// buildRoleLinks initializes the roles in RBAC.
176-
public async buildRoleLinks(rmMap: Map<string, rbac.RoleManager>): Promise<void> {
177+
public async buildRoleLinks(rmMap: Map<string, RoleManager>): Promise<void> {
177178
const astMap = this.model.get('g');
178179
if (!astMap) {
179180
return;
180181
}
181182
for (const key of astMap.keys()) {
182183
const ast = astMap.get(key);
183-
let rm = rmMap.get(key);
184+
const rm = rmMap.get(key);
184185
if (!rm) {
185-
rm = new DefaultRoleManager(10);
186-
rmMap.set(key, rm);
186+
throw new Error("Role manager didn't exist.");
187187
}
188188
await ast?.buildRoleLinks(rm);
189189
}

0 commit comments

Comments
 (0)