password.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import { createRoute, OpenAPIHono } from '@hono/zod-openapi'
  2. import { AuthService } from '../../../modules/auth/auth.service'
  3. import { UserService } from '../../../modules/users/user.service'
  4. import { z } from '@hono/zod-openapi'
  5. import { ErrorSchema } from '../../../utils/errorHandler'
  6. import { AppDataSource } from '../../../data-source'
  7. import { AuthContext } from '../../../types/context'
  8. import { UserSchema } from '@/server/modules/users/user.schema'
  9. const userService = new UserService(AppDataSource)
  10. const authService = new AuthService(userService)
  11. const LoginSchema = z.object({
  12. username: z.string().min(3).openapi({
  13. example: 'admin',
  14. description: '用户名'
  15. }),
  16. password: z.string().min(6).openapi({
  17. example: 'admin123',
  18. description: '密码'
  19. })
  20. })
  21. const UserResponseSchema = UserSchema
  22. const TokenResponseSchema = z.object({
  23. token: z.string().openapi({
  24. example: 'jwt.token.here',
  25. description: 'JWT Token'
  26. }),
  27. user: UserResponseSchema
  28. })
  29. const loginRoute = createRoute({
  30. method: 'post',
  31. path: '/login',
  32. request: {
  33. body: {
  34. content: {
  35. 'application/json': {
  36. schema: LoginSchema
  37. }
  38. }
  39. }
  40. },
  41. responses: {
  42. 200: {
  43. description: '登录成功',
  44. content: {
  45. 'application/json': {
  46. schema: TokenResponseSchema
  47. }
  48. }
  49. },
  50. 401: {
  51. description: '用户名或密码错误',
  52. content: {
  53. 'application/json': {
  54. schema: ErrorSchema
  55. }
  56. }
  57. },
  58. 500: {
  59. description: '服务器内部错误',
  60. content: {
  61. 'application/json': {
  62. schema: ErrorSchema
  63. }
  64. }
  65. }
  66. }
  67. })
  68. const app = new OpenAPIHono<AuthContext>().openapi(loginRoute, async (c) => {
  69. try {
  70. const { username, password } = c.req.valid('json')
  71. const result = await authService.login(username, password)
  72. return c.json(result, 200)
  73. } catch (error) {
  74. // 认证相关错误返回401
  75. if (error instanceof Error &&
  76. (error.message.includes('User not found') ||
  77. error.message.includes('Invalid password') ||
  78. error.message.includes('User account is disabled'))) {
  79. return c.json(
  80. {
  81. code: 401,
  82. message: error.message.includes('User account is disabled') ? '账户已禁用' : '用户名或密码错误'
  83. },
  84. 401
  85. )
  86. }
  87. // 其他错误重新抛出,由错误处理中间件处理
  88. throw error
  89. }
  90. });
  91. export default app