@lobehub/chat 1.122.5 → 1.122.6
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/CHANGELOG.md +17 -0
- package/changelog/v1.json +5 -0
- package/package.json +1 -1
- package/packages/database/src/server/models/__tests__/nextauth.test.ts +556 -0
- package/packages/utils/src/server/__tests__/auth.test.ts +1 -1
- package/packages/utils/src/server/auth.ts +2 -2
- package/src/app/(backend)/api/webhooks/logto/route.ts +0 -9
- package/src/config/auth.ts +0 -4
- package/src/libs/next-auth/adapter/index.ts +201 -103
- package/src/libs/next-auth/auth.config.ts +10 -22
- package/src/libs/next-auth/edge.ts +26 -0
- package/src/libs/next-auth/index.ts +24 -11
- package/src/libs/trpc/edge/context.ts +2 -2
- package/src/libs/trpc/lambda/context.ts +2 -2
- package/src/middleware.ts +2 -2
- package/src/server/routers/lambda/user.test.ts +17 -4
- package/src/server/routers/lambda/user.ts +15 -6
- package/src/server/services/nextAuthUser/index.test.ts +108 -0
- package/src/server/services/nextAuthUser/index.ts +6 -282
- package/src/app/(backend)/api/auth/adapter/route.ts +0 -137
- /package/src/{server/services/nextAuthUser → libs/next-auth/adapter}/utils.ts +0 -0
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,23 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.122.6](https://github.com/lobehub/lobe-chat/compare/v1.122.5...v1.122.6)
|
6
|
+
|
7
|
+
<sup>Released on **2025-09-04**</sup>
|
8
|
+
|
9
|
+
<br/>
|
10
|
+
|
11
|
+
<details>
|
12
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
13
|
+
|
14
|
+
</details>
|
15
|
+
|
16
|
+
<div align="right">
|
17
|
+
|
18
|
+
[](#readme-top)
|
19
|
+
|
20
|
+
</div>
|
21
|
+
|
5
22
|
### [Version 1.122.5](https://github.com/lobehub/lobe-chat/compare/v1.122.4...v1.122.5)
|
6
23
|
|
7
24
|
<sup>Released on **2025-09-04**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.122.
|
3
|
+
"version": "1.122.6",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -0,0 +1,556 @@
|
|
1
|
+
import type {
|
2
|
+
AdapterAccount,
|
3
|
+
AdapterAuthenticator,
|
4
|
+
AdapterSession,
|
5
|
+
AdapterUser,
|
6
|
+
VerificationToken,
|
7
|
+
} from '@auth/core/adapters';
|
8
|
+
import { eq } from 'drizzle-orm';
|
9
|
+
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
10
|
+
|
11
|
+
import { LobeNextAuthDbAdapter } from '@/libs/next-auth/adapter';
|
12
|
+
|
13
|
+
import { getTestDBInstance } from '../../../core/dbForTest';
|
14
|
+
import {
|
15
|
+
nextauthAccounts,
|
16
|
+
nextauthAuthenticators,
|
17
|
+
nextauthSessions,
|
18
|
+
nextauthVerificationTokens,
|
19
|
+
users,
|
20
|
+
} from '../../../schemas';
|
21
|
+
|
22
|
+
let serverDB = await getTestDBInstance();
|
23
|
+
|
24
|
+
let nextAuthAdapter = LobeNextAuthDbAdapter(serverDB);
|
25
|
+
|
26
|
+
const userId = 'user-db';
|
27
|
+
const user: AdapterUser = {
|
28
|
+
id: userId,
|
29
|
+
name: 'John Doe',
|
30
|
+
email: 'john.doe@example.com',
|
31
|
+
emailVerified: new Date(),
|
32
|
+
image: 'https://example.com/avatar.jpg',
|
33
|
+
};
|
34
|
+
|
35
|
+
const sessionToken = 'session-token';
|
36
|
+
|
37
|
+
beforeAll(async () => {
|
38
|
+
await serverDB.delete(users);
|
39
|
+
await serverDB.delete(nextauthAccounts);
|
40
|
+
await serverDB.delete(nextauthAuthenticators);
|
41
|
+
await serverDB.delete(nextauthSessions);
|
42
|
+
await serverDB.delete(nextauthVerificationTokens);
|
43
|
+
});
|
44
|
+
|
45
|
+
beforeEach(async () => {
|
46
|
+
process.env.KEY_VAULTS_SECRET = 'ofQiJCXLF8mYemwfMWLOHoHimlPu91YmLfU7YZ4lreQ=';
|
47
|
+
// insert a user
|
48
|
+
// @ts-expect-error: createUser is defined
|
49
|
+
await nextAuthAdapter.createUser(user);
|
50
|
+
});
|
51
|
+
|
52
|
+
afterEach(async () => {
|
53
|
+
await serverDB.delete(users);
|
54
|
+
});
|
55
|
+
|
56
|
+
afterAll(async () => {
|
57
|
+
await serverDB.delete(users);
|
58
|
+
await serverDB.delete(nextauthAccounts);
|
59
|
+
await serverDB.delete(nextauthAuthenticators);
|
60
|
+
await serverDB.delete(nextauthSessions);
|
61
|
+
await serverDB.delete(nextauthVerificationTokens);
|
62
|
+
process.env.KEY_VAULTS_SECRET = undefined;
|
63
|
+
});
|
64
|
+
|
65
|
+
/**
|
66
|
+
* The tests below only test the database operation functionality,
|
67
|
+
* the mock values might not represent the actual value
|
68
|
+
*/
|
69
|
+
describe('LobeNextAuthDbAdapter', () => {
|
70
|
+
describe('users', () => {
|
71
|
+
describe('createUser', () => {
|
72
|
+
it('should create a new user', async () => {
|
73
|
+
expect(nextAuthAdapter).toBeDefined();
|
74
|
+
expect(nextAuthAdapter.createUser).toBeDefined();
|
75
|
+
const anotherUserId = 'user-db-2';
|
76
|
+
const anotherUserName = 'John Doe 2';
|
77
|
+
const anotherEmail = 'john.doe.2@example.com';
|
78
|
+
// @ts-expect-error: createUser is defined
|
79
|
+
const createdUser = await nextAuthAdapter.createUser({
|
80
|
+
...user,
|
81
|
+
id: anotherUserId,
|
82
|
+
name: anotherUserName,
|
83
|
+
email: anotherEmail,
|
84
|
+
});
|
85
|
+
expect(createdUser).toBeDefined();
|
86
|
+
expect(createdUser.id).toBe(anotherUserId);
|
87
|
+
expect(createdUser.name).toBe(anotherUserName);
|
88
|
+
expect(createdUser.email).toBe(anotherEmail);
|
89
|
+
expect(createdUser.emailVerified).toBe(user.emailVerified);
|
90
|
+
expect(createdUser.image).toBe(user.image);
|
91
|
+
});
|
92
|
+
|
93
|
+
it('should not create a user if it already exists', async () => {
|
94
|
+
expect(nextAuthAdapter).toBeDefined();
|
95
|
+
expect(nextAuthAdapter.createUser).toBeDefined();
|
96
|
+
// @ts-expect-error: createUser is defined
|
97
|
+
await nextAuthAdapter.createUser(user);
|
98
|
+
// Should not create a new user if it already exists
|
99
|
+
expect(
|
100
|
+
await serverDB.query.users.findMany({ where: eq(users.email, user.email) }),
|
101
|
+
).toHaveLength(1);
|
102
|
+
});
|
103
|
+
|
104
|
+
it('should not create a user if email exist', async () => {
|
105
|
+
expect(nextAuthAdapter).toBeDefined();
|
106
|
+
expect(nextAuthAdapter.createUser).toBeDefined();
|
107
|
+
const anotherUserId = 'user-db-2';
|
108
|
+
const anotherUserName = 'John Doe 2';
|
109
|
+
// @ts-expect-error: createUser is defined
|
110
|
+
await nextAuthAdapter.createUser({
|
111
|
+
...user,
|
112
|
+
id: anotherUserId,
|
113
|
+
name: anotherUserName,
|
114
|
+
});
|
115
|
+
// Should not create a new user if email already exists
|
116
|
+
expect(
|
117
|
+
await serverDB.query.users.findMany({ where: eq(users.email, user.email) }),
|
118
|
+
).toHaveLength(1);
|
119
|
+
});
|
120
|
+
|
121
|
+
it('should create a user if id not exist and email is null', async () => {
|
122
|
+
// In previous version, it will link the account to the existing user if the email is null
|
123
|
+
// issue: https://github.com/lobehub/lobe-chat/issues/4918
|
124
|
+
expect(nextAuthAdapter).toBeDefined();
|
125
|
+
expect(nextAuthAdapter.createUser).toBeDefined();
|
126
|
+
|
127
|
+
const existUserId = 'user-db-1';
|
128
|
+
const existUserName = 'John Doe 1';
|
129
|
+
// @ts-expect-error: createUser is defined
|
130
|
+
await nextAuthAdapter.createUser({
|
131
|
+
...user,
|
132
|
+
id: existUserId,
|
133
|
+
name: existUserName,
|
134
|
+
email: '',
|
135
|
+
});
|
136
|
+
|
137
|
+
const anotherUserId = 'user-db-2';
|
138
|
+
const anotherUserName = 'John Doe 2';
|
139
|
+
// @ts-expect-error: createUser is defined
|
140
|
+
await nextAuthAdapter.createUser({
|
141
|
+
...user,
|
142
|
+
id: anotherUserId,
|
143
|
+
name: anotherUserName,
|
144
|
+
email: '',
|
145
|
+
});
|
146
|
+
// Should create a new user if id not exists and email is null
|
147
|
+
expect(
|
148
|
+
await serverDB.query.users.findMany({ where: eq(users.id, anotherUserId) }),
|
149
|
+
).toHaveLength(1);
|
150
|
+
});
|
151
|
+
|
152
|
+
it('should create a user if id not exist even email is invalid type', async () => {
|
153
|
+
// In previous version, it will link the account to the existing user if the email is null
|
154
|
+
// issue: https://github.com/lobehub/lobe-chat/issues/4918
|
155
|
+
expect(nextAuthAdapter).toBeDefined();
|
156
|
+
expect(nextAuthAdapter.createUser).toBeDefined();
|
157
|
+
|
158
|
+
const existUserId = 'user-db-1';
|
159
|
+
const existUserName = 'John Doe 1';
|
160
|
+
// @ts-expect-error: createUser is defined
|
161
|
+
await nextAuthAdapter.createUser({
|
162
|
+
...user,
|
163
|
+
id: existUserId,
|
164
|
+
name: existUserName,
|
165
|
+
email: Object({}), // assign a non-string value
|
166
|
+
});
|
167
|
+
|
168
|
+
const anotherUserId = 'user-db-2';
|
169
|
+
const anotherUserName = 'John Doe 2';
|
170
|
+
// @ts-expect-error: createUser is defined
|
171
|
+
await nextAuthAdapter.createUser({
|
172
|
+
...user,
|
173
|
+
id: anotherUserId,
|
174
|
+
name: anotherUserName,
|
175
|
+
// @ts-expect-error: try to assign undefined value
|
176
|
+
email: undefined,
|
177
|
+
});
|
178
|
+
|
179
|
+
// Should create a new user if id not exists and email is null
|
180
|
+
expect(
|
181
|
+
await serverDB.query.users.findMany({ where: eq(users.id, anotherUserId) }),
|
182
|
+
).toHaveLength(1);
|
183
|
+
});
|
184
|
+
});
|
185
|
+
|
186
|
+
describe('deleteUser', () => {
|
187
|
+
it('should delete a user', async () => {
|
188
|
+
expect(nextAuthAdapter).toBeDefined();
|
189
|
+
expect(nextAuthAdapter.deleteUser).toBeDefined();
|
190
|
+
// @ts-expect-error: deleteUser is defined
|
191
|
+
await nextAuthAdapter.deleteUser(userId);
|
192
|
+
const deletedUser = await serverDB.query.users.findFirst({ where: eq(users.id, userId) });
|
193
|
+
expect(deletedUser).toBeUndefined();
|
194
|
+
});
|
195
|
+
});
|
196
|
+
|
197
|
+
describe('getUser', () => {
|
198
|
+
it('should get a user', async () => {
|
199
|
+
expect(nextAuthAdapter).toBeDefined();
|
200
|
+
expect(nextAuthAdapter.getUser).toBeDefined();
|
201
|
+
// @ts-expect-error: getUser is defined
|
202
|
+
const fetchedUser = await nextAuthAdapter.getUser(userId);
|
203
|
+
expect(fetchedUser).toBeDefined();
|
204
|
+
expect(fetchedUser?.id).toBe(user.id);
|
205
|
+
expect(fetchedUser?.name).toBe(user.name);
|
206
|
+
expect(fetchedUser?.email).toBe(user.email);
|
207
|
+
expect(fetchedUser?.emailVerified).toEqual(user.emailVerified);
|
208
|
+
expect(fetchedUser?.image).toBe(user.image);
|
209
|
+
});
|
210
|
+
});
|
211
|
+
|
212
|
+
describe('getUserByEmail', () => {
|
213
|
+
it('should get a user by email', async () => {
|
214
|
+
expect(nextAuthAdapter).toBeDefined();
|
215
|
+
expect(nextAuthAdapter.getUserByEmail).toBeDefined();
|
216
|
+
// @ts-expect-error: getUserByEmail is defined
|
217
|
+
const fetchedUser = await nextAuthAdapter.getUserByEmail(user.email);
|
218
|
+
expect(fetchedUser).toBeDefined();
|
219
|
+
expect(fetchedUser?.id).toBe(user.id);
|
220
|
+
expect(fetchedUser?.name).toBe(user.name);
|
221
|
+
expect(fetchedUser?.email).toBe(user.email);
|
222
|
+
expect(fetchedUser?.emailVerified).toEqual(user.emailVerified);
|
223
|
+
expect(fetchedUser?.image).toBe(user.image);
|
224
|
+
});
|
225
|
+
});
|
226
|
+
|
227
|
+
describe('getUserByAccount', () => {
|
228
|
+
it('should get a user by account', async () => {
|
229
|
+
const account: AdapterAccount = {
|
230
|
+
providerAccountId: 'provider-account-id',
|
231
|
+
userId: userId,
|
232
|
+
provider: 'auth0',
|
233
|
+
type: 'email',
|
234
|
+
};
|
235
|
+
// @ts-expect-error: linkAccount is defined
|
236
|
+
await nextAuthAdapter.linkAccount(account);
|
237
|
+
expect(nextAuthAdapter).toBeDefined();
|
238
|
+
expect(nextAuthAdapter.getUserByAccount).toBeDefined();
|
239
|
+
// @ts-expect-error: getUserByAccount is defined
|
240
|
+
const fetchedUser = await nextAuthAdapter.getUserByAccount(account);
|
241
|
+
expect(fetchedUser).toBeDefined();
|
242
|
+
expect(fetchedUser?.id).toBe(user.id);
|
243
|
+
expect(fetchedUser?.name).toBe(user.name);
|
244
|
+
expect(fetchedUser?.email).toBe(user.email);
|
245
|
+
expect(fetchedUser?.emailVerified).toEqual(user.emailVerified);
|
246
|
+
expect(fetchedUser?.image).toBe(user.image);
|
247
|
+
});
|
248
|
+
});
|
249
|
+
|
250
|
+
describe('updateUser', () => {
|
251
|
+
it('should update a user', async () => {
|
252
|
+
expect(nextAuthAdapter).toBeDefined();
|
253
|
+
expect(nextAuthAdapter.updateUser).toBeDefined();
|
254
|
+
const updatedName = 'updated' + user.name;
|
255
|
+
const updatedEmail = 'updated' + user.email;
|
256
|
+
// @ts-expect-error: updateUser is defined
|
257
|
+
const updatedUser = await nextAuthAdapter.updateUser({
|
258
|
+
id: userId,
|
259
|
+
name: updatedName,
|
260
|
+
email: updatedEmail,
|
261
|
+
});
|
262
|
+
expect(updatedUser).toBeDefined();
|
263
|
+
expect(updatedUser.id).toBe(userId);
|
264
|
+
expect(updatedUser.name).toBe(updatedName);
|
265
|
+
expect(updatedUser.email).toBe(updatedEmail);
|
266
|
+
});
|
267
|
+
});
|
268
|
+
});
|
269
|
+
|
270
|
+
describe('authenticators', () => {
|
271
|
+
describe('createAuthenticator', () => {
|
272
|
+
it('should create a new authenticator', async () => {
|
273
|
+
// Create an authenticator and link to the exists user
|
274
|
+
const params: AdapterAuthenticator = {
|
275
|
+
credentialBackedUp: false,
|
276
|
+
credentialDeviceType: 'type',
|
277
|
+
credentialID: 'some-id',
|
278
|
+
credentialPublicKey: 'some-key',
|
279
|
+
userId: userId,
|
280
|
+
providerAccountId: 'provider-account-id',
|
281
|
+
counter: 1,
|
282
|
+
};
|
283
|
+
expect(nextAuthAdapter).toBeDefined();
|
284
|
+
expect(nextAuthAdapter.createAuthenticator).toBeDefined();
|
285
|
+
// @ts-expect-error: createAuthenticator is defined
|
286
|
+
const authenticator = await nextAuthAdapter.createAuthenticator(params);
|
287
|
+
|
288
|
+
expect(authenticator).toBeDefined();
|
289
|
+
expect(authenticator.userId).toBe(params.userId);
|
290
|
+
expect(authenticator.providerAccountId).toBe(params.providerAccountId);
|
291
|
+
});
|
292
|
+
});
|
293
|
+
|
294
|
+
describe('getAuthenticator', () => {
|
295
|
+
it('should get an authenticator', async () => {
|
296
|
+
// Create an authenticator and link to the exists user
|
297
|
+
const params: AdapterAuthenticator = {
|
298
|
+
credentialBackedUp: false,
|
299
|
+
credentialDeviceType: 'type',
|
300
|
+
credentialID: 'some-id',
|
301
|
+
credentialPublicKey: 'some-key',
|
302
|
+
userId: userId,
|
303
|
+
providerAccountId: 'provider-account-id',
|
304
|
+
counter: 1,
|
305
|
+
};
|
306
|
+
// @ts-expect-error: createAuthenticator is defined
|
307
|
+
await nextAuthAdapter.createAuthenticator(params);
|
308
|
+
expect(nextAuthAdapter).toBeDefined();
|
309
|
+
expect(nextAuthAdapter.getAuthenticator).toBeDefined();
|
310
|
+
// @ts-expect-error: getAuthenticator is defined
|
311
|
+
const fetchedAuthenticator = await nextAuthAdapter.getAuthenticator(params.credentialID);
|
312
|
+
expect(fetchedAuthenticator).toBeDefined();
|
313
|
+
expect(fetchedAuthenticator?.userId).toBe(params.userId);
|
314
|
+
expect(fetchedAuthenticator?.providerAccountId).toBe(params.providerAccountId);
|
315
|
+
});
|
316
|
+
});
|
317
|
+
|
318
|
+
describe('updateAuthenticatorCounter', () => {
|
319
|
+
it('should update an authenticator counter', async () => {
|
320
|
+
// Create an authenticator and link to the exists user
|
321
|
+
const params: AdapterAuthenticator = {
|
322
|
+
credentialBackedUp: false,
|
323
|
+
credentialDeviceType: 'type',
|
324
|
+
credentialID: 'some-id',
|
325
|
+
credentialPublicKey: 'some-key',
|
326
|
+
userId: userId,
|
327
|
+
providerAccountId: 'provider-account-id',
|
328
|
+
counter: 1,
|
329
|
+
};
|
330
|
+
// @ts-expect-error: createAuthenticator is defined
|
331
|
+
await nextAuthAdapter.createAuthenticator(params);
|
332
|
+
expect(nextAuthAdapter).toBeDefined();
|
333
|
+
expect(nextAuthAdapter.updateAuthenticatorCounter).toBeDefined();
|
334
|
+
// @ts-expect-error: updateAuthenticatorCounter is defined
|
335
|
+
const updatedAuthenticator = await nextAuthAdapter.updateAuthenticatorCounter(
|
336
|
+
params.credentialID,
|
337
|
+
2,
|
338
|
+
);
|
339
|
+
expect(updatedAuthenticator).toBeDefined();
|
340
|
+
expect(updatedAuthenticator.counter).toBe(2);
|
341
|
+
});
|
342
|
+
});
|
343
|
+
|
344
|
+
describe('listAuthenticatorsByUserId', () => {
|
345
|
+
it('should list authenticators by user id', async () => {
|
346
|
+
// Create an authenticator and link to the exists user
|
347
|
+
const params: AdapterAuthenticator = {
|
348
|
+
credentialBackedUp: false,
|
349
|
+
credentialDeviceType: 'type',
|
350
|
+
credentialID: 'some-id',
|
351
|
+
credentialPublicKey: 'some-key',
|
352
|
+
userId: userId,
|
353
|
+
providerAccountId: 'provider-account-id',
|
354
|
+
counter: 1,
|
355
|
+
};
|
356
|
+
// @ts-expect-error: createAuthenticator is defined
|
357
|
+
await nextAuthAdapter.createAuthenticator(params);
|
358
|
+
expect(nextAuthAdapter).toBeDefined();
|
359
|
+
expect(nextAuthAdapter.listAuthenticatorsByUserId).toBeDefined();
|
360
|
+
// @ts-expect-error: listAuthenticatorsByUserId is defined
|
361
|
+
const authenticators = await nextAuthAdapter.listAuthenticatorsByUserId(userId);
|
362
|
+
expect(authenticators).toBeDefined();
|
363
|
+
expect(authenticators.length).toBeGreaterThan(0);
|
364
|
+
expect(authenticators[0].userId).toBe(params.userId);
|
365
|
+
expect(authenticators[0].providerAccountId).toBe(params.providerAccountId);
|
366
|
+
});
|
367
|
+
});
|
368
|
+
});
|
369
|
+
|
370
|
+
describe('session', () => {
|
371
|
+
describe('createSession', () => {
|
372
|
+
it('should create a new session', async () => {
|
373
|
+
const data: AdapterSession = {
|
374
|
+
sessionToken,
|
375
|
+
userId: userId,
|
376
|
+
expires: new Date(),
|
377
|
+
};
|
378
|
+
expect(nextAuthAdapter).toBeDefined();
|
379
|
+
expect(nextAuthAdapter.createSession).toBeDefined();
|
380
|
+
|
381
|
+
// @ts-expect-error: createSession is defined
|
382
|
+
const session = await nextAuthAdapter.createSession(data);
|
383
|
+
|
384
|
+
expect(session).toBeDefined();
|
385
|
+
expect(session.sessionToken).toBe(data.sessionToken);
|
386
|
+
expect(session.userId).toBe(data.userId);
|
387
|
+
expect(session.expires).toEqual(data.expires);
|
388
|
+
});
|
389
|
+
});
|
390
|
+
|
391
|
+
describe('updateSession', () => {
|
392
|
+
it('should update a session', async () => {
|
393
|
+
const data: AdapterSession = {
|
394
|
+
sessionToken,
|
395
|
+
userId: userId,
|
396
|
+
expires: new Date(),
|
397
|
+
};
|
398
|
+
// @ts-expect-error: createSession is defined
|
399
|
+
await nextAuthAdapter.createSession(data);
|
400
|
+
const updatedExpires = new Date();
|
401
|
+
expect(nextAuthAdapter).toBeDefined();
|
402
|
+
expect(nextAuthAdapter.updateSession).toBeDefined();
|
403
|
+
// @ts-expect-error: updateSession is defined
|
404
|
+
const updatedSession = await nextAuthAdapter.updateSession({
|
405
|
+
sessionToken,
|
406
|
+
expires: updatedExpires,
|
407
|
+
});
|
408
|
+
expect(updatedSession).toBeDefined();
|
409
|
+
expect(updatedSession?.sessionToken).toBe(data.sessionToken);
|
410
|
+
expect(updatedSession?.expires).toEqual(updatedExpires);
|
411
|
+
});
|
412
|
+
});
|
413
|
+
|
414
|
+
describe('getSessionAndUser', () => {
|
415
|
+
it('should get a session and user', async () => {
|
416
|
+
// create session
|
417
|
+
const data = {
|
418
|
+
sessionToken,
|
419
|
+
userId: userId,
|
420
|
+
expires: new Date(),
|
421
|
+
};
|
422
|
+
// @ts-expect-error: createSession is defined
|
423
|
+
await nextAuthAdapter.createSession(data);
|
424
|
+
|
425
|
+
// @ts-expect-error: getSessionAndUser is defined
|
426
|
+
const sessionAndUser = await nextAuthAdapter.getSessionAndUser(sessionToken);
|
427
|
+
expect(sessionAndUser?.session.sessionToken).toBe(sessionToken);
|
428
|
+
expect(sessionAndUser?.user.id).toBe(user.id);
|
429
|
+
});
|
430
|
+
});
|
431
|
+
|
432
|
+
describe('deleteSession', () => {
|
433
|
+
it('should delete a session', async () => {
|
434
|
+
const data = {
|
435
|
+
sessionToken,
|
436
|
+
userId: userId,
|
437
|
+
expires: new Date(),
|
438
|
+
};
|
439
|
+
// @ts-expect-error: createSession is defined
|
440
|
+
await nextAuthAdapter.createSession(data);
|
441
|
+
|
442
|
+
// @ts-expect-error: deleteSession is defined
|
443
|
+
await nextAuthAdapter.deleteSession(sessionToken);
|
444
|
+
const session = await serverDB.query.nextauthSessions.findFirst({
|
445
|
+
where: eq(nextauthSessions.sessionToken, sessionToken),
|
446
|
+
});
|
447
|
+
expect(session).toBeUndefined();
|
448
|
+
});
|
449
|
+
});
|
450
|
+
});
|
451
|
+
|
452
|
+
describe('verificationToken', () => {
|
453
|
+
describe('createVerificationToken', () => {
|
454
|
+
it('should create a new verification token', async () => {
|
455
|
+
const token: VerificationToken = {
|
456
|
+
identifier: 'identifier',
|
457
|
+
expires: new Date(),
|
458
|
+
token: 'token',
|
459
|
+
};
|
460
|
+
// @ts-expect-error: createVerificationToken is defined
|
461
|
+
const createdToken = await nextAuthAdapter.createVerificationToken(token);
|
462
|
+
expect(createdToken).toBeDefined();
|
463
|
+
expect(createdToken?.identifier).toBe(token.identifier);
|
464
|
+
expect(createdToken?.expires).toEqual(token.expires);
|
465
|
+
expect(createdToken?.token).toBe(token.token);
|
466
|
+
});
|
467
|
+
});
|
468
|
+
|
469
|
+
describe('useVerificationToken', () => {
|
470
|
+
it('should use a verification token if exist', async () => {
|
471
|
+
const token: VerificationToken = {
|
472
|
+
identifier: 'identifier',
|
473
|
+
expires: new Date(),
|
474
|
+
token: 'token2',
|
475
|
+
};
|
476
|
+
// @ts-expect-error: createVerificationToken is defined
|
477
|
+
await nextAuthAdapter.createVerificationToken(token);
|
478
|
+
// @ts-expect-error: useVerificationToken is defined
|
479
|
+
await nextAuthAdapter.useVerificationToken(token.token);
|
480
|
+
});
|
481
|
+
|
482
|
+
it('should return null if the token does not exist', async () => {
|
483
|
+
const token: VerificationToken = {
|
484
|
+
identifier: 'identifier',
|
485
|
+
expires: new Date(),
|
486
|
+
token: 'token-not-exist',
|
487
|
+
};
|
488
|
+
// @ts-expect-error: useVerificationToken is defined
|
489
|
+
const result = await nextAuthAdapter.useVerificationToken(token.token);
|
490
|
+
expect(result).toBeNull();
|
491
|
+
});
|
492
|
+
});
|
493
|
+
});
|
494
|
+
|
495
|
+
describe('accounts', () => {
|
496
|
+
describe('linkAccount', () => {
|
497
|
+
it('should link an account', async () => {
|
498
|
+
const account: AdapterAccount = {
|
499
|
+
providerAccountId: 'provider-account-id',
|
500
|
+
userId: userId,
|
501
|
+
provider: 'auth0',
|
502
|
+
type: 'email',
|
503
|
+
};
|
504
|
+
// @ts-expect-error: linkAccount is defined
|
505
|
+
const insertedAccount = await nextAuthAdapter.linkAccount(account);
|
506
|
+
expect(insertedAccount).toBeDefined();
|
507
|
+
expect(insertedAccount?.providerAccountId).toBe(account.providerAccountId);
|
508
|
+
expect(insertedAccount?.userId).toBe(userId);
|
509
|
+
expect(insertedAccount?.provider).toBe(account.provider);
|
510
|
+
expect(insertedAccount?.type).toBe(account.type);
|
511
|
+
});
|
512
|
+
});
|
513
|
+
|
514
|
+
describe('getAccount', () => {
|
515
|
+
it('should get an account', async () => {
|
516
|
+
const account: AdapterAccount = {
|
517
|
+
providerAccountId: 'provider-account-id',
|
518
|
+
userId: userId,
|
519
|
+
provider: 'auth0',
|
520
|
+
type: 'email',
|
521
|
+
};
|
522
|
+
// @ts-expect-error: linkAccount is defined
|
523
|
+
await nextAuthAdapter.linkAccount(account);
|
524
|
+
// @ts-expect-error: getAccount is defined
|
525
|
+
const fetchedAccount = await nextAuthAdapter.getAccount(
|
526
|
+
account.providerAccountId,
|
527
|
+
account.provider,
|
528
|
+
);
|
529
|
+
expect(fetchedAccount).toBeDefined();
|
530
|
+
expect(fetchedAccount?.providerAccountId).toBe(account.providerAccountId);
|
531
|
+
expect(fetchedAccount?.userId).toBe(userId);
|
532
|
+
expect(fetchedAccount?.provider).toBe(account.provider);
|
533
|
+
expect(fetchedAccount?.type).toBe(account.type);
|
534
|
+
});
|
535
|
+
});
|
536
|
+
|
537
|
+
describe('unlinkAccount', () => {
|
538
|
+
it('should unlink an account', async () => {
|
539
|
+
const account: AdapterAccount = {
|
540
|
+
providerAccountId: 'provider-account-id',
|
541
|
+
userId: userId,
|
542
|
+
provider: 'auth0',
|
543
|
+
type: 'email',
|
544
|
+
};
|
545
|
+
// @ts-expect-error: linkAccount is defined
|
546
|
+
await nextAuthAdapter.linkAccount(account);
|
547
|
+
// @ts-expect-error: unlinkAccount is defined
|
548
|
+
await nextAuthAdapter.unlinkAccount(account);
|
549
|
+
const fetchedAccount = await serverDB.query.nextauthAccounts.findFirst({
|
550
|
+
where: eq(nextauthAccounts.providerAccountId, account.providerAccountId),
|
551
|
+
});
|
552
|
+
expect(fetchedAccount).toBeUndefined();
|
553
|
+
});
|
554
|
+
});
|
555
|
+
});
|
556
|
+
});
|
@@ -12,9 +12,9 @@ export const getUserAuth = async () => {
|
|
12
12
|
}
|
13
13
|
|
14
14
|
if (enableNextAuth) {
|
15
|
-
const { default:
|
15
|
+
const { default: NextAuthEdge } = await import('@/libs/next-auth/edge');
|
16
16
|
|
17
|
-
const session = await
|
17
|
+
const session = await NextAuthEdge.auth();
|
18
18
|
|
19
19
|
const userId = session?.user.id;
|
20
20
|
|
@@ -36,15 +36,6 @@ export const POST = async (req: Request): Promise<NextResponse> => {
|
|
36
36
|
},
|
37
37
|
);
|
38
38
|
}
|
39
|
-
case 'User.SuspensionStatus.Updated': {
|
40
|
-
if (data.isSuspended) {
|
41
|
-
return nextAuthUserService.safeSignOutUser({
|
42
|
-
provider: 'logto',
|
43
|
-
providerAccountId: data.id,
|
44
|
-
});
|
45
|
-
}
|
46
|
-
return NextResponse.json({ message: 'user reactivated', success: true }, { status: 200 });
|
47
|
-
}
|
48
39
|
|
49
40
|
default: {
|
50
41
|
pino.warn(
|
package/src/config/auth.ts
CHANGED
@@ -18,8 +18,6 @@ declare global {
|
|
18
18
|
|
19
19
|
NEXT_AUTH_DEBUG?: string;
|
20
20
|
|
21
|
-
NEXT_AUTH_SSO_SESSION_STRATEGY?: string;
|
22
|
-
|
23
21
|
AUTH0_CLIENT_ID?: string;
|
24
22
|
AUTH0_CLIENT_SECRET?: string;
|
25
23
|
AUTH0_ISSUER?: string;
|
@@ -161,7 +159,6 @@ export const getAuthConfig = () => {
|
|
161
159
|
NEXT_AUTH_SECRET: z.string().optional(),
|
162
160
|
NEXT_AUTH_SSO_PROVIDERS: z.string().optional().default('auth0'),
|
163
161
|
NEXT_AUTH_DEBUG: z.boolean().optional().default(false),
|
164
|
-
NEXT_AUTH_SSO_SESSION_STRATEGY: z.enum(['jwt', 'database']).optional().default('jwt'),
|
165
162
|
|
166
163
|
// Auth0
|
167
164
|
AUTH0_CLIENT_ID: z.string().optional(),
|
@@ -224,7 +221,6 @@ export const getAuthConfig = () => {
|
|
224
221
|
NEXT_AUTH_SSO_PROVIDERS: process.env.NEXT_AUTH_SSO_PROVIDERS,
|
225
222
|
NEXT_AUTH_SECRET: process.env.NEXT_AUTH_SECRET,
|
226
223
|
NEXT_AUTH_DEBUG: !!process.env.NEXT_AUTH_DEBUG,
|
227
|
-
NEXT_AUTH_SSO_SESSION_STRATEGY: process.env.NEXT_AUTH_SSO_SESSION_STRATEGY || 'jwt',
|
228
224
|
|
229
225
|
// Auth0
|
230
226
|
AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID,
|