@travetto/auth 3.0.0-rc.0 → 3.0.0-rc.10

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,5 @@
1
1
  <!-- This file was generated by @travetto/doc and should not be modified directly -->
2
- <!-- Please modify https://github.com/travetto/travetto/tree/main/module/auth/doc.ts and execute "npx trv doc" to rebuild -->
2
+ <!-- Please modify https://github.com/travetto/travetto/tree/main/module/auth/DOC.ts and execute "npx trv doc" to rebuild -->
3
3
  # Authentication
4
4
  ## Authentication scaffolding for the travetto framework
5
5
 
@@ -63,7 +63,14 @@ As referenced above, a [Principal Structure](https://github.com/travetto/travett
63
63
  ```typescript
64
64
  export interface Authenticator<T = unknown, P extends Principal = Principal, C = unknown> {
65
65
  /**
66
- * Verify the payload, verifying the payload is correctly identified.
66
+ * Allows for the authenticator to be initialized if needed
67
+ * @param ctx
68
+ */
69
+ initialize?(ctx: C): Promise<void>;
70
+
71
+ /**
72
+ * Verify the payload, ensuring the payload is correctly identified.
73
+ *
67
74
  * @returns Valid principal if authenticated
68
75
  * @returns undefined if authentication is valid, but incomplete (multi-step)
69
76
  * @throws AppError if authentication fails
@@ -105,50 +112,24 @@ Overall, the structure is simple, but drives home the primary use cases of the f
105
112
  * To have access to the principal
106
113
 
107
114
  ## Common Utilities
108
- The [AuthUtil](https://github.com/travetto/travetto/tree/main/module/auth/src/util.ts#L24) provides the following functionality:
115
+ The [AuthUtil](https://github.com/travetto/travetto/tree/main/module/auth/src/util.ts#L11) provides the following functionality:
109
116
 
110
117
  **Code: Auth util structure**
111
118
  ```typescript
112
- import * as crypto from 'crypto';
113
- import * as util from 'util';
119
+ import crypto from 'crypto';
120
+ import util from 'util';
114
121
  import { AppError, Util } from '@travetto/base';
115
122
  const pbkdf2 = util.promisify(crypto.pbkdf2);
116
- type PermSet = Set<string> | ReadonlySet<string>;
117
- type PermissionChecker = {
118
- all: (perms: PermSet) => boolean;
119
- any: (perms: PermSet) => boolean;
120
- };
121
- type PermissionCheckerSet = {
122
- includes: (perms: PermSet) => boolean;
123
- excludes: (perms: PermSet) => boolean;
124
- check: (value: PermSet) => boolean;
125
- };
126
123
  /**
127
124
  * Standard auth utilities
128
125
  */
129
126
  export class AuthUtil {
130
127
  /**
131
- * Build a permission checker against the provided permissions
132
- *
133
- * @param perms Set of permissions to check
134
- * @param defaultIfEmpty If no perms passed, default to empty
135
- */
136
- /**
137
- * Build a permission checker off of an include, and exclude set
128
+ * Build matcher for role permissions in allow/deny fashion
138
129
  *
139
- * @param include Which permissions to include
140
- * @param exclude Which permissions to exclude
141
- * @param matchAll Whether not all permissions should be matched
130
+ * @param roles Roles to build matcher for
142
131
  */
143
- static permissionChecker(include: Iterable<string>, exclude: Iterable<string>, mode: 'all' | 'any' = 'any'): PermissionCheckerSet ;
144
- /**
145
- * Build a permission checker off of an include, and exclude set
146
- *
147
- * @param include Which permissions to include
148
- * @param exclude Which permissions to exclude
149
- * @param matchAll Whether not all permissions should be matched
150
- */
151
- static checkPermissions(permissions: Iterable<string>, include: Iterable<string>, exclude: Iterable<string>, mode: 'all' | 'any' = 'any'): void ;
132
+ static roleMatcher(roles: string[]): (perms: Set<string>) => boolean ;
152
133
  /**
153
134
  * Generate a hash for a given value
154
135
  *
@@ -170,13 +151,18 @@ export class AuthUtil {
170
151
  }
171
152
  ```
172
153
 
173
- `permissionSetChecker` is probably the only functionality that needs to be explained.The function operates in a `DENY` / `ALLOW` mode. This means that a permission check will succeed only if:
154
+ `roleMatcher` is probably the only functionality that needs to be explained. The function extends the core allow/deny matcher functionality from [Base](https://github.com/travetto/travetto/tree/main/module/base#readme "Environment config and common utilities for travetto applications.")'s Util class.
155
+
156
+ An example of role checks could be:
157
+
158
+
159
+ * Admin
160
+ * !Editor
161
+ * Owner+Author
174
162
 
163
+ The code would check the list in order, which would result in the following logic:
175
164
 
176
- * The user is logged in
177
- * If `matchAll` is false:
178
- * The user does not have any permissions in the exclusion list
179
- * The include list is empty, or the user has at least one permission in the include list.
180
- * Else
181
- * The user does not have all permissions in the exclusion list
182
- * The include list is empty, or the user has all permissions in the include list.
165
+ * If the user is an admin, always allow
166
+ * If the user has the editor role, deny
167
+ * If the user is both an owner and an author allow
168
+ * By default, deny due to the presence of positive checks
File without changes
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/auth",
3
- "displayName": "Authentication",
4
- "version": "3.0.0-rc.0",
3
+ "version": "3.0.0-rc.10",
5
4
  "description": "Authentication scaffolding for the travetto framework",
6
5
  "keywords": [
7
6
  "authentication",
@@ -15,16 +14,19 @@
15
14
  "name": "Travetto Framework"
16
15
  },
17
16
  "files": [
18
- "index.ts",
17
+ "__index__.ts",
19
18
  "src"
20
19
  ],
21
- "main": "index.ts",
20
+ "main": "__index__.ts",
22
21
  "repository": {
23
22
  "url": "https://github.com/travetto/travetto.git",
24
23
  "directory": "module/auth"
25
24
  },
26
25
  "dependencies": {
27
- "@travetto/base": "^3.0.0-rc.0"
26
+ "@travetto/base": "^3.0.0-rc.10"
27
+ },
28
+ "travetto": {
29
+ "displayName": "Authentication"
28
30
  },
29
31
  "private": false,
30
32
  "publishConfig": {
@@ -7,7 +7,14 @@ import { Principal } from './principal';
7
7
  */
8
8
  export interface Authenticator<T = unknown, P extends Principal = Principal, C = unknown> {
9
9
  /**
10
- * Verify the payload, verifying the payload is correctly identified.
10
+ * Allows for the authenticator to be initialized if needed
11
+ * @param ctx
12
+ */
13
+ initialize?(ctx: C): Promise<void>;
14
+
15
+ /**
16
+ * Verify the payload, ensuring the payload is correctly identified.
17
+ *
11
18
  * @returns Valid principal if authenticated
12
19
  * @returns undefined if authentication is valid, but incomplete (multi-step)
13
20
  * @throws AppError if authentication fails
@@ -2,7 +2,7 @@
2
2
  * A user principal, including permissions and details
3
3
  *
4
4
  * @concrete ../internal/types:PrincipalTarget
5
- * @augments `@trv:rest/Context`
5
+ * @augments `@travetto/rest:Context`
6
6
  */
7
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
8
  export interface Principal<D = { [key: string]: any }> {
package/src/util.ts CHANGED
@@ -1,89 +1,36 @@
1
- import * as crypto from 'crypto';
2
- import * as util from 'util';
1
+ import crypto from 'crypto';
2
+ import util from 'util';
3
3
 
4
4
  import { AppError, Util } from '@travetto/base';
5
5
 
6
6
  const pbkdf2 = util.promisify(crypto.pbkdf2);
7
7
 
8
- type PermSet = Set<string> | ReadonlySet<string>;
9
-
10
- type PermissionChecker = {
11
- all: (perms: PermSet) => boolean;
12
- any: (perms: PermSet) => boolean;
13
- };
14
-
15
- type PermissionCheckerSet = {
16
- includes: (perms: PermSet) => boolean;
17
- excludes: (perms: PermSet) => boolean;
18
- check: (value: PermSet) => boolean;
19
- };
20
-
21
8
  /**
22
9
  * Standard auth utilities
23
10
  */
24
11
  export class AuthUtil {
25
12
 
26
- static #checkExcCache = new Map<string, PermissionChecker>();
27
- static #checkIncCache = new Map<string, PermissionChecker>();
28
-
29
- /**
30
- * Build a permission checker against the provided permissions
31
- *
32
- * @param perms Set of permissions to check
33
- * @param defaultIfEmpty If no perms passed, default to empty
34
- */
35
- static #buildChecker(perms: Iterable<string>, defaultIfEmpty: boolean): PermissionChecker {
36
- const permArr = [...perms].map(x => x.toLowerCase());
37
- let all = (_: PermSet): boolean => defaultIfEmpty;
38
- let any = (_: PermSet): boolean => defaultIfEmpty;
39
- if (permArr.length) {
40
- all = (uPerms: PermSet): boolean => permArr.every(x => uPerms.has(x));
41
- any = (uPerms: PermSet): boolean => permArr.some(x => uPerms.has(x));
13
+ static #matchPermissionSet(rule: string[], perms: Set<string>): boolean {
14
+ for (const el of rule) {
15
+ if (!perms.has(el)) {
16
+ return false;
17
+ }
42
18
  }
43
- return { all, any };
19
+ return true;
44
20
  }
45
21
 
46
22
  /**
47
- * Build a permission checker off of an include, and exclude set
23
+ * Build matcher for role permissions in allow/deny fashion
48
24
  *
49
- * @param include Which permissions to include
50
- * @param exclude Which permissions to exclude
51
- * @param matchAll Whether not all permissions should be matched
25
+ * @param roles Roles to build matcher for
52
26
  */
53
- static permissionChecker(include: Iterable<string>, exclude: Iterable<string>, mode: 'all' | 'any' = 'any'): PermissionCheckerSet {
54
- const incKey = [...include].sort().join(',');
55
- const excKey = [...exclude].sort().join(',');
56
-
57
- if (!this.#checkIncCache.has(incKey)) {
58
- this.#checkIncCache.set(incKey, this.#buildChecker(include, true));
59
- }
60
- if (!this.#checkExcCache.has(excKey)) {
61
- this.#checkExcCache.set(excKey, this.#buildChecker(exclude, false));
62
- }
63
-
64
- const includes = this.#checkIncCache.get(incKey)![mode];
65
- const excludes = this.#checkExcCache.get(excKey)![mode];
66
-
67
- return {
68
- includes, excludes, check: (perms: PermSet) => includes(perms) && !excludes(perms)
69
- };
27
+ static roleMatcher(roles: string[]): (perms: Set<string>) => boolean {
28
+ return Util.allowDenyMatcher<string[], [Set<string>]>(roles,
29
+ x => x.split('|'),
30
+ this.#matchPermissionSet.bind(this),
31
+ );
70
32
  }
71
33
 
72
- /**
73
- * Build a permission checker off of an include, and exclude set
74
- *
75
- * @param include Which permissions to include
76
- * @param exclude Which permissions to exclude
77
- * @param matchAll Whether not all permissions should be matched
78
- */
79
- static checkPermissions(permissions: Iterable<string>, include: Iterable<string>, exclude: Iterable<string>, mode: 'all' | 'any' = 'any'): void {
80
- const { check } = this.permissionChecker(include, exclude, mode);
81
- if (!check(!(permissions instanceof Set) ? new Set(permissions) : permissions)) {
82
- throw new AppError('Insufficient permissions', 'permissions');
83
- }
84
- }
85
-
86
-
87
34
  /**
88
35
  * Generate a hash for a given value
89
36
  *