diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index a99bd5a..2a737d2 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -35,6 +35,7 @@ import { Palette, Settings, Tv, + UserPlus, Users, Video, } from 'lucide-react'; @@ -4579,7 +4580,6 @@ const SiteConfigComponent = ({ const { alertModal, showAlert, hideAlert } = useAlertModal(); const { isLoading, withLoading } = useLoadingState(); const [showEnableCommentsModal, setShowEnableCommentsModal] = useState(false); - const [showEnableRegistrationModal, setShowEnableRegistrationModal] = useState(false); const [siteSettings, setSiteSettings] = useState({ SiteName: '', Announcement: '', @@ -4678,21 +4678,6 @@ const SiteConfigComponent = ({ DanmakuApiToken: config.SiteConfig.DanmakuApiToken || '87654321', TMDBApiKey: config.SiteConfig.TMDBApiKey || '', EnableComments: config.SiteConfig.EnableComments || false, - EnableRegistration: config.SiteConfig.EnableRegistration || false, - RegistrationRequireTurnstile: config.SiteConfig.RegistrationRequireTurnstile || false, - LoginRequireTurnstile: config.SiteConfig.LoginRequireTurnstile || false, - TurnstileSiteKey: config.SiteConfig.TurnstileSiteKey || '', - TurnstileSecretKey: config.SiteConfig.TurnstileSecretKey || '', - DefaultUserTags: config.SiteConfig.DefaultUserTags || [], - EnableOIDCLogin: config.SiteConfig.EnableOIDCLogin || false, - EnableOIDCRegistration: config.SiteConfig.EnableOIDCRegistration || false, - OIDCIssuer: config.SiteConfig.OIDCIssuer || '', - OIDCAuthorizationEndpoint: config.SiteConfig.OIDCAuthorizationEndpoint || '', - OIDCTokenEndpoint: config.SiteConfig.OIDCTokenEndpoint || '', - OIDCUserInfoEndpoint: config.SiteConfig.OIDCUserInfoEndpoint || '', - OIDCClientId: config.SiteConfig.OIDCClientId || '', - OIDCClientSecret: config.SiteConfig.OIDCClientSecret || '', - OIDCButtonText: config.SiteConfig.OIDCButtonText || '', }); } }, [config]); @@ -4771,29 +4756,6 @@ const SiteConfigComponent = ({ setShowEnableCommentsModal(false); }; - // 处理注册开关变化 - const handleRegistrationToggle = (checked: boolean) => { - if (checked) { - // 如果要开启注册,弹出确认框 - setShowEnableRegistrationModal(true); - } else { - // 直接关闭注册 - setSiteSettings((prev) => ({ - ...prev, - EnableRegistration: false, - })); - } - }; - - // 确认开启注册 - const handleConfirmEnableRegistration = () => { - setSiteSettings((prev) => ({ - ...prev, - EnableRegistration: true, - })); - setShowEnableRegistrationModal(false); - }; - // 保存站点配置 const handleSave = async () => { await withLoading('saveSiteConfig', async () => { @@ -5313,500 +5275,6 @@ const SiteConfigComponent = ({ - {/* 注册相关配置 */} -
-

- 注册配置 -

- - {/* 开启注册 */} -
-
- - -
-

- 开启后登录页面将显示注册按钮,允许用户自行注册账号。 -

-
- - {/* 注册启用Cloudflare Turnstile */} -
-
- - -
-

- 开启后注册时需要通过Cloudflare Turnstile人机验证。 -

-
- - {/* 登录启用Cloudflare Turnstile */} -
-
- - -
-

- 开启后登录时需要通过Cloudflare Turnstile人机验证。 -

-
- - {/* Cloudflare Turnstile Site Key */} -
- - - setSiteSettings((prev) => ({ - ...prev, - TurnstileSiteKey: e.target.value, - })) - } - className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> -

- 在Cloudflare Dashboard中获取的Site Key(公钥) -

-
- - {/* Cloudflare Turnstile Secret Key */} -
- - - setSiteSettings((prev) => ({ - ...prev, - TurnstileSecretKey: e.target.value, - })) - } - className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> -

