Files
record-app-next/lib/auth.ts

127 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// lib/auth.ts
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "./database";
import GoogleProvider from "next-auth/providers/google";
import CredentialsProvider from "next-auth/providers/credentials";
import { UserService } from "./services/user.service";
import { AuthOptions } from "next-auth";
// 验证和清理 NEXTAUTH_URL
function getValidatedNextAuthUrl(): string {
const url = process.env.NEXTAUTH_URL;
if (!url) {
throw new Error("NEXTAUTH_URL 环境变量未设置");
}
// 清理 URL移除多余的引号
let cleanUrl = url.trim();
if (cleanUrl.startsWith('"') && cleanUrl.endsWith('"')) {
cleanUrl = cleanUrl.slice(1, -1);
}
if (cleanUrl.startsWith("'") && cleanUrl.endsWith("'")) {
cleanUrl = cleanUrl.slice(1, -1);
}
// 确保 URL 格式正确
try {
new URL(cleanUrl);
} catch (error) {
throw new Error(`无效的 NEXTAUTH_URL: ${cleanUrl}`);
}
return cleanUrl;
}
export const authOptions: AuthOptions = {
adapter: PrismaAdapter(prisma),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
CredentialsProvider({
name: "Credentials",
credentials: {
email: { label: "Email", type: "text" },
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
if (!credentials?.email || !credentials?.password) {
throw new Error("请输入邮箱和密码");
}
try {
const user = await UserService.getUserByEmail(credentials.email);
if (!user || !user.hashedPassword) {
throw new Error("用户不存在或未设置密码");
}
const isPasswordValid = await UserService.verifyPassword(
user,
credentials.password
);
if (!isPasswordValid) {
throw new Error("密码错误");
}
return user;
} catch (error) {
throw error;
}
},
}),
],
session: {
strategy: "jwt",
},
callbacks: {
async jwt({ token, user, account }) {
if (user) {
token.id = user.id;
token.email = user.email;
token.name = user.name;
}
return token;
},
async session({ session, token }) {
if (token?.id && session.user) {
session.user.id = token.id as string;
session.user.email = token.email as string;
session.user.name = token.name as string;
}
return session;
},
async signIn({ user, account, profile }) {
// 允许所有用户登录
return true;
},
async redirect({ url, baseUrl }) {
// 确保重定向到正确的页面
if (url.startsWith("/")) return `${baseUrl}${url}`;
else if (new URL(url).origin === baseUrl) return url;
return `${baseUrl}/dashboard`;
},
},
pages: {
signIn: "/login",
},
secret: process.env.NEXTAUTH_SECRET,
debug: process.env.NODE_ENV === "development",
// 使用验证后的 URL
url: getValidatedNextAuthUrl(),
};