better permission compiler

This commit is contained in:
Jan Prochazka
2022-03-21 20:37:04 +01:00
parent a1b7ad18af
commit 26881a3e39

View File

@@ -1,10 +1,14 @@
import _escapeRegExp from 'lodash/escapeRegExp'; import _escapeRegExp from 'lodash/escapeRegExp';
import _isString from 'lodash/isString'; import _isString from 'lodash/isString';
import _compact from 'lodash/compact'; import _compact from 'lodash/compact';
import _flatten from 'lodash/flatten';
interface CompiledPermissionLevel {
re: RegExp;
type: 'allow' | 'deny';
}
interface CompiledPermissions { interface CompiledPermissions {
revoke: RegExp; levels: CompiledPermissionLevel[];
allow: RegExp;
} }
function compileRegexp(permissions) { function compileRegexp(permissions) {
@@ -14,25 +18,58 @@ function compileRegexp(permissions) {
export function compilePermissions(permissions: string[] | string): CompiledPermissions { export function compilePermissions(permissions: string[] | string): CompiledPermissions {
if (!permissions) return null; if (!permissions) return null;
if (_isString(permissions)) permissions = permissions.split(',');
if (_isString(permissions)) permissions = permissions.split(/,|;|\||\s/);
else permissions = _flatten(permissions.map(x => x.split(/,|;|\||\s/)));
permissions = _compact(permissions.map(x => x.trim())); permissions = _compact(permissions.map(x => x.trim()));
const revoke = permissions.filter(x => x.startsWith('~')).map(x => x.substring(1));
const allow = permissions.filter(x => !x.startsWith('~')); let lastType = null;
return { let lastItems = [];
revoke: compileRegexp(revoke),
allow: compileRegexp(allow), const res: CompiledPermissions = {
levels: [],
}; };
for (const item of permissions) {
const type = item.startsWith('~') ? 'deny' : 'allow';
const perm = item.startsWith('~') ? item.substring(1) : item;
if (lastType != null && type != lastType) {
res.levels.push({
re: compileRegexp(lastItems),
type: lastType,
});
lastItems = [];
}
lastItems.push(perm);
lastType = type;
}
if (lastItems.length > 0) {
res.levels.push({
re: compileRegexp(lastItems),
type: lastType,
});
}
return res;
} }
export function testPermission(tested: string, permissions: CompiledPermissions) { export function testPermission(tested: string, permissions: CompiledPermissions) {
if (!permissions) return true; let allow = true;
if (!permissions.revoke) return true;
if (tested.match(permissions.revoke)) { if (!permissions) {
if (!tested.match(permissions.allow)) { return true;
return false; }
for (const level of permissions.levels) {
if (tested.match(level.re)) {
if (level.type == 'allow') allow = true;
if (level.type == 'deny') allow = false;
} }
} }
return true; return allow;
} }