Skip to content
This repository was archived by the owner on Oct 16, 2018. It is now read-only.

Commit e0d1a79

Browse files
committed
feat(utils): implemented roles engine
1 parent 25b733c commit e0d1a79

8 files changed

Lines changed: 1726 additions & 57 deletions

File tree

utils/botpress-util-roles/.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["env"]
3+
}
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
11
.cache
22
node_modules
3-
dist
3+
dist
4+
.*.swp
5+
._*
6+
.DS_Store
7+
.git
8+
.hg
9+
.npmrc
10+
.lock-wscript
11+
.svn
12+
.wafpickle-*
13+
config.gypi
14+
CVS
15+
npm-debug.log
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.npmignore
2+
src

utils/botpress-util-roles/index.js

Whitespace-only changes.

utils/botpress-util-roles/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
"name": "@botpress/util-roles",
33
"version": "1.0.0",
44
"description": "Botpress utility package that handles roles checking",
5-
"main": "index.js",
5+
"main": "dist/index.js",
66
"author": "Botpress, Inc.",
77
"license": "AGPL-3.0",
88
"private": false,
99
"devDependencies": {
10+
"babel-preset-env": "^1.6.1",
11+
"jest": "^22.4.3",
1012
"parcel-bundler": "^1.7.1"
1113
},
1214
"scripts": {
13-
"watch": "parcel watch index.js",
14-
"build": "parcel build index.js"
15+
"watch": "parcel watch src/index.js",
16+
"build": "parcel build src/index.js",
17+
"test": "jest --watch"
1518
}
1619
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
export function ressourceMatches(pattern, res) {
2+
const separator = /[\/\.]/
3+
pattern = pattern || ''
4+
5+
if (!~pattern.indexOf('*')) {
6+
pattern = pattern += '.*'
7+
}
8+
9+
const parts = pattern.split(separator)
10+
let testParts = res.split(separator)
11+
12+
let matches = true
13+
for (let ii = 0; matches && ii < parts.length; ii++) {
14+
if (parts[ii] === '*') {
15+
continue
16+
} else if (ii < testParts.length) {
17+
matches = parts[ii].toLowerCase() === testParts[ii].toLowerCase()
18+
} else {
19+
matches = false
20+
}
21+
}
22+
23+
return matches
24+
}
25+
26+
export function checkRule(rules, operation, ressource) {
27+
operation = /^r|read$/i.test(operation) ? 'r' : operation
28+
operation = /^w|write$/i.test(operation) ? 'w' : operation
29+
30+
if (operation !== 'r' && operation !== 'w') {
31+
throw new Error('Invalid rule operation: ' + operation)
32+
}
33+
34+
let permission = false // Everything is restricted by default
35+
36+
for (let rule of rules) {
37+
if (ressourceMatches(rule.res, ressource)) {
38+
if (rule.op.length === 4) {
39+
if (rule.op[1] === operation) {
40+
permission = rule.op[0] === '+'
41+
} else if (rule.op[3] === operation) {
42+
permission = rule.op[2] === '+'
43+
} else {
44+
permission = false
45+
}
46+
}
47+
if (rule.op.length === 3) {
48+
permission = rule.op[0] === '+'
49+
} else if (rule.op[1] === operation) {
50+
permission = rule.op[0] === '+'
51+
} else {
52+
// leave the permission untouched
53+
}
54+
}
55+
}
56+
57+
return permission
58+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { ressourceMatches, checkRule } from './index'
2+
3+
test('ressourceMatches', () => {
4+
expect(ressourceMatches('', '')).toBe(true)
5+
expect(ressourceMatches('*', 'everything.will.match')).toBe(true)
6+
expect(ressourceMatches('everything.*', 'everything.will.match')).toBe(true)
7+
expect(ressourceMatches('everything.*.match', 'everything.here.match')).toBe(true)
8+
expect(ressourceMatches('everything.*.match.again', 'everything.here.match.again')).toBe(true)
9+
expect(ressourceMatches('everything.*.*.again', 'everything.here.match.again')).toBe(true)
10+
expect(ressourceMatches('*.will.*.again', 'everything.will.match.again')).toBe(true)
11+
expect(ressourceMatches('everything', 'everything.will.match')).toBe(true)
12+
13+
expect(ressourceMatches('', 'nothing.will.match')).toBe(false)
14+
expect(ressourceMatches('nothing.match', 'nothing.will.match')).toBe(false)
15+
expect(ressourceMatches('this.*.match', 'nothing.will.match')).toBe(false)
16+
expect(ressourceMatches('*.*.match', 'nothing.will.work')).toBe(false)
17+
expect(ressourceMatches('a.b.c', 'b.a.c')).toBe(false)
18+
expect(ressourceMatches('*.b.c', 'b.a.c')).toBe(false)
19+
})
20+
21+
test('checkRule', () => {
22+
const rules = [
23+
// 2 chars
24+
{ op: '+r', res: '1' },
25+
{ op: '-w', res: '1' },
26+
{ op: '+w', res: '1.a' },
27+
// 3 chars
28+
{ op: '+rw', res: '2' },
29+
{ op: '-rw', res: '2.a' },
30+
{ op: '+r', res: '2.a.b' },
31+
// 4 chars
32+
{ op: '+r+w', res: '2.a.c' },
33+
{ op: '+r-w', res: '3' },
34+
{ op: '+w-r', res: '3.a' }
35+
]
36+
37+
expect(checkRule(rules, 'read', '1')).toBe(true)
38+
expect(checkRule(rules, 'write', '1')).toBe(false)
39+
expect(checkRule(rules, 'write', '1.a')).toBe(true)
40+
expect(checkRule(rules, 'write', '1.b')).toBe(false)
41+
expect(checkRule(rules, 'read', '1.b')).toBe(true)
42+
43+
expect(checkRule(rules, 'read', '2')).toBe(true)
44+
expect(checkRule(rules, 'write', '2')).toBe(true)
45+
expect(checkRule(rules, 'read', '2.b')).toBe(true)
46+
expect(checkRule(rules, 'write', '2.b')).toBe(true)
47+
expect(checkRule(rules, 'read', '2.a')).toBe(false)
48+
expect(checkRule(rules, 'write', '2.a')).toBe(false)
49+
expect(checkRule(rules, 'write', '2.a.b')).toBe(false)
50+
expect(checkRule(rules, 'read', '2.a.b')).toBe(true)
51+
expect(checkRule(rules, 'read', '2.a.c')).toBe(true)
52+
expect(checkRule(rules, 'write', '2.a.c')).toBe(true)
53+
54+
expect(checkRule(rules, 'read', '3')).toBe(true)
55+
expect(checkRule(rules, 'write', '3')).toBe(false)
56+
expect(checkRule(rules, 'write', '3.a')).toBe(true)
57+
expect(checkRule(rules, 'read', '3.a')).toBe(false)
58+
})

0 commit comments

Comments
 (0)