@stevenkellner/team-conduct-api 2.0.6 → 2.0.8

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.
@@ -26,12 +26,12 @@ type ExpectedUserRoles = UserRole | ExpectedUserRoles[] | {
26
26
  * 5. Ensures the person is signed in (has signInProperties)
27
27
  * 6. Verifies the person has the required roles
28
28
  *
29
- * @param rawUserId - The raw user ID string from authentication context (null if not authenticated)
29
+ * @param userAuthId - The raw user authentication ID string from authentication context (null if not authenticated)
30
30
  * @param teamId - The ID of the team to check membership and roles for
31
31
  * @param roles - The expected role requirements (supports AND/OR logic via ExpectedUserRoles)
32
32
  * @returns The validated User.Id if all checks pass
33
33
  * @throws {FunctionsError} 'unauthenticated' - If rawUserId is null
34
34
  * @throws {FunctionsError} 'permission-denied' - If any validation check fails
35
35
  */
36
- export declare function checkAuthentication(rawUserId: string | null, teamId: Team.Id, roles: ExpectedUserRoles): Promise<User.Id>;
36
+ export declare function checkAuthentication(userAuthId: string | null, teamId: Team.Id, roles: ExpectedUserRoles): Promise<User.Id>;
37
37
  export {};
@@ -30,17 +30,20 @@ function hasUserRoles(userRoles, expectedRoles) {
30
30
  * 5. Ensures the person is signed in (has signInProperties)
31
31
  * 6. Verifies the person has the required roles
32
32
  *
33
- * @param rawUserId - The raw user ID string from authentication context (null if not authenticated)
33
+ * @param userAuthId - The raw user authentication ID string from authentication context (null if not authenticated)
34
34
  * @param teamId - The ID of the team to check membership and roles for
35
35
  * @param roles - The expected role requirements (supports AND/OR logic via ExpectedUserRoles)
36
36
  * @returns The validated User.Id if all checks pass
37
37
  * @throws {FunctionsError} 'unauthenticated' - If rawUserId is null
38
38
  * @throws {FunctionsError} 'permission-denied' - If any validation check fails
39
39
  */
40
- async function checkAuthentication(rawUserId, teamId, roles) {
41
- if (rawUserId === null)
40
+ async function checkAuthentication(userAuthId, teamId, roles) {
41
+ if (userAuthId === null)
42
42
  throw new firebase_function_1.FunctionsError('unauthenticated', 'User is not authenticated');
43
- const userId = types_1.User.Id.builder.build(rawUserId);
43
+ const userAuthenticationId = await Firestore_1.Firestore.shared.userAuthentication(userAuthId).snapshot();
44
+ if (!userAuthenticationId.exists)
45
+ throw new firebase_function_1.FunctionsError('permission-denied', 'User authentication does not exist');
46
+ const userId = types_1.User.Id.builder.build(userAuthenticationId.data);
44
47
  const userSnapshot = await Firestore_1.Firestore.shared.user(userId).snapshot();
45
48
  if (!userSnapshot.exists)
46
49
  throw new firebase_function_1.FunctionsError('permission-denied', 'User does not exist');
@@ -9,6 +9,7 @@ const firebase_utils_1 = require("./firebase-utils");
9
9
  (0, mocha_1.describe)('checkAuthentication', () => {
10
10
  const teamId = index_1.Team.Id.builder.build('11111111-1111-4111-1111-111111111111');
11
11
  const personId = index_1.Person.Id.builder.build('22222222-2222-4222-2222-222222222222');
12
+ const userAuthId = 'auth-123';
12
13
  const userId = index_1.User.Id.builder.build('user123');
13
14
  (0, mocha_1.describe)('checkAuthentication - basic validation', () => {
14
15
  (0, mocha_1.it)('should throw "unauthenticated" error if rawUserId is null', async () => {
@@ -16,25 +17,41 @@ const firebase_utils_1 = require("./firebase-utils");
16
17
  await (0, checkAuthentication_1.checkAuthentication)(null, teamId, 'team-manager');
17
18
  }, 'unauthenticated', 'User is not authenticated');
18
19
  });
20
+ (0, mocha_1.it)('should throw "permission-denied" if user authentication does not exist', async () => {
21
+ (0, firebase_utils_1.configureFirebase)({
22
+ userAuthentications: firebase_utils_1.Collection.docs({
23
+ [userAuthId]: firebase_utils_1.Document.empty()
24
+ })
25
+ });
26
+ await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
27
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, 'team-manager');
28
+ }, 'permission-denied', 'User authentication does not exist');
29
+ });
19
30
  (0, mocha_1.it)('should throw "permission-denied" if user does not exist', async () => {
20
31
  (0, firebase_utils_1.configureFirebase)({
32
+ userAuthentications: firebase_utils_1.Collection.docs({
33
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
34
+ }),
21
35
  users: firebase_utils_1.Collection.docs({
22
36
  [userId.value]: firebase_utils_1.Document.empty()
23
37
  })
24
38
  });
25
39
  await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
26
- await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, 'team-manager');
40
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, 'team-manager');
27
41
  }, 'permission-denied', 'User does not exist');
28
42
  });
