diff --git a/packages/tools/src/testPermission.ts b/packages/tools/src/testPermission.ts index 322476b3e..2fc50bea8 100644 --- a/packages/tools/src/testPermission.ts +++ b/packages/tools/src/testPermission.ts @@ -1,10 +1,14 @@ import _escapeRegExp from 'lodash/escapeRegExp'; import _isString from 'lodash/isString'; import _compact from 'lodash/compact'; +import _flatten from 'lodash/flatten'; +interface CompiledPermissionLevel { + re: RegExp; + type: 'allow' | 'deny'; +} interface CompiledPermissions { - revoke: RegExp; - allow: RegExp; + levels: CompiledPermissionLevel[]; } function compileRegexp(permissions) { @@ -14,25 +18,58 @@ function compileRegexp(permissions) { export function compilePermissions(permissions: string[] | string): CompiledPermissions { 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())); - const revoke = permissions.filter(x => x.startsWith('~')).map(x => x.substring(1)); - const allow = permissions.filter(x => !x.startsWith('~')); - return { - revoke: compileRegexp(revoke), - allow: compileRegexp(allow), + + let lastType = null; + let lastItems = []; + + 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) { - if (!permissions) return true; - if (!permissions.revoke) return true; + let allow = true; - if (tested.match(permissions.revoke)) { - if (!tested.match(permissions.allow)) { - return false; + if (!permissions) { + return true; + } + + 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; }