SystemUserLogic.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | saiadmin [ saiadmin快速开发框架 ]
  4. // +----------------------------------------------------------------------
  5. // | Author: sai <1430792918@qq.com>
  6. // +----------------------------------------------------------------------
  7. namespace plugin\saiadmin\app\logic\system;
  8. use plugin\saiadmin\app\cache\UserAuthCache;
  9. use plugin\saiadmin\app\cache\UserInfoCache;
  10. use plugin\saiadmin\app\cache\UserMenuCache;
  11. use plugin\saiadmin\app\model\system\SystemDept;
  12. use plugin\saiadmin\app\model\system\SystemRole;
  13. use plugin\saiadmin\app\model\system\SystemUser;
  14. use plugin\saiadmin\exception\ApiException;
  15. use plugin\saiadmin\basic\think\BaseLogic;
  16. use Webman\Event\Event;
  17. use Tinywan\Jwt\JwtToken;
  18. /**
  19. * 用户信息逻辑层
  20. */
  21. class SystemUserLogic extends BaseLogic
  22. {
  23. /**
  24. * 构造函数
  25. */
  26. public function __construct()
  27. {
  28. $this->model = new SystemUser();
  29. }
  30. /**
  31. * 分页数据列表
  32. * @param mixed $where
  33. * @return array
  34. */
  35. public function indexList($where): array
  36. {
  37. $query = $this->search($where);
  38. $query->with(['depts']);
  39. $query->auth($this->adminInfo['deptList']);
  40. return $this->getList($query);
  41. }
  42. /**
  43. * 用户列表数据
  44. * @param mixed $where
  45. * @return array
  46. */
  47. public function openUserList($where): array
  48. {
  49. $query = $this->search($where);
  50. $query->field('id, username, realname, avatar, phone, email');
  51. return $this->getList($query);
  52. }
  53. /**
  54. * 读取用户信息
  55. * @param mixed $id
  56. * @return array
  57. */
  58. public function getUser($id): array
  59. {
  60. $admin = $this->model->findOrEmpty($id);
  61. $data = $admin->hidden(['password'])->toArray();
  62. $data['roleList'] = $admin->roles->toArray() ?: [];
  63. $data['postList'] = $admin->posts->toArray() ?: [];
  64. $data['deptList'] = $admin->depts ? $admin->depts->toArray() : [];
  65. return $data;
  66. }
  67. /**
  68. * 读取数据
  69. * @param $id
  70. * @return array
  71. */
  72. public function read($id): array
  73. {
  74. $data = $this->getUser($id);
  75. if ($this->adminInfo['id'] > 1) {
  76. // 部门保护
  77. if (!$this->deptProtect($this->adminInfo['deptList'], $data['dept_id'])) {
  78. throw new ApiException('没有权限操作该部门数据');
  79. }
  80. }
  81. return $data;
  82. }
  83. /**
  84. * 添加数据
  85. * @param $data
  86. * @return mixed
  87. */
  88. public function add($data): mixed
  89. {
  90. $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
  91. return $this->transaction(function () use ($data) {
  92. $role_ids = $data['role_ids'] ?? [];
  93. $post_ids = $data['post_ids'] ?? [];
  94. if ($this->adminInfo['id'] > 1) {
  95. // 部门保护
  96. if (!$this->deptProtect($this->adminInfo['deptList'], $data['dept_id'])) {
  97. throw new ApiException('没有权限操作该部门数据');
  98. }
  99. // 越权保护
  100. if (!$this->roleProtect($this->adminInfo['roleList'], $role_ids)) {
  101. throw new ApiException('没有权限操作该角色数据');
  102. }
  103. }
  104. $user = SystemUser::create($data);
  105. $user->roles()->detach();
  106. $user->posts()->detach();
  107. $user->roles()->saveAll($role_ids);
  108. if (!empty($post_ids)) {
  109. $user->posts()->save($post_ids);
  110. }
  111. return $user;
  112. });
  113. }
  114. /**
  115. * 修改数据
  116. * @param $id
  117. * @param $data
  118. * @return mixed
  119. */
  120. public function edit($id, $data): mixed
  121. {
  122. unset($data['password']);
  123. return $this->transaction(function () use ($data, $id) {
  124. $role_ids = $data['role_ids'] ?? [];
  125. $post_ids = $data['post_ids'] ?? [];
  126. // 仅可修改当前部门和子部门的用户
  127. $query = $this->model->where('id', $id);
  128. $query->auth($this->adminInfo['deptList']);
  129. $user = $query->findOrEmpty();
  130. if ($user->isEmpty()) {
  131. throw new ApiException('没有权限操作该数据');
  132. }
  133. if ($this->adminInfo['id'] > 1) {
  134. // 部门保护
  135. if (!$this->deptProtect($this->adminInfo['deptList'], $data['dept_id'])) {
  136. throw new ApiException('没有权限操作该部门数据');
  137. }
  138. // 越权保护
  139. if (!$this->roleProtect($this->adminInfo['roleList'], $role_ids)) {
  140. throw new ApiException('没有权限操作该角色数据');
  141. }
  142. }
  143. $result = parent::edit($id, $data);
  144. if ($result) {
  145. $user->roles()->detach();
  146. $user->posts()->detach();
  147. $user->roles()->saveAll($role_ids);
  148. if (!empty($post_ids)) {
  149. $user->posts()->save($post_ids);
  150. }
  151. UserInfoCache::clearUserInfo($id);
  152. UserAuthCache::clearUserAuth($id);
  153. UserMenuCache::clearUserMenu($id);
  154. }
  155. return $result;
  156. });
  157. }
  158. /**
  159. * 删除数据
  160. * @param $ids
  161. * @return bool
  162. */
  163. public function destroy($ids): bool
  164. {
  165. if (is_array($ids)) {
  166. if (count($ids) > 1) {
  167. throw new ApiException('禁止批量删除操作');
  168. }
  169. $ids = $ids[0];
  170. }
  171. if ($ids == 1) {
  172. throw new ApiException('超级管理员禁止删除');
  173. }
  174. $query = $this->model->where('id', $ids);
  175. $query->auth($this->adminInfo['deptList']);
  176. $user = $query->findOrEmpty();
  177. if ($user->isEmpty()) {
  178. throw new ApiException('没有权限操作该数据');
  179. }
  180. if ($this->adminInfo['id'] > 1) {
  181. $role_ids = $user->roles->toArray() ?: [];
  182. if (!empty($role_ids)) {
  183. // 越权保护
  184. if (!$this->roleProtect($this->adminInfo['roleList'], array_column($role_ids, 'id'))) {
  185. throw new ApiException('没有权限操作该角色数据');
  186. }
  187. }
  188. }
  189. UserInfoCache::clearUserInfo($ids);
  190. UserAuthCache::clearUserAuth($ids);
  191. UserMenuCache::clearUserMenu($ids);
  192. return parent::destroy($ids);
  193. }
  194. /**
  195. * 用户登录
  196. * @param string $username
  197. * @param string $password
  198. * @param string $type
  199. * @return array
  200. */
  201. public function login(string $username, string $password, string $type): array
  202. {
  203. $adminInfo = $this->model->where('username', $username)->findOrEmpty();
  204. $status = 1;
  205. $message = '登录成功';
  206. if ($adminInfo->isEmpty()) {
  207. $message = '账号或密码错误,请重新输入!';
  208. throw new ApiException($message);
  209. }
  210. if ($adminInfo->status === 2) {
  211. $status = 0;
  212. $message = '您已被禁止登录!';
  213. }
  214. if (!password_verify($password, $adminInfo->password)) {
  215. $status = 0;
  216. $message = '账号或密码错误,请重新输入!';
  217. }
  218. if ($status === 0) {
  219. // 登录事件
  220. Event::emit('user.login', compact('username', 'status', 'message'));
  221. throw new ApiException($message);
  222. }
  223. $adminInfo->login_time = date('Y-m-d H:i:s');
  224. $adminInfo->login_ip = request()->getRealIp();
  225. $adminInfo->save();
  226. $access_exp = config('plugin.saiadmin.saithink.access_exp', 3 * 3600);
  227. $token = JwtToken::generateToken([
  228. 'access_exp' => $access_exp,
  229. 'id' => $adminInfo->id,
  230. 'username' => $adminInfo->username,
  231. 'type' => $type,
  232. 'plat' => 'saiadmin',
  233. ]);
  234. // 登录事件
  235. $admin_id = $adminInfo->id;
  236. Event::emit('user.login', compact('username', 'status', 'message', 'admin_id'));
  237. return $token;
  238. }
  239. /**
  240. * 更新资料
  241. * @param mixed $id
  242. * @param mixed $data
  243. * @return bool
  244. */
  245. public function updateInfo($id, $data): bool
  246. {
  247. $this->model->update($data, ['id' => $id], ['realname', 'gender', 'phone', 'email', 'avatar', 'signed']);
  248. return true;
  249. }
  250. /**
  251. * 密码修改
  252. * @param $adminId
  253. * @param $oldPassword
  254. * @param $newPassword
  255. * @return bool
  256. */
  257. public function modifyPassword($adminId, $oldPassword, $newPassword): bool
  258. {
  259. $model = $this->model->findOrEmpty($adminId);
  260. if (password_verify($oldPassword, $model->password)) {
  261. $model->password = password_hash($newPassword, PASSWORD_DEFAULT);
  262. return $model->save();
  263. } else {
  264. throw new ApiException('原密码错误');
  265. }
  266. }
  267. /**
  268. * 修改数据
  269. */
  270. public function authEdit($id, $data)
  271. {
  272. if ($this->adminInfo['id'] > 1) {
  273. // 判断用户是否可以操作
  274. $query = SystemUser::where('id', $id);
  275. $query->auth($this->adminInfo['deptList']);
  276. $user = $query->findOrEmpty();
  277. if ($user->isEmpty()) {
  278. throw new ApiException('没有权限操作该数据');
  279. }
  280. }
  281. parent::edit($id, $data);
  282. }
  283. /**
  284. * 部门保护
  285. * @param $dept
  286. * @param $dept_id
  287. * @return bool
  288. */
  289. public function deptProtect($dept, $dept_id): bool
  290. {
  291. // 部门保护
  292. $deptIds = [$dept['id']];
  293. $deptLevel = $dept['level'] . $dept['id'] . ',';
  294. $dept_ids = SystemDept::whereLike('level', $deptLevel . '%')->column('id');
  295. $deptIds = array_merge($deptIds, $dept_ids);
  296. if (!in_array($dept_id, $deptIds)) {
  297. return false;
  298. }
  299. return true;
  300. }
  301. /**
  302. * 越权保护
  303. * @param $roleList
  304. * @param $role_ids
  305. * @return bool
  306. */
  307. public function roleProtect($roleList, $role_ids): bool
  308. {
  309. // 越权保护
  310. $levelArr = array_column($roleList, 'level');
  311. $maxLevel = max($levelArr);
  312. $currentLevel = SystemRole::whereIn('id', $role_ids)->max('level');
  313. if ($currentLevel >= $maxLevel) {
  314. return false;
  315. }
  316. return true;
  317. }
  318. }