56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
import type { AuthIdentityType, AuthPublicUser, AuthUser } from "./types.ts";
|
|
|
|
export function normalizeEmail(value: string): string {
|
|
return value.trim().toLowerCase();
|
|
}
|
|
|
|
export function normalizeUsername(value: string): string {
|
|
return value.trim().toLowerCase();
|
|
}
|
|
|
|
export function normalizePhone(value: string): string {
|
|
const trimmed = value.trim();
|
|
const prefix = trimmed.startsWith("+") ? "+" : "";
|
|
return prefix + trimmed.replace(/\D/g, "");
|
|
}
|
|
|
|
export function normalizeIdentity(type: AuthIdentityType, value: string): string {
|
|
if (type === "email") return normalizeEmail(value);
|
|
if (type === "phone") return normalizePhone(value);
|
|
return normalizeUsername(value);
|
|
}
|
|
|
|
export function inferIdentityType(value: string): AuthIdentityType {
|
|
const input = value.trim();
|
|
if (input.includes("@")) return "email";
|
|
if (/^\+?[0-9 ()-]{7,}$/.test(input)) return "phone";
|
|
return "username";
|
|
}
|
|
|
|
export function publicUser(user: AuthUser): AuthPublicUser {
|
|
return {
|
|
id: user.id,
|
|
username: user.username,
|
|
displayName: user.displayName,
|
|
avatarUrl: user.avatarUrl,
|
|
status: user.status,
|
|
roles: [...user.roles],
|
|
emailVerified: user.emailVerified,
|
|
phoneVerified: user.phoneVerified,
|
|
mfaEnabled: user.mfaEnabled,
|
|
};
|
|
}
|
|
|
|
/** Return a same-origin path for post-authentication navigation. */
|
|
export function safeAuthReturnTo(value: string | undefined, origin: string): string | undefined {
|
|
if (!value) return undefined;
|
|
try {
|
|
const base = new URL(origin);
|
|
const target = new URL(value, base);
|
|
if (target.origin !== base.origin) return undefined;
|
|
return `${target.pathname}${target.search}${target.hash}`;
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|