123 lines
3.1 KiB
TypeScript
123 lines
3.1 KiB
TypeScript
import 'server-only'
|
||
import { NextAuthOptions } from "next-auth"
|
||
import type { User as NextAuthUser } from "next-auth"
|
||
import CredentialsProvider from "next-auth/providers/credentials"
|
||
import bcrypt from "bcryptjs"
|
||
import { db } from "./db"
|
||
|
||
export const authOptions: NextAuthOptions = {
|
||
providers: [
|
||
CredentialsProvider({
|
||
name: "credentials",
|
||
credentials: {
|
||
id: { label: "用户ID", type: "text" },
|
||
password: { label: "密码", type: "password" }
|
||
},
|
||
async authorize(credentials, req): Promise<NextAuthUser | null> {
|
||
if (!credentials?.id || !credentials?.password) {
|
||
return null
|
||
}
|
||
|
||
try {
|
||
// 查找用户
|
||
const user = await db.user.findUnique({
|
||
where: {
|
||
id: credentials.id
|
||
},
|
||
include: {
|
||
roles: {
|
||
include: { permissions: true }
|
||
},
|
||
dept: true
|
||
}
|
||
})
|
||
|
||
if (!user) {
|
||
return null
|
||
}
|
||
|
||
// 验证密码
|
||
const isPasswordValid = await bcrypt.compare(credentials.password, user.password)
|
||
|
||
|
||
if (!isPasswordValid) {
|
||
return null
|
||
}
|
||
|
||
// 更新最近登录时间
|
||
await db.user.update({
|
||
where: { id: user.id },
|
||
data: { lastLoginAt: new Date() }
|
||
})
|
||
|
||
// 返回用户信息、角色和权限
|
||
const roles = user.roles.map((r) => r.name)
|
||
const permissions = Array.from(
|
||
new Set(user.roles.flatMap((r) =>
|
||
r.permissions.map((p) => p.name)
|
||
))
|
||
)
|
||
return {
|
||
id: user.id,
|
||
name: user.name,
|
||
status: user.status,
|
||
deptCode: user.deptCode,
|
||
roles,
|
||
permissions,
|
||
isSuperAdmin: user.isSuperAdmin
|
||
} as any
|
||
} catch (error) {
|
||
console.error("Auth error:", error)
|
||
return null
|
||
}
|
||
}
|
||
})
|
||
],
|
||
session: {
|
||
strategy: "jwt",
|
||
maxAge: 30 * 24 * 60 * 60, // 30 days
|
||
},
|
||
jwt: {
|
||
maxAge: 30 * 24 * 60 * 60, // 30 days
|
||
},
|
||
pages: {
|
||
signIn: "/login",
|
||
},
|
||
callbacks: {
|
||
async jwt({ token, user }) {
|
||
// 初次登录时,将用户信息保存到JWT token中
|
||
if (user) {
|
||
const u = user as any
|
||
token = {
|
||
...token,
|
||
id: u.id,
|
||
name: u.name,
|
||
status: u.status,
|
||
deptCode: u.deptCode,
|
||
roles: u.roles,
|
||
permissions: u.permissions,
|
||
isSuperAdmin: u.isSuperAdmin,
|
||
}
|
||
}
|
||
return token
|
||
},
|
||
async session({ session, token }) {
|
||
// 将JWT token中的信息传递给session
|
||
if (session.user) {
|
||
const t = token as any
|
||
session.user = {
|
||
...session.user,
|
||
id: t.id,
|
||
name: t.name,
|
||
status: t.status,
|
||
deptCode: t.deptCode,
|
||
roles: t.roles,
|
||
permissions: t.permissions,
|
||
isSuperAdmin: t.isSuperAdmin,
|
||
}
|
||
}
|
||
return session
|
||
}
|
||
},
|
||
secret: process.env.NEXTAUTH_SECRET,
|
||
} |