user.controller.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify'
  2. import { UserService } from '../services/user.service'
  3. import { MemberTokenManagerService } from '../services/member-token-manager.service'
  4. import {
  5. ListUserQuery,
  6. LoginBody,
  7. RegisterBody,
  8. ResetPasswordBody,
  9. CreateUserBody,
  10. UpdateUserBody
  11. } from '../dto/user.dto'
  12. import { UserRole } from '../entities/user.entity'
  13. export class UserController {
  14. private userService: UserService
  15. private tokenManagerService: MemberTokenManagerService
  16. constructor(app: FastifyInstance) {
  17. this.userService = new UserService(app)
  18. this.tokenManagerService = new MemberTokenManagerService(app)
  19. }
  20. async register(request: FastifyRequest<{ Body: RegisterBody }>, reply: FastifyReply) {
  21. try {
  22. const { password, name } = request.body
  23. const existingUser = await this.userService.findByName(name)
  24. if (existingUser) {
  25. return reply.code(400).send({ message: '用户名已存在' })
  26. }
  27. const user = await this.userService.create(password, name)
  28. const token = await reply.jwtSign({ id: user.id, name: user.name, role: user.role })
  29. return reply.code(201).send({
  30. user: {
  31. id: user.id,
  32. name: user.name
  33. },
  34. token
  35. })
  36. } catch (error) {
  37. return reply.code(500).send({ message: '注册失败' })
  38. }
  39. }
  40. async login(request: FastifyRequest<{ Body: LoginBody }>, reply: FastifyReply) {
  41. try {
  42. const { name, password } = request.body
  43. if (!name || !password) {
  44. return reply.code(400).send({ message: '请输入用户名和密码' })
  45. }
  46. const user = await this.userService.findByName(name)
  47. if (!user) {
  48. return reply.code(401).send({ message: '用户名或密码错误' })
  49. }
  50. if (!user.password) {
  51. return reply.code(401).send({ message: '该用户未设置密码,请联系管理员' })
  52. }
  53. const isValidPassword = await this.userService.validatePassword(user, password)
  54. if (!isValidPassword) {
  55. return reply.code(401).send({ message: '用户名或密码错误' })
  56. }
  57. // 单点登录:使该用户的所有其他token失效
  58. await this.tokenManagerService.invalidateUserTokens(user.id)
  59. const token = await reply.jwtSign({ id: user.id, name: user.name, role: user.role })
  60. return reply.send({
  61. user: {
  62. id: user.id,
  63. name: user.name
  64. },
  65. token,
  66. message: '登录成功,其他设备已自动下线'
  67. })
  68. } catch (error) {
  69. return reply.code(500).send({ message: '登录失败' })
  70. }
  71. }
  72. async profile(request: FastifyRequest, reply: FastifyReply) {
  73. try {
  74. const user = await this.userService.findById(request.user.id)
  75. return reply.send({
  76. id: user.id,
  77. name: user.name,
  78. role: user.role
  79. })
  80. } catch (error) {
  81. return reply.code(500).send({ message: '获取用户信息失败' })
  82. }
  83. }
  84. async resetPassword(request: FastifyRequest<{ Body: ResetPasswordBody }>, reply: FastifyReply) {
  85. try {
  86. const { password } = request.body
  87. if (password.length < 8 || !/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(password)) {
  88. return reply.code(400).send({ message: '密码长度必须至少8位,包含大小写字母和数字' })
  89. }
  90. await this.userService.resetPassword(request.user.id, password)
  91. return reply.send({ message: '密码重置成功' })
  92. } catch (error) {
  93. return reply.code(500).send({ message: '重置密码失败' })
  94. }
  95. }
  96. async list(request: FastifyRequest<{ Querystring: ListUserQuery }>, reply: FastifyReply) {
  97. try {
  98. const { user, query } = request
  99. if (!user) {
  100. return reply.code(403).send({
  101. error: 'Forbidden',
  102. message: 'Unauthorized access'
  103. })
  104. }
  105. const parentId = user.id
  106. const { page, size } = query
  107. const result = await this.userService.findAllChildUsers(parentId, page, size)
  108. return reply.send(result)
  109. } catch (error) {
  110. request.log.error({ error }, '获取用户列表失败')
  111. const errorMessage = error instanceof Error ? error.message : '获取用户列表失败'
  112. return reply.code(500).send({
  113. message: '获取用户列表失败',
  114. error: errorMessage
  115. })
  116. }
  117. }
  118. async getAllUsers(request: FastifyRequest, reply: FastifyReply) {
  119. const users = await this.userService.findAllUsers()
  120. return reply.send(users)
  121. }
  122. async createUser(request: FastifyRequest<{ Body: CreateUserBody }>, reply: FastifyReply) {
  123. try {
  124. const { password, name, role } = request.body
  125. const existingUser = await this.userService.findByName(name)
  126. if (existingUser) {
  127. return reply.code(400).send({ message: '用户名已存在' })
  128. }
  129. const user = await this.userService.create(password, name, role, request.user.id)
  130. return reply.code(201).send({
  131. user: {
  132. id: user.id,
  133. name: user.name,
  134. role: user.role,
  135. createdAt: user.createdAt,
  136. updatedAt: user.updatedAt
  137. }
  138. })
  139. } catch (error) {
  140. return reply.code(500).send({ message: '创建用户失败' })
  141. }
  142. }
  143. async updateUser(request: FastifyRequest<{ Body: UpdateUserBody }>, reply: FastifyReply) {
  144. try {
  145. const { id, name, password, role } = request.body
  146. try {
  147. await this.userService.findById(id)
  148. } catch (error) {
  149. return reply.code(404).send({ message: '用户不存在' })
  150. }
  151. if (name) {
  152. const existingUser = await this.userService.findByName(name)
  153. if (existingUser && existingUser.id !== id) {
  154. return reply.code(400).send({ message: '用户名已存在' })
  155. }
  156. }
  157. const updatedUser = await this.userService.updateUser(id, { name, password, role })
  158. return reply.send({
  159. user: {
  160. id: updatedUser.id,
  161. name: updatedUser.name,
  162. role: updatedUser.role,
  163. createdAt: updatedUser.createdAt,
  164. updatedAt: updatedUser.updatedAt
  165. }
  166. })
  167. } catch (error) {
  168. return reply.code(500).send({ message: '更新用户失败' })
  169. }
  170. }
  171. async getChildApiUsers(request: FastifyRequest<{ Querystring: { parentId?: number } }>, reply: FastifyReply) {
  172. try {
  173. const parentId = request.query.parentId || request.user.id
  174. const childUsers = await this.userService.findChildChannelUsers(parentId)
  175. return reply.send({
  176. users: childUsers
  177. })
  178. } catch (error) {
  179. return reply.code(500).send({ message: '获取子用户失败' })
  180. }
  181. }
  182. /**
  183. * 用户登出
  184. * 使当前token失效
  185. */
  186. async logout(request: FastifyRequest, reply: FastifyReply) {
  187. try {
  188. // 使当前用户的所有token失效(包括当前token)
  189. await this.tokenManagerService.invalidateUserTokens(request.user.id)
  190. return reply.send({
  191. message: '登出成功,所有设备已下线'
  192. })
  193. } catch (error) {
  194. return reply.code(500).send({ message: '登出失败' })
  195. }
  196. }
  197. }