import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify' import { UserService } from '../services/user.service' import { MemberTokenManagerService } from '../services/member-token-manager.service' import { ListUserQuery, LoginBody, RegisterBody, ResetPasswordBody, CreateUserBody, UpdateUserBody } from '../dto/user.dto' import { UserRole } from '../entities/user.entity' export class UserController { private userService: UserService private tokenManagerService: MemberTokenManagerService constructor(app: FastifyInstance) { this.userService = new UserService(app) this.tokenManagerService = new MemberTokenManagerService(app) } async register(request: FastifyRequest<{ Body: RegisterBody }>, reply: FastifyReply) { try { const { password, name } = request.body const existingUser = await this.userService.findByName(name) if (existingUser) { return reply.code(400).send({ message: '用户名已存在' }) } const user = await this.userService.create(password, name) const token = await reply.jwtSign({ id: user.id, name: user.name, role: user.role }) return reply.code(201).send({ user: { id: user.id, name: user.name }, token }) } catch (error) { return reply.code(500).send({ message: '注册失败' }) } } async login(request: FastifyRequest<{ Body: LoginBody }>, reply: FastifyReply) { try { const { name, password } = request.body if (!name || !password) { return reply.code(400).send({ message: '请输入用户名和密码' }) } const user = await this.userService.findByName(name) if (!user) { return reply.code(401).send({ message: '用户名或密码错误' }) } if (!user.password) { return reply.code(401).send({ message: '该用户未设置密码,请联系管理员' }) } const isValidPassword = await this.userService.validatePassword(user, password) if (!isValidPassword) { return reply.code(401).send({ message: '用户名或密码错误' }) } // 单点登录:使该用户的所有其他token失效 await this.tokenManagerService.invalidateUserTokens(user.id) const token = await reply.jwtSign({ id: user.id, name: user.name, role: user.role }) return reply.send({ user: { id: user.id, name: user.name }, token, message: '登录成功,其他设备已自动下线' }) } catch (error) { return reply.code(500).send({ message: '登录失败' }) } } async profile(request: FastifyRequest, reply: FastifyReply) { try { const user = await this.userService.findById(request.user.id) return reply.send({ id: user.id, name: user.name, role: user.role }) } catch (error) { return reply.code(500).send({ message: '获取用户信息失败' }) } } async resetPassword(request: FastifyRequest<{ Body: ResetPasswordBody }>, reply: FastifyReply) { try { const { password } = request.body if (password.length < 8 || !/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(password)) { return reply.code(400).send({ message: '密码长度必须至少8位,包含大小写字母和数字' }) } await this.userService.resetPassword(request.user.id, password) return reply.send({ message: '密码重置成功' }) } catch (error) { return reply.code(500).send({ message: '重置密码失败' }) } } async list(request: FastifyRequest<{ Querystring: ListUserQuery }>, reply: FastifyReply) { try { const { user, query } = request if (!user) { return reply.code(403).send({ error: 'Forbidden', message: 'Unauthorized access' }) } const parentId = user.id const { page, size } = query const result = await this.userService.findAllChildUsers(parentId, page, size) return reply.send(result) } catch (error) { request.log.error({ error }, '获取用户列表失败') const errorMessage = error instanceof Error ? error.message : '获取用户列表失败' return reply.code(500).send({ message: '获取用户列表失败', error: errorMessage }) } } async getAllUsers(request: FastifyRequest, reply: FastifyReply) { const users = await this.userService.findAllUsers() return reply.send(users) } async createUser(request: FastifyRequest<{ Body: CreateUserBody }>, reply: FastifyReply) { try { const { password, name, role } = request.body const existingUser = await this.userService.findByName(name) if (existingUser) { return reply.code(400).send({ message: '用户名已存在' }) } const user = await this.userService.create(password, name, role, request.user.id) return reply.code(201).send({ user: { id: user.id, name: user.name, role: user.role, createdAt: user.createdAt, updatedAt: user.updatedAt } }) } catch (error) { return reply.code(500).send({ message: '创建用户失败' }) } } async updateUser(request: FastifyRequest<{ Body: UpdateUserBody }>, reply: FastifyReply) { try { const { id, name, password, role } = request.body try { await this.userService.findById(id) } catch (error) { return reply.code(404).send({ message: '用户不存在' }) } if (name) { const existingUser = await this.userService.findByName(name) if (existingUser && existingUser.id !== id) { return reply.code(400).send({ message: '用户名已存在' }) } } const updatedUser = await this.userService.updateUser(id, { name, password, role }) return reply.send({ user: { id: updatedUser.id, name: updatedUser.name, role: updatedUser.role, createdAt: updatedUser.createdAt, updatedAt: updatedUser.updatedAt } }) } catch (error) { return reply.code(500).send({ message: '更新用户失败' }) } } async getChildApiUsers(request: FastifyRequest<{ Querystring: { parentId?: number } }>, reply: FastifyReply) { try { const parentId = request.query.parentId || request.user.id const childUsers = await this.userService.findChildChannelUsers(parentId) return reply.send({ users: childUsers }) } catch (error) { return reply.code(500).send({ message: '获取子用户失败' }) } } /** * 用户登出 * 使当前token失效 */ async logout(request: FastifyRequest, reply: FastifyReply) { try { // 使当前用户的所有token失效(包括当前token) await this.tokenManagerService.invalidateUserTokens(request.user.id) return reply.send({ message: '登出成功,所有设备已下线' }) } catch (error) { return reply.code(500).send({ message: '登出失败' }) } } }