- 在Cloudflare Dashboard中获取的Secret Key(私钥),用于服务端验证 -

-
- - {/* 默认用户组 */} -
- - -

- 新注册的用户将自动分配到选中的用户组,选择"无用户组"为无限制 -

-
-
- - {/* OIDC配置 */} -
-

- OIDC配置 -

- - {/* 启用OIDC登录 */} -
-
- - -
-

- 开启后登录页面将显示OIDC登录按钮 -

-
- - {/* 启用OIDC注册 */} -
-
- - -
-

- 开启后允许通过OIDC方式注册新用户(需要先启用OIDC登录) -

-
- - {/* OIDC Issuer */} -
- -
- - setSiteSettings((prev) => ({ - ...prev, - OIDCIssuer: e.target.value, - })) - } - className='flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> - -
-

- OIDC提供商的Issuer URL,填写后可点击"自动发现"按钮自动获取端点配置 -

-
- - {/* Authorization Endpoint */} -
- - - setSiteSettings((prev) => ({ - ...prev, - OIDCAuthorizationEndpoint: e.target.value, - })) - } - className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> -

- 用户授权的端点URL -

-
- - {/* Token Endpoint */} -
- - - setSiteSettings((prev) => ({ - ...prev, - OIDCTokenEndpoint: e.target.value, - })) - } - className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> -

- 交换授权码获取token的端点URL -

-
- - {/* UserInfo Endpoint */} -
- - - setSiteSettings((prev) => ({ - ...prev, - OIDCUserInfoEndpoint: e.target.value, - })) - } - className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> -

- 获取用户信息的端点URL -

-
- - {/* OIDC Client ID */} -
- - - setSiteSettings((prev) => ({ - ...prev, - OIDCClientId: e.target.value, - })) - } - className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> -

- 在OIDC提供商处注册应用后获得的Client ID -

-
- - {/* OIDC Client Secret */} -
- - - setSiteSettings((prev) => ({ - ...prev, - OIDCClientSecret: e.target.value, - })) - } - className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> -

- 在OIDC提供商处注册应用后获得的Client Secret -

-
- - {/* OIDC Redirect URI - 只读显示 */} -
- -
- - -
-

- 这是系统自动生成的回调地址,基于环境变量SITE_BASE。请在OIDC提供商(如Keycloak、Auth0等)的应用配置中添加此地址作为允许的重定向URI -

-
- - {/* OIDC登录按钮文字 */} -
- - - setSiteSettings((prev) => ({ - ...prev, - OIDCButtonText: e.target.value, - })) - } - className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' - /> -

- 自定义OIDC登录按钮显示的文字,如"使用企业账号登录"、"使用SSO登录"等。留空则显示默认文字"使用OIDC登录" -

