@lobehub/chat 1.80.2 → 1.80.3

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 CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.80.3](https://github.com/lobehub/lobe-chat/compare/v1.80.2...v1.80.3)
6
+
7
+ <sup>Released on **2025-04-16**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Refactor to get user info from api.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Refactor to get user info from api, closes [#7444](https://github.com/lobehub/lobe-chat/issues/7444) ([4c1fb4a](https://github.com/lobehub/lobe-chat/commit/4c1fb4a))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 1.80.2](https://github.com/lobehub/lobe-chat/compare/v1.80.1...v1.80.2)
6
31
 
7
32
  <sup>Released on **2025-04-16**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Refactor to get user info from api."
6
+ ]
7
+ },
8
+ "date": "2025-04-16",
9
+ "version": "1.80.3"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "fixes": [
package/next.config.ts CHANGED
@@ -33,8 +33,12 @@ const nextConfig: NextConfig = {
33
33
  '@lobehub/ui',
34
34
  'gpt-tokenizer',
35
35
  ],
36
+ // oidc provider depend on constructor.name
37
+ // but swc minification will remove the name
38
+ // so we need to disable it
39
+ // refs: https://github.com/lobehub/lobe-chat/pull/7430
40
+ serverMinification: false,
36
41
  webVitalsAttribution: ['CLS', 'LCP'],
37
- webpackMemoryOptimizations: true,
38
42
  },
