diff --git a/app/(auth)/actions.ts b/app/(auth)/actions.ts index 4c3bfd2dc..071f2e587 100644 --- a/app/(auth)/actions.ts +++ b/app/(auth)/actions.ts @@ -44,9 +44,10 @@ export const login = async ( email: formData.get("email"), password: formData.get("password"), }); + const normalizedEmail = validatedData.email.trim().toLowerCase(); await signIn("credentials", { - email: validatedData.email, + email: normalizedEmail, password: validatedData.password, redirect: false, }); @@ -86,15 +87,16 @@ export const register = async ( email: formData.get("email"), password: formData.get("password"), }); + const normalizedEmail = validatedData.email.trim().toLowerCase(); - const [user] = await getUser(validatedData.email); + const [user] = await getUser(normalizedEmail); if (user) { return { status: "user_exists" } as RegisterActionState; } - await createUser(validatedData.email, validatedData.password); + await createUser(normalizedEmail, validatedData.password); await signIn("credentials", { - email: validatedData.email, + email: normalizedEmail, password: validatedData.password, redirect: false, }); diff --git a/app/(auth)/auth.config.ts b/app/(auth)/auth.config.ts index d3859dc2a..64bb6fb54 100644 --- a/app/(auth)/auth.config.ts +++ b/app/(auth)/auth.config.ts @@ -1,13 +1,10 @@ import type { NextAuthConfig } from "next-auth"; -import { isIP } from "node:net"; export function buildAuthConfig(authUrl?: string | null): NextAuthConfig { const resolvedAuthUrl = authUrl || process.env.AUTH_URL || ""; const isSecure = resolvedAuthUrl.startsWith("https://"); - const hostName = resolvedAuthUrl ? new URL(resolvedAuthUrl).hostname : undefined; - // Browsers may reject `Domain` cookies for IP hosts; keep them host-only in that case. - const cookieDomain = - hostName && hostName !== "localhost" && isIP(hostName) === 0 ? hostName : undefined; + // Use host-only cookies to avoid cross-domain login issues in multi-domain deployments. + const cookieDomain = undefined; return { trustHost: true, diff --git a/app/(auth)/auth.ts b/app/(auth)/auth.ts index 90db58565..e3be1c5ba 100644 --- a/app/(auth)/auth.ts +++ b/app/(auth)/auth.ts @@ -115,7 +115,14 @@ function createBaseProviders(googleClientId?: string, googleClientSecret?: strin } // 2. 邮箱密码登录逻辑 - const { email, password } = credentials; + const email = String(credentials?.email || "").trim().toLowerCase(); + const password = String(credentials?.password || ""); + + if (!email || !password) { + await compare(password || "", DUMMY_PASSWORD); + return null; + } + const users = await getUser(email); if (users.length === 0) { diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index f0e3f2d3f..40c557a21 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -548,7 +548,7 @@ export default function Page() { {/* 钉钉登录 iframe 弹窗 / 多组织选择 */} {showDingTalkModal && (
{ if (e.target === e.currentTarget) closeDingTalkModal(); }} diff --git a/components/home/lovart-home.tsx b/components/home/lovart-home.tsx index 4cb89c455..cd7b83eb4 100644 --- a/components/home/lovart-home.tsx +++ b/components/home/lovart-home.tsx @@ -594,7 +594,7 @@ export function LovartHome({ }; const handleEmailLogin = async () => { - const email = loginEmail.trim(); + const email = loginEmail.trim().toLowerCase(); if (!email || !loginPassword) { toast.error("请输入邮箱和密码"); return; @@ -608,7 +608,7 @@ export function LovartHome({ redirect: false, }); - if (result?.error) { + if (!result || result.error || result.ok === false) { toast.error("登录失败,请检查账号密码"); return; } @@ -1235,7 +1235,7 @@ export function LovartHome({ {loginDialogOpen ? (
setLoginDialogOpen(false)} >
{ + const normalizedEmail = email.trim().toLowerCase(); + if (!normalizedEmail) { + return []; + } + try { return await db .select() .from(user) - .where(eq(user.email, email)) + .where(sql`lower(${user.email}) = ${normalizedEmail}`) .orderBy(desc(user.createdAt)); } catch (_error) { throw new ChatSDKError( @@ -81,9 +86,10 @@ export async function getUser(email: string): Promise { export async function createUser(email: string, password: string) { const hashedPassword = generateHashedPassword(password); + const normalizedEmail = email.trim().toLowerCase(); try { - return await db.insert(user).values({ email, password: hashedPassword }); + return await db.insert(user).values({ email: normalizedEmail, password: hashedPassword }); } catch (_error) { throw new ChatSDKError("bad_request:database", "Failed to create user"); }