@lobehub/chat 1.19.10 → 1.19.12

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.

Potentially problematic release.


This version of @lobehub/chat might be problematic. Click here for more details.

package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.19.12](https://github.com/lobehub/lobe-chat/compare/v1.19.11...v1.19.12)
6
+
7
+ <sup>Released on **2024-09-20**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Support webhooks for casdoor.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Support webhooks for casdoor, closes [#3942](https://github.com/lobehub/lobe-chat/issues/3942) ([1f2f6a5](https://github.com/lobehub/lobe-chat/commit/1f2f6a5))
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
+
30
+ ### [Version 1.19.11](https://github.com/lobehub/lobe-chat/compare/v1.19.10...v1.19.11)
31
+
32
+ <sup>Released on **2024-09-20**</sup>
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - **misc**: Custom model initialization not taking effect error.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's fixed
44
+
45
+ - **misc**: Custom model initialization not taking effect error, closes [#4038](https://github.com/lobehub/lobe-chat/issues/4038) ([0e0d208](https://github.com/lobehub/lobe-chat/commit/0e0d208))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 1.19.10](https://github.com/lobehub/lobe-chat/compare/v1.19.9...v1.19.10)
6
56
 
7
57
  <sup>Released on **2024-09-20**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.19.10",
3
+ "version": "1.19.12",
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,60 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ interface User {
4
+ name: string;
5
+ id: string;
6
+ type: 'normal-user' | 'admin' | 'super-admin';
7
+ displayName: string;
8
+ firstName: string;
9
+ lastName: string;
10
+ avatar: string;
11
+ email: string;
12
+ emailVerified: boolean;
13
+ }
14
+
15
+ interface UserDataUpdatedEvent {
16
+ user: string; // 用户名
17
+ action: 'update-user';
18
+ extendedUser: User; // 扩展用户信息
19
+ }
20
+
21
+ const userDataUpdatedEvent: UserDataUpdatedEvent = {
22
+ user: 'admin',
23
+ action: 'update-user',
24
+ extendedUser: {
25
+ name: 'admin',
26
+ id: '35edace3-00c6-41e1-895e-97c519b1d8cc',
27
+ type: 'normal-user',
28
+ displayName: 'Admin',
29
+ firstName: '',
30
+ lastName: '',
31
+ avatar: 'https://cdn.casbin.org/img/casbin.svg',
32
+ email: 'admin@example.cn',
33
+ emailVerified: false,
34
+ },
35
+ };
36
+
37
+ const AUTH_CASDOOR_WEBHOOK_SECRET = 'casdoor-secret';
38
+
39
+ // Test Casdoor Webhooks in Local dev, here is some tips:
40
+ // - Replace the var `AUTH_CASDOOR_WETHOOK_SECRET` with the actual value in your `.env` file
41
+ // - Start web request: If you want to run the test, replace `describe.skip` with `describe` below
42
+ // - Run this test with command:
43
+ // pnpm vitest --run --testNamePattern='^ ?Test Casdoor Webhooks in Local dev' src/app/api/webhooks/casdoor/__tests__/route.test.ts
44
+
45
+ describe.skip('Test Casdoor Webhooks in Local dev', () => {
46
+ // describe('Test Casdoor Webhooks in Local dev', () => {
47
+ it('should send a POST request with casdoor headers', async () => {
48
+ const url = 'http://localhost:3010/api/webhooks/casdoor'; // 替换为目标URL
49
+ const data = userDataUpdatedEvent;
50
+ const response = await fetch(url, {
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ 'casdoor-secret': AUTH_CASDOOR_WEBHOOK_SECRET,
55
+ },
56
+ body: JSON.stringify(data),
57
+ });
58
+ expect(response.status).toBe(200); // 检查响应状态
59
+ });
60
+ });
@@ -0,0 +1,40 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ import { authEnv } from '@/config/auth';
4
+ import { pino } from '@/libs/logger';
5
+ import { NextAuthUserService } from '@/server/services/nextAuthUser';
6
+
7
+ import { validateRequest } from './validateRequest';
8
+
9
+ export const POST = async (req: Request): Promise<NextResponse> => {
10
+ const payload = await validateRequest(req, authEnv.CASDOOR_WEBHOOK_SECRET);
11
+
12
+ if (!payload) {
13
+ return NextResponse.json(
14
+ { error: 'webhook verification failed or payload was malformed' },
15
+ { status: 400 },
16
+ );
17
+ }
18
+
19
+ const { action, extendedUser } = payload;
20
+
21
+ pino.trace(`casdoor webhook payload: ${{ action, extendedUser }}`);
22
+
23
+ const nextAuthUserService = new NextAuthUserService();
24
+ switch (action) {
25
+ case 'update-user': {
26
+ return nextAuthUserService.safeUpdateUser(extendedUser.id, {
27
+ avatar: extendedUser?.avatar,
28
+ email: extendedUser?.email,
29
+ fullName: extendedUser.displayName,
30
+ });
31
+ }
32
+
33
+ default: {
34
+ pino.warn(
35
+ `${req.url} received event type "${action}", but no handler is defined for this type`,
36
+ );
37
+ return NextResponse.json({ error: `unrecognised payload type: ${action}` }, { status: 400 });
38
+ }
39
+ }
40
+ };
@@ -0,0 +1,38 @@
1
+ import { headers } from 'next/headers';
2
+
3
+ import { authEnv } from '@/config/auth';
4
+
5
+ export type CasdoorUserEntity = {
6
+ avatar?: string;
7
+ displayName: string;
8
+ email?: string;
9
+ id: string;
10
+ };
11
+
12
+ interface CasdoorWebhookPayload {
13
+ action: string;
14
+ // Only support user event currently
15
+ extendedUser: CasdoorUserEntity;
16
+ }
17
+
18
+ export const validateRequest = async (request: Request, secret?: string) => {
19
+ const payloadString = await request.text();
20
+ const headerPayload = headers();
21
+ const casdoorSecret = headerPayload.get('casdoor-secret')!;
22
+ try {
23
+ if (casdoorSecret === secret) {
24
+ return JSON.parse(payloadString) as CasdoorWebhookPayload;
25
+ } else {
26
+ console.warn(
27
+ '[Casdoor]: secret verify failed, please check your secret in `CASDOOR_WEBHOOK_SECRET`',
28
+ );
29
+ return;
30
+ }
31
+ } catch (e) {
32
+ if (!authEnv.CASDOOR_WEBHOOK_SECRET) {
33
+ throw new Error('`CASDOOR_WEBHOOK_SECRET` environment variable is missing.');
34
+ }
35
+ console.error('[Casdoor]: incoming webhook failed in verification.\n', e);
36
+ return;
37
+ }
38
+ };
@@ -201,6 +201,9 @@ export const getAuthConfig = () => {
201
201
  LOGTO_CLIENT_SECRET: z.string().optional(),
202
202
  LOGTO_ISSUER: z.string().optional(),
203
203
  LOGTO_WEBHOOK_SIGNING_KEY: z.string().optional(),
204
+
205
+ // Casdoor
206
+ CASDOOR_WEBHOOK_SECRET: z.string().optional(),
204
207
  },
205
208
 
206
209
  runtimeEnv: {
@@ -259,6 +262,9 @@ export const getAuthConfig = () => {
259
262
  LOGTO_CLIENT_SECRET: process.env.LOGTO_CLIENT_SECRET,
260
263
  LOGTO_ISSUER: process.env.LOGTO_ISSUER,
261
264
  LOGTO_WEBHOOK_SIGNING_KEY: process.env.LOGTO_WEBHOOK_SIGNING_KEY,
265
+
266
+ // Casdoor
267
+ CASDOOR_WEBHOOK_SECRET: process.env.CASDOOR_WEBHOOK_SECRET,
262
268
  },
263
269
  });
264
270
  };
