fix email login

This commit is contained in:
songtianlun 2025-06-14 21:04:23 +08:00
parent 2a60e35fc5
commit e2c31e4620
2 changed files with 107 additions and 8 deletions

View File

@ -1,7 +1,8 @@
"use client"
import { useState } from "react"
import { signIn, getProviders } from "next-auth/react"
import { useState, useEffect } from "react"
import { signIn, getProviders, useSession } from "next-auth/react"
import { useRouter, useSearchParams } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
@ -14,6 +15,38 @@ export default function SignInPage() {
const [email, setEmail] = useState("")
const [isLoading, setIsLoading] = useState(false)
const [message, setMessage] = useState("")
const { data: session, status } = useSession()
const router = useRouter()
const searchParams = useSearchParams()
// 检查用户是否已登录,如果已登录则重定向
useEffect(() => {
if (status === "authenticated" && session) {
const callbackUrl = searchParams.get("callbackUrl") || "/"
router.push(callbackUrl)
}
}, [status, session, router, searchParams])
// 如果正在加载会话状态显示loading
if (status === "loading") {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50">
<Card className="w-full max-w-md">
<CardContent className="flex items-center justify-center p-6">
<div className="text-center">
<div className="w-8 h-8 bg-gray-200 rounded-full animate-pulse mx-auto mb-2"></div>
<p className="text-sm text-muted-foreground">...</p>
</div>
</CardContent>
</Card>
</div>
)
}
// 如果已经登录,不显示登录表单(虽然会重定向,但防止闪烁)
if (status === "authenticated") {
return null
}
const handleEmailSignIn = async (e: React.FormEvent) => {
e.preventDefault()
@ -41,7 +74,8 @@ export default function SignInPage() {
const handleGoogleSignIn = async () => {
setIsLoading(true)
try {
await signIn("google", { callbackUrl: "/" })
const callbackUrl = searchParams.get("callbackUrl") || "/"
await signIn("google", { callbackUrl })
} catch (error) {
setMessage("Google登录失败请重试")
setIsLoading(false)

75
auth.ts
View File

@ -11,6 +11,7 @@ export const { auth, handlers, signIn, signOut } = NextAuth({
Google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
allowDangerousEmailAccountLinking: true,
}),
Nodemailer({
server: {
@ -28,13 +29,77 @@ export const { auth, handlers, signIn, signOut } = NextAuth({
signIn: "/auth/signin",
error: "/auth/error",
},
events: {
async linkAccount({ user, account, profile }) {
if (profile?.email && user.id) {
await db.user.update({
where: { id: user.id },
data: {
email: profile.email,
name: profile.name || user.name,
image: (profile as any)?.picture || user.image,
emailVerified: (profile as any)?.email_verified ? new Date() : null,
},
})
}
},
},
callbacks: {
async signIn({ user, account, profile, email, credentials }) {
if (!user.email) return false
if (account?.provider === "nodemailer") {
return true
}
if (account?.provider === "google" && user.email) {
const existingUser = await db.user.findUnique({
where: { email: user.email },
include: { accounts: true },
})
if (existingUser) {
const hasGoogleAccount = existingUser.accounts.some(
acc => acc.provider === "google"
)
if (!hasGoogleAccount) {
await db.account.create({
data: {
userId: existingUser.id,
type: account.type,
provider: account.provider,
providerAccountId: account.providerAccountId,
refresh_token: account.refresh_token as string | null,
access_token: account.access_token as string | null,
expires_at: account.expires_at,
token_type: account.token_type,
scope: account.scope,
id_token: account.id_token as string | null,
session_state: account.session_state as string | null,
},
})
await db.user.update({
where: { id: existingUser.id },
data: {
name: profile?.name || existingUser.name,
image: (profile as any)?.picture || existingUser.image,
emailVerified: (profile as any)?.email_verified ? new Date() : existingUser.emailVerified,
},
})
}
}
}
return true
},
async session({ token, session }) {
if (token) {
session.user.id = token.id
session.user.name = token.name
session.user.email = token.email
session.user.image = token.picture
session.user.id = token.id as string
session.user.name = token.name as string
session.user.email = token.email as string
session.user.image = token.picture as string
}
return session
@ -42,7 +107,7 @@ export const { auth, handlers, signIn, signOut } = NextAuth({
async jwt({ user, token }) {
const dbUser = await db.user.findFirst({
where: {
email: token.email,
email: token.email!,
},
})