29
43
  (0, mocha_1.it)('should throw "permission-denied" if user is not a member of the team', async () => {
30
44
  const emptyTeams = new typescript_common_functionality_1.Dictionary(index_1.Team.Id.builder);
31
45
  (0, firebase_utils_1.configureFirebase)({
46
+ userAuthentications: firebase_utils_1.Collection.docs({
47
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
48
+ }),
32
49
  users: firebase_utils_1.Collection.docs({
33
50
  [userId.value]: firebase_utils_1.Document.user(userId, emptyTeams)
34
51
  })
35
52
  });
36
53
  await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
37
- await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, 'team-manager');
54
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, 'team-manager');
38
55
  }, 'permission-denied', 'User is not a member of the team');
39
56
  });
40
57
  (0, mocha_1.it)('should throw "permission-denied" if person does not exist', async () => {
@@ -45,6 +62,9 @@ const firebase_utils_1 = require("./firebase-utils");
45
62
  personId: personId.guidString
46
63
  }));
47
64
  (0, firebase_utils_1.configureFirebase)({
65
+ userAuthentications: firebase_utils_1.Collection.docs({
66
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
67
+ }),
48
68
  users: firebase_utils_1.Collection.docs({
49
69
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
50
70
  }),
@@ -57,7 +77,7 @@ const firebase_utils_1 = require("./firebase-utils");
57
77
  })
58
78
  });
59
79
  await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
60
- await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, 'team-manager');
80
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, 'team-manager');
61
81
  }, 'permission-denied', 'Person does not exist');
62
82
  });
63
83
  (0, mocha_1.it)('should throw "permission-denied" if person is not signed in', async () => {
@@ -68,6 +88,9 @@ const firebase_utils_1 = require("./firebase-utils");
68
88
  personId: personId.guidString
69
89
  }));
70
90
  (0, firebase_utils_1.configureFirebase)({
91
+ userAuthentications: firebase_utils_1.Collection.docs({
92
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
93
+ }),
71
94
  users: firebase_utils_1.Collection.docs({
72
95
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
73
96
  }),
@@ -80,7 +103,7 @@ const firebase_utils_1 = require("./firebase-utils");
80
103
  })
81
104
  });
82
105
  await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
83
- await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, 'team-manager');
106
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, 'team-manager');
84
107
  }, 'permission-denied', 'Person is not signed in');
85
108
  });
86
109
  });
@@ -93,6 +116,9 @@ const firebase_utils_1 = require("./firebase-utils");
93
116
  personId: personId.guidString
94
117
  }));
95
118
  (0, firebase_utils_1.configureFirebase)({
119
+ userAuthentications: firebase_utils_1.Collection.docs({
120
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
121
+ }),
96
122
  users: firebase_utils_1.Collection.docs({
97
123
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
98
124
  }),
@@ -105,7 +131,7 @@ const firebase_utils_1 = require("./firebase-utils");
105
131
  })
106
132
  });
107
133
  await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
108
- await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, 'team-manager');
134
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, 'team-manager');
109
135
  }, 'permission-denied', 'User does not have the required roles');
110
136
  });
111
137
  (0, mocha_1.it)('should return userId if user has required single role', async () => {
@@ -116,6 +142,9 @@ const firebase_utils_1 = require("./firebase-utils");
116
142
  personId: personId.guidString
117
143
  }));
118
144
  (0, firebase_utils_1.configureFirebase)({
145
+ userAuthentications: firebase_utils_1.Collection.docs({
146
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
147
+ }),
119
148
  users: firebase_utils_1.Collection.docs({
120
149
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
121
150
  }),
@@ -127,7 +156,7 @@ const firebase_utils_1 = require("./firebase-utils");
127
156
  })
