Jelajahi Sumber

调通了用户登录注册

yourname 6 bulan lalu
induk
melakukan
8fd90d565b

+ 2 - 2
src/server/api.ts

@@ -4,7 +4,7 @@ import { authMiddleware } from './middleware/auth.middleware'
 import { checkPermission } from './middleware/permission.middleware'
 import base from './api/base'
 import { userOpenApiApp } from './api/user'
-// import { authOpenApiApp } from './api/auth'
+import { authOpenApiApp } from './api/auth'
 
 // const app = new OpenAPIHono()
 
@@ -23,7 +23,7 @@ const createApi = (app:OpenAPIHono) => {
   // Register routes
   app.route('/api/v1', base)
   app.route('/api/v1', userOpenApiApp)
-  // app.route('/api/v1/auth', new AuthController().routes())
+  app.route('/api/v1', authOpenApiApp)
 
   // OpenAPI documentation endpoint
   app.doc('/doc', {

+ 143 - 0
src/server/api/auth.ts

@@ -0,0 +1,143 @@
+import { createRoute, OpenAPIHono } from '@hono/zod-openapi'
+import { AuthService } from '../modules/auth/auth.service'
+import { UserService } from '../modules/users/user.service'
+import { User } from '../modules/users/user.entity'
+import { z } from 'zod'
+import { HTTPException } from 'hono/http-exception'
+
+// 扩展Context类型
+type AuthContext = {
+  Variables: {
+    user: User
+  }
+}
+
+const app = new OpenAPIHono<AuthContext>()
+const authService = new AuthService()
+const userService = new UserService()
+
+// Schema 定义
+const LoginSchema = z.object({
+  username: z.string().min(3).openapi({
+    example: 'john_doe',
+    description: '用户名'
+  }),
+  password: z.string().min(6).openapi({
+    example: 'password123',
+    description: '密码'
+  })
+})
+
+const RegisterSchema = LoginSchema.extend({
+  email: z.string().email().openapi({
+    example: 'john@example.com',
+    description: '邮箱'
+  })
+})
+
+const TokenResponseSchema = z.object({
+  token: z.string().openapi({
+    example: 'jwt.token.here',
+    description: 'JWT Token'
+  }),
+  user: z.object({
+    id: z.number(),
+    username: z.string()
+  })
+})
+
+// 登录路由
+const loginRoute = createRoute({
+  method: 'post',
+  path: '/auth/login',
+  request: {
+    body: {
+      content: {
+        'application/json': {
+          schema: LoginSchema
+        }
+      }
+    }
+  },
+  responses: {
+    200: {
+      description: '登录成功',
+      content: {
+        'application/json': {
+          schema: TokenResponseSchema
+        }
+      }
+    },
+    401: { description: '用户名或密码错误' }
+  }
+})
+
+app.openapi(loginRoute, async (c) => {
+  const { username, password } = c.req.valid('json')
+  const result = await authService.login(username, password)
+  return c.json(result)
+})
+
+// 注册路由
+const registerRoute = createRoute({
+  method: 'post',
+  path: '/auth/register',
+  request: {
+    body: {
+      content: {
+        'application/json': {
+          schema: RegisterSchema
+        }
+      }
+    }
+  },
+  responses: {
+    201: {
+      description: '注册成功',
+      content: {
+        'application/json': {
+          schema: TokenResponseSchema
+        }
+      }
+    },
+    400: { description: '用户名已存在' }
+  }
+})
+
+app.openapi(registerRoute, async (c) => {
+  const { username, password, email } = c.req.valid('json')
+  const user = await userService.createUser({ username, password, email })
+  const token = authService.generateToken(user)
+  return c.json({ token, user }, 201)
+})
+
+// 获取当前用户信息路由
+const meRoute = createRoute({
+  method: 'get',
+  path: '/auth/me',
+  security: [{ Bearer: [] }],
+  responses: {
+    200: {
+      description: '获取成功',
+      content: {
+        'application/json': {
+          schema: z.object({
+            id: z.number(),
+            username: z.string()
+          })
+        }
+      }
+    },
+    401: { description: '未授权' }
+  }
+})
+
+app.openapi(meRoute, async (c) => {
+  const user = c.get('user')
+  return c.json({
+    id: user.id,
+    username: user.username
+  })
+})
+
+export const authOpenApiApp = app

+ 1 - 1
src/server/api/base.ts

@@ -134,7 +134,7 @@ app.openapi(runMigrationRoute, async (c) => {
       migrations: migrations.map((m: Migration) => m.name)
     })
   } catch (error) {
-    throw new HTTPException(500, {cause: error})
+    throw error
   }
 })
 

