@lobehub/chat 1.69.2 → 1.69.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 +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +2 -2
- package/src/app/[variants]/(auth)/next-auth/signin/AuthSignInBox.tsx +161 -0
- package/src/app/[variants]/(auth)/next-auth/signin/page.tsx +11 -0
- package/src/app/[variants]/(main)/profile/(home)/features/SSOProvidersList/index.tsx +1 -1
- package/src/{app/[variants]/(main)/profile/(home)/features/SSOProvidersList → components/NextAuth}/AuthIcons.tsx +8 -6
- package/src/libs/next-auth/auth.config.ts +1 -0
- package/src/middleware.ts +1 -1
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.69.3](https://github.com/lobehub/lobe-chat/compare/v1.69.2...v1.69.3)
|
6
|
+
|
7
|
+
<sup>Released on **2025-03-08**</sup>
|
8
|
+
|
9
|
+
#### 💄 Styles
|
10
|
+
|
11
|
+
- **misc**: Add login ui for next-auth.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### Styles
|
19
|
+
|
20
|
+
- **misc**: Add login ui for next-auth, closes [#6434](https://github.com/lobehub/lobe-chat/issues/6434) ([541f275](https://github.com/lobehub/lobe-chat/commit/541f275))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
### [Version 1.69.2](https://github.com/lobehub/lobe-chat/compare/v1.69.1...v1.69.2)
|
6
31
|
|
7
32
|
<sup>Released on **2025-03-07**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.69.
|
3
|
+
"version": "1.69.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",
|
@@ -165,7 +165,7 @@
|
|
165
165
|
"epub2": "^3.0.2",
|
166
166
|
"fast-deep-equal": "^3.1.3",
|
167
167
|
"file-type": "^20.0.0",
|
168
|
-
"framer-motion": "^
|
168
|
+
"framer-motion": "^12.0.0",
|
169
169
|
"gpt-tokenizer": "^2.8.1",
|
170
170
|
"html-to-text": "^9.0.5",
|
171
171
|
"i18next": "^24.2.1",
|
@@ -0,0 +1,161 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { LobeChat } from '@lobehub/ui/brand';
|
4
|
+
import { Button, Col, Flex, Row, Skeleton, Typography } from 'antd';
|
5
|
+
import { createStyles } from 'antd-style';
|
6
|
+
import { AuthError } from 'next-auth';
|
7
|
+
import { signIn } from 'next-auth/react';
|
8
|
+
import { useRouter, useSearchParams } from 'next/navigation';
|
9
|
+
import { memo } from 'react';
|
10
|
+
import { useTranslation } from 'react-i18next';
|
11
|
+
|
12
|
+
import BrandWatermark from '@/components/BrandWatermark';
|
13
|
+
import AuthIcons from '@/components/NextAuth/AuthIcons';
|
14
|
+
import { DOCUMENTS_REFER_URL, PRIVACY_URL, TERMS_URL } from '@/const/url';
|
15
|
+
import { useUserStore } from '@/store/user';
|
16
|
+
|
17
|
+
const { Title, Paragraph } = Typography;
|
18
|
+
|
19
|
+
const useStyles = createStyles(({ css, token }) => ({
|
20
|
+
button: css`
|
21
|
+
text-transform: capitalize;
|
22
|
+
`,
|
23
|
+
container: css`
|
24
|
+
min-width: 360px;
|
25
|
+
border: 1px solid ${token.colorBorder};
|
26
|
+
border-radius: ${token.borderRadiusLG}px;
|
27
|
+
background: ${token.colorBgContainer};
|
28
|
+
`,
|
29
|
+
contentCard: css`
|
30
|
+
padding-block: 2.5rem;
|
31
|
+
padding-inline: 2rem;
|
32
|
+
`,
|
33
|
+
description: css`
|
34
|
+
margin: 0;
|
35
|
+
color: ${token.colorTextSecondary};
|
36
|
+
`,
|
37
|
+
footer: css`
|
38
|
+
padding: 1rem;
|
39
|
+
border-block-start: 1px solid ${token.colorBorder};
|
40
|
+
border-radius: 0 0 8px 8px;
|
41
|
+
|
42
|
+
color: ${token.colorTextDescription};
|
43
|
+
|
44
|
+
background: ${token.colorBgElevated};
|
45
|
+
`,
|
46
|
+
text: css`
|
47
|
+
text-align: center;
|
48
|
+
`,
|
49
|
+
title: css`
|
50
|
+
margin: 0;
|
51
|
+
color: ${token.colorTextHeading};
|
52
|
+
`,
|
53
|
+
}));
|
54
|
+
|
55
|
+
const BtnListLoading = memo(() => {
|
56
|
+
return (
|
57
|
+
<Flex gap={'small'} vertical>
|
58
|
+
<Skeleton.Button active style={{ minWidth: 300 }} />
|
59
|
+
<Skeleton.Button active style={{ minWidth: 300 }} />
|
60
|
+
<Skeleton.Button active style={{ minWidth: 300 }} />
|
61
|
+
</Flex>
|
62
|
+
);
|
63
|
+
});
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Follow the implementation from AuthJS official documentation,
|
67
|
+
* but using client components.
|
68
|
+
* ref: https://authjs.dev/guides/pages/signin
|
69
|
+
*/
|
70
|
+
export default memo(() => {
|
71
|
+
const { styles } = useStyles();
|
72
|
+
const { t } = useTranslation('clerk');
|
73
|
+
const router = useRouter();
|
74
|
+
|
75
|
+
const oAuthSSOProviders = useUserStore((s) => s.oAuthSSOProviders);
|
76
|
+
|
77
|
+
const searchParams = useSearchParams();
|
78
|
+
|
79
|
+
// Redirect back to the page url
|
80
|
+
const callbackUrl = searchParams.get('callbackUrl') ?? '';
|
81
|
+
|
82
|
+
const handleSignIn = async (provider: string) => {
|
83
|
+
try {
|
84
|
+
await signIn(provider, { redirectTo: callbackUrl });
|
85
|
+
} catch (error) {
|
86
|
+
// Signin can fail for a number of reasons, such as the user
|
87
|
+
// not existing, or the user not having the correct role.
|
88
|
+
// In some cases, you may want to redirect to a custom error
|
89
|
+
if (error instanceof AuthError) {
|
90
|
+
return router.push(`/next-auth/?error=${error.type}`);
|
91
|
+
}
|
92
|
+
|
93
|
+
// Otherwise if a redirects happens Next.js can handle it
|
94
|
+
// so you can just re-thrown the error and let Next.js handle it.
|
95
|
+
// Docs: https://nextjs.org/docs/app/api-reference/functions/redirect#server-component
|
96
|
+
throw error;
|
97
|
+
}
|
98
|
+
};
|
99
|
+
|
100
|
+
const footerBtns = [
|
101
|
+
{ href: DOCUMENTS_REFER_URL, id: 0, label: t('footerPageLink__help') },
|
102
|
+
{ href: PRIVACY_URL, id: 1, label: t('footerPageLink__privacy') },
|
103
|
+
{ href: TERMS_URL, id: 2, label: t('footerPageLink__terms') },
|
104
|
+
];
|
105
|
+
|
106
|
+
return (
|
107
|
+
<div className={styles.container}>
|
108
|
+
<div className={styles.contentCard}>
|
109
|
+
{/* Card Body */}
|
110
|
+
<Flex gap="large" vertical>
|
111
|
+
{/* Header */}
|
112
|
+
<div className={styles.text}>
|
113
|
+
<Title className={styles.title} level={4}>
|
114
|
+
<div>
|
115
|
+
<LobeChat size={48} />
|
116
|
+
</div>
|
117
|
+
{t('signIn.start.title', { applicationName: 'LobeChat' })}
|
118
|
+
</Title>
|
119
|
+
<Paragraph className={styles.description}>{t('signIn.start.subtitle')}</Paragraph>
|
120
|
+
</div>
|
121
|
+
{/* Content */}
|
122
|
+
<Flex gap="small" vertical>
|
123
|
+
{oAuthSSOProviders ? (
|
124
|
+
oAuthSSOProviders.map((provider) => (
|
125
|
+
<Button
|
126
|
+
className={styles.button}
|
127
|
+
icon={AuthIcons(provider, 16)}
|
128
|
+
key={provider}
|
129
|
+
onClick={() => handleSignIn(provider)}
|
130
|
+
>
|
131
|
+
{provider}
|
132
|
+
</Button>
|
133
|
+
))
|
134
|
+
) : (
|
135
|
+
<BtnListLoading />
|
136
|
+
)}
|
137
|
+
</Flex>
|
138
|
+
</Flex>
|
139
|
+
</div>
|
140
|
+
<div className={styles.footer}>
|
141
|
+
{/* Footer */}
|
142
|
+
<Row>
|
143
|
+
<Col span={12}>
|
144
|
+
<Flex justify="left" style={{ height: '100%' }}>
|
145
|
+
<BrandWatermark />
|
146
|
+
</Flex>
|
147
|
+
</Col>
|
148
|
+
<Col offset={4} span={8}>
|
149
|
+
<Flex justify="right">
|
150
|
+
{footerBtns.map((btn) => (
|
151
|
+
<Button key={btn.id} onClick={() => router.push(btn.href)} size="small" type="text">
|
152
|
+
{btn.label}
|
153
|
+
</Button>
|
154
|
+
))}
|
155
|
+
</Flex>
|
156
|
+
</Col>
|
157
|
+
</Row>
|
158
|
+
</div>
|
159
|
+
</div>
|
160
|
+
);
|
161
|
+
});
|
@@ -10,7 +10,7 @@ import { userService } from '@/services/user';
|
|
10
10
|
import { useUserStore } from '@/store/user';
|
11
11
|
import { userProfileSelectors } from '@/store/user/selectors';
|
12
12
|
|
13
|
-
import AuthIcons from '
|
13
|
+
import AuthIcons from '@/components/NextAuth/AuthIcons';
|
14
14
|
|
15
15
|
const { Item } = List;
|
16
16
|
|
@@ -12,10 +12,6 @@ import {
|
|
12
12
|
} from '@lobehub/ui/icons';
|
13
13
|
import React from 'react';
|
14
14
|
|
15
|
-
const iconProps = {
|
16
|
-
size: 32,
|
17
|
-
};
|
18
|
-
|
19
15
|
const iconComponents: { [key: string]: React.ElementType } = {
|
20
16
|
'auth0': Auth0,
|
21
17
|
'authelia': Authelia.Color,
|
@@ -29,9 +25,15 @@ const iconComponents: { [key: string]: React.ElementType } = {
|
|
29
25
|
'zitadel': Zitadel.Color,
|
30
26
|
};
|
31
27
|
|
32
|
-
|
28
|
+
/**
|
29
|
+
* Get the auth icons component for the given id
|
30
|
+
* @param id
|
31
|
+
* @param size default is 36
|
32
|
+
* @returns
|
33
|
+
*/
|
34
|
+
const AuthIcons = (id: string, size = 36) => {
|
33
35
|
const IconComponent = iconComponents[id] || iconComponents.default;
|
34
|
-
return <IconComponent {
|
36
|
+
return <IconComponent size={size}/>;
|
35
37
|
};
|
36
38
|
|
37
39
|
export default AuthIcons;
|