user.service.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import { HTTPException } from 'hono/http-exception'
  2. import { DataSource } from 'typeorm';
  3. import { UserEntity as User } from './user.entity';
  4. import * as bcrypt from 'bcrypt';
  5. import { Repository } from 'typeorm';
  6. import { Role } from './role.entity';
  7. const SALT_ROUNDS = 10;
  8. export class UserService {
  9. private userRepository: Repository<User>;
  10. private roleRepository: Repository<Role>;
  11. private readonly dataSource: DataSource;
  12. constructor(dataSource: DataSource) {
  13. this.dataSource = dataSource;
  14. this.userRepository = this.dataSource.getRepository(User);
  15. this.roleRepository = this.dataSource.getRepository(Role);
  16. }
  17. async createUser(userData: Partial<User>): Promise<User> {
  18. try {
  19. if (userData.password) {
  20. userData.password = await bcrypt.hash(userData.password, SALT_ROUNDS);
  21. }
  22. const user = this.userRepository.create(userData);
  23. return await this.userRepository.save(user);
  24. } catch (error) {
  25. console.error('Error creating user:', error);
  26. throw new HTTPException(400,{ message: 'Failed to create user', cause: error})
  27. }
  28. }
  29. async getUserById(id: number): Promise<User | null> {
  30. try {
  31. return await this.userRepository.findOne({
  32. where: { id },
  33. relations: ['roles']
  34. });
  35. } catch (error) {
  36. console.error('Error getting user:', error);
  37. throw new Error('Failed to get user');
  38. }
  39. }
  40. async getUserByUsername(username: string): Promise<User | null> {
  41. try {
  42. return await this.userRepository.findOne({
  43. where: { username },
  44. relations: ['roles']
  45. });
  46. } catch (error) {
  47. console.error('Error getting user:', error);
  48. throw new Error('Failed to get user');
  49. }
  50. }
  51. async getUserByPhone(phone: string): Promise<User | null> {
  52. try {
  53. return await this.userRepository.findOne({
  54. where: { phone: phone },
  55. relations: ['roles']
  56. });
  57. } catch (error) {
  58. console.error('Error getting user by phone:', error);
  59. throw new Error('Failed to get user by phone');
  60. }
  61. }
  62. async updateUser(id: number, updateData: Partial<User>): Promise<User | null> {
  63. try {
  64. if (updateData.password) {
  65. updateData.password = await bcrypt.hash(updateData.password, SALT_ROUNDS);
  66. }
  67. await this.userRepository.update(id, updateData);
  68. return this.getUserById(id);
  69. } catch (error) {
  70. console.error('Error updating user:', error);
  71. throw new Error('Failed to update user');
  72. }
  73. }
  74. async deleteUser(id: number): Promise<void> {
  75. try {
  76. await this.userRepository.delete(id);
  77. } catch (error) {
  78. console.error('Error deleting user:', error);
  79. throw new Error('Failed to delete user');
  80. }
  81. }
  82. async getUsersWithPagination(params: {
  83. page: number;
  84. pageSize: number;
  85. keyword?: string;
  86. }): Promise<[User[], number]> {
  87. try {
  88. const { page, pageSize, keyword } = params;
  89. const skip = (page - 1) * pageSize;
  90. const queryBuilder = this.userRepository
  91. .createQueryBuilder('user')
  92. .leftJoinAndSelect('user.roles', 'roles')
  93. .skip(skip)
  94. .take(pageSize);
  95. if (keyword) {
  96. queryBuilder.where(
  97. 'user.username LIKE :keyword OR user.nickname LIKE :keyword OR user.phone LIKE :keyword',
  98. { keyword: `%${keyword}%` }
  99. );
  100. }
  101. return await queryBuilder.getManyAndCount();
  102. } catch (error) {
  103. console.error('Error getting users with pagination:', error);
  104. throw new Error('Failed to get users');
  105. }
  106. }
  107. async verifyPassword(user: User, password: string): Promise<boolean> {
  108. return password === user.password || bcrypt.compare(password, user.password)
  109. }
  110. async assignRoles(userId: number, roleIds: number[]): Promise<User | null> {
  111. try {
  112. const user = await this.getUserById(userId);
  113. if (!user) return null;
  114. const roles = await this.roleRepository.findByIds(roleIds);
  115. user.roles = roles;
  116. return await this.userRepository.save(user);
  117. } catch (error) {
  118. console.error('Error assigning roles:', error);
  119. throw new Error('Failed to assign roles');
  120. }
  121. }
  122. async getUsers(): Promise<User[]> {
  123. try {
  124. const users = await this.userRepository.find({
  125. relations: ['roles']
  126. });
  127. return users;
  128. } catch (error) {
  129. console.error('Error getting users:', error);
  130. throw new HTTPException(500, { message: 'Failed to get users', cause: error })
  131. }
  132. }
  133. getUserRepository(): Repository<User> {
  134. return this.userRepository;
  135. }
  136. async getUserByAccount(account: string): Promise<User | null> {
  137. try {
  138. return await this.userRepository.findOne({
  139. where: [{ username: account }, { email: account }],
  140. relations: ['roles']
  141. });
  142. } catch (error) {
  143. console.error('Error getting user by account:', error);
  144. throw new Error('Failed to get user by account');
  145. }
  146. }
  147. }