feat(auth): persist login provider for restored sessions
This commit is contained in:
@@ -11,9 +11,10 @@
|
||||
* - 浏览器 → `localStorage` driver;SSR → memory driver(unstorage 自动)
|
||||
* - 单例挂在 class 静态字段,规避 HMR 复用污染
|
||||
* - `hasXxx` = `token != null && token.length > 0`,对齐 Dart 端 `isNotEmpty` 语义
|
||||
* - `clearAuthData` 顺序清理:loginToken → guestToken → refreshToken,任一失败立即返回
|
||||
* - `clearAuthData` 顺序清理:loginToken → loginProvider → guestToken → refreshToken,任一失败立即返回
|
||||
*/
|
||||
|
||||
import { LoginStatus, type LoginStatus as LoginStatusT } from "@/data/dto/auth";
|
||||
import { Result, type Result as ResultT, SpAsyncUtil } from "@/utils";
|
||||
import { StorageKeys } from "../storage_keys";
|
||||
import type { IAuthStorage } from "./iauth_storage";
|
||||
@@ -48,6 +49,22 @@ export class AuthStorage implements IAuthStorage {
|
||||
return SpAsyncUtil.remove(StorageKeys.loginToken);
|
||||
}
|
||||
|
||||
// ---- login provider ----
|
||||
|
||||
async getLoginProvider(): Promise<ResultT<LoginStatusT | null>> {
|
||||
const r = await SpAsyncUtil.getString(StorageKeys.loginProvider);
|
||||
if (!r.success) return Result.err(r.error);
|
||||
if (r.data === null || r.data.length === 0) return Result.ok(null);
|
||||
if (isLoginStatus(r.data)) return Result.ok(r.data);
|
||||
return Result.ok(null);
|
||||
}
|
||||
setLoginProvider(provider: LoginStatusT): Promise<ResultT<void>> {
|
||||
return SpAsyncUtil.setString(StorageKeys.loginProvider, provider);
|
||||
}
|
||||
clearLoginProvider(): Promise<ResultT<void>> {
|
||||
return SpAsyncUtil.remove(StorageKeys.loginProvider);
|
||||
}
|
||||
|
||||
// ---- guest token ----
|
||||
|
||||
getGuestToken(): Promise<ResultT<string | null>> {
|
||||
@@ -103,10 +120,16 @@ export class AuthStorage implements IAuthStorage {
|
||||
async clearAuthData(): Promise<ResultT<void>> {
|
||||
const r1 = await this.clearLoginToken();
|
||||
if (!r1.success) return r1;
|
||||
const r2 = await this.clearGuestToken();
|
||||
const r2 = await this.clearLoginProvider();
|
||||
if (!r2.success) return r2;
|
||||
const r3 = await this.clearRefreshToken();
|
||||
const r3 = await this.clearGuestToken();
|
||||
if (!r3.success) return r3;
|
||||
const r4 = await this.clearRefreshToken();
|
||||
if (!r4.success) return r4;
|
||||
return this.clearFacebookId();
|
||||
}
|
||||
}
|
||||
|
||||
function isLoginStatus(value: string): value is LoginStatusT {
|
||||
return Object.values(LoginStatus).includes(value as LoginStatusT);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
* IAuthStorage 接口
|
||||
*
|
||||
* 对齐 Dart 端 `IAuthStorage`(lib/data/services/storage/iauth_storage.dart):
|
||||
* - loginToken / guestToken / deviceId / refreshToken / facebookId 五个字段的 CRUD
|
||||
* - loginToken / loginProvider / guestToken / deviceId / refreshToken / facebookId 字段的 CRUD
|
||||
* - `clearAuthData()` 批量清空登录态
|
||||
* - 所有方法返回 `Promise<Result<T>>`,与 Dart `Future<Result<T>>` 对齐
|
||||
*/
|
||||
|
||||
import type { Result } from "@/utils";
|
||||
import type { LoginStatus } from "@/data/dto/auth";
|
||||
|
||||
export interface IAuthStorage {
|
||||
getLoginToken(): Promise<Result<string | null>>;
|
||||
@@ -17,6 +18,10 @@ export interface IAuthStorage {
|
||||
hasLoginToken(): Promise<Result<boolean>>;
|
||||
clearLoginToken(): Promise<Result<void>>;
|
||||
|
||||
getLoginProvider(): Promise<Result<LoginStatus | null>>;
|
||||
setLoginProvider(provider: LoginStatus): Promise<Result<void>>;
|
||||
clearLoginProvider(): Promise<Result<void>>;
|
||||
|
||||
getGuestToken(): Promise<Result<string | null>>;
|
||||
setGuestToken(token: string): Promise<Result<void>>;
|
||||
hasGuestToken(): Promise<Result<boolean>>;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
export const StorageKeys = {
|
||||
// auth
|
||||
loginToken: "login_token",
|
||||
loginProvider: "login_provider",
|
||||
guestToken: "guest_token",
|
||||
deviceId: "device_id",
|
||||
refreshToken: "refresh_token",
|
||||
|
||||
Reference in New Issue
Block a user