sys_user_service.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. from datetime import datetime, timedelta
  2. from typing import Optional
  3. from sqlalchemy import select
  4. from core.enums import StatusTypeEnum, DeleteTypeEnum
  5. from core.exceptions import ServiceWarning
  6. from domain.dtos import SysUserDto, SysUserCreateDto, SysUserUpdateDto
  7. from domain.models import SysUserModel
  8. from domain.services.admin.common_services import CommonService
  9. from domain.services.base_services import CurdServiceBase
  10. from utils import PwdUtil
  11. class SysUserService(
  12. CurdServiceBase[SysUserModel, SysUserDto, SysUserCreateDto, SysUserUpdateDto]
  13. ):
  14. def __init__(self, db_name: Optional[str] = None):
  15. super().__init__(
  16. SysUserModel,
  17. SysUserDto,
  18. SysUserCreateDto,
  19. SysUserUpdateDto,
  20. db_name=db_name,
  21. )
  22. self._common_service = CommonService()
  23. async def get_user_detail_by_id(self, id: int):
  24. """
  25. 查询用户详细信息
  26. :param id:
  27. :return:
  28. """
  29. data = await self._common_service.get_user_detail_by_id(id)
  30. return data
  31. async def get_user_by_username(self, username: str) -> SysUserModel | None:
  32. """
  33. 根据用户名查询用户
  34. :param username:
  35. :return:
  36. """
  37. try:
  38. async with await self._get_async_db() as db:
  39. user = (
  40. (
  41. await db.execute(
  42. select(SysUserModel)
  43. .where(
  44. SysUserModel.username == username,
  45. SysUserModel.status == StatusTypeEnum.NORMAL.key,
  46. SysUserModel.is_del == DeleteTypeEnum.NORMAL.key,
  47. )
  48. .distinct()
  49. )
  50. )
  51. .scalars()
  52. .first()
  53. )
  54. return user
  55. except Exception as e:
  56. raise ServiceWarning(f"查询用户失败:{str(e)}")
  57. async def get_user_by_phone(self, phone: str) -> SysUserModel | None:
  58. """
  59. 根据手机号查询用户名
  60. :param phone:
  61. :return:
  62. """
  63. try:
  64. async with self._get_async_db() as db:
  65. user = (
  66. (
  67. await db.execute(
  68. select(SysUserModel)
  69. .where(
  70. SysUserModel.phonenumber == phone,
  71. SysUserModel.status == StatusTypeEnum.NORMAL.key,
  72. SysUserModel.is_del == DeleteTypeEnum.NORMAL.key,
  73. )
  74. .distinct()
  75. )
  76. )
  77. .scalars()
  78. .first()
  79. )
  80. return user
  81. except Exception as e:
  82. raise ServiceWarning(f"查询用户失败:{str(e)}")
  83. async def get_user_by_email(self, email: str) -> SysUserModel | None:
  84. """
  85. 根据电子邮箱查询用户
  86. :param email:
  87. :return:
  88. """
  89. try:
  90. async with self._get_async_db() as db:
  91. user = (
  92. (
  93. await db.execute(
  94. select(SysUserModel)
  95. .where(
  96. SysUserModel.email == email,
  97. SysUserModel.status == StatusTypeEnum.NORMAL.key,
  98. SysUserModel.is_del == DeleteTypeEnum.NORMAL.key,
  99. )
  100. .distinct()
  101. )
  102. )
  103. .scalars()
  104. .first()
  105. )
  106. return user
  107. except Exception as e:
  108. raise ServiceWarning(f"查询用户失败:{str(e)}")
  109. async def create_user(self, create_dto: SysUserCreateDto):
  110. """
  111. 创建用户
  112. :param create_dto:
  113. :return:
  114. """
  115. await self.check_user_exists(create_dto)
  116. create_dto.password = PwdUtil.get_password_hash(create_dto.password)
  117. try:
  118. async with self._get_async_db() as db:
  119. user = SysUserModel(**create_dto.to_dict())
  120. db.add(user)
  121. await db.commit()
  122. await db.refresh(user)
  123. return user
  124. except Exception as e:
  125. raise ServiceWarning(f"创建用户失败:{str(e)}")
  126. async def update_user(self, update_dto: SysUserUpdateDto):
  127. """
  128. 更新用户
  129. :param update_dto:
  130. :return:
  131. """
  132. user = await self.check_user(update_dto.user_id)
  133. await self.check_user_exists(update_dto, update_dto.user_id)
  134. if not user:
  135. raise ServiceWarning("用户不存在")
  136. try:
  137. async with self._get_async_db() as db:
  138. new_user = self._apply_map_update_model(user, update_dto)
  139. await db.commit()
  140. await db.refresh(new_user)
  141. return new_user
  142. except Exception as e:
  143. raise ServiceWarning(f"更新用户失败:{str(e)}")
  144. async def check_user_exists(
  145. self, dto: SysUserCreateDto | SysUserUpdateDto, user_id: int = None
  146. ):
  147. """
  148. 检查用户是否存在
  149. :param dto:
  150. :param user_id:
  151. :return:
  152. """
  153. await self.check_user_username_exists(dto.username, user_id)
  154. await self.check_user_phone_exists(dto.phone, user_id)
  155. await self.check_user_email_exists(dto.email, user_id)
  156. async def check_user_username_exists(self, username: str, user_id: int = None):
  157. """
  158. 检查用户是否存在
  159. :param username:
  160. :param user_id:
  161. :return:
  162. """
  163. user = await self.get_user_by_username(username)
  164. if user and user.id != user_id:
  165. raise ServiceWarning("用户名已存在")
  166. async def check_user_phone_exists(self, phone: str, user_id: int = None):
  167. """
  168. 检查用户是否存在
  169. :param phone:
  170. :param user_id:
  171. :return:
  172. """
  173. user = await self.get_user_by_phone(phone)
  174. if user and user.id != user_id:
  175. raise ServiceWarning("手机号已存在")
  176. async def check_user_email_exists(self, email: str, user_id: int = None):
  177. """
  178. 检查用户是否存在
  179. :param email:
  180. :param user_id:
  181. :return:
  182. """
  183. user = await self.get_user_by_email(email)
  184. if user and user.id != user_id:
  185. raise ServiceWarning("邮箱已存在")
  186. async def check_user(self, user_id: int):
  187. """
  188. 删除用户
  189. :param user_id:
  190. :return:
  191. """
  192. user = await self.get(user_id)
  193. if not user:
  194. raise ServiceWarning("用户不存在")
  195. if user.status == StatusTypeEnum.DISABLE.key:
  196. raise ServiceWarning("用户已禁用")
  197. if user.is_del == DeleteTypeEnum.DELETE.key:
  198. raise ServiceWarning("用户已删除")
  199. if user.is_lock == 1:
  200. raise ServiceWarning("用户已锁定")
  201. return user
  202. async def reset_password(self, user_id, new_password):
  203. """
  204. 重置密码
  205. :param user_id:
  206. :param new_password:
  207. :return:
  208. """
  209. try:
  210. async with self._get_async_db() as db:
  211. user = await db.get(SysUserModel, user_id)
  212. if user:
  213. user.password = PwdUtil.get_password_hash(new_password)
  214. await db.commit()
  215. await db.refresh(user)
  216. return user
  217. else:
  218. raise ValueError(f"未查询到ID为{user_id}的用户")
  219. except Exception as e:
  220. raise ServiceWarning(f"重置密码失败:{str(e)}")
  221. async def unlock_user(self, user_id):
  222. """
  223. 解锁用户
  224. :param user_id:
  225. :return:
  226. """
  227. user = await self.get(user_id)
  228. try:
  229. async with self._get_async_db() as db:
  230. if user:
  231. user.is_lock = 0
  232. await db.commit()
  233. await db.refresh(user)
  234. return user
  235. else:
  236. raise ValueError(f"未查询到ID为{user_id}的用户")
  237. except Exception as e:
  238. raise ServiceWarning(f"解锁用户失败:{str(e)}")
  239. async def login(self, username: str, password: str):
  240. """
  241. 登录
  242. :param username:
  243. :param password:
  244. :return:
  245. """
  246. if not isinstance(username, str) or not username.strip():
  247. raise ServiceWarning("用户名不能为空")
  248. try:
  249. user = await self.get_user_by_username(username)
  250. if not user:
  251. user = await self.get_user_by_phone(username)
  252. if not user:
  253. user = await self.get_user_by_email(username)
  254. if not user:
  255. raise ServiceWarning("用户不存在")
  256. if user.status == StatusTypeEnum.DISABLE.key:
  257. raise ServiceWarning("用户已禁用")
  258. if user.is_del == DeleteTypeEnum.DELETE.key:
  259. raise ServiceWarning("用户已删除")
  260. if user.is_lock == 1 and datetime.now() - user.lock_at <= timedelta(
  261. minutes=10
  262. ):
  263. raise ServiceWarning("用户已锁定")
  264. if PwdUtil.verify_password(password, user.password):
  265. async with self._get_async_db() as db:
  266. user.login_fail_count = 0
  267. user.is_lock = 0
  268. await db.commit()
  269. await db.refresh(user)
  270. return user
  271. else:
  272. async with self._get_async_db() as db:
  273. if user.login_fail_count >= 5:
  274. user.is_lock = 1
  275. user.lock_at = datetime.now()
  276. else:
  277. user.login_fail_count += 1
  278. await db.commit()
  279. await db.refresh(user)
  280. raise ServiceWarning("密码错误")
  281. except Exception as e:
  282. raise ServiceWarning(f"登录失败:{str(e)}")
  283. async def change_password(self, user_id, old_password, new_password):
  284. """
  285. 修改密码
  286. :param user_id:
  287. :param old_password:
  288. :param new_password:
  289. :return:
  290. """
  291. user = await self.check_user(user_id)
  292. if not PwdUtil.verify_password(old_password, user.password):
  293. raise ServiceWarning("旧密码错误")
  294. try:
  295. async with self._get_async_db() as db:
  296. user.password = PwdUtil.get_password_hash(new_password)
  297. await db.commit()
  298. await db.refresh(user)
  299. return user
  300. except Exception as e:
  301. raise ServiceWarning(f"修改密码失败:{str(e)}")