feat(auth): mark test accounts in login requests
This commit is contained in:
@@ -8,7 +8,7 @@ import type { FetchHook } from "ofetch";
|
|||||||
import { ApiPath } from "../../../data/services/api/api_path";
|
import { ApiPath } from "../../../data/services/api/api_path";
|
||||||
import { ApiError, ErrorCode } from "../../../data/services/api/api_result";
|
import { ApiError, ErrorCode } from "../../../data/services/api/api_result";
|
||||||
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
||||||
import { deviceIdentifier, Result } from "@/utils";
|
import { AppEnvUtil, deviceIdentifier, Result } from "@/utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 不需要 auth token 刷新的路径
|
* 不需要 auth token 刷新的路径
|
||||||
@@ -105,7 +105,7 @@ async function refreshGuestToken(baseUrl: string): Promise<void> {
|
|||||||
const response = await fetch(`${baseUrl}${ApiPath.guestLogin}`, {
|
const response = await fetch(`${baseUrl}${ApiPath.guestLogin}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ deviceId }),
|
body: JSON.stringify(withTestAccountFlag({ deviceId })),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -125,6 +125,12 @@ async function refreshGuestToken(baseUrl: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function withTestAccountFlag<T extends Record<string, unknown>>(
|
||||||
|
payload: T,
|
||||||
|
): T & { isTestAccount: boolean } {
|
||||||
|
return { ...payload, isTestAccount: !AppEnvUtil.isProduction() };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 401 → 刷新 token 并重试
|
* 401 → 刷新 token 并重试
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
export class AppleLoginRequest {
|
export class AppleLoginRequest {
|
||||||
declare readonly identityToken: string;
|
declare readonly identityToken: string;
|
||||||
declare readonly platform: string;
|
declare readonly platform: string;
|
||||||
|
declare readonly isTestAccount: boolean;
|
||||||
|
|
||||||
private constructor(input: AppleLoginRequestInput) {
|
private constructor(input: AppleLoginRequestInput) {
|
||||||
const data = AppleLoginRequestSchema.parse(input);
|
const data = AppleLoginRequestSchema.parse(input);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export class FacebookLoginRequest {
|
|||||||
declare readonly accessToken: string;
|
declare readonly accessToken: string;
|
||||||
declare readonly platform: string;
|
declare readonly platform: string;
|
||||||
declare readonly guestId: string;
|
declare readonly guestId: string;
|
||||||
|
declare readonly isTestAccount: boolean;
|
||||||
|
|
||||||
private constructor(input: FacebookLoginRequestInput) {
|
private constructor(input: FacebookLoginRequestInput) {
|
||||||
const data = FacebookLoginRequestSchema.parse(input);
|
const data = FacebookLoginRequestSchema.parse(input);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
export class FbIdLoginRequest {
|
export class FbIdLoginRequest {
|
||||||
declare readonly fbId: string;
|
declare readonly fbId: string;
|
||||||
declare readonly avatarUrl: string;
|
declare readonly avatarUrl: string;
|
||||||
|
declare readonly isTestAccount: boolean;
|
||||||
|
|
||||||
private constructor(input: FbIdLoginRequestInput) {
|
private constructor(input: FbIdLoginRequestInput) {
|
||||||
const data = FbIdLoginRequestSchema.parse(input);
|
const data = FbIdLoginRequestSchema.parse(input);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export class GoogleLoginRequest {
|
|||||||
declare readonly idToken: string;
|
declare readonly idToken: string;
|
||||||
declare readonly platform: string;
|
declare readonly platform: string;
|
||||||
declare readonly guestId: string;
|
declare readonly guestId: string;
|
||||||
|
declare readonly isTestAccount: boolean;
|
||||||
|
|
||||||
private constructor(input: GoogleLoginRequestInput) {
|
private constructor(input: GoogleLoginRequestInput) {
|
||||||
const data = GoogleLoginRequestSchema.parse(input);
|
const data = GoogleLoginRequestSchema.parse(input);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
|
|
||||||
export class GuestLoginRequest {
|
export class GuestLoginRequest {
|
||||||
declare readonly deviceId: string;
|
declare readonly deviceId: string;
|
||||||
|
declare readonly isTestAccount: boolean;
|
||||||
|
|
||||||
private constructor(input: GuestLoginRequestInput) {
|
private constructor(input: GuestLoginRequestInput) {
|
||||||
const data = GuestLoginRequestSchema.parse(input);
|
const data = GuestLoginRequestSchema.parse(input);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export class LoginRequest {
|
|||||||
declare readonly password: string;
|
declare readonly password: string;
|
||||||
declare readonly platform: string;
|
declare readonly platform: string;
|
||||||
declare readonly guestId: string;
|
declare readonly guestId: string;
|
||||||
|
declare readonly isTestAccount: boolean;
|
||||||
|
|
||||||
private constructor(input: LoginRequestInput) {
|
private constructor(input: LoginRequestInput) {
|
||||||
const data = LoginRequestSchema.parse(input);
|
const data = LoginRequestSchema.parse(input);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export class RegisterRequest {
|
|||||||
declare readonly password: string;
|
declare readonly password: string;
|
||||||
declare readonly platform: string;
|
declare readonly platform: string;
|
||||||
declare readonly guestId: string;
|
declare readonly guestId: string;
|
||||||
|
declare readonly isTestAccount: boolean;
|
||||||
|
|
||||||
private constructor(input: RegisterRequestInput) {
|
private constructor(input: RegisterRequestInput) {
|
||||||
const data = RegisterRequestSchema.parse(input);
|
const data = RegisterRequestSchema.parse(input);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
SendCodeRequest,
|
SendCodeRequest,
|
||||||
} from "@/data/dto/auth";
|
} from "@/data/dto/auth";
|
||||||
import { User } from "@/data/dto/user";
|
import { User } from "@/data/dto/user";
|
||||||
import { Result, Logger } from "@/utils";
|
import { AppEnvUtil, Result, Logger } from "@/utils";
|
||||||
import type { IAuthRepository } from "@/data/repositories/interfaces";
|
import type { IAuthRepository } from "@/data/repositories/interfaces";
|
||||||
import { AuthStorage, type IAuthStorage } from "@/data/storage/auth";
|
import { AuthStorage, type IAuthStorage } from "@/data/storage/auth";
|
||||||
import { UserStorage, type IUserStorage } from "@/data/storage/user";
|
import { UserStorage, type IUserStorage } from "@/data/storage/user";
|
||||||
@@ -37,6 +37,7 @@ const log = new Logger("DataRepositoriesAuthRepository");
|
|||||||
|
|
||||||
/** 硬编码平台名,对齐 Dart `PlatformUtil.platformName.toLowerCase()`(Web 平台)。 */
|
/** 硬编码平台名,对齐 Dart `PlatformUtil.platformName.toLowerCase()`(Web 平台)。 */
|
||||||
const WEB_PLATFORM = "web";
|
const WEB_PLATFORM = "web";
|
||||||
|
const TEST_ACCOUNT_FLAG = "isTestAccount";
|
||||||
|
|
||||||
export class AuthRepository implements IAuthRepository {
|
export class AuthRepository implements IAuthRepository {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -59,13 +60,15 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
}): Promise<Result<void>> {
|
}): Promise<Result<void>> {
|
||||||
return Result.wrap(async () => {
|
return Result.wrap(async () => {
|
||||||
await this.api.register(
|
await this.api.register(
|
||||||
RegisterRequest.from({
|
RegisterRequest.from(
|
||||||
username: input.username,
|
withTestAccountFlag({
|
||||||
email: input.email,
|
username: input.username,
|
||||||
password: input.password,
|
email: input.email,
|
||||||
platform: WEB_PLATFORM,
|
password: input.password,
|
||||||
guestId: input.guestId ?? "",
|
platform: WEB_PLATFORM,
|
||||||
}),
|
guestId: input.guestId ?? "",
|
||||||
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -79,13 +82,15 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
}): Promise<Result<LoginResponse>> {
|
}): Promise<Result<LoginResponse>> {
|
||||||
return Result.wrap(async () => {
|
return Result.wrap(async () => {
|
||||||
const response = await this.api.emailLogin(
|
const response = await this.api.emailLogin(
|
||||||
LoginRequest.from({
|
LoginRequest.from(
|
||||||
email: input.email ?? "",
|
withTestAccountFlag({
|
||||||
username: input.username ?? "",
|
email: input.email ?? "",
|
||||||
password: input.password,
|
username: input.username ?? "",
|
||||||
platform: WEB_PLATFORM,
|
password: input.password,
|
||||||
guestId: input.guestId ?? "",
|
platform: WEB_PLATFORM,
|
||||||
}),
|
guestId: input.guestId ?? "",
|
||||||
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
await this._saveLoginData(response);
|
await this._saveLoginData(response);
|
||||||
return response;
|
return response;
|
||||||
@@ -131,7 +136,7 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
});
|
});
|
||||||
return Result.wrap(async () => {
|
return Result.wrap(async () => {
|
||||||
const response = await this.api.guestLogin(
|
const response = await this.api.guestLogin(
|
||||||
GuestLoginRequest.from({ deviceId }),
|
GuestLoginRequest.from(withTestAccountFlag({ deviceId })),
|
||||||
);
|
);
|
||||||
log.debug("[AuthRepository.guestLogin] API call SUCCESS (Zod parsed)", {
|
log.debug("[AuthRepository.guestLogin] API call SUCCESS (Zod parsed)", {
|
||||||
hasToken: !!response.token,
|
hasToken: !!response.token,
|
||||||
@@ -160,11 +165,13 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
}): Promise<Result<LoginResponse>> {
|
}): Promise<Result<LoginResponse>> {
|
||||||
return this._socialLogin(() =>
|
return this._socialLogin(() =>
|
||||||
this.api.googleLogin(
|
this.api.googleLogin(
|
||||||
GoogleLoginRequest.from({
|
GoogleLoginRequest.from(
|
||||||
idToken: input.idToken,
|
withTestAccountFlag({
|
||||||
platform: WEB_PLATFORM,
|
idToken: input.idToken,
|
||||||
guestId: input.guestId ?? "",
|
platform: WEB_PLATFORM,
|
||||||
}),
|
guestId: input.guestId ?? "",
|
||||||
|
}),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -176,11 +183,13 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
}): Promise<Result<LoginResponse>> {
|
}): Promise<Result<LoginResponse>> {
|
||||||
return this._socialLogin(() =>
|
return this._socialLogin(() =>
|
||||||
this.api.facebookLogin(
|
this.api.facebookLogin(
|
||||||
FacebookLoginRequest.from({
|
FacebookLoginRequest.from(
|
||||||
accessToken: input.accessToken,
|
withTestAccountFlag({
|
||||||
platform: WEB_PLATFORM,
|
accessToken: input.accessToken,
|
||||||
guestId: input.guestId ?? "",
|
platform: WEB_PLATFORM,
|
||||||
}),
|
guestId: input.guestId ?? "",
|
||||||
|
}),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -192,10 +201,12 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
}): Promise<Result<LoginResponse>> {
|
}): Promise<Result<LoginResponse>> {
|
||||||
return this._socialLogin(() =>
|
return this._socialLogin(() =>
|
||||||
this.api.facebookIdLogin(
|
this.api.facebookIdLogin(
|
||||||
FbIdLoginRequest.from({
|
FbIdLoginRequest.from(
|
||||||
fbId: input.fbId,
|
withTestAccountFlag({
|
||||||
avatarUrl: input.avatarUrl ?? "",
|
fbId: input.fbId,
|
||||||
}),
|
avatarUrl: input.avatarUrl ?? "",
|
||||||
|
}),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -208,10 +219,12 @@ export class AuthRepository implements IAuthRepository {
|
|||||||
async appleLogin(identityToken: string): Promise<Result<LoginResponse>> {
|
async appleLogin(identityToken: string): Promise<Result<LoginResponse>> {
|
||||||
return this._socialLogin(() =>
|
return this._socialLogin(() =>
|
||||||
this.api.appleLogin(
|
this.api.appleLogin(
|
||||||
AppleLoginRequest.from({
|
AppleLoginRequest.from(
|
||||||
identityToken,
|
withTestAccountFlag({
|
||||||
platform: WEB_PLATFORM,
|
identityToken,
|
||||||
}),
|
platform: WEB_PLATFORM,
|
||||||
|
}),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -305,3 +318,12 @@ export const authRepository = new AuthRepository(
|
|||||||
AuthStorage.getInstance(),
|
AuthStorage.getInstance(),
|
||||||
UserStorage.getInstance(),
|
UserStorage.getInstance(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function withTestAccountFlag<T extends Record<string, unknown>>(
|
||||||
|
payload: T,
|
||||||
|
): T & { isTestAccount: boolean } {
|
||||||
|
return {
|
||||||
|
...payload,
|
||||||
|
[TEST_ACCOUNT_FLAG]: !AppEnvUtil.isProduction(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { z } from "zod";
|
|||||||
export const AppleLoginRequestSchema = z.object({
|
export const AppleLoginRequestSchema = z.object({
|
||||||
identityToken: z.string(),
|
identityToken: z.string(),
|
||||||
platform: z.string(),
|
platform: z.string(),
|
||||||
|
isTestAccount: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type AppleLoginRequestInput = z.input<typeof AppleLoginRequestSchema>;
|
export type AppleLoginRequestInput = z.input<typeof AppleLoginRequestSchema>;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const FacebookLoginRequestSchema = z.object({
|
|||||||
accessToken: z.string(),
|
accessToken: z.string(),
|
||||||
platform: z.string(),
|
platform: z.string(),
|
||||||
guestId: z.string().default(""),
|
guestId: z.string().default(""),
|
||||||
|
isTestAccount: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type FacebookLoginRequestInput = z.input<typeof FacebookLoginRequestSchema>;
|
export type FacebookLoginRequestInput = z.input<typeof FacebookLoginRequestSchema>;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { z } from "zod";
|
|||||||
export const FbIdLoginRequestSchema = z.object({
|
export const FbIdLoginRequestSchema = z.object({
|
||||||
fbId: z.string(),
|
fbId: z.string(),
|
||||||
avatarUrl: z.string().default(""),
|
avatarUrl: z.string().default(""),
|
||||||
|
isTestAccount: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type FbIdLoginRequestInput = z.input<typeof FbIdLoginRequestSchema>;
|
export type FbIdLoginRequestInput = z.input<typeof FbIdLoginRequestSchema>;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const GoogleLoginRequestSchema = z.object({
|
|||||||
idToken: z.string(),
|
idToken: z.string(),
|
||||||
platform: z.string(),
|
platform: z.string(),
|
||||||
guestId: z.string().default(""),
|
guestId: z.string().default(""),
|
||||||
|
isTestAccount: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GoogleLoginRequestInput = z.input<typeof GoogleLoginRequestSchema>;
|
export type GoogleLoginRequestInput = z.input<typeof GoogleLoginRequestSchema>;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
export const GuestLoginRequestSchema = z.object({
|
export const GuestLoginRequestSchema = z.object({
|
||||||
deviceId: z.string(),
|
deviceId: z.string(),
|
||||||
|
isTestAccount: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GuestLoginRequestInput = z.input<typeof GuestLoginRequestSchema>;
|
export type GuestLoginRequestInput = z.input<typeof GuestLoginRequestSchema>;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export const LoginRequestSchema = z.object({
|
|||||||
password: z.string(),
|
password: z.string(),
|
||||||
platform: z.string(),
|
platform: z.string(),
|
||||||
guestId: z.string().default(""),
|
guestId: z.string().default(""),
|
||||||
|
isTestAccount: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type LoginRequestInput = z.input<typeof LoginRequestSchema>;
|
export type LoginRequestInput = z.input<typeof LoginRequestSchema>;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export const RegisterRequestSchema = z.object({
|
|||||||
password: z.string(),
|
password: z.string(),
|
||||||
platform: z.string(),
|
platform: z.string(),
|
||||||
guestId: z.string().default(""),
|
guestId: z.string().default(""),
|
||||||
|
isTestAccount: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type RegisterRequestInput = z.input<typeof RegisterRequestSchema>;
|
export type RegisterRequestInput = z.input<typeof RegisterRequestSchema>;
|
||||||
|
|||||||
Reference in New Issue
Block a user