From e05dd650ab4bc37df1edcf4884326a46baec5362 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Thu, 14 May 2026 00:48:15 +0800 Subject: [PATCH] feat(auth): add legacy password login failure message and FAQ guidance for upgrade issues --- astrbot/dashboard/routes/auth.py | 9 +++++++ docs/en/faq.md | 12 +++++++++ docs/zh/faq.md | 12 +++++++++ tests/test_dashboard.py | 42 ++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) diff --git a/astrbot/dashboard/routes/auth.py b/astrbot/dashboard/routes/auth.py index a9ba692ba..2824f7ee6 100644 --- a/astrbot/dashboard/routes/auth.py +++ b/astrbot/dashboard/routes/auth.py @@ -38,6 +38,13 @@ DEFAULT_PASSWORD_LOGIN_FAILURE_MESSAGE = ( "随机强密码。请使用日志中提供的的初始密码来登录。了解更多:" "https://docs.astrbot.app/faq.html" ) +LEGACY_PASSWORD_LOGIN_FAILURE_MESSAGE = ( + "Incorrect username or password. If you cannot log in after upgrading " + "AstrBot even though the password is correct, see " + "https://docs.astrbot.app/en/faq.html\n\n" + "用户名或密码错误。如果你在升级 AstrBot 后遇到了密码正确但无法登录的情况," + "请参考 https://docs.astrbot.app/faq.html" +) class AuthRoute(Route): @@ -181,6 +188,8 @@ class AuthRoute(Route): await asyncio.sleep(3) if req_password == "astrbot": return Response().error(DEFAULT_PASSWORD_LOGIN_FAILURE_MESSAGE).__dict__ + if is_legacy_dashboard_password(password): + return Response().error(LEGACY_PASSWORD_LOGIN_FAILURE_MESSAGE).__dict__ return Response().error("用户名或密码错误").__dict__ async def logout(self): diff --git a/docs/en/faq.md b/docs/en/faq.md index e0dc7307d..c9f0b10f9 100644 --- a/docs/en/faq.md +++ b/docs/en/faq.md @@ -70,6 +70,18 @@ The segment should look like: After restart, AstrBot will automatically generate a random password with the fixed username `astrbot`; check the startup logs. +### Correct Password Cannot Log In After Upgrading AstrBot + +If you are sure the dashboard password is correct but still cannot log in after upgrading AstrBot, the old WebUI static files may be incompatible with the newer backend. + +Solution: + +1. Stop AstrBot. +2. Delete the `dist` folder under AstrBot's `data` directory: `AstrBot/data/dist`. +3. Restart AstrBot. + +After restart, AstrBot will reload or download WebUI files that match the current version. + ## Bot Core Related ### How to Let AstrBot Control My Mac / Windows / Linux Computer? diff --git a/docs/zh/faq.md b/docs/zh/faq.md index 64792747d..e7a230b07 100644 --- a/docs/zh/faq.md +++ b/docs/zh/faq.md @@ -71,6 +71,18 @@ Set dashboard.host in data/cmd_config.json to enable remote access. 重启后 AstrBot 将会自动生成随机的密码以及固定的用户名 `astrbot`,请在日志查看。 +### 升级 AstrBot 后密码正确但无法登录 + +如果你确认管理面板密码正确,但升级 AstrBot 后仍然无法登录,可能是旧版 WebUI 静态文件缓存与新版后端不兼容。 + +解决方案: + +1. 停止 AstrBot。 +2. 删除 AstrBot 的 `data` 目录下的 `dist` 文件夹,即 `AstrBot/data/dist`。 +3. 重新启动 AstrBot。 + +重启后,AstrBot 会重新加载或下载匹配当前版本的 WebUI 文件。 + ## AstrBot 使用相关 ### 如何让 AstrBot 控制我的 Mac / Windows / Linux 电脑? diff --git a/tests/test_dashboard.py b/tests/test_dashboard.py index 295b8c1e5..3957a87d8 100644 --- a/tests/test_dashboard.py +++ b/tests/test_dashboard.py @@ -413,6 +413,48 @@ async def test_legacy_md5_dashboard_password_keeps_legacy_auth_until_edit( ) +@pytest.mark.asyncio +async def test_legacy_md5_login_failure_includes_upgrade_faq_hint( + app: Quart, + core_lifecycle_td: AstrBotCoreLifecycle, +): + original_dashboard_config = copy.deepcopy( + core_lifecycle_td.astrbot_config["dashboard"] + ) + test_client = app.test_client() + legacy_password = "AstrbotLegacy123" + + try: + core_lifecycle_td.astrbot_config["dashboard"]["username"] = "astrbot" + core_lifecycle_td.astrbot_config["dashboard"]["password"] = ( + hash_legacy_dashboard_password(legacy_password) + ) + core_lifecycle_td.astrbot_config["dashboard"]["pbkdf2_password"] = "" + await _set_dashboard_password_change_required(core_lifecycle_td, False) + await set_password_storage_upgraded( + core_lifecycle_td.db, + core_lifecycle_td.astrbot_config, + False, + ) + + response = await test_client.post( + "/api/auth/login", + json={"username": "astrbot", "password": "WrongPassword123"}, + ) + data = await response.get_json() + + assert data["status"] == "error" + assert data["message"].startswith("Incorrect username or password.") + assert "用户名或密码错误" in data["message"] + assert "https://docs.astrbot.app/en/faq.html" in data["message"] + assert "https://docs.astrbot.app/faq.html" in data["message"] + finally: + await _restore_dashboard_password_state( + core_lifecycle_td, + original_dashboard_config, + ) + + @pytest.mark.asyncio async def test_password_storage_flag_repairs_after_rollback_clears_pbkdf2( app: Quart,