import db from '@/lib/db/client'; import { hashPassword } from '@/lib/password'; import { generateAccessToken } from '@/lib/token'; import { createRoute, z } from '@hono/zod-openapi'; import { isNil } from 'lodash'; import type { AuthItem } from './type'; import { createBodyRequest, createErrorResult, createHonoApp, createServerErrorResponse, createSuccessResponse, createUnauthorizedErrorResponse, createValidatorErrorResponse, } from '../common/utils'; import { authItemSchema, authLoginRequestSchema, authLoginResponseSchema, createUserSchema, } from './schema'; import { passport, verifyJWT } from './utils'; const tags = ['auth']; const app = createHonoApp(); export const authApi = app .openapi( createRoute({ tags, method: 'get', summary: '获取用户信息', path: '/profile', responses: { ...createSuccessResponse( '获取成功', z .object({ result: z.boolean(), data: authItemSchema.or(z.null()), }) .openapi('获取用户信息响应数据'), ), ...createServerErrorResponse(), }, }), async (c) => { try { const isAuthenticated = await verifyJWT(c); if (!isAuthenticated) return c.json({ result: false, data: null }, 200); const { id } = c.var.user; const user = await db.user.findUnique({ where: { id }, select: { id: true, username: true, email: true, createdAt: true, updatedAt: true, }, }); if (isNil(user)) return c.json({ result: false, data: null }, 200); return c.json({ result: true, data: user }, 200); } catch (error) { return c.json(createErrorResult('获取用户失败', error), 500); } }, ) .openapi( createRoute({ tags, summary: '用戶註冊', method: 'post', path: '/signup', request: createBodyRequest(createUserSchema), responses: { ...createSuccessResponse('Login success', authLoginResponseSchema), ...createValidatorErrorResponse(), ...createServerErrorResponse(), }, }), async (c) => { const data = await c.req.json(); const validatedData = await createUserSchema.safeParseAsync(data); try { if (validatedData.success) { const user = await db.user.create({ data: { ...validatedData.data, password: hashPassword(validatedData.data.password), }, }); const token = generateAccessToken(user); return c.json({ token }, 200); } return c.json(createErrorResult('参数验证失败', validatedData.error), 400); } catch (error) { return c.json(createErrorResult('服务器错误', error), 500); } }, ) .openapi( createRoute({ tags, summary: '用戶登入', method: 'post', path: '/login', request: createBodyRequest(authLoginRequestSchema), responses: { ...createSuccessResponse('登录成功', authLoginResponseSchema), ...createValidatorErrorResponse(), ...createUnauthorizedErrorResponse('认证失败'), ...createServerErrorResponse(), }, }), async (c) => { const body = await c.req.json(); const validatedData = authLoginRequestSchema.safeParse(body); if (!validatedData.success) { return c.json(createErrorResult('参数验证失败', validatedData.error), 400); } const authReq = { ...c.req.raw, body: validatedData.data, }; return new Promise((resolve) => { passport.authenticate('local', (err: any, user: AuthItem, info: any) => { if (err) return err.code === 401 ? resolve(c.json(createErrorResult('认证失败', err), 401)) : resolve(c.json(createErrorResult('服务器错误', err), 500)); const token = generateAccessToken(user); return resolve(c.json({ token }, 200)); })(authReq, (c.res as any).raw); }); }, ) .openapi( createRoute({ tags, summary: '用戶列表', method: 'get', path: '/', responses: { ...createSuccessResponse('用户列表', z.array(createUserSchema)), }, }), async (c) => { const users = await db.user.findMany(); return c.json(users, 200); }, );