@@ -0,0 +1,49 @@
1
+ import { OIDCConfig, OIDCUserConfig } from '@auth/core/providers';
2
+
3
+ import { CommonProviderConfig } from './sso.config';
4
+
5
+ interface CasdoorProfile extends Record<string, any> {
6
+ avatar: string;
7
+ displayName: string;
8
+ email: string;
9
+ emailVerified: boolean;
10
+ firstName: string;
11
+ id: string;
12
+ lastName: string;
13
+ name: string;
14
+ owner: string;
15
+ permanentAvatar: string;
16
+ }
17
+
18
+ function LobeCasdoorProvider(config: OIDCUserConfig<CasdoorProfile>): OIDCConfig<CasdoorProfile> {
19
+ return {
20
+ ...CommonProviderConfig,
21
+ ...config,
22
+ id: 'casdoor',
23
+ name: 'Casdoor',
24
+ profile(profile) {
25
+ return {
26
+ email: profile.email,
27
+ emailVerified: profile.emailVerified ? new Date() : null,
28
+ image: profile.avatar,
29
+ name: profile.displayName ?? profile.firstName ?? profile.lastName,
30
+ providerAccountId: profile.id,
31
+ };
32
+ },
33
+ type: 'oidc',
34
+ };
35
+ }
36
+
37
+ const provider = {
38
+ id: 'casdoor',
39
+ provider: LobeCasdoorProvider({
40
+ authorization: {
41
+ params: { scope: 'openid profile email' },
42
+ },
43
+ clientId: process.env.AUTH_CASDOOR_ID,
44
+ clientSecret: process.env.AUTH_CASDOOR_SECRET,
45
+ issuer: process.env.AUTH_CASDOOR_ISSUER,
46
+ }),
47
+ };
48
+
49
+ export default provider;
@@ -2,10 +2,22 @@ import Auth0 from './auth0';
2
2
  import Authelia from './authelia';
3
3
  import Authentik from './authentik';
4
4
  import AzureAD from './azure-ad';
5
+ import Casdoor from './casdoor';
5
6
  import CloudflareZeroTrust from './cloudflare-zero-trust';
6
7
  import GenericOIDC from './generic-oidc';
7
8
  import Github from './github';
8
9
  import Logto from './logto';
9
10
  import Zitadel from './zitadel';
10
11
 
11
- export const ssoProviders = [Auth0, Authentik, AzureAD, GenericOIDC, Github, Zitadel, Authelia, Logto, CloudflareZeroTrust];
12
+ export const ssoProviders = [
13
+ Auth0,
14
+ Authentik,
15
+ AzureAD,
16
+ GenericOIDC,
17
+ Github,
18
+ Zitadel,
19
+ Authelia,
20
+ Logto,
21
+ CloudflareZeroTrust,
22
+ Casdoor,
23
+ ];
@@ -173,6 +173,7 @@ export const getServerGlobalConfig = () => {
173
173
  },
174
174
  ollama: {
175
175
  enabled: ENABLED_OLLAMA,
176
+ enabledModels: extractEnabledModels(OLLAMA_MODEL_LIST),
176
177
  fetchOnClient: !OLLAMA_PROXY_URL,
177
178
  serverModelCards: transformToChatModelCards({
178
179
  defaultChatModels: OllamaProviderCard.chatModels,