import type { NextAuthOptions } from "next-auth" import CredentialsProvider from "next-auth/providers/credentials" import { prisma } from "./prisma" import bcrypt from "bcryptjs" export const authOptions: NextAuthOptions = { providers: [ CredentialsProvider({ name: "credentials", credentials: { email: { label: "Email", type: "email" }, password: { label: "Password", type: "password" } }, async authorize(credentials) { if (!credentials?.email || !credentials?.password) { throw new Error("请输入邮箱和密码") } const user = await prisma.user.findUnique({ where: { email: credentials.email } }) if (!user || !user.password) { throw new Error("用户不存在") } const isValid = await bcrypt.compare(credentials.password, user.password) if (!isValid) { throw new Error("密码错误") } // 检查用户是否被停用 if (!user.isActive) { throw new Error("账户已被停用,请联系管理员") } // 记录登录日志 await prisma.loginLog.create({ data: { userId: user.id, email: user.email, userName: user.name, success: true, } }) const hasSeenHelp = (user as { hasSeenHelp?: boolean }).hasSeenHelp ?? false return { id: user.id, email: user.email, name: user.name, hasSeenHelp, } } }) ], session: { strategy: "jwt" }, pages: { signIn: "/auth/signin", }, callbacks: { async jwt({ token, user, trigger, session }) { if (user) { token.id = user.id token.hasSeenHelp = (user as any).hasSeenHelp ?? token.hasSeenHelp } if (trigger === 'update' && session?.user?.hasSeenHelp !== undefined) { token.hasSeenHelp = session.user.hasSeenHelp } if (token.id && token.hasSeenHelp === undefined) { const dbUser = await prisma.user.findUnique({ where: { id: token.id as string }, }) as { hasSeenHelp?: boolean } | null token.hasSeenHelp = dbUser?.hasSeenHelp ?? false } return token }, async session({ session, token }) { if (session.user) { session.user.id = token.id as string session.user.hasSeenHelp = (token as any).hasSeenHelp ?? false } return session } }, // 强制不使用 Secure Cookie,解决代理访问时的协议误判问题 useSecureCookies: false, cookies: { sessionToken: { name: `next-auth.session-token`, options: { httpOnly: true, sameSite: 'lax', path: '/', secure: false } } } }