登录页UI及长时间未操作锁定逻辑优化
This commit is contained in:
@@ -25,6 +25,26 @@ let extendPromise: Promise<{ token: string | null; authFailed: boolean }> | null
|
||||
let initialized = false;
|
||||
const channel = typeof BroadcastChannel !== "undefined" ? new BroadcastChannel("ctms-auth") : null;
|
||||
|
||||
const getLastActiveAt = (session: ReturnType<typeof useSessionStore>) =>
|
||||
Math.max(session.lastUserActiveAt, session.lastNetworkActiveAt);
|
||||
|
||||
const reconcileSessionState = (now: number = Date.now()) => {
|
||||
const session = useSessionStore();
|
||||
if (session.locked) return false;
|
||||
const idleTimeoutMs = IDLE_TIMEOUT_MINUTES * 60 * 1000;
|
||||
const autoLogoutMs = AUTO_LOGOUT_TIMEOUT_HOURS * 60 * 60 * 1000;
|
||||
const lastActiveAt = getLastActiveAt(session);
|
||||
if (now - lastActiveAt > autoLogoutMs) {
|
||||
forceLogout(LOGOUT_REASON_TIMEOUT);
|
||||
return false;
|
||||
}
|
||||
if (now - lastActiveAt > idleTimeoutMs) {
|
||||
lockSession("idle");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const broadcast = (message: BroadcastMessage) => {
|
||||
if (channel) {
|
||||
channel.postMessage(message);
|
||||
@@ -81,9 +101,9 @@ const scheduleIdleCheck = () => {
|
||||
}
|
||||
const idleTimeoutMs = IDLE_TIMEOUT_MINUTES * 60 * 1000;
|
||||
const autoLogoutMs = AUTO_LOGOUT_TIMEOUT_HOURS * 60 * 60 * 1000;
|
||||
const baseActiveAt = Math.min(session.lastUserActiveAt, session.lastNetworkActiveAt);
|
||||
const idleRemain = baseActiveAt + idleTimeoutMs - now;
|
||||
const logoutRemain = baseActiveAt + autoLogoutMs - now;
|
||||
const lastActiveAt = getLastActiveAt(session);
|
||||
const idleRemain = lastActiveAt + idleTimeoutMs - now;
|
||||
const logoutRemain = lastActiveAt + autoLogoutMs - now;
|
||||
const nextCheck = Math.min(idleRemain, logoutRemain);
|
||||
if (nextCheck <= 0) {
|
||||
checkIdle();
|
||||
@@ -103,19 +123,7 @@ const checkIdle = () => {
|
||||
scheduleIdleCheck();
|
||||
return;
|
||||
}
|
||||
const idleTimeoutMs = IDLE_TIMEOUT_MINUTES * 60 * 1000;
|
||||
const autoLogoutMs = AUTO_LOGOUT_TIMEOUT_HOURS * 60 * 60 * 1000;
|
||||
const now = Date.now();
|
||||
const idleElapsed = now - session.lastUserActiveAt > idleTimeoutMs && now - session.lastNetworkActiveAt > idleTimeoutMs;
|
||||
const autoLogoutElapsed =
|
||||
now - session.lastUserActiveAt > autoLogoutMs && now - session.lastNetworkActiveAt > autoLogoutMs;
|
||||
if (autoLogoutElapsed) {
|
||||
forceLogout(LOGOUT_REASON_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
if (idleElapsed) {
|
||||
lockSession("idle");
|
||||
}
|
||||
if (!reconcileSessionState(Date.now())) return;
|
||||
scheduleIdleCheck();
|
||||
};
|
||||
|
||||
@@ -131,6 +139,14 @@ export const initSessionManager = () => {
|
||||
markUserActive(now);
|
||||
};
|
||||
events.forEach((event) => window.addEventListener(event, onUserActivity, { passive: true }));
|
||||
window.addEventListener("focus", () => {
|
||||
checkIdle();
|
||||
});
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (!document.hidden) {
|
||||
checkIdle();
|
||||
}
|
||||
});
|
||||
if (channel) {
|
||||
channel.onmessage = (event) => handleBroadcast(event.data as BroadcastMessage);
|
||||
}
|
||||
@@ -150,6 +166,7 @@ export const initSessionManager = () => {
|
||||
export const markUserActive = (at: number = Date.now()) => {
|
||||
const session = useSessionStore();
|
||||
if (session.locked) return;
|
||||
if (!reconcileSessionState(at)) return;
|
||||
session.recordUserActivity(at);
|
||||
broadcast({ type: "ACTIVE", at });
|
||||
scheduleIdleCheck();
|
||||
@@ -158,6 +175,7 @@ export const markUserActive = (at: number = Date.now()) => {
|
||||
export const markNetworkActive = (at: number = Date.now()) => {
|
||||
const session = useSessionStore();
|
||||
if (session.locked) return;
|
||||
if (!reconcileSessionState(at)) return;
|
||||
session.recordNetworkActivity(at);
|
||||
broadcast({ type: "NETWORK", at });
|
||||
scheduleIdleCheck();
|
||||
@@ -169,7 +187,7 @@ export const lockSession = (reason: "idle" | "extend_failed" | "token_invalid")
|
||||
if (session.locked) return;
|
||||
const email = auth.user?.email || "";
|
||||
const autoLogoutMs = AUTO_LOGOUT_TIMEOUT_HOURS * 60 * 60 * 1000;
|
||||
const deadlineAt = Math.min(session.lastUserActiveAt, session.lastNetworkActiveAt) + autoLogoutMs;
|
||||
const deadlineAt = getLastActiveAt(session) + autoLogoutMs;
|
||||
session.lock(reason, email, deadlineAt);
|
||||
broadcast({ type: "LOCK", reason, email, deadlineAt });
|
||||
scheduleIdleCheck();
|
||||
@@ -264,7 +282,7 @@ export const startTokenKeepAlive = () => {
|
||||
if (!expAt) return;
|
||||
const remaining = expAt - Date.now();
|
||||
const timeoutMs = IDLE_TIMEOUT_MINUTES * 60 * 1000;
|
||||
const active = Date.now() - session.lastUserActiveAt < timeoutMs || Date.now() - session.lastNetworkActiveAt < timeoutMs;
|
||||
const active = Date.now() - getLastActiveAt(session) < timeoutMs;
|
||||
if (active && remaining < EXTEND_EARLY_SECONDS * 1000) {
|
||||
void extendAccessToken("early");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user