feat(session): sign out and revoke root token

This commit is contained in:
Aaron Liu 2025-05-23 16:45:48 +08:00
parent 896fff5d30
commit 59bb76d3fc
7 changed files with 45 additions and 5 deletions

View File

@ -48,6 +48,7 @@
"continue": "Next",
"back": "Back",
"logout": "Sign out",
"signingOut": "Signing out...",
"loggedOut": "You are signed out now.",
"clickToRefresh": "Click to refresh"
},

View File

@ -49,6 +49,7 @@
"continue": "次へ",
"back": "前へ",
"logout": "ログアウト",
"signingOut": "ログアウト中...",
"loggedOut": "ログアウトしました",
"clickToRefresh": "CAPTCHAを再読み込み"
},

View File

@ -49,6 +49,7 @@
"continue": "下一步",
"back": "上一步",
"logout": "退出登录",
"signingOut": "正在退出登录...",
"loggedOut": "您已退出登录",
"clickToRefresh": "点击刷新验证码"
},

View File

@ -49,6 +49,7 @@
"continue": "下一步",
"back": "上一步",
"logout": "退出登入",
"signingOut": "正在退出登入...",
"loggedOut": "您已退出登入",
"clickToRefresh": "點選重新整理驗證碼"
},

View File

@ -231,6 +231,24 @@ export function sendRefreshToken(req: RefreshTokenRequest): ThunkResponse<Token>
};
}
export function sendSignout(req: RefreshTokenRequest): ThunkResponse<string> {
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<ListResponse> {
return async (dispatch, _getState) => {
return await dispatch(

View File

@ -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");
}, []);

View File

@ -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<Promise<User>> {
return user;
};
}
export function signout(): AppThunk<void> {
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();
};
}