128
157
  })
129
158
  });
130
- const result = await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, 'team-manager');
159
+ const result = await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, 'team-manager');
131
160
  (0, core_1.expect)(result).toBeEqual(userId);
132
161
  });
133
162
  (0, mocha_1.it)('should throw "permission-denied" if user does not have all required roles (AND logic)', async () => {
@@ -138,6 +167,9 @@ const firebase_utils_1 = require("./firebase-utils");
138
167
  personId: personId.guidString
139
168
  }));
140
169
  (0, firebase_utils_1.configureFirebase)({
170
+ userAuthentications: firebase_utils_1.Collection.docs({
171
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
172
+ }),
141
173
  users: firebase_utils_1.Collection.docs({
142
174
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
143
175
  }),
@@ -150,7 +182,7 @@ const firebase_utils_1 = require("./firebase-utils");
150
182
  })
151
183
  });
152
184
  await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
153
- await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, ['person-manager', 'team-manager']);
185
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, ['person-manager', 'team-manager']);
154
186
  }, 'permission-denied', 'User does not have the required roles');
155
187
  });
156
188
  (0, mocha_1.it)('should return userId if user has all required roles (AND logic)', async () => {
@@ -161,6 +193,9 @@ const firebase_utils_1 = require("./firebase-utils");
161
193
  personId: personId.guidString
162
194
  }));
163
195
  (0, firebase_utils_1.configureFirebase)({
196
+ userAuthentications: firebase_utils_1.Collection.docs({
197
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
198
+ }),
164
199
  users: firebase_utils_1.Collection.docs({
165
200
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
166
201
  }),
@@ -172,7 +207,7 @@ const firebase_utils_1 = require("./firebase-utils");
172
207
  })
173
208
  })
174
209
  });
175
- const result = await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, ['person-manager', 'team-manager']);
210
+ const result = await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, ['person-manager', 'team-manager']);
176
211
  (0, core_1.expect)(result).toBeEqual(userId);
177
212
  });
178
213
  (0, mocha_1.it)('should return userId if user has at least one required role (OR logic)', async () => {
@@ -183,6 +218,9 @@ const firebase_utils_1 = require("./firebase-utils");
183
218
  personId: personId.guidString
184
219
  }));
185
220
  (0, firebase_utils_1.configureFirebase)({
221
+ userAuthentications: firebase_utils_1.Collection.docs({
222
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
223
+ }),
186
224
  users: firebase_utils_1.Collection.docs({
187
225
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
188
226
  }),
@@ -194,7 +232,7 @@ const firebase_utils_1 = require("./firebase-utils");
194
232
  })
195
233
  })
196
234
  });
197
- const result = await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, { anyOf: ['person-manager', 'team-manager'] });
235
+ const result = await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, { anyOf: ['person-manager', 'team-manager'] });
198
236
  (0, core_1.expect)(result).toBeEqual(userId);
199
237
  });
200
238
  (0, mocha_1.it)('should throw "permission-denied" if user does not have any required role (OR logic)', async () => {
@@ -205,6 +243,9 @@ const firebase_utils_1 = require("./firebase-utils");
205
243
  personId: personId.guidString
206
244
  }));
207
245
  (0, firebase_utils_1.configureFirebase)({
246
+ userAuthentications: firebase_utils_1.Collection.docs({
247
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
248
+ }),
208
249
  users: firebase_utils_1.Collection.docs({
209
250
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
210
251
  }),
@@ -217,7 +258,7 @@ const firebase_utils_1 = require("./firebase-utils");
217
258
  })
218
259
  });
219
260
  await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
220
- await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, { anyOf: ['person-manager', 'team-manager'] });
261
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, { anyOf: ['person-manager', 'team-manager'] });
221
262
  }, 'permission-denied', 'User does not have the required roles');
222
263
  });
223
264
  (0, mocha_1.it)('should handle complex nested role requirements (AND with OR)', async () => {
@@ -228,6 +269,9 @@ const firebase_utils_1 = require("./firebase-utils");
228
269
  personId: personId.guidString
229
270
  }));
