From 59bb76d3fc86fb39e6ad4e3a5f53c3df9092f476 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Fri, 23 May 2025 16:45:48 +0800 Subject: [PATCH] feat(session): sign out and revoke root token --- public/locales/en-US/application.json | 1 + public/locales/ja-JP/application.json | 1 + public/locales/zh-CN/application.json | 1 + public/locales/zh-TW/application.json | 1 + src/api/api.ts | 18 ++++++++++++++++++ src/component/Frame/NavBar/UserAction.tsx | 6 ++---- src/redux/thunks/session.ts | 22 +++++++++++++++++++++- 7 files changed, 45 insertions(+), 5 deletions(-) diff --git a/public/locales/en-US/application.json b/public/locales/en-US/application.json index 5f77206..e49a2e5 100644 --- a/public/locales/en-US/application.json +++ b/public/locales/en-US/application.json @@ -48,6 +48,7 @@ "continue": "Next", "back": "Back", "logout": "Sign out", + "signingOut": "Signing out...", "loggedOut": "You are signed out now.", "clickToRefresh": "Click to refresh" }, diff --git a/public/locales/ja-JP/application.json b/public/locales/ja-JP/application.json index 19f37c6..43b66fd 100644 --- a/public/locales/ja-JP/application.json +++ b/public/locales/ja-JP/application.json @@ -49,6 +49,7 @@ "continue": "次へ", "back": "前へ", "logout": "ログアウト", + "signingOut": "ログアウト中...", "loggedOut": "ログアウトしました", "clickToRefresh": "CAPTCHAを再読み込み" }, diff --git a/public/locales/zh-CN/application.json b/public/locales/zh-CN/application.json index 584d053..a0ea859 100644 --- a/public/locales/zh-CN/application.json +++ b/public/locales/zh-CN/application.json @@ -49,6 +49,7 @@ "continue": "下一步", "back": "上一步", "logout": "退出登录", + "signingOut": "正在退出登录...", "loggedOut": "您已退出登录", "clickToRefresh": "点击刷新验证码" }, diff --git a/public/locales/zh-TW/application.json b/public/locales/zh-TW/application.json index 8f43d56..8f5957e 100644 --- a/public/locales/zh-TW/application.json +++ b/public/locales/zh-TW/application.json @@ -49,6 +49,7 @@ "continue": "下一步", "back": "上一步", "logout": "退出登入", + "signingOut": "正在退出登入...", "loggedOut": "您已退出登入", "clickToRefresh": "點選重新整理驗證碼" }, diff --git a/src/api/api.ts b/src/api/api.ts index 2513ef4..9256c8c 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -231,6 +231,24 @@ export function sendRefreshToken(req: RefreshTokenRequest): ThunkResponse }; } +export function sendSignout(req: RefreshTokenRequest): ThunkResponse { + return async (dispatch, _getState) => { + return await dispatch( + send( + "/session/token", + { + data: req, + method: "DELETE", + }, + { + ...defaultOpts, + noCredential: true, + }, + ), + ); + }; +} + export function getFileList(req: ListFileService, skipSnackbar = true): ThunkResponse { return async (dispatch, _getState) => { return await dispatch( diff --git a/src/component/Frame/NavBar/UserAction.tsx b/src/component/Frame/NavBar/UserAction.tsx index 8b1dbd1..ab79422 100644 --- a/src/component/Frame/NavBar/UserAction.tsx +++ b/src/component/Frame/NavBar/UserAction.tsx @@ -18,8 +18,8 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { GroupPermission } from "../../../api/user.ts"; -import { closeMusicPlayer } from "../../../redux/globalStateSlice.ts"; import { useAppDispatch } from "../../../redux/hooks.ts"; +import { signout } from "../../../redux/thunks/session.ts"; import SessionManager, { Session } from "../../../session"; import { GroupBS } from "../../../session/utils.ts"; import UserAvatar from "../../Common/User/UserAvatar.tsx"; @@ -55,9 +55,7 @@ const UserPopover = ({ open, onClose, ...rest }: PopoverProps) => { }; const signOut = useCallback(() => { - SessionManager.signOutCurrent(); - dispatch(closeMusicPlayer()); - navigate("/session"); + dispatch(signout()); onClose && onClose({}, "backdropClick"); }, []); diff --git a/src/redux/thunks/session.ts b/src/redux/thunks/session.ts index a5ea818..295f5b3 100644 --- a/src/redux/thunks/session.ts +++ b/src/redux/thunks/session.ts @@ -1,11 +1,12 @@ import i18next from "i18next"; -import { getUserInfo } from "../../api/api.ts"; +import { getUserInfo, sendSignout } from "../../api/api.ts"; import { LoginResponse, User } from "../../api/user.ts"; import { router } from "../../router"; import SessionManager, { UserSettings } from "../../session"; import { refreshTimeZone } from "../../util/datetime.ts"; import { clearSessionCache } from "../fileManagerSlice.ts"; import { + closeMusicPlayer, setDarkMode, setDrawerWidth, setPolicyOptionCache, @@ -13,6 +14,7 @@ import { setUserInfoCache, } from "../globalStateSlice.ts"; import { AppThunk } from "../store.ts"; +import { longRunningTaskWithSnackbar } from "./file.ts"; import { updateSiteConfig } from "./site.ts"; export function refreshUserSession(session: LoginResponse, redirect: string | null): AppThunk { @@ -56,3 +58,21 @@ export function loadUserInfo(uid: string): AppThunk> { return user; }; } + +export function signout(): AppThunk { + return async (dispatch, _getState) => { + const current = SessionManager.currentLoginOrNull(); + if (!current) { + return; + } + + await longRunningTaskWithSnackbar( + dispatch(sendSignout({ refresh_token: current.token.refresh_token })), + "application:login.signingOut", + ); + + router.navigate("/session"); + dispatch(closeMusicPlayer()); + SessionManager.signOutCurrent(); + }; +}