RoleController.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <?php
  2. namespace plugin\admin\app\controller;
  3. use plugin\admin\app\common\Auth;
  4. use plugin\admin\app\common\Tree;
  5. use plugin\admin\app\model\Role;
  6. use plugin\admin\app\model\Rule;
  7. use support\exception\BusinessException;
  8. use support\Request;
  9. use support\Response;
  10. use Throwable;
  11. /**
  12. * 角色管理
  13. */
  14. class RoleController extends Crud
  15. {
  16. /**
  17. * 不需要鉴权的方法
  18. * @var array
  19. */
  20. protected $noNeedAuth = ['select'];
  21. /**
  22. * @var Role
  23. */
  24. protected $model = null;
  25. /**
  26. * 构造函数
  27. */
  28. public function __construct()
  29. {
  30. $this->model = new Role;
  31. }
  32. /**
  33. * 浏览
  34. * @return Response
  35. * @throws Throwable
  36. */
  37. public function index(): Response
  38. {
  39. return raw_view('role/index');
  40. }
  41. /**
  42. * 查询
  43. * @param Request $request
  44. * @return Response
  45. * @throws BusinessException
  46. */
  47. public function select(Request $request): Response
  48. {
  49. $id = $request->get('id');
  50. [$where, $format, $limit, $field, $order] = $this->selectInput($request);
  51. $role_ids = Auth::getScopeRoleIds(true);
  52. if (!$id) {
  53. $where['id'] = ['in', $role_ids];
  54. } elseif (!in_array($id, $role_ids)) {
  55. throw new BusinessException('无权限');
  56. }
  57. $query = $this->doSelect($where, $field, $order);
  58. return $this->doFormat($query, $format, $limit);
  59. }
  60. /**
  61. * 插入
  62. * @param Request $request
  63. * @return Response
  64. * @throws BusinessException
  65. * @throws Throwable
  66. */
  67. public function insert(Request $request): Response
  68. {
  69. if ($request->method() === 'POST') {
  70. $data = $this->insertInput($request);
  71. $pid = $data['pid'] ?? null;
  72. if (!$pid) {
  73. return $this->json(1, '请选择父级角色组');
  74. }
  75. if (!Auth::isSuperAdmin() && !in_array($pid, Auth::getScopeRoleIds(true))) {
  76. return $this->json(1, '父级角色组超出权限范围');
  77. }
  78. $this->checkRules($pid, $data['rules'] ?? '');
  79. $id = $this->doInsert($data);
  80. return $this->json(0, 'ok', ['id' => $id]);
  81. }
  82. return raw_view('role/insert');
  83. }
  84. /**
  85. * 更新
  86. * @param Request $request
  87. * @return Response
  88. * @throws BusinessException|Throwable
  89. */
  90. public function update(Request $request): Response
  91. {
  92. if ($request->method() === 'GET') {
  93. return raw_view('role/update');
  94. }
  95. [$id, $data] = $this->updateInput($request);
  96. $is_supper_admin = Auth::isSuperAdmin();
  97. $descendant_role_ids = Auth::getScopeRoleIds();
  98. if (!$is_supper_admin && !in_array($id, $descendant_role_ids)) {
  99. return $this->json(1, '无数据权限');
  100. }
  101. $role = Role::find($id);
  102. if (!$role) {
  103. return $this->json(1, '数据不存在');
  104. }
  105. $is_supper_role = $role->rules === '*';
  106. // 超级角色组不允许更改rules pid 字段
  107. if ($is_supper_role) {
  108. unset($data['rules'], $data['pid']);
  109. }
  110. if (key_exists('pid', $data)) {
  111. $pid = $data['pid'];
  112. if (!$pid) {
  113. return $this->json(1, '请选择父级角色组');
  114. }
  115. if ($pid == $id) {
  116. return $this->json(1, '父级不能是自己');
  117. }
  118. if (!$is_supper_admin && !in_array($pid, Auth::getScopeRoleIds(true))) {
  119. return $this->json(1, '父级超出权限范围');
  120. }
  121. } else {
  122. $pid = $role->pid;
  123. }
  124. if (!$is_supper_role) {
  125. $this->checkRules($pid, $data['rules'] ?? '');
  126. }
  127. $this->doUpdate($id, $data);
  128. // 删除所有子角色组中已经不存在的权限
  129. if (!$is_supper_role) {
  130. $tree = new Tree(Role::select(['id', 'pid'])->get());
  131. $descendant_roles = $tree->getDescendant([$id]);
  132. $descendant_role_ids = array_column($descendant_roles, 'id');
  133. $rule_ids = $data['rules'] ? explode(',', $data['rules']) : [];
  134. foreach ($descendant_role_ids as $role_id) {
  135. $tmp_role = Role::find($role_id);
  136. $tmp_rule_ids = $role->getRuleIds();
  137. $tmp_rule_ids = array_intersect(explode(',',$tmp_role->rules), $tmp_rule_ids);
  138. $tmp_role->rules = implode(',', $tmp_rule_ids);
  139. $tmp_role->save();
  140. }
  141. }
  142. return $this->json(0);
  143. }
  144. /**
  145. * 删除
  146. * @param Request $request
  147. * @return Response
  148. * @throws BusinessException
  149. */
  150. public function delete(Request $request): Response
  151. {
  152. $ids = $this->deleteInput($request);
  153. if (in_array(1, $ids)) {
  154. return $this->json(1, '无法删除超级管理员角色');
  155. }
  156. if (!Auth::isSuperAdmin() && array_diff($ids, Auth::getScopeRoleIds())) {
  157. return $this->json(1, '无删除权限');
  158. }
  159. $tree = new Tree(Role::get());
  160. $descendants = $tree->getDescendant($ids);
  161. if ($descendants) {
  162. $ids = array_merge($ids, array_column($descendants, 'id'));
  163. }
  164. $this->doDelete($ids);
  165. return $this->json(0);
  166. }
  167. /**
  168. * 获取角色权限
  169. * @param Request $request
  170. * @return Response
  171. */
  172. public function rules(Request $request): Response
  173. {
  174. $role_id = $request->get('id');
  175. if (empty($role_id)) {
  176. return $this->json(0, 'ok', []);
  177. }
  178. if (!Auth::isSuperAdmin() && !in_array($role_id, Auth::getScopeRoleIds(true))) {
  179. return $this->json(1, '角色组超出权限范围');
  180. }
  181. $rule_id_string = Role::where('id', $role_id)->value('rules');
  182. if ($rule_id_string === '') {
  183. return $this->json(0, 'ok', []);
  184. }
  185. $rules = Rule::get();
  186. $include = [];
  187. if ($rule_id_string !== '*') {
  188. $include = explode(',', $rule_id_string);
  189. }
  190. $items = [];
  191. foreach ($rules as $item) {
  192. $items[] = [
  193. 'name' => $item->title ?? $item->name ?? $item->id,
  194. 'value' => (string)$item->id,
  195. 'id' => $item->id,
  196. 'pid' => $item->pid,
  197. ];
  198. }
  199. $tree = new Tree($items);
  200. return $this->json(0, 'ok', $tree->getTree($include));
  201. }
  202. /**
  203. * 检查权限字典是否合法
  204. * @param int $role_id
  205. * @param $rule_ids
  206. * @return void
  207. * @throws BusinessException
  208. */
  209. protected function checkRules(int $role_id, $rule_ids)
  210. {
  211. if ($rule_ids) {
  212. $rule_ids = explode(',', $rule_ids);
  213. if (in_array('*', $rule_ids)) {
  214. throw new BusinessException('非法数据');
  215. }
  216. $rule_exists = Rule::whereIn('id', $rule_ids)->pluck('id');
  217. if (count($rule_exists) != count($rule_ids)) {
  218. throw new BusinessException('权限不存在');
  219. }
  220. $rule_id_string = Role::where('id', $role_id)->value('rules');
  221. if ($rule_id_string === '') {
  222. throw new BusinessException('数据超出权限范围');
  223. }
  224. if ($rule_id_string === '*') {
  225. return;
  226. }
  227. $legal_rule_ids = explode(',', $rule_id_string);
  228. if (array_diff($rule_ids, $legal_rule_ids)) {
  229. throw new BusinessException('数据超出权限范围');
  230. }
  231. }
  232. }
  233. }