diff --git a/napcat.webui/src/controllers/webui_manager.ts b/napcat.webui/src/controllers/webui_manager.ts index dfd3e741..6c17b2f9 100644 --- a/napcat.webui/src/controllers/webui_manager.ts +++ b/napcat.webui/src/controllers/webui_manager.ts @@ -33,6 +33,14 @@ export default class WebUIManager { return data.data } + public static async changePasswordFromDefault(newToken: string) { + const { data } = await serverRequest.post>( + '/auth/update_token', + { newToken, fromDefault: true } + ) + return data.data + } + public static async checkUsingDefaultToken() { const { data } = await serverRequest.get>( '/auth/check_using_default_token' diff --git a/napcat.webui/src/pages/dashboard/config/change_password.tsx b/napcat.webui/src/pages/dashboard/config/change_password.tsx index 08dc84d0..3e3ed307 100644 --- a/napcat.webui/src/pages/dashboard/config/change_password.tsx +++ b/napcat.webui/src/pages/dashboard/config/change_password.tsx @@ -1,5 +1,6 @@ import { Input } from '@heroui/input' import { useLocalStorage } from '@uidotdev/usehooks' +import { useEffect, useState } from 'react' import { Controller, useForm } from 'react-hook-form' import toast from 'react-hot-toast' import { useNavigate } from 'react-router-dom' @@ -11,6 +12,9 @@ import SaveButtons from '@/components/button/save_buttons' import WebUIManager from '@/controllers/webui_manager' const ChangePasswordCard = () => { + const [isDefaultToken, setIsDefaultToken] = useState(false) + const [isLoadingCheck, setIsLoadingCheck] = useState(true) + const { control, handleSubmit: handleWebuiSubmit, @@ -29,9 +33,32 @@ const ChangePasswordCard = () => { const navigate = useNavigate() const [_, setToken] = useLocalStorage(key.token, '') + // 检查是否使用默认密码 + useEffect(() => { + const checkDefaultToken = async () => { + try { + const isDefault = await WebUIManager.checkUsingDefaultToken() + setIsDefaultToken(isDefault) + } catch (error) { + console.error('检查默认密码状态失败:', error) + } finally { + setIsLoadingCheck(false) + } + } + + checkDefaultToken() + }, []) + const onSubmit = handleWebuiSubmit(async (data) => { try { - await WebUIManager.changePassword(data.oldToken, data.newToken) + if (isDefaultToken) { + // 从默认密码更新 + await WebUIManager.changePasswordFromDefault(data.newToken) + } else { + // 正常密码更新 + await WebUIManager.changePassword(data.oldToken, data.newToken) + } + toast.success('修改成功') setToken('') localStorage.removeItem(key.token) @@ -42,33 +69,57 @@ const ChangePasswordCard = () => { } }) + if (isLoadingCheck) { + return ( + <> + 修改密码 - NapCat WebUI +
+
加载中...
+
+ + ) + } + return ( <> 修改密码 - NapCat WebUI - ( - - )} - /> + + {isDefaultToken && ( +
+

+ 检测到您正在使用默认密码,为了安全起见,请立即设置新密码。 +

+
+ )} + + {!isDefaultToken && ( + ( + + )} + /> + )} + ( )} /> + (token || '') const [isLoading, setIsLoading] = useState(false) const [, setLocalToken] = useLocalStorage(key.token, '') - const onSubmit = async () => { if (!tokenValue) { toast.error('请输入token') diff --git a/src/webui/src/api/Auth.ts b/src/webui/src/api/Auth.ts index 96fd3834..0022eaca 100644 --- a/src/webui/src/api/Auth.ts +++ b/src/webui/src/api/Auth.ts @@ -93,11 +93,16 @@ export const checkHandler: RequestHandler = async (req, res) => { // 修改密码(token) export const UpdateTokenHandler: RequestHandler = async (req, res) => { - const { oldToken, newToken } = req.body; + const { oldToken, newToken, fromDefault } = req.body; const authorization = req.headers.authorization; - if (isEmpty(oldToken) || isEmpty(newToken)) { - return sendError(res, 'oldToken or newToken is empty'); + if (isEmpty(newToken)) { + return sendError(res, 'newToken is empty'); + } + + // 如果不是从默认密码更新,则需要验证旧密码 + if (!fromDefault && isEmpty(oldToken)) { + return sendError(res, 'oldToken is required when not updating from default password'); } try { @@ -108,7 +113,18 @@ export const UpdateTokenHandler: RequestHandler = async (req, res) => { AuthHelper.revokeCredential(Credential); } - await WebUiConfig.UpdateToken(oldToken, newToken); + if (fromDefault) { + // 从默认密码更新,直接设置新密码 + const currentConfig = await WebUiConfig.GetWebUIConfig(); + if (!currentConfig.defaultToken) { + return sendError(res, 'Current password is not default password'); + } + await WebUiConfig.UpdateWebUIConfig({ token: newToken, defaultToken: false }); + } else { + // 正常的密码更新流程 + await WebUiConfig.UpdateToken(oldToken, newToken); + } + return sendSuccess(res, 'Token updated successfully'); } catch (e: any) { return sendError(res, `Failed to update token: ${e.message}`);