// server/utils/auth.ts - Better Auth 服务端实例,邮箱密码登录 + 用户 API token import { randomBytes } from "node:crypto"; import { betterAuth } from "better-auth"; import { prismaAdapter } from "better-auth/adapters/prisma"; import type { H3Event } from "h3"; import { toWebRequest } from "h3"; import { prisma } from "~~/server/utils/db"; /** * Better Auth 全局实例 * * - 使用 Prisma MySQL/MariaDB 适配器 * - 只启用邮箱/密码登录,无邮箱验证和密码重置(保持最简) * - 注册时通过 databaseHook 自动生成 32 位 hex apiToken * apiToken 供 OCS 油猴脚本跨域调用 /api/search 时在 body 中携带 * - apiToken 不允许客户端直接设置(input: false),但随 session 返回给登录用户 */ export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: "mysql" }), session: { expiresIn: 60 * 60 * 24 * 14, // 14 天过期 updateAge: 60 * 60 * 24 // 每天自动续期 }, emailAndPassword: { enabled: true }, user: { additionalFields: { apiToken: { type: "string", required: false, // 客户端(signup/updateUser)不能设置此字段,只由 databaseHooks 写入 input: false } } }, databaseHooks: { user: { create: { // 注册时自动生成 apiToken,格式与旧 ACCESS_TOKEN 字段一致(32 位 hex) before: async (user) => { return { data: { ...user, apiToken: randomBytes(16).toString("hex") } }; } } } } }); /** * 从 H3 事件中读取 Better Auth session * * 封装 toWebRequest 转换,避免在每个 handler 中重复导入和调用 * 未登录或 session 无效时返回 null */ export const getAuthSession = (event: H3Event) => auth.api.getSession({ headers: toWebRequest(event).headers });