-
-
- {/* 操作按钮 */}
+ ); +}; + +// 注册配置组件 +const RegistrationConfigComponent = ({ + config, + refreshConfig, +}: { + config: AdminConfig | null; + refreshConfig: () => Promise; +}) => { + const { alertModal, showAlert, hideAlert } = useAlertModal(); + const { isLoading, withLoading } = useLoadingState(); + const [showEnableRegistrationModal, setShowEnableRegistrationModal] = useState(false); + const [registrationSettings, setRegistrationSettings] = useState<{ + EnableRegistration: boolean; + RegistrationRequireTurnstile: boolean; + LoginRequireTurnstile: boolean; + TurnstileSiteKey: string; + TurnstileSecretKey: string; + DefaultUserTags: string[]; + EnableOIDCLogin: boolean; + EnableOIDCRegistration: boolean; + OIDCIssuer: string; + OIDCAuthorizationEndpoint: string; + OIDCTokenEndpoint: string; + OIDCUserInfoEndpoint: string; + OIDCClientId: string; + OIDCClientSecret: string; + OIDCButtonText: string; + }>({ + EnableRegistration: false, + RegistrationRequireTurnstile: false, + LoginRequireTurnstile: false, + TurnstileSiteKey: '', + TurnstileSecretKey: '', + DefaultUserTags: [], + EnableOIDCLogin: false, + EnableOIDCRegistration: false, + OIDCIssuer: '', + OIDCAuthorizationEndpoint: '', + OIDCTokenEndpoint: '', + OIDCUserInfoEndpoint: '', + OIDCClientId: '', + OIDCClientSecret: '', + OIDCButtonText: '', + }); + + useEffect(() => { + if (config?.SiteConfig) { + setRegistrationSettings({ + EnableRegistration: config.SiteConfig.EnableRegistration || false, + RegistrationRequireTurnstile: config.SiteConfig.RegistrationRequireTurnstile || false, + LoginRequireTurnstile: config.SiteConfig.LoginRequireTurnstile || false, + TurnstileSiteKey: config.SiteConfig.TurnstileSiteKey || '', + TurnstileSecretKey: config.SiteConfig.TurnstileSecretKey || '', + DefaultUserTags: config.SiteConfig.DefaultUserTags || [], + EnableOIDCLogin: config.SiteConfig.EnableOIDCLogin || false, + EnableOIDCRegistration: config.SiteConfig.EnableOIDCRegistration || false, + OIDCIssuer: config.SiteConfig.OIDCIssuer || '', + OIDCAuthorizationEndpoint: config.SiteConfig.OIDCAuthorizationEndpoint || '', + OIDCTokenEndpoint: config.SiteConfig.OIDCTokenEndpoint || '', + OIDCUserInfoEndpoint: config.SiteConfig.OIDCUserInfoEndpoint || '', + OIDCClientId: config.SiteConfig.OIDCClientId || '', + OIDCClientSecret: config.SiteConfig.OIDCClientSecret || '', + OIDCButtonText: config.SiteConfig.OIDCButtonText || '', + }); + } + }, [config]); + + // 处理注册开关变化 + const handleRegistrationToggle = (checked: boolean) => { + if (checked) { + setShowEnableRegistrationModal(true); + } else { + setRegistrationSettings((prev) => ({ + ...prev, + EnableRegistration: false, + })); + } + }; + + // 确认开启注册 + const handleConfirmEnableRegistration = () => { + setRegistrationSettings((prev) => ({ + ...prev, + EnableRegistration: true, + })); + setShowEnableRegistrationModal(false); + }; + + // 保存注册配置 + const handleSave = async () => { + await withLoading('saveRegistrationConfig', async () => { + try { + if (!config) { + throw new Error('配置未加载'); + } + + // 合并站点配置和注册配置 + const updatedSiteConfig = { + ...config.SiteConfig, + ...registrationSettings, + }; + + const resp = await fetch('/api/admin/site', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(updatedSiteConfig), + }); + + if (!resp.ok) { + const data = await resp.json().catch(() => ({})); + throw new Error(data.error || `保存失败: ${resp.status}`); + } + + showSuccess('保存成功, 请刷新页面', showAlert); + await refreshConfig(); + } catch (err) { + showError(err instanceof Error ? err.message : '保存失败', showAlert); + throw err; + } + }); + }; + + if (!config) { + return ( +
+ 加载中... +
+ ); + } + + return ( +
+ {/* 注册相关配置 */} +
+

+ 注册配置 +

+ + {/* 开启注册 */} +
+
+ + +
+

+ 开启后登录页面将显示注册按钮,允许用户自行注册账号。 +

+
+ + {/* 注册启用Cloudflare Turnstile */} +
+
+ + +
+

+ 开启后注册时需要通过Cloudflare Turnstile人机验证。 +

+
+ + {/* 登录启用Cloudflare Turnstile */} +
+
+ + +
+

+ 开启后登录时需要通过Cloudflare Turnstile人机验证。 +

+
+ + {/* Cloudflare Turnstile Site Key */} +
+ + + setRegistrationSettings((prev) => ({ + ...prev, + TurnstileSiteKey: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 在Cloudflare Dashboard中获取的Site Key(公钥) +

+
+ + {/* Cloudflare Turnstile Secret Key */} +
+ + + setRegistrationSettings((prev) => ({ + ...prev, + TurnstileSecretKey: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 在Cloudflare Dashboard中获取的Secret Key(私钥),用于服务端验证 +

+
+ + {/* 默认用户组 */} +
+ + +

+ 新注册的用户将自动分配到选中的用户组,选择"无用户组"为无限制 +

+
+
+ + {/* OIDC配置 */} +
+

+ OIDC配置 +

+ + {/* 启用OIDC登录 */} +
+
+ + +
+

+ 开启后登录页面将显示OIDC登录按钮 +

+
+ + {/* 启用OIDC注册 */} +
+
+ + +
+

+ 开启后允许通过OIDC方式注册新用户(需要先启用OIDC登录) +

+
+ + {/* OIDC Issuer */} +
+ +
+ + setRegistrationSettings((prev) => ({ + ...prev, + OIDCIssuer: e.target.value, + })) + } + className='flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> + +
+

+ OIDC提供商的Issuer URL,填写后可点击"自动发现"按钮自动获取端点配置 +

+
+ + {/* Authorization Endpoint */} +
+ + + setRegistrationSettings((prev) => ({ + ...prev, + OIDCAuthorizationEndpoint: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 用户授权的端点URL +

+
+ + {/* Token Endpoint */} +
+ + + setRegistrationSettings((prev) => ({ + ...prev, + OIDCTokenEndpoint: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 交换授权码获取token的端点URL +

+
+ + {/* UserInfo Endpoint */} +
+ + + setRegistrationSettings((prev) => ({ + ...prev, + OIDCUserInfoEndpoint: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 获取用户信息的端点URL +

+
+ + {/* OIDC Client ID */} +
+ + + setRegistrationSettings((prev) => ({ + ...prev, + OIDCClientId: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 在OIDC提供商处注册应用后获得的Client ID +

+
+ + {/* OIDC Client Secret */} +
+ + + setRegistrationSettings((prev) => ({ + ...prev, + OIDCClientSecret: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 在OIDC提供商处注册应用后获得的Client Secret +

+
+ + {/* OIDC Redirect URI - 只读显示 */} +
+ +
+ + +
+

+ 这是系统自动生成的回调地址,基于环境变量SITE_BASE。请在OIDC提供商(如Keycloak、Auth0等)的应用配置中添加此地址作为允许的重定向URI +

+
+ + {/* OIDC登录按钮文字 */} +
+ + + setRegistrationSettings((prev) => ({ + ...prev, + OIDCButtonText: e.target.value, + })) + } + className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent' + /> +

+ 自定义OIDC登录按钮显示的文字,如"使用企业账号登录"、"使用SSO登录"等。留空则显示默认文字"使用OIDC登录" +

+
+
+ + {/* 操作按钮 */} +
+ +
+ + {/* 通用弹窗组件 */} + {/* 开启注册确认弹窗 */} {showEnableRegistrationModal && @@ -5949,7 +6072,7 @@ const SiteConfigComponent = ({

- 为了您的安全和避免潜在的法律风险,如果您的网站部署在公网不建议开启。 + 为了您的安全和避免潜在的法律风险,如果您的网站部署在公网不建议开启。

@@ -6856,6 +6979,7 @@ function AdminPageClient() { videoSource: false, liveSource: false, siteConfig: false, + registrationConfig: false, categoryConfig: false, configFile: false, dataMigration: false, @@ -7008,6 +7132,21 @@ function AdminPageClient() { + {/* 注册配置标签 */} + + } + isExpanded={expandedTabs.registrationConfig} + onToggle={() => toggleTab('registrationConfig')} + > + + + {/* 主题配置标签 */}