-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrbac-role-finder.js
126 lines (114 loc) · 3.14 KB
/
rbac-role-finder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// closest role finder
const roles = {
manager: ['a', 'b', 'c'],
owner: ['a', 'b', 'c', 'd', 'e', 'f'],
marketing: ['a', 'e'],
developer: ['b', 'c', 'd'],
user: ['a', 'b'],
};
const cache = {};
function assignRole(acl) {}
class Permission {
name;
role;
constructor(name, role) {
this.name = name;
this.role = role;
}
}
class RoleSet {
constructor() {
this.root = null;
}
sorted = new WeakMap();
addRoles(role) {
Object.keys(role).forEach((roleName) => {
this.addPermission(role[roleName], roleName);
});
}
sortPermissions(permissions) {
permissions.sort(function (a, b) {
const textA = a.toLowerCase();
const textB = b.toLowerCase();
return textA < textB ? -1 : textA > textB ? 1 : 0;
});
}
addPermission(permissions, role) {
if (!this.sorted[permissions]) {
this.sortPermissions(permissions);
this.sorted[permissions] = true;
}
// if no permission added yet add one to root
if (!this.root) {
this.root = {};
this.addNewRootPermissionTree(permissions, role);
} else {
// check if a permission tree at root already exist
if (!this.root[permissions[0]]) {
this.addNewRootPermissionTree(permissions, role);
} else {
// add to an existing root tree
this.addToExistingPermissionTree(permissions, role);
}
}
}
addNewRootPermissionTree(permissions, role) {
let curr = this.root;
for (let i = 0; i < permissions.length; i++) {
const permNode = new Permission(permissions[i]);
curr[permNode.name] = permNode;
curr = permNode;
}
curr.role = role;
}
addToExistingPermissionTree(permissions, role) {
let curr = this.root;
for (let i = 0; i < permissions.length; i++) {
if (curr[permissions[i]]) {
curr = curr[permissions[i]];
continue;
}
const permNode = new Permission(permissions[i]);
curr[permNode.name] = permNode;
curr = permNode;
}
curr.role = role;
}
findRoleAndPerms(permissions) {
if (!this.sorted[permissions]) {
this.sortPermissions(permissions);
this.sorted[permissions] = true;
}
const noRole = { role: undefined, permissions: [] };
let role;
let curr = this.root[permissions[0]];
if(!curr) {
return noRole;
}
let indexForPerm = 0;
for (let i = 0; i < permissions.length; i++) {
if (curr.role) {
indexForPerm = i;
role = curr.role;
}
if (curr[permissions[i + 1]]) {
curr = curr[permissions[i + 1]];
} else {
break;
}
}
if (indexForPerm) {
return { role: role, permissions: permissions.slice(indexForPerm + 1) };
} else {
return noRole;
}
}
}
let roleTrie = new RoleSet();
roleTrie.addRoles(roles);
console.log(roleTrie.findRoleAndPerms(['a', 'b']));
console.log(roleTrie.findRoleAndPerms(['a', 'e']));
console.log(roleTrie.findRoleAndPerms(['b', 'c', 'd']));
console.log(roleTrie.findRoleAndPerms(['a', 'b', 'd', 'c', 'e']));
console.log(roleTrie.findRoleAndPerms(['a', 'b', 'c', 'd', 'e', 'f']));
console.log(roleTrie.findRoleAndPerms(['d', 'c', 'a', 'e', 'b']));