@brika/auth 0.1.1
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 +207 -0
- package/package.json +50 -0
- package/src/__tests__/AuthClient.test.ts +736 -0
- package/src/__tests__/AuthService.test.ts +140 -0
- package/src/__tests__/ScopeService.test.ts +156 -0
- package/src/__tests__/SessionService.test.ts +311 -0
- package/src/__tests__/UserService-avatar.test.ts +277 -0
- package/src/__tests__/UserService.test.ts +223 -0
- package/src/__tests__/canAccess.test.ts +166 -0
- package/src/__tests__/disabledScopes.test.ts +101 -0
- package/src/__tests__/middleware.test.ts +190 -0
- package/src/__tests__/plugin.test.ts +78 -0
- package/src/__tests__/requireSession.test.ts +78 -0
- package/src/__tests__/routes-auth.test.ts +248 -0
- package/src/__tests__/routes-profile.test.ts +403 -0
- package/src/__tests__/routes-scopes.test.ts +64 -0
- package/src/__tests__/routes-sessions.test.ts +235 -0
- package/src/__tests__/routes-users.test.ts +477 -0
- package/src/__tests__/serveImage.test.ts +277 -0
- package/src/__tests__/setup.test.ts +270 -0
- package/src/__tests__/verifyToken.test.ts +219 -0
- package/src/client/AuthClient.ts +312 -0
- package/src/client/http-client.ts +84 -0
- package/src/client/index.ts +19 -0
- package/src/config.ts +82 -0
- package/src/constants.ts +10 -0
- package/src/index.ts +16 -0
- package/src/lib/define-roles.ts +35 -0
- package/src/lib/define-scopes.ts +48 -0
- package/src/middleware/canAccess.ts +126 -0
- package/src/middleware/index.ts +13 -0
- package/src/middleware/requireAuth.ts +35 -0
- package/src/middleware/requireScope.ts +46 -0
- package/src/middleware/verifyToken.ts +52 -0
- package/src/plugin.ts +86 -0
- package/src/react/AuthProvider.tsx +105 -0
- package/src/react/hooks.ts +128 -0
- package/src/react/index.ts +51 -0
- package/src/react/withScopeGuard.tsx +73 -0
- package/src/roles.ts +40 -0
- package/src/schemas.ts +112 -0
- package/src/scopes.ts +60 -0
- package/src/server/index.ts +44 -0
- package/src/server/requireSession.ts +44 -0
- package/src/server/routes/auth.ts +102 -0
- package/src/server/routes/cookie.ts +7 -0
- package/src/server/routes/index.ts +32 -0
- package/src/server/routes/profile.ts +162 -0
- package/src/server/routes/scopes.ts +22 -0
- package/src/server/routes/sessions.ts +68 -0
- package/src/server/routes/setup.ts +50 -0
- package/src/server/routes/users.ts +175 -0
- package/src/server/serveImage.ts +91 -0
- package/src/services/AuthService.ts +80 -0
- package/src/services/ScopeService.ts +94 -0
- package/src/services/SessionService.ts +245 -0
- package/src/services/UserService.ts +245 -0
- package/src/setup.ts +99 -0
- package/src/tanstack/index.ts +15 -0
- package/src/tanstack/routeBuilder.ts +311 -0
- package/src/types.ts +118 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brika/auth - User Route Tests (CRUD, password reset)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'bun:test';
|
|
6
|
+
import { stub, useTestBed } from '@brika/di/testing';
|
|
7
|
+
import type { Middleware } from '@brika/router';
|
|
8
|
+
import { TestApp } from '@brika/router/testing';
|
|
9
|
+
import { userRoutes } from '../server/routes/users';
|
|
10
|
+
import { UserService } from '../services/UserService';
|
|
11
|
+
import { Role, Scope, type Session, type User } from '../types';
|
|
12
|
+
|
|
13
|
+
function withSession(session: Session): Middleware {
|
|
14
|
+
return async (c, next) => {
|
|
15
|
+
c.set('session', session);
|
|
16
|
+
await next();
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const adminSession: Session = {
|
|
21
|
+
id: 'sess-admin',
|
|
22
|
+
userId: 'user-admin',
|
|
23
|
+
userEmail: 'admin@test.com',
|
|
24
|
+
userName: 'Admin',
|
|
25
|
+
userRole: Role.ADMIN,
|
|
26
|
+
scopes: [Scope.ADMIN_ALL],
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const userSession: Session = {
|
|
30
|
+
id: 'sess-user',
|
|
31
|
+
userId: 'user-regular',
|
|
32
|
+
userEmail: 'user@test.com',
|
|
33
|
+
userName: 'User',
|
|
34
|
+
userRole: Role.USER,
|
|
35
|
+
scopes: [Scope.WORKFLOW_READ, Scope.BOARD_READ],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const now = new Date();
|
|
39
|
+
|
|
40
|
+
const adminUser: User = {
|
|
41
|
+
id: 'user-admin',
|
|
42
|
+
email: 'admin@test.com',
|
|
43
|
+
name: 'Admin',
|
|
44
|
+
role: Role.ADMIN,
|
|
45
|
+
avatarHash: null,
|
|
46
|
+
createdAt: now,
|
|
47
|
+
updatedAt: now,
|
|
48
|
+
isActive: true,
|
|
49
|
+
scopes: [],
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const regularUser: User = {
|
|
53
|
+
id: 'user-regular',
|
|
54
|
+
email: 'user@test.com',
|
|
55
|
+
name: 'User',
|
|
56
|
+
role: Role.USER,
|
|
57
|
+
avatarHash: null,
|
|
58
|
+
createdAt: now,
|
|
59
|
+
updatedAt: now,
|
|
60
|
+
isActive: true,
|
|
61
|
+
scopes: [],
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// ─── GET /api/users ─────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
describe('GET /api/users — as admin', () => {
|
|
67
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
68
|
+
|
|
69
|
+
useTestBed(() => {
|
|
70
|
+
stub(UserService, {
|
|
71
|
+
listUsers: () => [adminUser, regularUser],
|
|
72
|
+
});
|
|
73
|
+
app = TestApp.create(userRoutes, [withSession(adminSession)]);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('returns list of users', async () => {
|
|
77
|
+
const res = await app.get('/api/users');
|
|
78
|
+
expect(res.status).toBe(200);
|
|
79
|
+
const body = res.body as {
|
|
80
|
+
users: User[];
|
|
81
|
+
};
|
|
82
|
+
expect(body.users).toHaveLength(2);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('GET /api/users — as regular user', () => {
|
|
87
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
88
|
+
|
|
89
|
+
useTestBed(() => {
|
|
90
|
+
stub(UserService);
|
|
91
|
+
app = TestApp.create(userRoutes, [withSession(userSession)]);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('returns 403 without admin scope', async () => {
|
|
95
|
+
const res = await app.get('/api/users');
|
|
96
|
+
expect(res.status).toBe(403);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('GET /api/users — unauthenticated', () => {
|
|
101
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
102
|
+
|
|
103
|
+
useTestBed(() => {
|
|
104
|
+
stub(UserService);
|
|
105
|
+
app = TestApp.create(userRoutes);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('returns 401 without session', async () => {
|
|
109
|
+
const res = await app.get('/api/users');
|
|
110
|
+
expect(res.status).toBe(401);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ─── POST /api/users ────────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
describe('POST /api/users — as admin', () => {
|
|
117
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
118
|
+
let setPasswordCalled: boolean;
|
|
119
|
+
|
|
120
|
+
useTestBed(() => {
|
|
121
|
+
setPasswordCalled = false;
|
|
122
|
+
stub(UserService, {
|
|
123
|
+
createUser: (email: string, name: string, role: Role) => ({
|
|
124
|
+
...regularUser,
|
|
125
|
+
id: 'new-user',
|
|
126
|
+
email,
|
|
127
|
+
name,
|
|
128
|
+
role,
|
|
129
|
+
}),
|
|
130
|
+
setPassword: async () => {
|
|
131
|
+
setPasswordCalled = true;
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
app = TestApp.create(userRoutes, [withSession(adminSession)]);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('creates user and returns user object', async () => {
|
|
138
|
+
const res = await app.post('/api/users', {
|
|
139
|
+
email: 'new@test.com',
|
|
140
|
+
name: 'New User',
|
|
141
|
+
role: Role.USER,
|
|
142
|
+
});
|
|
143
|
+
expect(res.status).toBe(200);
|
|
144
|
+
const body = res.body as {
|
|
145
|
+
status: number;
|
|
146
|
+
body: {
|
|
147
|
+
user: User;
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
expect(body.body.user.email).toBe('new@test.com');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('sets password when provided', async () => {
|
|
154
|
+
await app.post('/api/users', {
|
|
155
|
+
email: 'new@test.com',
|
|
156
|
+
name: 'New User',
|
|
157
|
+
role: Role.USER,
|
|
158
|
+
password: 'Secret123!',
|
|
159
|
+
});
|
|
160
|
+
expect(setPasswordCalled).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('skips setPassword when password is not provided', async () => {
|
|
164
|
+
await app.post('/api/users', {
|
|
165
|
+
email: 'new@test.com',
|
|
166
|
+
name: 'New User',
|
|
167
|
+
role: Role.USER,
|
|
168
|
+
});
|
|
169
|
+
expect(setPasswordCalled).toBe(false);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('POST /api/users — as regular user', () => {
|
|
174
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
175
|
+
|
|
176
|
+
useTestBed(() => {
|
|
177
|
+
stub(UserService);
|
|
178
|
+
app = TestApp.create(userRoutes, [withSession(userSession)]);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test('returns 403 for non-admin', async () => {
|
|
182
|
+
const res = await app.post('/api/users', {
|
|
183
|
+
email: 'test@y.com',
|
|
184
|
+
name: 'Test',
|
|
185
|
+
role: Role.USER,
|
|
186
|
+
});
|
|
187
|
+
expect(res.status).toBe(403);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('POST /api/users — unauthenticated', () => {
|
|
192
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
193
|
+
|
|
194
|
+
useTestBed(() => {
|
|
195
|
+
stub(UserService);
|
|
196
|
+
app = TestApp.create(userRoutes);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('returns 401 without session', async () => {
|
|
200
|
+
const res = await app.post('/api/users', {
|
|
201
|
+
email: 'test@y.com',
|
|
202
|
+
name: 'Test',
|
|
203
|
+
role: Role.USER,
|
|
204
|
+
});
|
|
205
|
+
expect(res.status).toBe(401);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// ─── GET /api/users/:id ─────────────────────────────────────────────────────
|
|
210
|
+
|
|
211
|
+
describe('GET /api/users/:id — as admin', () => {
|
|
212
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
213
|
+
|
|
214
|
+
useTestBed(() => {
|
|
215
|
+
stub(UserService, {
|
|
216
|
+
getUser: (id: string) => {
|
|
217
|
+
if (id === 'user-regular') {
|
|
218
|
+
return regularUser;
|
|
219
|
+
}
|
|
220
|
+
if (id === 'user-admin') {
|
|
221
|
+
return adminUser;
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
app = TestApp.create(userRoutes, [withSession(adminSession)]);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test('returns user by id', async () => {
|
|
230
|
+
const res = await app.get('/api/users/user-regular');
|
|
231
|
+
expect(res.status).toBe(200);
|
|
232
|
+
const body = res.body as {
|
|
233
|
+
user: User;
|
|
234
|
+
};
|
|
235
|
+
expect(body.user.email).toBe('user@test.com');
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test('returns 404 for unknown user', async () => {
|
|
239
|
+
const res = await app.get('/api/users/nonexistent');
|
|
240
|
+
expect(res.status).toBe(404);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
describe('GET /api/users/:id — as regular user', () => {
|
|
245
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
246
|
+
|
|
247
|
+
useTestBed(() => {
|
|
248
|
+
stub(UserService, {
|
|
249
|
+
getUser: () => regularUser,
|
|
250
|
+
});
|
|
251
|
+
app = TestApp.create(userRoutes, [withSession(userSession)]);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test('can access own profile', async () => {
|
|
255
|
+
const res = await app.get('/api/users/user-regular');
|
|
256
|
+
expect(res.status).toBe(200);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('returns 403 when accessing another user', async () => {
|
|
260
|
+
const res = await app.get('/api/users/user-admin');
|
|
261
|
+
expect(res.status).toBe(403);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
describe('GET /api/users/:id — unauthenticated', () => {
|
|
266
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
267
|
+
|
|
268
|
+
useTestBed(() => {
|
|
269
|
+
stub(UserService);
|
|
270
|
+
app = TestApp.create(userRoutes);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('returns 401 without session', async () => {
|
|
274
|
+
const res = await app.get('/api/users/user-admin');
|
|
275
|
+
expect(res.status).toBe(401);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// ─── PUT /api/users/:id/password ────────────────────────────────────────────
|
|
280
|
+
|
|
281
|
+
describe('PUT /api/users/:id/password — as admin', () => {
|
|
282
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
283
|
+
|
|
284
|
+
useTestBed(() => {
|
|
285
|
+
stub(UserService, {
|
|
286
|
+
getUser: (id: string) => (id === 'user-regular' ? regularUser : null),
|
|
287
|
+
setPassword: async () => {},
|
|
288
|
+
});
|
|
289
|
+
app = TestApp.create(userRoutes, [withSession(adminSession)]);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test('resets password for existing user', async () => {
|
|
293
|
+
const res = await app.put('/api/users/user-regular/password', {
|
|
294
|
+
password: 'NewPass123!',
|
|
295
|
+
});
|
|
296
|
+
expect(res.status).toBe(200);
|
|
297
|
+
expect(
|
|
298
|
+
(
|
|
299
|
+
res.body as {
|
|
300
|
+
ok: boolean;
|
|
301
|
+
}
|
|
302
|
+
).ok
|
|
303
|
+
).toBe(true);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test('returns 400 when password is missing', async () => {
|
|
307
|
+
const res = await app.put('/api/users/user-regular/password', {});
|
|
308
|
+
expect(res.status).toBe(400);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test('returns 404 for unknown user', async () => {
|
|
312
|
+
const res = await app.put('/api/users/nonexistent/password', {
|
|
313
|
+
password: 'ValidPass123!',
|
|
314
|
+
});
|
|
315
|
+
expect(res.status).toBe(404);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
describe('PUT /api/users/:id/password — as regular user', () => {
|
|
320
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
321
|
+
|
|
322
|
+
useTestBed(() => {
|
|
323
|
+
stub(UserService);
|
|
324
|
+
app = TestApp.create(userRoutes, [withSession(userSession)]);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
test('returns 403 for non-admin', async () => {
|
|
328
|
+
const res = await app.put('/api/users/user-regular/password', {
|
|
329
|
+
password: 'ValidPass123!',
|
|
330
|
+
});
|
|
331
|
+
expect(res.status).toBe(403);
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
describe('PUT /api/users/:id/password — unauthenticated', () => {
|
|
336
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
337
|
+
|
|
338
|
+
useTestBed(() => {
|
|
339
|
+
stub(UserService);
|
|
340
|
+
app = TestApp.create(userRoutes);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test('returns 401 without session', async () => {
|
|
344
|
+
const res = await app.put('/api/users/user-regular/password', {
|
|
345
|
+
password: 'ValidPass123!',
|
|
346
|
+
});
|
|
347
|
+
expect(res.status).toBe(401);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// ─── PUT /api/users/:id ─────────────────────────────────────────────────────
|
|
352
|
+
|
|
353
|
+
describe('PUT /api/users/:id — as admin', () => {
|
|
354
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
355
|
+
|
|
356
|
+
useTestBed(() => {
|
|
357
|
+
stub(UserService, {
|
|
358
|
+
updateUser: (
|
|
359
|
+
_id: string,
|
|
360
|
+
updates: {
|
|
361
|
+
name?: string;
|
|
362
|
+
}
|
|
363
|
+
) => ({
|
|
364
|
+
...regularUser,
|
|
365
|
+
name: updates.name ?? regularUser.name,
|
|
366
|
+
}),
|
|
367
|
+
});
|
|
368
|
+
app = TestApp.create(userRoutes, [withSession(adminSession)]);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
test('updates user fields', async () => {
|
|
372
|
+
const res = await app.put('/api/users/user-regular', {
|
|
373
|
+
name: 'Updated Name',
|
|
374
|
+
});
|
|
375
|
+
expect(res.status).toBe(200);
|
|
376
|
+
const body = res.body as {
|
|
377
|
+
user: User;
|
|
378
|
+
};
|
|
379
|
+
expect(body.user.name).toBe('Updated Name');
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
describe('PUT /api/users/:id — as regular user', () => {
|
|
384
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
385
|
+
|
|
386
|
+
useTestBed(() => {
|
|
387
|
+
stub(UserService);
|
|
388
|
+
app = TestApp.create(userRoutes, [withSession(userSession)]);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test('returns 403 for non-admin', async () => {
|
|
392
|
+
const res = await app.put('/api/users/user-regular', {
|
|
393
|
+
name: 'Test',
|
|
394
|
+
});
|
|
395
|
+
expect(res.status).toBe(403);
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
describe('PUT /api/users/:id — unauthenticated', () => {
|
|
400
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
401
|
+
|
|
402
|
+
useTestBed(() => {
|
|
403
|
+
stub(UserService);
|
|
404
|
+
app = TestApp.create(userRoutes);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
test('returns 401 without session', async () => {
|
|
408
|
+
const res = await app.put('/api/users/user-regular', {
|
|
409
|
+
name: 'Test',
|
|
410
|
+
});
|
|
411
|
+
expect(res.status).toBe(401);
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// ─── DELETE /api/users/:id ──────────────────────────────────────────────────
|
|
416
|
+
|
|
417
|
+
describe('DELETE /api/users/:id — as admin', () => {
|
|
418
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
419
|
+
|
|
420
|
+
useTestBed(() => {
|
|
421
|
+
stub(UserService, {
|
|
422
|
+
getUser: (id: string) => (id === 'user-regular' ? regularUser : null),
|
|
423
|
+
deleteUser: () => {},
|
|
424
|
+
});
|
|
425
|
+
app = TestApp.create(userRoutes, [withSession(adminSession)]);
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
test('deletes another user', async () => {
|
|
429
|
+
const res = await app.delete('/api/users/user-regular');
|
|
430
|
+
expect(res.status).toBe(200);
|
|
431
|
+
expect(
|
|
432
|
+
(
|
|
433
|
+
res.body as {
|
|
434
|
+
ok: boolean;
|
|
435
|
+
}
|
|
436
|
+
).ok
|
|
437
|
+
).toBe(true);
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
test('returns 400 when trying to self-delete', async () => {
|
|
441
|
+
const res = await app.delete('/api/users/user-admin');
|
|
442
|
+
expect(res.status).toBe(400);
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
test('returns 404 for unknown user', async () => {
|
|
446
|
+
const res = await app.delete('/api/users/nonexistent');
|
|
447
|
+
expect(res.status).toBe(404);
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
describe('DELETE /api/users/:id — as regular user', () => {
|
|
452
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
453
|
+
|
|
454
|
+
useTestBed(() => {
|
|
455
|
+
stub(UserService);
|
|
456
|
+
app = TestApp.create(userRoutes, [withSession(userSession)]);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
test('returns 403 for non-admin', async () => {
|
|
460
|
+
const res = await app.delete('/api/users/user-regular');
|
|
461
|
+
expect(res.status).toBe(403);
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
describe('DELETE /api/users/:id — unauthenticated', () => {
|
|
466
|
+
let app: ReturnType<typeof TestApp.create>;
|
|
467
|
+
|
|
468
|
+
useTestBed(() => {
|
|
469
|
+
stub(UserService);
|
|
470
|
+
app = TestApp.create(userRoutes);
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
test('returns 401 without session', async () => {
|
|
474
|
+
const res = await app.delete('/api/users/user-regular');
|
|
475
|
+
expect(res.status).toBe(401);
|
|
476
|
+
});
|
|
477
|
+
});
|