AuthGroupService.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. <?php
  2. namespace Ycbl\AdminAuth\Service;
  3. use Exception;
  4. use Hyperf\DbConnection\Db;
  5. use Hyperf\Di\Annotation\Inject;
  6. use Hyperf\Utils\Collection;
  7. use Ycbl\AdminAuth\Dao\AuthGroup;
  8. use Ycbl\AdminAuth\Dao\AuthGroupAccess;
  9. use Ycbl\AdminAuth\Dao\AuthRule;
  10. use Ycbl\AdminAuth\Dao\User;
  11. class AuthGroupService
  12. {
  13. /**
  14. * @Inject
  15. * @var AuthGroup
  16. */
  17. protected $authGroupDao;
  18. /**
  19. * @Inject
  20. * @var AuthRule
  21. */
  22. protected $authRuleDao;
  23. /**
  24. * @Inject
  25. * @var AuthGroupAccess
  26. */
  27. protected $authGroupAccessDao;
  28. /**
  29. * @Inject
  30. * @var User
  31. */
  32. protected $userDao;
  33. /**
  34. * @Inject
  35. * @var AuthService
  36. */
  37. protected $auth;
  38. /**
  39. * 获取当前用户权限组列表
  40. * @return array
  41. */
  42. public function getList($withSelf = false)
  43. {
  44. $children_group_ids = $this->getChildrenGroupIds($withSelf);
  45. $group_list = $this->authGroupDao->getGroupsById($children_group_ids)->toArray();
  46. $authTree = make(TreeService::class)->init($group_list);
  47. $result = $authTree->getArr();
  48. $group_name = [];
  49. foreach ($result as $k => $v) {
  50. $group_name[$v['id']] = $v['name'];
  51. }
  52. $list = $this->authGroupDao->getGroupsById(array_keys($group_name))->toArray();
  53. $group_list = [];
  54. foreach ($list as $k => $v) {
  55. $group_list[$v['id']] = $v;
  56. }
  57. $list = [];
  58. foreach ($group_name as $k => $v) {
  59. if (isset($group_list[$k])) {
  60. $group_list[$k]['name'] = $v;
  61. $list[] = $group_list[$k];
  62. }
  63. }
  64. return $list;
  65. }
  66. /**
  67. * 创建权限组
  68. * @param $pid
  69. * @param $name
  70. * @param $rules
  71. * @return bool
  72. * @throws Exception
  73. */
  74. public function createGroup($pid, $name, $rules)
  75. {
  76. $children_group_ids = $this->getChildrenGroupIds(true);
  77. if (!in_array($pid, $children_group_ids)) {
  78. throw new Exception('父组别超出权限范围');
  79. }
  80. $parent_model = $this->authGroupDao->getOneGroupsById($pid);
  81. if (!$parent_model) {
  82. throw new Exception('父组别未找到');
  83. }
  84. // 父级别的规则节点
  85. $parent_rules = explode(',', $parent_model->rules);
  86. // 当前组别的规则节点
  87. $current_rules = $this->auth->getRuleIds();// 当前组别的规则节点
  88. // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限
  89. $rules = in_array('*', $parent_rules) ? $rules : array_intersect($parent_rules, $rules);
  90. // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
  91. $rules = in_array('*', $current_rules) ? $rules : array_intersect($current_rules, $rules);
  92. $data = [
  93. 'pid' => $pid,
  94. 'name' => $name,
  95. 'rules' => implode(',', $rules),
  96. ];
  97. return $this->authGroupDao->insertGroup($data);
  98. }
  99. /**
  100. * 编辑权限组
  101. * @param $group_id
  102. * @param $pid
  103. * @param $rules
  104. * @param $name
  105. * @param $status
  106. * @return bool
  107. * @throws Exception
  108. */
  109. public function editAuthGroup($group_id, $pid, $rules, $name, $status)
  110. {
  111. $current_group = $this->authGroupDao->getOneGroupsById($group_id);
  112. if (!$current_group) {
  113. throw new Exception('记录未找到');
  114. }
  115. $children_group_ids = $this->getChildrenGroupIds(true);
  116. if (!in_array($group_id, $children_group_ids)) {
  117. throw new Exception('您没有权限');
  118. }
  119. if (!in_array($pid, $children_group_ids)) {
  120. throw new Exception('父组别超出权限范围');
  121. }
  122. $children_group_list = $this->authGroupDao->getGroupsById($children_group_ids);
  123. $tree = make(TreeService::class)->init($children_group_list->toArray());
  124. if (in_array($pid, $tree->getChildrenIds($group_id))) {
  125. throw new Exception('父组别不能是它的子组别及本身');
  126. }
  127. $rules = explode(',', $rules);
  128. $parent_group = $this->authGroupDao->getOneGroupsById($pid);
  129. if (!$parent_group) {
  130. throw new Exception('父组别未找到');
  131. }
  132. // 父级别的规则节点
  133. $parent_rules = explode(',', $parent_group->rules);
  134. // 当前组别的规则节点
  135. $current_rules = $this->auth->getRuleIds();
  136. // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限
  137. $rules = in_array('*', $parent_rules) ? $rules : array_intersect($parent_rules, $rules);
  138. // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
  139. $rules = in_array('*', $current_rules) ? $rules : array_intersect($current_rules, $rules);
  140. $rules = implode(',', $rules);
  141. $children_ids = $tree->getChildrenIds($group_id);
  142. $children_group = $this->authGroupDao->getGroupsById($children_ids);
  143. Db::transaction(function () use ($children_group, $group_id, $status, $rules, $name, $pid) {
  144. $updateData = [
  145. 'pid' => $pid,
  146. 'name' => $name,
  147. 'rules' => $rules,
  148. 'status' => $status,
  149. ];
  150. $this->authGroupDao->updateGroupById($group_id, $updateData);
  151. foreach ($children_group as $key => $value) {
  152. $value->rules = implode(',', array_intersect(explode(',', $value->rules), explode(',', $rules)));
  153. $value->save();
  154. }
  155. });
  156. return true;
  157. }
  158. /**
  159. * 删除权限组
  160. * @param $ids
  161. * @return int|mixed
  162. * @throws Exception
  163. */
  164. public function deleteAuthGroup($ids)
  165. {
  166. if (!is_array($ids)) {
  167. $ids = explode(',', $ids);
  168. }
  169. $group_list = $this->auth->getGroups();
  170. $group_ids = array_map(function ($group) {
  171. return $group['id'];
  172. }, $group_list);
  173. // 移除掉当前管理员所在组别
  174. $ids = array_diff($ids, $group_ids);
  175. $group_list = $this->authGroupDao->getGroupsById($ids);
  176. foreach ($group_list as $key => $value) {
  177. $group_user = $this->authGroupAccessDao->getUsersByGroupId((array)$value->id)->toArray();
  178. if ($group_user) {
  179. $ids = array_diff($ids, [$value->id]);
  180. continue;
  181. }
  182. $group_child = $this->authGroupDao->getGroupsByPid([$value->id])->toArray();
  183. if ($group_child) {
  184. $ids = array_diff($ids, [$value->id]);
  185. continue;
  186. }
  187. }
  188. if (!$ids) {
  189. throw new Exception('你不能删除含有子组和管理员的组');
  190. }
  191. return $this->authGroupDao->deleteGroup($ids);
  192. }
  193. /**
  194. * 获取权限组节点树
  195. * @param $pid
  196. * @param null $id
  197. * @return array
  198. * @throws Exception
  199. */
  200. public function getRoueTree($pid, $id = null)
  201. {
  202. $parent_group = $this->authGroupDao->getOneGroupsById($pid);
  203. $current_group = $this->authGroupDao->getOneGroupsById($id);
  204. if (($pid || $parent_group) && (!$id || $current_group)) {
  205. $rule_list = $this->authRuleDao->getRuleList()->toArray();
  206. //读取父类角色所有节点列表
  207. $parent_rule_list = [];
  208. if (in_array('*', explode(',', $parent_group->rules ?? ""))) {
  209. $parent_rule_list = $rule_list;
  210. } else {
  211. $parent_rule_ids = explode(',', $parent_group->rules ?? "");
  212. foreach ($rule_list as $k => $v) {
  213. if (in_array($v['id'], $parent_rule_ids)) {
  214. $parent_rule_list[] = $v;
  215. }
  216. }
  217. }
  218. //当前所有可选规则列表
  219. $rule_tree = make(TreeService::class)->init($parent_rule_list);
  220. //当前所有角色组列表
  221. $children_group_ids = $this->getChildrenGroupIds(true);
  222. $children_groups = $this->authGroupDao->getGroupsById($children_group_ids)->toArray();
  223. $group_tree = make(TreeService::class)->init($children_groups);
  224. //当前角色下的规则ID
  225. $admin_rule_ids = $this->auth->getRuleIds();
  226. //是否是超级管理员
  227. $super_admin = $this->auth->isSuperAdmin();
  228. //当前拥有的规则ID集合
  229. $current_rule_ids = $id ? explode(',', $current_group->rules ?? "") : [];
  230. if (!$id || !in_array($pid, $children_group_ids) || !in_array($pid, $group_tree->getChildrenIds($id, true))) {
  231. $parent_rule_list = $rule_tree->getTreeList($rule_tree->getTreeArray(0));
  232. $has_childes = [];
  233. foreach ($parent_rule_list as $k => $v) {
  234. if ($v['hasChild']) {
  235. $has_childes[] = $v['id'];
  236. }
  237. }
  238. $parent_rule_ids = array_map(function ($item) {
  239. return $item['id'];
  240. }, $parent_rule_list);
  241. $node_list = [];
  242. foreach ($parent_rule_list as $K => $v) {
  243. if (!$super_admin && !in_array($v['id'], $admin_rule_ids)) {
  244. continue;
  245. }
  246. if ($v['pid'] && !in_array($v['id'], $parent_rule_ids)) {
  247. continue;
  248. }
  249. $state = array('selected' => in_array($v['id'], $current_rule_ids) && !in_array($v['id'], $has_childes));
  250. $node_list[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => $v['title'], 'type' => 'menu', 'state' => $state);
  251. }
  252. return $node_list;
  253. } else {
  254. throw new Exception("父组别不能是它的子组别");
  255. }
  256. } else {
  257. throw new Exception("角色组未找到");
  258. }
  259. }
  260. /**
  261. * 取出当前管理员所拥有权限的分组ID
  262. * @param false $withSelf
  263. * @return array
  264. */
  265. public function getChildrenGroupIds($withSelf = false)
  266. {
  267. $groups = $this->auth->getGroups();
  268. $groups_ids = [];
  269. foreach ($groups as $k => $v) {
  270. $groups_ids[] = $v['id'];
  271. }
  272. $origin_group_ids = $groups_ids;
  273. foreach ($groups as $k => $v) {
  274. if (in_array($v['pid'], $origin_group_ids)) {
  275. $groups_ids = array_diff($groups_ids, [$v['id']]);
  276. unset($groups[$k]);
  277. }
  278. }
  279. // 取出所有分组
  280. $group_list = $this->authGroupDao->getEnableGroups()->toArray();
  281. $obj_list = [];
  282. foreach ($groups as $k => $v) {
  283. if ($v['rules'] === '*') {
  284. $obj_list = $group_list;
  285. break;
  286. }
  287. $tree = make(TreeService::class)->init($group_list);
  288. $children_list = $tree->getChildren($v['id'], true);
  289. $children_tree = make(TreeService::class)->init($children_list);
  290. $obj = $children_tree->getTreeList($children_tree->getTreeArray($v['pid']));
  291. $obj_list = array_merge($obj_list, $obj);
  292. }
  293. $children_group_ids = [];
  294. foreach ($obj_list as $k => $v) {
  295. $children_group_ids[] = $v['id'];
  296. }
  297. if (!$withSelf) {
  298. $children_group_ids = array_diff($children_group_ids, $groups_ids);
  299. }
  300. return $children_group_ids;
  301. }
  302. /**
  303. * 获取当前用户的子用户ID
  304. * @param false $with_self
  305. * @return array|Collection
  306. */
  307. public function getChildrenAdminIds($with_self = false)
  308. {
  309. if (!$this->auth->isSuperAdmin()) {
  310. $group_ids = $this->getChildrenGroupIds();
  311. if (empty($group_ids)) {
  312. $children_admin_ids = [];
  313. } else {
  314. $children_admin_ids = $this->authGroupAccessDao->getUsersByGroupId($group_ids)->pluck('uid')->toArray();
  315. }
  316. } else {
  317. $children_admin_ids = $this->userDao->getAllUserIds()->toArray();
  318. }
  319. if ($with_self) {
  320. //包含自身 则添加自身ID
  321. if (!in_array($this->auth->getUserId(), $children_admin_ids)) {
  322. $children_admin_ids[] = $this->auth->getUserId();
  323. }
  324. } else {
  325. //不包含自身则排除自身ID
  326. $children_admin_ids = array_diff($children_admin_ids, [$this->auth->getUserId()]);
  327. }
  328. return $children_admin_ids;
  329. }
  330. }