+ 10 - 10
src/server/api/user.ts

@@ -46,14 +46,14 @@ const createUserRoute = createRoute({
   }
 });
 
-export const createUserHandler = app.openapi(createUserRoute, async (c) => {
+const createUserHandler = app.openapi(createUserRoute, async (c) => {
   const data = c.req.valid('query');
   const user = await userService.createUser(data);
   return c.json(user, 201);
 });
 
 // 获取用户列表
-export const listUsersRoute = createRoute({
+const listUsersRoute = createRoute({
   method: 'get',
   path: '/users',
   responses: {
@@ -68,7 +68,7 @@ export const listUsersRoute = createRoute({
   }
 });
 
-export const listUsersHandler = app.openapi(
+const listUsersHandler = app.openapi(
   listUsersRoute,
   async (c) => {
     const users = await userService.getUsers();
@@ -85,7 +85,7 @@ export const listUsersHandler = app.openapi(
 );
 
 // 获取单个用户
-export const getUserRoute = createRoute({
+const getUserRoute = createRoute({
   method: 'get',
   path: '/users/{id}',
   request: {
@@ -106,7 +106,7 @@ export const getUserRoute = createRoute({
   }
 });
 
-export const getUserHandler = app.openapi(
+const getUserHandler = app.openapi(
   getUserRoute,
   async (c) => {
     const { id } = c.req.valid('param');
@@ -117,7 +117,7 @@ export const getUserHandler = app.openapi(
 );
 
 // 更新用户
-export const updateUserRoute = createRoute({
+const updateUserRoute = createRoute({
   method: 'patch',
   path: '/users/{id}',
   request: {
@@ -145,7 +145,7 @@ export const updateUserRoute = createRoute({
   }
 });
 
-export const updateUserHandler = app.openapi(
+const updateUserHandler = app.openapi(
   updateUserRoute,
   async (c) => {
     const { id } = c.req.valid('param');
@@ -157,7 +157,7 @@ export const updateUserHandler = app.openapi(
 );
 
 // 删除用户
-export const deleteUserRoute = createRoute({
+const deleteUserRoute = createRoute({
   method: 'delete',
   path: '/users/{id}',
   request: {
@@ -171,7 +171,7 @@ export const deleteUserRoute = createRoute({
   }
 });
 
-export const deleteUserHandler = app.openapi(
+const deleteUserHandler = app.openapi(
   deleteUserRoute,
   async (c) => {
     const { id } = c.req.valid('param');
@@ -180,7 +180,7 @@ export const deleteUserHandler = app.openapi(
   }
 );
 
-export const userRoutes = {
+const userRoutes = {
   createUser: createUserHandler,
   listUsers: listUsersHandler,
   getUser: getUserHandler,

+ 2 - 2
src/server/middleware/errorHandler.ts

@@ -7,7 +7,7 @@ export const errorHandler = async (err: Error, c: Context) => {
       { 
         error: err.message,
         status: err.status ,
-        cause: err.cause
+        cause: err.cause instanceof Error ? err.cause.message : err.cause
       },
       err.status
     )
@@ -15,7 +15,7 @@ export const errorHandler = async (err: Error, c: Context) => {
 
   return c.json(
     { 
-      error: 'Internal Server Error',
+      error: err.message || 'Internal Server Error',
       status: 500 
     },
     500

+ 1 - 1
src/server/migrations/001-CreateUserTables.ts

@@ -1,7 +1,7 @@
 import { MigrationInterface, QueryRunner } from "typeorm";
 
 export class CreateUserTables implements MigrationInterface {
-    name = 'CreateUserTables'
+    name = 'CreateUserTables1748424204000'
 
     public async up(queryRunner: QueryRunner): Promise<void> {
         await queryRunner.query(`

+ 1 - 1
src/server/modules/auth/auth.service.ts

@@ -1,4 +1,4 @@
-import * as jwt from 'jsonwebtoken';
+import jwt from 'jsonwebtoken';
 import { UserService } from '../users/user.service';
 import { User } from '../users/user.entity';
 

+ 2 - 1
src/server/modules/users/user.service.ts

@@ -25,7 +25,8 @@ export class UserService {
       return await this.userRepository.save(user);
     } catch (error) {
       console.error('Error creating user:', error);
-      throw new Error('Failed to create user');
+      // throw new Error('Failed to create user');
+      throw new HTTPException(400,{ message: 'Failed to create user', cause: error})
     }
   }