user.service.mt.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. import { DataSource } from 'typeorm';
  2. import { UserEntityMt } from '../entities/user.entity.mt';
  3. import { RoleServiceMt } from './role.service.mt';
  4. import { ConcreteCrudService } from '@d8d/shared-crud';
  5. import * as bcrypt from 'bcrypt';
  6. const SALT_ROUNDS = 10;
  7. export class UserServiceMt extends ConcreteCrudService<UserEntityMt> {
  8. private roleService: RoleServiceMt;
  9. constructor(dataSource: DataSource) {
  10. super(UserEntityMt, {
  11. userTracking: {
  12. createdByField: 'createdBy',
  13. updatedByField: 'updatedBy'
  14. },
  15. tenantOptions: {
  16. tenantIdField: 'tenantId',
  17. autoExtractFromContext: true
  18. }
  19. });
  20. this.roleService = new RoleServiceMt(dataSource);
  21. }
  22. /**
  23. * 创建用户,自动设置租户ID并加密密码
  24. */
  25. async createUser(userData: Partial<UserEntityMt>, tenantId?: number): Promise<UserEntityMt> {
  26. try {
  27. // 检查用户名是否已存在(租户内唯一)
  28. if (userData.username) {
  29. const existingUser = await this.getUserByUsername(userData.username, tenantId);
  30. if (existingUser) {
  31. throw new Error('用户名已存在');
  32. }
  33. }
  34. if (userData.password) {
  35. userData.password = await bcrypt.hash(userData.password, SALT_ROUNDS);
  36. }
  37. // 如果提供了租户ID,自动设置
  38. if (tenantId !== undefined) {
  39. userData.tenantId = tenantId;
  40. } else {
  41. // 如果没有提供租户ID,设置默认租户ID为1
  42. userData.tenantId = 1;
  43. }
  44. return await this.create(userData);
  45. } catch (error) {
  46. console.error('Error creating user:', error);
  47. throw new Error(`Failed to create user: ${error instanceof Error ? error.message : String(error)}`);
  48. }
  49. }
  50. /**
  51. * 根据用户名获取用户(自动添加租户过滤)
  52. */
  53. async getUserByUsername(username: string, tenantId?: number): Promise<UserEntityMt | null> {
  54. try {
  55. const where: any = { username };
  56. // 如果提供了租户ID,添加租户过滤
  57. if (tenantId !== undefined) {
  58. where.tenantId = tenantId;
  59. }
  60. return await this.repository.findOne({ where, relations: ['roles', 'avatarFile'] });
  61. } catch (error) {
  62. console.error('Error getting user by username:', error);
  63. throw new Error('Failed to get user by username');
  64. }
  65. }
  66. /**
  67. * 根据手机号获取用户(自动添加租户过滤)
  68. */
  69. async getUserByPhone(phone: string, tenantId?: number): Promise<UserEntityMt | null> {
  70. try {
  71. const where: any = { phone };
  72. // 如果提供了租户ID,添加租户过滤
  73. if (tenantId !== undefined) {
  74. where.tenantId = tenantId;
  75. }
  76. return await this.repository.findOne({ where, relations: ['roles', 'avatarFile'] });
  77. } catch (error) {
  78. console.error('Error getting user by phone:', error);
  79. throw new Error('Failed to get user by phone');
  80. }
  81. }
  82. /**
  83. * 根据账号(用户名或邮箱)获取用户(自动添加租户过滤)
  84. */
  85. async getUserByAccount(account: string, tenantId?: number): Promise<UserEntityMt | null> {
  86. try {
  87. const where: any = [
  88. { username: account },
  89. { email: account }
  90. ];
  91. // 如果提供了租户ID,添加租户过滤
  92. if (tenantId !== undefined) {
  93. where.forEach((condition: any) => {
  94. condition.tenantId = tenantId;
  95. });
  96. }
  97. return await this.repository.findOne({ where, relations: ['roles', 'avatarFile'] });
  98. } catch (error) {
  99. console.error('Error getting user by account:', error);
  100. throw new Error('Failed to get user by account');
  101. }
  102. }
  103. /**
  104. * 验证密码
  105. */
  106. async verifyPassword(user: UserEntityMt, password: string): Promise<boolean> {
  107. return password === user.password || bcrypt.compare(password, user.password);
  108. }
  109. /**
  110. * 为用户分配角色
  111. */
  112. async assignRoles(userId: number, roleIds: number[], tenantId?: number): Promise<UserEntityMt | null> {
  113. try {
  114. const user = await this.getById(userId, ['roles']);
  115. if (!user) return null;
  116. // 验证租户一致性
  117. if (tenantId !== undefined && user.tenantId !== tenantId) {
  118. throw new Error('无权操作该用户');
  119. }
  120. // 获取角色实体
  121. const roles = [];
  122. for (const roleId of roleIds) {
  123. const role = await this.roleService.getById(roleId);
  124. if (role) {
  125. // 验证角色租户一致性
  126. if (tenantId !== undefined && role.tenantId !== tenantId) {
  127. throw new Error(`无权操作角色ID: ${roleId}`);
  128. }
  129. roles.push(role);
  130. }
  131. }
  132. // 分配角色
  133. user.roles = roles;
  134. return await this.repository.save(user);
  135. } catch (error) {
  136. console.error('Error assigning roles:', error);
  137. throw new Error('Failed to assign roles');
  138. }
  139. }
  140. /**
  141. * 根据ID获取用户(自动添加租户过滤)
  142. */
  143. async getUserById(id: number, tenantId?: number): Promise<UserEntityMt | null> {
  144. try {
  145. const where: any = { id };
  146. // 如果提供了租户ID,添加租户过滤
  147. if (tenantId !== undefined) {
  148. where.tenantId = tenantId;
  149. }
  150. return await this.repository.findOne({ where, relations: ['roles', 'avatarFile'] });
  151. } catch (error) {
  152. console.error('Error getting user by id:', error);
  153. throw new Error('Failed to get user by id');
  154. }
  155. }
  156. /**
  157. * 更新用户信息(自动添加租户过滤)
  158. */
  159. async updateUser(id: number, userData: Partial<UserEntityMt>, tenantId?: number): Promise<UserEntityMt | null> {
  160. try {
  161. // 首先验证用户是否存在且属于指定租户
  162. const existingUser = await this.getUserById(id, tenantId);
  163. if (!existingUser) return null;
  164. // 如果更新密码,需要加密
  165. if (userData.password) {
  166. userData.password = await bcrypt.hash(userData.password, SALT_ROUNDS);
  167. }
  168. return await this.update(id, userData);
  169. } catch (error) {
  170. console.error('Error updating user:', error);
  171. throw new Error('Failed to update user');
  172. }
  173. }
  174. /**
  175. * 删除用户(自动添加租户过滤)
  176. */
  177. async deleteUser(id: number, tenantId?: number): Promise<boolean> {
  178. try {
  179. // 首先验证用户是否存在且属于指定租户
  180. const existingUser = await this.getUserById(id, tenantId);
  181. if (!existingUser) return false;
  182. return await this.delete(id);
  183. } catch (error) {
  184. console.error('Error deleting user:', error);
  185. throw new Error('Failed to delete user');
  186. }
  187. }
  188. /**
  189. * 获取所有用户(自动添加租户过滤)
  190. */
  191. async getUsers(tenantId?: number): Promise<UserEntityMt[]> {
  192. try {
  193. const where: any = {};
  194. // 如果提供了租户ID,添加租户过滤
  195. if (tenantId !== undefined) {
  196. where.tenantId = tenantId;
  197. }
  198. const [users] = await this.getList(1, 100, undefined, undefined, where, ['roles', 'avatarFile']);
  199. return users;
  200. } catch (error) {
  201. console.error('Error getting users:', error);
  202. throw new Error(`Failed to get users: ${error instanceof Error ? error.message : String(error)}`);
  203. }
  204. }
  205. }