230
271
  (0, firebase_utils_1.configureFirebase)({
272
+ userAuthentications: firebase_utils_1.Collection.docs({
273
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
274
+ }),
231
275
  users: firebase_utils_1.Collection.docs({
232
276
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
233
277
  }),
@@ -239,7 +283,7 @@ const firebase_utils_1 = require("./firebase-utils");
239
283
  })
240
284
  })
241
285
  });
242
- const result = await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, [
286
+ const result = await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, [
243
287
  'person-manager',
244
288
  { anyOf: ['fine-manager', 'team-manager'] }
245
289
  ]);
@@ -253,6 +297,9 @@ const firebase_utils_1 = require("./firebase-utils");
253
297
  personId: personId.guidString
254
298
  }));
255
299
  (0, firebase_utils_1.configureFirebase)({
300
+ userAuthentications: firebase_utils_1.Collection.docs({
301
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
302
+ }),
256
303
  users: firebase_utils_1.Collection.docs({
257
304
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
258
305
  }),
@@ -265,7 +312,7 @@ const firebase_utils_1 = require("./firebase-utils");
265
312
  })
266
313
  });
267
314
  await (0, firebase_utils_1.expectThrowsFunctionsError)(async () => {
268
- await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, [
315
+ await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, [
269
316
  'person-manager',
270
317
  { anyOf: ['fine-manager', 'team-manager'] }
271
318
  ]);
@@ -281,6 +328,9 @@ const firebase_utils_1 = require("./firebase-utils");
281
328
  personId: personId.guidString
282
329
  }));
283
330
  (0, firebase_utils_1.configureFirebase)({
331
+ userAuthentications: firebase_utils_1.Collection.docs({
332
+ [userAuthId]: firebase_utils_1.Document.data(userId.value)
333
+ }),
284
334
  users: firebase_utils_1.Collection.docs({
285
335
  [userId.value]: firebase_utils_1.Document.user(userId, teams)
286
336
  }),
@@ -298,7 +348,7 @@ const firebase_utils_1 = require("./firebase-utils");
298
348
  })
299
349
  })
300
350
  });
301
- const result = await (0, checkAuthentication_1.checkAuthentication)(userId.value, teamId, 'fine-can-add');
351
+ const result = await (0, checkAuthentication_1.checkAuthentication)(userAuthId, teamId, 'fine-can-add');
302
352
  (0, core_1.expect)(result).toBeEqual(userId);
303
353
  });
304
354
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stevenkellner/team-conduct-api",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "description": "Firebase API for Team Conduct",
5
5
  "license": "MIT",
6
6
  "author": "Steven Kellner",
@@ -50,17 +50,21 @@ function hasUserRoles(userRoles: UserRole[], expectedRoles: ExpectedUserRoles):
50
50
  * 5. Ensures the person is signed in (has signInProperties)
51
51
  * 6. Verifies the person has the required roles
52
52
  *
53
- * @param rawUserId - The raw user ID string from authentication context (null if not authenticated)
53
+ * @param userAuthId - The raw user authentication ID string from authentication context (null if not authenticated)
54
54
  * @param teamId - The ID of the team to check membership and roles for
55
55
  * @param roles - The expected role requirements (supports AND/OR logic via ExpectedUserRoles)
56
56
  * @returns The validated User.Id if all checks pass
57
57
  * @throws {FunctionsError} 'unauthenticated' - If rawUserId is null
58
58
  * @throws {FunctionsError} 'permission-denied' - If any validation check fails
59
59
  */
60
- export async function checkAuthentication(rawUserId: string | null, teamId: Team.Id, roles: ExpectedUserRoles): Promise<User.Id> {
61
- if (rawUserId === null)
60
+ export async function checkAuthentication(userAuthId: string | null, teamId: Team.Id, roles: ExpectedUserRoles): Promise<User.Id> {
61
+ if (userAuthId === null)
62
62
  throw new FunctionsError('unauthenticated', 'User is not authenticated');
63
- const userId = User.Id.builder.build(rawUserId);
63
+
64
+ const userAuthenticationId = await Firestore.shared.userAuthentication(userAuthId).snapshot();
65
+ if (!userAuthenticationId.exists)
66
+ throw new FunctionsError('permission-denied', 'User authentication does not exist');
67
+ const userId = User.Id.builder.build(userAuthenticationId.data);
64
68
 
65
69
  const userSnapshot = await Firestore.shared.user(userId).snapshot();
66
70
  if (!userSnapshot.exists)