feat(auth): 登录注册 - 添加短信通知与组合验证支持
This commit is contained in:
@@ -6,12 +6,13 @@ import type { FeatureAvailability } from "@/stores/use-user-store";
|
||||
import { http, apiBaseURL } from "@/services/api/request";
|
||||
import type { PublicLogicalModel } from "@/services/api/logical-models";
|
||||
import type { OSSConnectionTestInput, OSSConnectionTestResult, OSSProvider, S3Preset } from "@/lib/oss-settings";
|
||||
import type { VerificationPolicy } from "./verification";
|
||||
|
||||
|
||||
let authSessionRequest: Promise<AuthSessionPayload> | null = null;
|
||||
let authSessionCache: { payload: AuthSessionPayload; expiresAt: number } | null = null;
|
||||
|
||||
function invalidateAuthSessionCache() {
|
||||
export function invalidateAuthSessionCache() {
|
||||
authSessionCache = null;
|
||||
}
|
||||
|
||||
@@ -19,6 +20,9 @@ export type LocalUser = {
|
||||
id: string;
|
||||
username: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
emailVerifiedAt?: string;
|
||||
phoneVerifiedAt?: string;
|
||||
displayName: string;
|
||||
avatarUrl?: string;
|
||||
identityProvider?: string;
|
||||
@@ -376,7 +380,7 @@ export type RuntimePolicySetting = {
|
||||
};
|
||||
|
||||
export function getAuthSettings() {
|
||||
return http.get<{ firstUser: boolean; registrationEnabled: boolean; linuxdoEnabled: boolean; emailEnabled: boolean; emailCodeRequired: boolean }>("/auth/settings");
|
||||
return http.get<VerificationPolicy & { firstUser: boolean; registrationEnabled: boolean; linuxdoEnabled: boolean; emailEnabled: boolean; emailCodeRequired: boolean; smsBindingAvailable: boolean; emailBindingAvailable: boolean }>("/auth/settings");
|
||||
}
|
||||
|
||||
export function linuxDOLoginURL(next: string, acceptedTerms?: boolean) {
|
||||
@@ -435,8 +439,10 @@ export function resetPassword(input: { email: string; emailCode: string; passwor
|
||||
return http.post<{ reset: boolean }>("/auth/password-reset", input);
|
||||
}
|
||||
|
||||
export function register(input: { username: string; email?: string; emailCode?: string; displayName?: string; password: string; acceptedTerms: boolean }) {
|
||||
return http.post<{ user: LocalUser }>("/auth/register", input);
|
||||
export async function register(input: { username: string; email?: string; emailCode?: string; phone?: string; smsCode?: string; ticket?: string; displayName?: string; password: string; acceptedTerms: boolean }) {
|
||||
const result = await http.post<{ user: LocalUser }>("/auth/register", input);
|
||||
invalidateAuthSessionCache();
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
|
||||
35
web/src/services/api/verification.ts
Normal file
35
web/src/services/api/verification.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { http } from "./request";
|
||||
import { invalidateAuthSessionCache, type LocalUser } from "./auth";
|
||||
|
||||
export type VerificationPolicy = {
|
||||
smsLogin: boolean;
|
||||
emailLogin: boolean;
|
||||
smsRegistration: boolean;
|
||||
emailRegistration: boolean;
|
||||
smsAndEmailRegistration: boolean;
|
||||
};
|
||||
export type VerificationMethod = "sms" | "email" | "sms_email";
|
||||
export type VerificationPurpose = "login" | "register" | "bind";
|
||||
export type VerificationDraft = { ticket: string; email: string; phone: string; emailCode: string; smsCode: string };
|
||||
export const emptyVerification: VerificationDraft = { ticket: "", email: "", phone: "", emailCode: "", smsCode: "" };
|
||||
export const methodLabels: Record<VerificationMethod, string> = { sms: "短信验证码", email: "邮件验证码", sms_email: "短信 + 邮箱双重验证" };
|
||||
|
||||
export function verificationMethods(policy: VerificationPolicy, purpose: "login" | "register"): VerificationMethod[] {
|
||||
if (purpose === "login") return [...(policy.smsLogin ? ["sms" as const] : []), ...(policy.emailLogin ? ["email" as const] : [])];
|
||||
if (policy.smsAndEmailRegistration) return ["sms_email"];
|
||||
return [...(policy.smsRegistration ? ["sms" as const] : []), ...(policy.emailRegistration ? ["email" as const] : [])];
|
||||
}
|
||||
export const startVerification = (input: { purpose: VerificationPurpose; method: VerificationMethod; email?: string; phone?: string; password?: string }) =>
|
||||
http.post<{ ticket: string; expiresIn: number; retryAfter: number }>("/auth/verification", input);
|
||||
export async function loginVerification(input: VerificationDraft) {
|
||||
const result = await http.post<{ user: LocalUser }>("/auth/verification/login", input);
|
||||
invalidateAuthSessionCache();
|
||||
return result;
|
||||
}
|
||||
export async function bindVerification(input: VerificationDraft) {
|
||||
const result = await http.post<{ user: LocalUser }>("/auth/verification/bind", input);
|
||||
invalidateAuthSessionCache();
|
||||
return result;
|
||||
}
|
||||
export const getVerificationPolicy = () => http.get<VerificationPolicy>("/admin/settings/auth-policy");
|
||||
export const saveVerificationPolicy = (input: VerificationPolicy) => http.put<VerificationPolicy>("/admin/settings/auth-policy", input);
|
||||
Reference in New Issue
Block a user