文件
hyb-oa/client/src/auth/authService.ts
T

109 行
2.8 KiB
TypeScript

import { apiRequestData } from "../api/http";
import { verifyEmailLoginCode } from "../api/auth";
import type { LoginRequest, LoginResponse, MeResponse } from "../api/types";
import { getDeviceFingerprint } from "./deviceFingerprint";
const JSON_HEADERS = {
"content-type": "application/json",
};
const REFRESH_SUCCESS_REPLAY_MS = 1000;
let refreshSessionPromise: Promise<LoginResponse> | null = null;
let refreshSessionReplay: { data: LoginResponse; expiresAt: number } | null = null;
let refreshSessionGeneration = 0;
export function resetRefreshSessionCache() {
refreshSessionGeneration += 1;
refreshSessionPromise = null;
refreshSessionReplay = null;
}
export async function loginWithPassword(payload: LoginRequest) {
resetRefreshSessionCache();
return apiRequestData<LoginResponse>("/api/auth/login", {
method: "POST",
auth: false,
retryOn401: false,
headers: {
...JSON_HEADERS,
"x-device-fingerprint": getDeviceFingerprint(),
},
body: JSON.stringify(payload),
});
}
export async function loginWithEmailCode(payload: { email: string; code: string }) {
resetRefreshSessionCache();
return verifyEmailLoginCode(payload);
}
async function requestRefreshSession() {
return apiRequestData<LoginResponse>("/api/auth/refresh", {
method: "POST",
auth: false,
retryOn401: false,
headers: {
"x-device-fingerprint": getDeviceFingerprint(),
},
});
}
export async function refreshSession() {
const now = Date.now();
if (refreshSessionReplay && refreshSessionReplay.expiresAt > now) {
return refreshSessionReplay.data;
}
if (!refreshSessionPromise) {
const generation = refreshSessionGeneration;
const requestPromise = requestRefreshSession()
.then((data) => {
if (generation === refreshSessionGeneration) {
refreshSessionReplay = {
data,
expiresAt: Date.now() + REFRESH_SUCCESS_REPLAY_MS,
};
}
return data;
})
.catch((error: unknown) => {
if (generation === refreshSessionGeneration) {
refreshSessionReplay = null;
}
throw error;
});
refreshSessionPromise = requestPromise;
void requestPromise
.finally(() => {
if (refreshSessionPromise === requestPromise) {
refreshSessionPromise = null;
}
})
.catch(() => undefined);
}
return refreshSessionPromise;
}
export async function logoutSession() {
try {
return await apiRequestData<Record<string, never>>("/api/auth/logout", {
method: "POST",
auth: false,
retryOn401: false,
});
} finally {
resetRefreshSessionCache();
}
}
export async function fetchCurrentEmployee(accessToken: string) {
return apiRequestData<MeResponse>("/api/me", {
auth: true,
retryOn401: false,
accessTokenOverride: accessToken,
});
}