39
43
  async headers() {
40
44
  return [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.80.2",
3
+ "version": "1.80.3",
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",
@@ -62,10 +62,15 @@ export class UserModel {
62
62
  getUserState = async (decryptor: DecryptUserKeyVaults) => {
63
63
  const result = await this.db
64
64
  .select({
65
+ avatar: users.avatar,
66
+ email: users.email,
67
+ firstName: users.firstName,
68
+ fullName: users.fullName,
65
69
  isOnboarded: users.isOnboarded,
70
+ lastName: users.lastName,
66
71
  preference: users.preference,
67
-
68
72
  settingsDefaultAgent: userSettings.defaultAgent,
73
+
69
74
  settingsGeneral: userSettings.general,
70
75
  settingsHotkey: userSettings.hotkey,
71
76
  settingsKeyVaults: userSettings.keyVaults,
@@ -73,6 +78,7 @@ export class UserModel {
73
78
  settingsSystemAgent: userSettings.systemAgent,
74
79
  settingsTTS: userSettings.tts,
75
80
  settingsTool: userSettings.tool,
81
+ username: users.username,
76
82
  })
77
83
  .from(users)
78
84
  .where(eq(users.id, this.userId))
@@ -105,10 +111,16 @@ export class UserModel {
105
111
  };
106
112
 
107
113
  return {
114
+ avatar: state.avatar || undefined,
115
+ email: state.email || undefined,
116
+ firstName: state.firstName || undefined,
117
+ fullName: state.fullName || undefined,
108
118
  isOnboarded: state.isOnboarded,
119
+ lastName: state.lastName || undefined,
109
120
  preference: state.preference as UserPreference,
110
121
  settings,
111
122
  userId: this.userId,
123
+ username: state.username || undefined,
112
124
  };
113
125
  };
114
126
 
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useSession } from 'next-auth/react';
4
- import { memo } from 'react';
4
+ import { memo, useEffect } from 'react';
5
5
  import { createStoreUpdater } from 'zustand-utils';
6
6
 
7
7
  import { useUserStore } from '@/store/user';
@@ -17,20 +17,27 @@ const UserUpdater = memo(() => {
17
17
  const nextUser = session?.user;
18
18
  const useStoreUpdater = createStoreUpdater(useUserStore);
19
19
 
20
- const lobeUser = {
21
- avatar: nextUser?.image,
22
- email: nextUser?.email,
23
- fullName: nextUser?.name,
24
- id: nextUser?.id,
25
- } as LobeUser;
26
-
27
20
  useStoreUpdater('isLoaded', isLoaded);
28
- useStoreUpdater('user', lobeUser);
29
21
  useStoreUpdater('isSignedIn', isSignedIn);
30
-
31
22
  useStoreUpdater('nextSession', session);
32
- useStoreUpdater('nextUser', nextUser);
33
23
 
24
+ // 使用 useEffect 处理需要保持同步的用户数据
25
+ useEffect(() => {
26
+ if (nextUser) {
27
+ const userAvatar = useUserStore.getState().user?.avatar;
28
+
29
+ const lobeUser = {
30
+ // 头像使用设置的,而不是从 next-auth 中获取
31
+ avatar: userAvatar || '',
32
+ email: nextUser.email,
33
+ fullName: nextUser.name,
34
+ id: nextUser.id,
35
+ } as LobeUser;
36
+
37
+ // 更新用户相关数据
38
+ useUserStore.setState({ nextUser: nextUser, user: lobeUser });
39
+ }
40
+ }, [nextUser]);
34
41
  return null;
35
42
  });
36
43
 
@@ -22,9 +22,10 @@ class OIDCAdapter {
22
22
  private name: string;
23
23
 
24
24
  constructor(name: string, db: LobeChatDatabase) {
25
+ log('[%s] Constructor called with name: %s', name, name);
26
+
25
27
  this.name = name;
26
28
  this.db = db;
27
- log('Creating adapter for model: %s', name);
28
29
  }
29
30
 
30
31
  /**
@@ -530,12 +531,10 @@ class OIDCAdapter {
530
531
  /**
531
532
  * 创建适配器工厂
532
533
  */
533
- static createAdapterFactory(db: LobeChatDatabase) {
534
+ static createAdapterFactory = (db: LobeChatDatabase) => {
534
535
  log('Creating adapter factory with database instance');
535
- return function (name: string) {
536
- return new OIDCAdapter(name, db);
537
- };
538
- }
536
+ return (name: string) => new OIDCAdapter(name, db);
537
+ };
539
538
  }
540
539
 
541
540
  export { OIDCAdapter as DrizzleAdapter };
@@ -272,6 +272,7 @@ export const createOIDCProvider = async (db: LobeChatDatabase): Promise<Provider
272
272
  const baseUrl = urlJoin(appEnv.APP_URL!, '/oidc');
273
273
 
274
274
  const provider = new Provider(baseUrl, configuration);
275
+ provider.proxy = true;
275
276
 
276
277
  provider.on('server_error', (ctx, err) => {
277
278
  logProvider('OIDC Provider Server Error: %O', err); // Use logProvider
@@ -85,17 +85,24 @@ export const userRouter = router({
85
85
  const hasExtraSession = await sessionModel.hasMoreThanN(1);
86
86
 
87
87
  return {
88
+ avatar: state.avatar,
88
89
  canEnablePWAGuide: hasMoreThan4Messages,
89
90
  canEnableTrace: hasMoreThan4Messages,
91
+ email: state.email,
92
+ firstName: state.firstName,
93
+
94
+ fullName: state.fullName,
95
+
90
96
  // 有消息,或者创建过助手,则认为有 conversation
91
97
  hasConversation: hasAnyMessages || hasExtraSession,
92
-
93
98
  // always return true for community version
94
99
  isOnboard: state.isOnboarded || true,
100
+ lastName: state.lastName,
95
101
  preference: state.preference as UserPreference,
96
102
  settings: state.settings,
97
103
  userId: ctx.userId,
98
- };
104
+ username: state.username,
105
+ } satisfies UserInitializationState;
99
106
  }),
100
107
 
101
108
  makeUserOnboarded: userProcedure.mutation(async ({ ctx }) => {
@@ -39,18 +39,21 @@ export class ClientService extends BaseClientService implements IUserService {
39
39
  encryptKeyVaultsStr ? JSON.parse(encryptKeyVaultsStr) : {},
40
40
  );
41
41
 
42
- const user = await UserModel.findById(clientDB as any, this.userId);
43
42
  const messageCount = await this.messageModel.count();
44
43
  const sessionCount = await this.sessionModel.count();
45
44
 
46
45
  return {
47
46
  ...state,
48
- avatar: user?.avatar as string,
47
+ avatar: state.avatar ?? '',
49
48
  canEnablePWAGuide: messageCount >= 4,
50
49
  canEnableTrace: messageCount >= 4,
50
+ firstName: state.firstName,
51
+ fullName: state.fullName,
51
52
  hasConversation: messageCount > 0 || sessionCount > 0,
52
53
  isOnboard: true,
54
+ lastName: state.lastName,
53
55
  preference: await this.preferenceStorage.getFromLocalStorage(),
56
+ username: state.username,
54
57
  };
55
58
  };
56
59
 
@@ -7,7 +7,7 @@ import { useOnlyFetchOnceSWR } from '@/libs/swr';
7
7
  import { userService } from '@/services/user';
8
8
  import type { UserStore } from '@/store/user';
9
9
  import type { GlobalServerConfig } from '@/types/serverConfig';
10
- import { UserInitializationState } from '@/types/user';
10
+ import { LobeUser, UserInitializationState } from '@/types/user';
11
11
  import type { UserSettings } from '@/types/user/settings';
12
12
  import { merge } from '@/utils/merge';
13
13
  import { setNamespace } from '@/utils/storeDebug';
@@ -91,7 +91,14 @@ export const createCommonSlice: StateCreator<
91
91
  // if there is avatar or userId (from client DB), update it into user
92
92
  const user =
93
93
  data.avatar || data.userId
94
- ? merge(get().user, { avatar: data.avatar, id: data.userId })
94
+ ? merge(get().user, {
95
+ avatar: data.avatar,
96
+ firstName: data.firstName,
97
+ fullName: data.fullName,
98
+ id: data.userId,
99
+ latestName: data.lastName,
100
+ username: data.username,
101
+ } as LobeUser)
95
102
  : get().user;
96
103
 
97
104
  set(
@@ -48,14 +48,19 @@ export interface UserInitializationState {
48
48
  avatar?: string;
49
49
  canEnablePWAGuide?: boolean;
50
50
  canEnableTrace?: boolean;
51
+ email?: string;
52
+ firstName?: string;
53
+ fullName?: string;
51
54
  hasConversation?: boolean;
52
55
  isOnboard?: boolean;
56
+ lastName?: string;
53
57
  preference: UserPreference;
54
58
  settings: DeepPartial<UserSettings>;
55
59
  userId?: string;
60
+ username?: string;
56
61
  }
57
62
 
58
63
  export const NextAuthAccountSchame = z.object({
59
64
  provider: z.string(),
60
65
  providerAccountId: z.string(),
61
- });
66
+ });