123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- import NextAuth from "next-auth"
- import GoogleProvider from "next-auth/providers/google"
- import GitHubProvider from "next-auth/providers/github"
- import CredentialsProvider from "next-auth/providers/credentials"
- import { db } from "./db"
- import { users, userActivities } from "./schema"
- import bcrypt from "bcryptjs"
- import { eq } from "drizzle-orm"
- import { CREDIT_CONFIG } from '@/lib/constants';
- export const { auth, handlers, signIn, signOut } = NextAuth({
- providers: [
- GoogleProvider({
- clientId: process.env.GOOGLE_CLIENT_ID!,
- clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
- }),
- GitHubProvider({
- clientId: process.env.GITHUB_CLIENT_ID!,
- clientSecret: process.env.GITHUB_CLIENT_SECRET!,
- }),
- CredentialsProvider({
- name: "credentials",
- credentials: {
- email: { label: "Email", type: "email" },
- password: { label: "Password", type: "password" }
- },
- async authorize(credentials) {
- if (!credentials?.email || !credentials?.password) {
- return null
- }
- try {
- const user = await db.query.users.findFirst({
- where: eq(users.email, credentials.email as string),
- })
- if (!user || !user.password) {
- return null
- }
- const passwordsMatch = await bcrypt.compare(
- credentials.password as string,
- user.password
- )
- if (!passwordsMatch) {
- return null
- }
- return {
- id: user.id,
- email: user.email,
- name: user.username,
- image: user.image,
- }
- } catch (error) {
- console.error('Auth error:', error)
- return null
- }
- },
- }),
- ],
- session: {
- strategy: "jwt",
- maxAge: 7 * 24 * 60 * 60, // 7 days
- },
- cookies: {
- sessionToken: {
- name: `next-auth.session-token`,
- options: {
- httpOnly: true,
- sameSite: 'lax',
- path: '/',
- secure: process.env.NODE_ENV === 'production',
- },
- },
- },
- callbacks: {
- async jwt({ token, user, account }) {
- if (user) {
- token.id = user.id
- token.email = user.email
- token.name = user.name
- token.image = user.image
- }
- return token
- },
- async session({ session, token }) {
- if (token) {
- session.user.id = token.id as string
- session.user.email = token.email as string
- session.user.name = token.name as string
- session.user.image = token.image as string
- }
- return session
- },
- async signIn({ user, account, profile }) {
- try {
- // 如果是OAuth登录,确保用户邮箱已验证
- if (account?.provider === "google" || account?.provider === "github") {
- if (user.email) {
- // 检查用户是否已存在
- const existingUser = await db.query.users.findFirst({
- where: eq(users.email, user.email),
- })
- if (existingUser) {
- // 更新用户的邮箱验证状态和信息
- await db.update(users)
- .set({
- isEmailVerified: true,
- emailVerified: new Date(),
- username: user.name || existingUser.username,
- image: user.image || existingUser.image,
- })
- .where(eq(users.email, user.email))
-
- // 更新user对象的id
- user.id = existingUser.id
- } else {
- // 创建新用户,注册赠送积分
- const [newUser] = await db.insert(users).values({
- email: user.email,
- username: user.name,
- image: user.image,
- isEmailVerified: true,
- emailVerified: new Date(),
- credits: CREDIT_CONFIG.REGISTRATION_BONUS,
- }).returning()
-
- // 记录注册赠送积分的活动
- try {
- await db.insert(userActivities).values({
- userId: newUser.id,
- type: 'registration_bonus',
- description: 'credit_description.registration_bonus',
- creditAmount: CREDIT_CONFIG.REGISTRATION_BONUS,
- metadata: JSON.stringify({
- source: 'registration_bonus',
- provider: account?.provider,
- email: newUser.email,
- type: 'registration_bonus',
- })
- });
- } catch (error) {
- console.error('记录OAuth注册积分活动失败:', error);
- }
-
- // 更新user对象的id
- user.id = newUser.id
- }
- }
- }
- return true
- } catch (error) {
- console.error('SignIn callback error:', error)
- return false
- }
- },
- },
- pages: {
- signIn: "/auth/login",
- },
- debug: process.env.NODE_ENV === 'development',
- })
- // 导出类型
- export type { Session } from "next-auth"
|