@unchainedshop/roles 4.3.4 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,111 @@
1
- # Roles (Unchained Engine)
1
+ [![npm version](https://img.shields.io/npm/v/@unchainedshop/roles.svg)](https://npmjs.com/package/@unchainedshop/roles)
2
+ [![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](https://opensource.org/licenses/EUPL-1.2)
2
3
 
3
- This package delivers inner logic for the ACL layer of all Unchained API's.
4
+ # @unchainedshop/roles
5
+
6
+ Role-based access control (RBAC) system for the Unchained Engine. Provides fine-grained permission management for API operations.
4
7
 
5
8
  Thanks to Nicolás López for the initial version of Roles: https://github.com/nicolaslopezj/roles
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @unchainedshop/roles
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```typescript
19
+ import { Roles, Role } from '@unchainedshop/roles';
20
+
21
+ // Create a new role
22
+ const editorRole = new Role('editor');
23
+
24
+ // Allow actions for the role
25
+ editorRole.allow('updateProduct', async (product, params, context) => {
26
+ // Return true if allowed, false otherwise
27
+ return context.userId != null;
28
+ });
29
+
30
+ // Check if a user has permission
31
+ const allowed = await Roles.userHasPermission(
32
+ { userId: 'user-123', user: { roles: ['editor'] } },
33
+ 'updateProduct',
34
+ [productObject, {}]
35
+ );
36
+ ```
37
+
38
+ ## API Overview
39
+
40
+ ### Roles Singleton
41
+
42
+ | Method | Description |
43
+ |--------|-------------|
44
+ | `Roles.registerAction` | Register a new action name |
45
+ | `Roles.registerHelper` | Register a new helper name |
46
+ | `Roles.getUserRoles` | Get user roles including special roles |
47
+ | `Roles.allow` | Check if any role allows an action |
48
+ | `Roles.userHasPermission` | Check if user has permission for action |
49
+
50
+ ### Role Class
51
+
52
+ | Method | Description |
53
+ |--------|-------------|
54
+ | `new Role(name)` | Create and register a new role |
55
+ | `role.allow(action, fn)` | Add allow rule for an action |
56
+ | `role.helper(name, fn)` | Add helper function to role |
57
+
58
+ ### Built-in Roles
59
+
60
+ | Role | Description |
61
+ |------|-------------|
62
+ | `Roles.adminRole` | Admin role with elevated privileges |
63
+ | `Roles.loggedInRole` | Applied to all logged-in users (`__loggedIn__`) |
64
+ | `Roles.allRole` | Applied to all users (`__all__`) |
65
+
66
+ ### Special Internal Roles
67
+
68
+ | Role | Description |
69
+ |------|-------------|
70
+ | `__all__` | Automatically assigned to everyone |
71
+ | `__loggedIn__` | Automatically assigned to authenticated users |
72
+ | `__notLoggedIn__` | Automatically assigned to anonymous users |
73
+ | `__notAdmin__` | Automatically assigned to non-admin users |
74
+
75
+ ### Utility Functions
76
+
77
+ | Export | Description |
78
+ |--------|-------------|
79
+ | `has` | Check if object has property |
80
+ | `isFunction` | Check if value is a function |
81
+ | `permissions` | Permission constants and helpers |
82
+
83
+ ### Types
84
+
85
+ | Export | Description |
86
+ |--------|-------------|
87
+ | `RolesInterface` | Interface for the Roles singleton |
88
+ | `RoleInterface` | Interface for Role instances |
89
+ | `RoleInterfaceFactory` | Factory type for Role class |
90
+ | `IRoleOptionConfig` | Configuration options for roles |
91
+ | `CheckPermissionArgs` | Arguments tuple for permission checks |
92
+
93
+ ## Configuration
94
+
95
+ ```typescript
96
+ import type { IRoleOptionConfig } from '@unchainedshop/roles';
97
+
98
+ const config: IRoleOptionConfig = {
99
+ additionalRoles: {
100
+ customRole: (roles, actions) => {
101
+ const role = new Role('customRole');
102
+ role.allow(actions.READ, () => true);
103
+ },
104
+ },
105
+ additionalActions: ['CUSTOM_ACTION'],
106
+ };
107
+ ```
108
+
109
+ ## License
110
+
111
+ EUPL-1.2
@@ -1,5 +1,4 @@
1
- export * from './roles.js';
2
- export { has } from './utils/has.js';
3
- export { isFunction } from './utils/isFunction.js';
4
- export { permissions } from './utils/permissions.js';
5
- //# sourceMappingURL=roles-index.d.ts.map
1
+ export * from './roles.ts';
2
+ export { has } from './utils/has.ts';
3
+ export { isFunction } from './utils/isFunction.ts';
4
+ export { permissions } from './utils/permissions.ts';
@@ -1,5 +1,4 @@
1
- export * from './roles.js';
2
- export { has } from './utils/has.js';
3
- export { isFunction } from './utils/isFunction.js';
4
- export { permissions } from './utils/permissions.js';
5
- //# sourceMappingURL=roles-index.js.map
1
+ export * from "./roles.js";
2
+ export { has } from "./utils/has.js";
3
+ export { isFunction } from "./utils/isFunction.js";
4
+ export { permissions } from "./utils/permissions.js";
package/lib/roles.d.ts CHANGED
@@ -34,22 +34,12 @@ export interface IRoleOptionConfig {
34
34
  additionalActions?: string[];
35
35
  }
36
36
  export declare const Roles: RolesInterface;
37
- /**
38
- * Constructs a new role
39
- */
40
37
  export declare class Role implements RoleInterface {
41
38
  name: string;
42
39
  allowRules: Record<string, any>;
43
40
  helpers: Record<string, any>;
44
41
  constructor(name: string);
45
- /**
46
- * Adds a helper to a role
47
- */
48
42
  helper(helper: string, func: any): void;
49
- /**
50
- * Adds allow properties to a role
51
- */
52
43
  allow(action: any, allow: any): void;
53
44
  }
54
45
  export {};
55
- //# sourceMappingURL=roles.d.ts.map
package/lib/roles.js CHANGED
@@ -1,28 +1,19 @@
1
- import { has } from './utils/has.js';
2
- import { isFunction } from './utils/isFunction.js';
1
+ import { has } from "./utils/has.js";
2
+ import { isFunction } from "./utils/isFunction.js";
3
3
  export const Roles = {
4
4
  roles: {},
5
5
  actions: [],
6
6
  helpers: [],
7
- /**
8
- * Creates a new action
9
- */
10
7
  registerAction(name) {
11
8
  if (!this.actions.includes(name)) {
12
9
  this.actions.push(name);
13
10
  }
14
11
  },
15
- /**
16
- * Creates a new helper
17
- */
18
12
  registerHelper(name) {
19
13
  if (!this.helpers.includes(name)) {
20
14
  this.helpers.push(name);
21
15
  }
22
16
  },
23
- /**
24
- * Get user roles
25
- */
26
17
  getUserRoles(userId, roles, includeSpecial) {
27
18
  const newRoles = [...(roles || [])];
28
19
  if (includeSpecial) {
@@ -39,9 +30,6 @@ export const Roles = {
39
30
  }
40
31
  return newRoles;
41
32
  },
42
- /**
43
- * Returns true if the user passes the allow check
44
- */
45
33
  async allow(context, roles, action, [obj, params]) {
46
34
  const userRoles = Roles.getUserRoles(context.userId, roles, true);
47
35
  return userRoles.reduce(async (roleIsAllowedPromise, role) => {
@@ -59,33 +47,24 @@ export const Roles = {
59
47
  return roleIsAllowed;
60
48
  }, Promise.resolve(false));
61
49
  },
62
- /**
63
- * To check if a user has permisisons to execute an action
64
- */
65
50
  userHasPermission: async (context, action, args) => {
66
51
  const roles = Array.isArray(context.user?.roles) ? context.user.roles : [];
67
52
  const allows = await Roles.allow(context, roles, action, args);
68
53
  return allows === true;
69
54
  },
70
55
  };
71
- /**
72
- * Constructs a new role
73
- */
74
56
  export class Role {
75
57
  name;
76
58
  allowRules;
77
59
  helpers;
78
60
  constructor(name) {
79
- this.name = name;
80
61
  if (has(Roles.roles, name))
81
62
  throw new Error(`"${name}" role is already defined`);
63
+ this.name = name;
82
64
  this.allowRules = {};
83
65
  this.helpers = {};
84
66
  Roles.roles[name] = this;
85
67
  }
86
- /**
87
- * Adds a helper to a role
88
- */
89
68
  helper(helper, func) {
90
69
  if (!Roles.helpers.includes(helper)) {
91
70
  Roles.registerHelper(helper);
@@ -102,9 +81,6 @@ export class Role {
102
81
  }
103
82
  this.helpers[helper].push(helperFn);
104
83
  }
105
- /**
106
- * Adds allow properties to a role
107
- */
108
84
  allow(action, allow) {
109
85
  if (!action) {
110
86
  throw new Error(`Action doesn't exist`);
@@ -123,16 +99,6 @@ export class Role {
123
99
  this.allowRules[action].push(allowFn);
124
100
  }
125
101
  }
126
- /**
127
- * The admin role, who recives the default actions.
128
- */
129
102
  Roles.adminRole = new Role('admin');
130
- /**
131
- * All the logged in users users
132
- */
133
103
  Roles.loggedInRole = new Role('__loggedIn__');
134
- /**
135
- * Always, no exception
136
- */
137
104
  Roles.allRole = new Role('__all__');
138
- //# sourceMappingURL=roles.js.map
@@ -1,2 +1 @@
1
1
  export declare const has: (obj: Record<string, any>, key: string) => boolean;
2
- //# sourceMappingURL=has.d.ts.map
package/lib/utils/has.js CHANGED
@@ -5,4 +5,3 @@ export const has = (obj, key) => {
5
5
  ? has(obj[key.split('.')[0]], keyParts.slice(1).join('.'))
6
6
  : obj.hasOwnProperty.call(obj, key)));
7
7
  };
8
- //# sourceMappingURL=has.js.map
@@ -1,2 +1 @@
1
1
  export declare const isFunction: (func: () => any) => boolean;
2
- //# sourceMappingURL=isFunction.d.ts.map
@@ -1,4 +1,3 @@
1
1
  export const isFunction = (func) => {
2
2
  return func && typeof func === 'function';
3
3
  };
4
- //# sourceMappingURL=isFunction.js.map
@@ -1,2 +1 @@
1
1
  export declare const permissions: (userRoles: any, allRoles: any) => Promise<any[]>;
2
- //# sourceMappingURL=permissions.d.ts.map
@@ -6,8 +6,6 @@ export const permissions = async (userRoles, allRoles) => {
6
6
  return Object.entries(foundRole.allowRules || {}).flatMap(([roleName, funcs]) => {
7
7
  return funcs.map(async (f) => {
8
8
  try {
9
- // return permissions that are by default activated for that role,
10
- // accidentally don't check context
11
9
  const r = await f(null, null, null);
12
10
  if (r)
13
11
  return roleName;
@@ -22,4 +20,3 @@ export const permissions = async (userRoles, allRoles) => {
22
20
  const resolvedActions = await Promise.all(actions);
23
21
  return [...new Set(resolvedActions)].filter(Boolean).toSorted((a, b) => a.localeCompare(b));
24
22
  };
25
- //# sourceMappingURL=permissions.js.map
package/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@unchainedshop/roles",
3
- "version": "4.3.4",
3
+ "version": "4.5.0",
4
4
  "description": "Roles package for unchained engine",
5
5
  "main": "lib/roles-index.js",
6
6
  "types": "lib/roles-index.d.ts",
7
7
  "type": "module",
8
+ "sideEffects": false,
8
9
  "scripts": {
9
10
  "clean": "tsc -b --clean",
10
11
  "build": "tsc -b",
11
12
  "prepublishOnly": "npm run clean && npm run build",
12
13
  "watch": "tsc -w",
13
- "test": "tsx --test",
14
- "test:watch": "tsx --test --watch"
14
+ "test": "node --test",
15
+ "test:watch": "node --test --watch"
15
16
  },
16
17
  "repository": {
17
18
  "type": "git",
@@ -22,8 +23,10 @@
22
23
  "ecommerce"
23
24
  ],
24
25
  "authors": [
25
- "Joël Meiller",
26
- "Pascal Kaufmann"
26
+ "Pascal Kaufmann",
27
+ "Mikael Araya",
28
+ "Vedran Rudelj",
29
+ "Joël Meiller"
27
30
  ],
28
31
  "license": "EUPL-1.2",
29
32
  "bugs": {
@@ -31,7 +34,7 @@
31
34
  },
32
35
  "homepage": "https://github.com/unchainedshop/unchained#readme",
33
36
  "devDependencies": {
34
- "@types/node": "^24.0.13",
37
+ "@types/node": "^25.0.0",
35
38
  "typescript": "^5.8.3"
36
39
  }
37
40
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"roles-index.d.ts","sourceRoot":"","sources":["../src/roles-index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"roles-index.js","sourceRoot":"","sources":["../src/roles-index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../src/roles.ts"],"names":[],"mappings":"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"}
package/lib/roles.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"roles.js","sourceRoot":"","sources":["../src/roles.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"has.d.ts","sourceRoot":"","sources":["../../src/utils/has.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,MAAM,KAAG,OAS3D,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"has.js","sourceRoot":"","sources":["../../src/utils/has.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAwB,EAAE,GAAW,EAAW,EAAE;IACpE,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEhC,OAAO,CACL,CAAC,CAAC,GAAG;QACL,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAClB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1D,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CACvC,CAAC;AACJ,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"isFunction.d.ts","sourceRoot":"","sources":["../../src/utils/isFunction.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,GAAG,KAAG,OAE5C,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"isFunction.js","sourceRoot":"","sources":["../../src/utils/isFunction.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAe,EAAW,EAAE;IACrD,OAAO,IAAI,IAAI,OAAO,IAAI,KAAK,UAAU,CAAC;AAC5C,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/utils/permissions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,GAAU,WAAW,GAAG,EAAE,UAAU,GAAG,mBAoB9D,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/utils/permissions.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,SAAc,EAAE,QAAa,EAAE,EAAE;IACjE,MAAM,OAAO,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC1C,MAAM,SAAS,GAAQ,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACjF,IAAI,CAAC,SAAS;YAAE,OAAO,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAM,EAAE,EAAE;YACnF,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;gBAC3B,IAAI,CAAC;oBACH,kEAAkE;oBAClE,mCAAmC;oBACnC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;oBACpC,IAAI,CAAC;wBAAE,OAAO,QAAQ,CAAC;oBACvB,OAAO,IAAI,CAAC;gBACd,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAM,EAAE,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACxG,CAAC,CAAC"}
@@ -1,5 +0,0 @@
1
- export * from './roles.js';
2
-
3
- export { has } from './utils/has.js';
4
- export { isFunction } from './utils/isFunction.js';
5
- export { permissions } from './utils/permissions.js';
package/src/roles.test.ts DELETED
@@ -1,295 +0,0 @@
1
- import { describe, it, beforeEach } from 'node:test';
2
- import assert from 'node:assert';
3
- import { isFunction, permissions, has } from './roles-index.js';
4
- import { Role, Roles } from './roles.js';
5
-
6
- describe('Role', () => {
7
- beforeEach(() => {
8
- Roles.roles = {};
9
- Roles.actions = [];
10
- Roles.helpers = [];
11
- });
12
-
13
- describe('constructor', () => {
14
- it('should create a new role with the given name', () => {
15
- assert.strictEqual(new Role('admin').name, 'admin');
16
- });
17
-
18
- it('should throw an error if a role with the same name already exists', () => {
19
- new Role('admin');
20
- assert.throws(() => new Role('admin'), /"admin" role is already defined/);
21
- });
22
- });
23
-
24
- describe('helper', () => {
25
- it('should add the helper function to the role', () => {
26
- const role = new Role('admin');
27
- role.helper('checkPermission', () => true);
28
- assert.strictEqual(typeof role.helpers.checkPermission[0], 'function');
29
- });
30
-
31
- it('should add the helper to the list of helpers if it does not exist', () => {
32
- const role = new Role('admin');
33
- role.helper('checkPermission', () => true);
34
- assert.deepStrictEqual(Roles.helpers, ['checkPermission']);
35
- });
36
-
37
- it('should convert a non-function value to a function that returns that value', () => {
38
- const role = new Role('admin');
39
- role.helper('checkPermission', true);
40
- assert.strictEqual(typeof role.helpers.checkPermission[0], 'function');
41
- assert.strictEqual(role.helpers.checkPermission[0](), true);
42
- });
43
- });
44
-
45
- describe('allow', () => {
46
- it('should add the allow function to the role', () => {
47
- const role = new Role('admin');
48
- role.allow('createUser', () => true);
49
- assert.strictEqual(typeof role.allowRules.createUser[0], 'function');
50
- });
51
-
52
- it('should add the action to the list of actions if it does not exist', () => {
53
- const role = new Role('admin');
54
- role.allow('createUser', () => true);
55
- assert.deepStrictEqual(Roles.actions, ['createUser']);
56
- });
57
-
58
- it('should throw an error if the action does not exist', () => {
59
- const role = new Role('admin');
60
- assert.throws(() => role.allow(null, () => true), /Action doesn't exist/);
61
- });
62
-
63
- it('should convert a non-function value to a function that returns that value', () => {
64
- const role = new Role('admin');
65
- role.allow('createUser', true);
66
- assert.strictEqual(typeof role.allowRules.createUser[0], 'function');
67
- assert.strictEqual(role.allowRules.createUser[0](), true);
68
- });
69
- });
70
-
71
- describe('Role utilities', () => {
72
- const testRole = new Role('test_role');
73
- const actionName = 'view_secret';
74
-
75
- it('should register an action rule', () => {
76
- const allowFn = () => true;
77
- testRole.allow(actionName, allowFn);
78
- assert.strictEqual(typeof testRole.allowRules[actionName][0], 'function');
79
- });
80
-
81
- it('should register a helper', () => {
82
- const helperFn = () => true;
83
- testRole.helper('test_helper', helperFn);
84
- assert.strictEqual(typeof testRole.helpers.test_helper[0], 'function');
85
- });
86
- });
87
-
88
- describe('Role Helper Registration', () => {
89
- it('should add a helper', () => {
90
- Roles.registerHelper('test_helper');
91
- assert.deepStrictEqual(Roles.helpers, ['test_helper']);
92
- });
93
-
94
- it('should add a helper attaching it to adminRole', () => {
95
- Roles.registerHelper('test_admin_helper');
96
- assert(Roles.helpers.includes('test_admin_helper'));
97
- });
98
-
99
- it('should skip adding helper if it already exists', () => {
100
- Roles.registerHelper('test_helper');
101
- Roles.registerHelper('test_admin_helper');
102
- assert(Roles.helpers.includes('test_helper'));
103
- assert(Roles.helpers.includes('test_admin_helper'));
104
- });
105
- });
106
-
107
- describe('Action registration', () => {
108
- it('should add an action', () => {
109
- Roles.registerAction('test_action');
110
- assert.deepStrictEqual(Roles.actions, ['test_action']);
111
- });
112
-
113
- it('should skip adding action if it already exists', () => {
114
- Roles.registerAction('test_action');
115
- assert.deepStrictEqual(Roles.actions, ['test_action']);
116
- });
117
- });
118
-
119
- describe('Role contruction', () => {
120
- it('should construct a new role', () => {
121
- assert.equal(new Role('test_role') instanceof Role, true);
122
- });
123
-
124
- it('should throw an error if given a role with similar name', () => {
125
- new Role('test_role');
126
- assert.throws(() => new Role('test_role'));
127
- });
128
- });
129
-
130
- describe('isFunction', () => {
131
- it('should return true given a function', () => {
132
- assert.strictEqual(
133
- isFunction(() => ({})),
134
- true,
135
- );
136
- });
137
-
138
- it('should return false given an improper function', () => {
139
- assert.strictEqual(isFunction('false' as any), false);
140
- });
141
- });
142
-
143
- describe('has', () => {
144
- it('should return true for existent key', () => {
145
- const obj = {
146
- foo: 'bar',
147
- };
148
- assert.strictEqual(has(obj, 'foo'), true);
149
- });
150
-
151
- it('should return true for existent nested key', () => {
152
- const obj = {
153
- foo: { bar: 'baz' },
154
- };
155
- assert.strictEqual(has(obj, 'foo.bar'), true);
156
- });
157
-
158
- it('should return false for non existent', () => {
159
- const obj = {
160
- foo: 'bar',
161
- };
162
- assert.strictEqual(has(obj, 'baz'), false);
163
- });
164
- });
165
- });
166
-
167
- describe('permissions', () => {
168
- it('should return an empty array if no user roles are provided', async () => {
169
- const userRoles = [];
170
- const allRoles = {
171
- admin: {
172
- name: 'admin',
173
- allowRules: {
174
- createUser: [async () => true, async () => false],
175
- },
176
- },
177
- };
178
- const result = await permissions(userRoles, allRoles);
179
- assert.deepStrictEqual(result, []);
180
- });
181
-
182
- it('should return the correct permissions for a single user role', async () => {
183
- const userRoles = ['admin'];
184
- const allRoles = {
185
- admin: {
186
- name: 'admin',
187
- allowRules: {
188
- createUser: [async () => true, async () => false],
189
- },
190
- },
191
- };
192
- const result = await permissions(userRoles, allRoles);
193
- assert.deepStrictEqual(result, ['createUser']);
194
- });
195
-
196
- it('should return the correct permissions for multiple user roles', async () => {
197
- const userRoles = ['admin', 'user'];
198
- const allRoles = {
199
- admin: {
200
- name: 'admin',
201
- allowRules: {
202
- createUser: [async () => true, async () => false],
203
- },
204
- },
205
- user: {
206
- name: 'user',
207
- allowRules: {
208
- viewUser: [async () => true, async () => false],
209
- },
210
- },
211
- };
212
- const result = await permissions(userRoles, allRoles);
213
- assert.deepStrictEqual(result, ['createUser', 'viewUser']);
214
- });
215
-
216
- it('should return unique and sorted permissions', async () => {
217
- const userRoles = ['admin', 'user'];
218
- const allRoles = {
219
- admin: {
220
- name: 'admin',
221
- allowRules: {
222
- createUser: [async () => true, async () => true],
223
- viewUser: [async () => true, async () => false],
224
- },
225
- },
226
- user: {
227
- name: 'user',
228
- allowRules: {
229
- viewUser: [async () => true, async () => true],
230
- },
231
- },
232
- };
233
- const result = await permissions(userRoles, allRoles);
234
- assert.deepStrictEqual(result, ['createUser', 'viewUser']);
235
- });
236
- });
237
-
238
- describe('registerAction', () => {
239
- it('should add a new action to the list of actions if it does not already exist', () => {
240
- const action = 'createUser';
241
- Roles.registerAction(action);
242
- assert(Roles.actions.includes(action));
243
- });
244
-
245
- it('should not add the same action multiple times', () => {
246
- const action = 'createUser';
247
- Roles.registerAction(action);
248
- Roles.registerAction(action);
249
- assert.deepStrictEqual(Roles.actions, [action]);
250
- });
251
- });
252
-
253
- describe('registerHelper', () => {
254
- it('should add a new helper to the list of helpers if it does not already exist', () => {
255
- const helper = 'checkAdmin';
256
- Roles.registerHelper(helper);
257
- assert(Roles.helpers.includes(helper));
258
- });
259
-
260
- it('should not add the same helper multiple times', () => {
261
- const helper = 'checkAdmin';
262
- Roles.registerHelper(helper);
263
- Roles.registerHelper(helper);
264
- assert.deepStrictEqual(Roles.helpers, [helper]);
265
- });
266
- });
267
-
268
- describe('getUserRoles', () => {
269
- it('should return the correct roles for a logged-in user', () => {
270
- const userId = 'user1';
271
- const roles = ['admin'];
272
- const includeSpecial = true;
273
- const expected = ['admin', '__all__', '__loggedIn__'];
274
- const result = Roles.getUserRoles(userId, roles, includeSpecial);
275
- assert.deepStrictEqual(result, expected);
276
- });
277
-
278
- it('should return the correct roles for a logged-out user', () => {
279
- const userId = null;
280
- const roles = ['admin'];
281
- const includeSpecial = true;
282
- const expected = ['admin', '__all__', '__notLoggedIn__'];
283
- const result = Roles.getUserRoles(userId as any, roles, includeSpecial);
284
- assert.deepStrictEqual(result, expected);
285
- });
286
-
287
- it('should return the correct roles when includeSpecial is false', () => {
288
- const userId = 'user1';
289
- const roles = ['admin'];
290
- const includeSpecial = false;
291
- const expected = ['admin'];
292
- const result = Roles.getUserRoles(userId, roles, includeSpecial);
293
- assert.deepStrictEqual(result, expected);
294
- });
295
- });
package/src/roles.ts DELETED
@@ -1,207 +0,0 @@
1
- import { has } from './utils/has.js';
2
- import { isFunction } from './utils/isFunction.js';
3
-
4
- interface RoleUserContext {
5
- userId?: string;
6
- user?: any;
7
- }
8
- export interface RoleInterface {
9
- name: string;
10
- allowRules: Record<string, any>;
11
- allow(action: string, fn: (root: any, props: any, context: RoleUserContext) => Promise<boolean>): void;
12
- helpers: Record<string, unknown>;
13
- }
14
-
15
- export type RoleInterfaceFactory = new (key: string) => RoleInterface;
16
-
17
- export type CheckPermissionArgs = [obj?: any, params?: any];
18
-
19
- export interface RolesInterface {
20
- roles: Record<string, RoleInterface>;
21
- actions: string[];
22
- helpers: string[];
23
- registerAction(name: string): void;
24
- registerHelper(name: string): void;
25
- getUserRoles(userId: string, roles: string[], includeSpecial: boolean): string[];
26
- allow(
27
- context: RoleUserContext,
28
- roles: string[],
29
- action?: string,
30
- args?: CheckPermissionArgs,
31
- ): Promise<boolean>;
32
- userHasPermission(
33
- context: RoleUserContext,
34
- action: string,
35
- args: CheckPermissionArgs,
36
- ): Promise<boolean>;
37
- adminRole?: RoleInterface;
38
- loggedInRole?: RoleInterface;
39
- allRole?: RoleInterface;
40
- }
41
-
42
- export interface RoleInterface {
43
- name: string;
44
- allowRules: Record<string, any>;
45
- allow(action: string, fn: (root: any, props: any, context: RoleUserContext) => Promise<boolean>): void;
46
- helpers: Record<string, unknown>;
47
- }
48
-
49
- export interface IRoleOptionConfig {
50
- additionalRoles?: Record<string, (role: RolesInterface, actions: Record<string, string>) => void>;
51
- additionalActions?: string[];
52
- }
53
-
54
- export const Roles: RolesInterface = {
55
- roles: {},
56
- actions: [],
57
- helpers: [],
58
- /**
59
- * Creates a new action
60
- */
61
- registerAction(name: string): void {
62
- if (!this.actions.includes(name)) {
63
- this.actions.push(name);
64
- }
65
- },
66
-
67
- /**
68
- * Creates a new helper
69
- */
70
- registerHelper(name: string): void {
71
- if (!this.helpers.includes(name)) {
72
- this.helpers.push(name);
73
- }
74
- },
75
-
76
- /**
77
- * Get user roles
78
- */
79
- getUserRoles(userId, roles, includeSpecial) {
80
- const newRoles = [...(roles || [])];
81
- if (includeSpecial) {
82
- newRoles.push('__all__');
83
- if (!userId) {
84
- newRoles.push('__notLoggedIn__');
85
- } else {
86
- newRoles.push('__loggedIn__');
87
- if (!newRoles.includes('admin')) {
88
- newRoles.push('__notAdmin__');
89
- }
90
- }
91
- }
92
-
93
- return newRoles;
94
- },
95
-
96
- /**
97
- * Returns true if the user passes the allow check
98
- */
99
- async allow(context, roles, action: string, [obj, params]: any) {
100
- const userRoles = Roles.getUserRoles(context.userId!, roles, true);
101
-
102
- return userRoles.reduce(async (roleIsAllowedPromise: Promise<boolean>, role) => {
103
- const roleIsAllowed = await roleIsAllowedPromise;
104
-
105
- if (roleIsAllowed) return true;
106
-
107
- if (Roles.roles[role] && Roles.roles[role].allowRules && Roles.roles[role].allowRules[action]) {
108
- return Roles.roles[role].allowRules[action].reduce(
109
- async (rulesIsAllowedPromise: Promise<boolean>, allowFn: any) => {
110
- const ruleIsAllowed = await rulesIsAllowedPromise;
111
- if (ruleIsAllowed) return true;
112
-
113
- return allowFn(obj, params, context);
114
- },
115
- Promise.resolve(false),
116
- );
117
- }
118
-
119
- return roleIsAllowed;
120
- }, Promise.resolve(false));
121
- },
122
-
123
- /**
124
- * To check if a user has permisisons to execute an action
125
- */
126
- userHasPermission: async (context, action, args) => {
127
- const roles = Array.isArray(context.user?.roles) ? context.user.roles : [];
128
- const allows = await Roles.allow(context, roles, action, args);
129
- return allows === true;
130
- },
131
- };
132
-
133
- /**
134
- * Constructs a new role
135
- */
136
- export class Role implements RoleInterface {
137
- allowRules: Record<string, any>;
138
-
139
- helpers: Record<string, any>;
140
-
141
- constructor(public name: string) {
142
- if (has(Roles.roles, name)) throw new Error(`"${name}" role is already defined`);
143
-
144
- this.allowRules = {};
145
- this.helpers = {};
146
-
147
- Roles.roles[name] = this as any as RoleInterface;
148
- }
149
-
150
- /**
151
- * Adds a helper to a role
152
- */
153
- helper(helper: string, func: any) {
154
- if (!Roles.helpers.includes(helper)) {
155
- Roles.registerHelper(helper);
156
- }
157
-
158
- let helperFn = func;
159
-
160
- if (!isFunction(helperFn)) {
161
- const clonedValue = structuredClone(helperFn);
162
- helperFn = () => {
163
- return clonedValue;
164
- };
165
- }
166
-
167
- if (!this.helpers[helper]) {
168
- this.helpers[helper] = [];
169
- }
170
-
171
- this.helpers[helper].push(helperFn);
172
- }
173
-
174
- /**
175
- * Adds allow properties to a role
176
- */
177
- allow(action, allow) {
178
- if (!action) {
179
- throw new Error(`Action doesn't exist`);
180
- }
181
- if (!Roles.actions.includes(action)) {
182
- Roles.registerAction(action);
183
- }
184
- let allowFn = allow;
185
- if (!isFunction(allowFn)) {
186
- const clonedValue = structuredClone(allowFn);
187
- allowFn = () => {
188
- return clonedValue;
189
- };
190
- }
191
- this.allowRules[action] = this.allowRules[action] || [];
192
- this.allowRules[action].push(allowFn);
193
- }
194
- }
195
-
196
- /**
197
- * The admin role, who recives the default actions.
198
- */
199
- Roles.adminRole = new Role('admin') as any as RoleInterface;
200
- /**
201
- * All the logged in users users
202
- */
203
- Roles.loggedInRole = new Role('__loggedIn__') as any as RoleInterface;
204
- /**
205
- * Always, no exception
206
- */
207
- Roles.allRole = new Role('__all__') as any as RoleInterface;
package/src/utils/has.ts DELETED
@@ -1,10 +0,0 @@
1
- export const has = (obj: Record<string, any>, key: string): boolean => {
2
- const keyParts = key.split('.');
3
-
4
- return (
5
- !!obj &&
6
- (keyParts.length > 1
7
- ? has(obj[key.split('.')[0]], keyParts.slice(1).join('.'))
8
- : obj.hasOwnProperty.call(obj, key))
9
- );
10
- };
@@ -1,3 +0,0 @@
1
- export const isFunction = (func: () => any): boolean => {
2
- return func && typeof func === 'function';
3
- };
@@ -1,21 +0,0 @@
1
- export const permissions = async (userRoles: any, allRoles: any) => {
2
- const actions = userRoles?.flatMap((role) => {
3
- const foundRole: any = Object.values(allRoles).find((r: any) => r.name === role);
4
- if (!foundRole) return [];
5
- return Object.entries(foundRole.allowRules || {}).flatMap(([roleName, funcs]: any) => {
6
- return funcs.map(async (f) => {
7
- try {
8
- // return permissions that are by default activated for that role,
9
- // accidentally don't check context
10
- const r = await f(null, null, null);
11
- if (r) return roleName;
12
- return null;
13
- } catch {
14
- return null;
15
- }
16
- });
17
- });
18
- });
19
- const resolvedActions = await Promise.all(actions);
20
- return [...new Set(resolvedActions)].filter(Boolean).toSorted((a: any, b: any) => a.localeCompare(b));
21
- };
package/tsconfig.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "../shared/base.tsconfig.json",
3
- "compilerOptions": {
4
- "declarationDir": "./lib",
5
- "rootDir": "./src",
6
- "outDir": "./lib",
7
-
8
- },
9
- "exclude": ["**/*.test.ts", "**/*.test.js", "tests", "lib"]
10
- }