/common/services/RBACService.php

https://github.com/liufee/cms · PHP · 509 lines · 436 code · 62 blank · 11 comment · 32 complexity · 9f02cb5d6f8e109b6b720df8af99cbae MD5 · raw file

  1. <?php
  2. /**
  3. * Author: lf
  4. * Blog: https://blog.feehi.com
  5. * Email: job@feehi.com
  6. * Created at: 2020-01-29 17:19
  7. */
  8. namespace common\services;
  9. use Yii;
  10. use backend\models\form\AssignPermissionForm;
  11. use backend\models\search\RBACRoleSearch;
  12. use backend\models\search\RBACPermissionSearch;
  13. use backend\components\CustomLog;
  14. use backend\models\form\RBACPermissionForm;
  15. use backend\models\form\RBACRoleForm;
  16. use yii\base\Event;
  17. use yii\base\Exception;
  18. use yii\helpers\ArrayHelper;
  19. use yii\web\NotFoundHttpException;
  20. class RBACService extends Service implements RBACServiceInterface
  21. {
  22. /** @var yii\rbac\ManagerInterface */
  23. private $authManager;
  24. public function init()
  25. {
  26. parent::init();
  27. $this->authManager = \Yii::$app->getAuthManager();
  28. }
  29. public function getSearchModel(array $options = [])
  30. {
  31. throw new Exception("Not need");
  32. }
  33. public function getModel($id, array $options = [])
  34. {
  35. throw new Exception("Not need");
  36. }
  37. public function newModel(array $options = [])
  38. {
  39. throw new Exception("Not need");
  40. }
  41. public function getNewPermissionModel()
  42. {
  43. return new RBACPermissionForm();
  44. }
  45. public function getPermissionSearchModel(array $options = [])
  46. {
  47. return new RBACPermissionSearch();
  48. }
  49. public function getPermissionList(array $query = [])
  50. {
  51. $items = $this->authManager->getPermissions();
  52. $permissions = [];
  53. foreach ($items as $item){
  54. $model = new RBACPermissionForm();
  55. $model->setAttributes($item);
  56. $permissions[] = $model->getAttributes();
  57. }
  58. ArrayHelper::multisort($permissions, 'sort');
  59. $searchModel = $this->getPermissionSearchModel();
  60. $dataProvider = $searchModel->search($query, ['permissions' => $permissions]);
  61. return [
  62. 'dataProvider' => $dataProvider,
  63. 'searchModel' => $searchModel,
  64. ];
  65. }
  66. public function createPermission(array $postData = [])
  67. {
  68. $formModel = $this->getNewPermissionModel();
  69. if ( !$formModel->load($postData) ){
  70. return $formModel;
  71. }
  72. if ($this->authManager->getPermission($formModel->name) !== null) {
  73. $formModel->addError('route', Yii::t('app', 'Permission exists'));
  74. $formModel->addError('method', Yii::t('app', 'Permission exists'));
  75. return false;
  76. }
  77. $permission = $this->authManager->createPermission($formModel->getName());
  78. $permission->description = $formModel->description;
  79. $permission->data = $formModel->getData();
  80. if( $this->authManager->add($permission) ){
  81. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  82. 'sender' => $formModel,
  83. 'description' => "创建 权限 (" . $formModel->getName() . ") " . print_r($formModel->getAttributes(), true),
  84. ]));
  85. return true;
  86. }
  87. return false;
  88. }
  89. public function getPermissionDetail($name)
  90. {
  91. $permission = $this->authManager->getPermission($name);
  92. $formModel = new RBACPermissionForm();
  93. $formModel->setAttributes($permission);
  94. return $formModel;
  95. }
  96. public function updatePermission($name, array $postData = [])
  97. {
  98. $formModel = $this->getNewPermissionModel();
  99. if ( !$formModel->load($postData) ){
  100. return $formModel->getErrors();
  101. }
  102. $oldPermission = $this->getPermissionDetail($name);
  103. $permission = $this->authManager->createPermission($formModel->getName());
  104. $permission->description = $formModel->description;
  105. $permission->data = $formModel->getData();
  106. if( $this->authManager->update($name, $permission) ){
  107. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  108. 'sender' => $formModel,
  109. 'description' => "修改 权限(" . $name . ") 从" . print_r($oldPermission, true) . "变更为" . print_r($formModel->getAttributes(), true),
  110. ]));
  111. return true;
  112. }
  113. return false;
  114. }
  115. public function deletePermission($name)
  116. {
  117. $permission = $this->authManager->createPermission($name);
  118. $result = $this->authManager->remove($permission);
  119. if( $result ){
  120. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  121. 'sender' => $this,
  122. 'description' => "删除 权限(" . $name . ")",
  123. ]));
  124. }
  125. return $result;
  126. }
  127. public function sortPermission($name, $sort)
  128. {
  129. $permission = $this->authManager->getPermission($name);
  130. $formModel = $this->getNewPermissionModel();
  131. $formModel->setAttributes($permission);
  132. $oldSort = $formModel->sort;
  133. $formModel->sort = $sort;
  134. $permission->data = $formModel->getData();
  135. $result = $this->authManager->update($name, $permission);
  136. if($result){
  137. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  138. 'sender' => $this,
  139. 'description' => "修改 权限(" . $name . ") 排序 " . $oldSort . "为" . $sort,
  140. ]));
  141. }
  142. return $result;
  143. }
  144. public function getNewRoleModel()
  145. {
  146. return new RBACRoleForm();
  147. }
  148. public function getRoleSearchModel(array $options=[])
  149. {
  150. return new RBACRoleSearch();
  151. }
  152. public function getRoleList(array $query = [])
  153. {
  154. $items = $this->authManager->getRoles();
  155. $roles = [];
  156. foreach ($items as $item) {
  157. $model = new RBACRoleForm();
  158. $model->setAttributes($item);
  159. $roles[] = $model->getAttributes();
  160. }
  161. ArrayHelper::multisort($roles, 'sort');
  162. $searchModel = $this->getRoleSearchModel();
  163. $dataProvider = $searchModel->search($query, ['roles'=>$roles]);
  164. return [
  165. 'dataProvider' => $dataProvider,
  166. 'searchModel' => $searchModel,
  167. ];
  168. }
  169. public function createRole(array $postData = [])
  170. {
  171. $formModel = $this->getNewRoleModel();
  172. if ( !$formModel->load($postData) ){
  173. return $formModel->getErrors();
  174. }
  175. if ($this->authManager->getRole($formModel->name) !== null) {
  176. $formModel->addError('name', Yii::t('app', 'Role exists'));
  177. return false;
  178. }
  179. $role = $this->authManager->createRole($formModel->name);
  180. $role->description = $formModel->description;
  181. $role->data = $formModel->getData();
  182. if( $this->authManager->add($role) ){
  183. //add role's permission
  184. $permissions = $formModel->getPermissions();
  185. foreach ($permissions as $permissionName){
  186. $permissionItem = $this->authManager->getPermission($permissionName);
  187. if( $permissionItem === null ) {
  188. throw new Exception("Not existed permission name " . $permissionName);
  189. }
  190. $result = $this->authManager->addChild($role, $permissionItem);
  191. if(!$result){
  192. return false;
  193. }
  194. }
  195. //add roles's child role
  196. $childRoles = $formModel->getRoles();
  197. foreach ($childRoles as $needAddChildRole){
  198. $childRole = $this->authManager->getRole($needAddChildRole);
  199. $result = $this->authManager->addChild($role, $childRole);
  200. if(!$result){
  201. return false;
  202. }
  203. }
  204. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  205. 'sender' => $formModel,
  206. 'description' => "创建角色 (" . $formModel->name . ") 权限为 " . print_r($permissions, true) . " 继承角色 " . print_r($childRoles, true) . "的权限"
  207. ]));
  208. return true;
  209. }
  210. return false;
  211. }
  212. public function getRoleDetail($name)
  213. {
  214. $role = $this->authManager->getRole($name);
  215. $formModel = new RBACRoleForm();
  216. $formModel->setAttributes($role);
  217. $formModel->setPermissions( $this->authManager->getPermissionsByRole($name) );
  218. $formModel->setRoles( $this->authManager->getChildRoles($name) );
  219. return $formModel;
  220. }
  221. public function updateRole($name, array $postData = [])
  222. {
  223. $formModel = $this->getNewRoleModel();
  224. if ( !$formModel->load($postData) ){
  225. return $formModel->getErrors();
  226. }
  227. $role = $this->authManager->getRole($name);
  228. if( $name != $formModel->name ){//修改角色名称
  229. if( $this->authManager->getRole($formModel->name) !== null ){
  230. return Yii::t('app', 'Role exists');
  231. }
  232. }
  233. $role->name = $formModel->name;
  234. $role->description = $formModel->description;
  235. $role->data = $formModel->getData();
  236. $oldPermissions = array_keys( $this->authManager->getPermissionsByRole($name) );
  237. $oldRoles = array_keys($this->authManager->getChildRoles($name));
  238. if( $this->authManager->update($name, $role) ){
  239. $permissions = $formModel->getPermissions();
  240. $needAdds = array_diff($permissions, $oldPermissions);
  241. foreach ($needAdds as $permission){
  242. $permission = $this->authManager->getPermission($permission);
  243. $this->authManager->addChild($role, $permission);
  244. }
  245. $needRemoves = array_diff($oldPermissions, $formModel->getPermissions());
  246. foreach ($needRemoves as $permission){
  247. $permission = $this->authManager->getPermission($permission);
  248. $this->authManager->removeChild($role, $permission);
  249. }
  250. $roles = $formModel->getRoles();
  251. $needAdds = array_diff($roles, $oldRoles);
  252. foreach ($needAdds as $needAdd){
  253. $needAdd = $this->authManager->getRole($needAdd);
  254. $this->authManager->addChild($role, $needAdd);
  255. }
  256. $needRemoves = array_diff($oldRoles, $formModel->getRoles());
  257. foreach ($needRemoves as $needRemove){
  258. $needRemove = $this->authManager->getRole($needRemove);
  259. if( !$needRemove ) continue;
  260. $this->authManager->removeChild($role, $needRemove);
  261. }
  262. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  263. 'sender' => $this,
  264. 'description' => "修改 角色 (" . $name . ") 把权限从" . print_r($oldPermissions, true) . " 修改为 " . print_r($permissions, true) . " 把子角色从 " . print_r($oldRoles, true) . " 修改为 " . print_r($roles, true),
  265. ]));
  266. return true;
  267. }
  268. return false;
  269. }
  270. public function sortRole($name, $sort)
  271. {
  272. $role = $this->authManager->getRole($name);
  273. if( $role === null ) throw new NotFoundHttpException("Not exits role " . $name);
  274. $formModel = $this->getNewRoleModel();
  275. $formModel->setAttributes($role);
  276. $oldSort = $formModel->sort;
  277. $formModel->sort = $sort;
  278. $role->data = $formModel->getData();
  279. $result = $this->authManager->update($name, $role);
  280. if($result){
  281. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  282. 'sender' => $this,
  283. 'description' => "修改 角色(" . $name . ")排序 " . $oldSort . "为" . $formModel->sort,
  284. ]));
  285. }
  286. return $result;
  287. }
  288. public function deleteRole($name)
  289. {
  290. $role = $this->authManager->getRole($name);
  291. if( $role === null ) throw new NotFoundHttpException("Not exits role " . $name);
  292. $permissions = $this->authManager->getPermissionsByRole($name);
  293. foreach ($permissions as $permission){
  294. $result = $this->authManager->remove($permission);
  295. if( !$result ){
  296. Yii::error("delete role remove permission " . $permission->name . " error");
  297. }
  298. }
  299. $result = $this->authManager->remove($role);
  300. if($result){
  301. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  302. 'sender' => $this,
  303. 'description' => "删除 角色(" . $name . ")",
  304. ]));
  305. }
  306. return $result;
  307. }
  308. public function getRoles()
  309. {
  310. $roles = [];
  311. foreach (array_keys($this->authManager->getRoles()) as $key){
  312. $roles[$key] = $key;
  313. }
  314. return $roles;
  315. }
  316. public function getPermissionsGroups()
  317. {
  318. $authManager = $this->authManager;
  319. $originPermissions = $authManager->getPermissions();
  320. $permissions = [];
  321. foreach ($originPermissions as $originPermission){
  322. $data = json_decode($originPermission->data, true);
  323. $temp = explode(":", $originPermission->name);
  324. $permissions[] = [
  325. 'name' => $originPermission->name,
  326. 'route' => $temp[0],
  327. 'method' => $temp[1],
  328. 'description' => $originPermission->description,
  329. 'group' => $data['group'],
  330. 'category' => $data['category'],
  331. 'sort' => $data['sort'],
  332. ];
  333. }
  334. ArrayHelper::multisort($permissions, 'sort');
  335. $data = [];
  336. foreach ($permissions as $permission){
  337. $data[$permission['group']][$permission['category']][] = $permission;
  338. }
  339. return $data;
  340. }
  341. public function getPermissionGroups()
  342. {
  343. $permissions = $this->getPermissionsGroups();
  344. $groups = array_keys($permissions);
  345. $newGroups = [];
  346. foreach ($groups as $group){
  347. $newGroups[$group] = $group;
  348. }
  349. return $newGroups;
  350. }
  351. public function getPermissionCategories()
  352. {
  353. $permissions = $this->getPermissionsGroups();
  354. $categories = [];
  355. foreach ($permissions as $permission){
  356. $categories = array_merge($categories, array_keys($permission));
  357. }
  358. $newCategories = [];
  359. foreach ($categories as $category){
  360. $newCategories[$category] = $category;
  361. }
  362. return $newCategories;
  363. }
  364. public function newAssignPermissionModel()
  365. {
  366. return new AssignPermissionForm();
  367. }
  368. public function getAssignPermissionDetail($userId)
  369. {
  370. $model = $this->newAssignPermissionModel();
  371. $tempPermissions = array_keys($this->authManager->getPermissionsByUser($userId));
  372. $permissions = [];
  373. foreach ($tempPermissions as $permission){
  374. $permissions[$permission] = $permission;
  375. }
  376. $data = [
  377. 'roles' => array_keys($this->authManager->getRolesByUser($userId)),
  378. 'permissions' => $permissions,
  379. ];
  380. $model->setAttributes($data);
  381. return $model;
  382. }
  383. public function assignPermission($postData, $userId)
  384. {
  385. $model = new AssignPermissionForm();
  386. if( !$model->load($postData) ){
  387. return $model;
  388. }
  389. $authManager = $this->authManager;
  390. $assignments = $authManager->getAssignments($userId);
  391. $roles = $permissions = [];
  392. foreach ($assignments as $key => $assignment){
  393. if( strpos($assignment->roleName, ':GET') || strpos($assignment->roleName, ':POST') || strpos($assignment->roleName, ':DELETE') ){
  394. $permissions[$key] = $assignment;
  395. }else{
  396. $roles[$key] = $assignment;
  397. }
  398. }
  399. $roles = array_keys($roles);
  400. $permissions = array_keys($permissions);
  401. $str = '';
  402. //角色roles
  403. $needAdds = array_diff($model->getRoles(), $roles);
  404. $needRemoves = array_diff($roles, $model->getRoles());
  405. if( !empty($needAdds) ) {
  406. $str .= " 增加了角色: ";
  407. foreach ($needAdds as $role) {
  408. $roleItem = $authManager->getRole($role);
  409. $authManager->assign($roleItem, $userId
  410. );
  411. $str .= " {$roleItem->name},";
  412. }
  413. }
  414. if( !empty($needRemoves) ) {
  415. $str .= ' 删除了角色: ';
  416. foreach ($needRemoves as $role) {
  417. $roleItem = $authManager->getRole($role);
  418. $authManager->revoke($roleItem, $userId);
  419. $str .= " {$roleItem->name},";
  420. }
  421. }
  422. //权限permission
  423. $needAdds = array_diff($model->getPermissions(), $permissions);
  424. $needRemoves = array_diff($permissions, $model->getPermissions());
  425. if( !empty($needAdds) ) {
  426. $str .= ' 增加了权限: ';
  427. foreach ($needAdds as $permission) {
  428. $permissionItem = $authManager->getPermission($permission);
  429. $authManager->assign($permissionItem, $userId);
  430. $str .= " {$permissionItem->name},";
  431. }
  432. }
  433. if( !empty($needRemoves) ) {
  434. $str .= ' 删除了权限: ';
  435. foreach ($needRemoves as $permission) {
  436. $permissionItem = $authManager->getPermission($permission);
  437. $authManager->revoke($permissionItem, $userId);
  438. $str .= " {$permissionItem->name},";
  439. }
  440. }
  441. Event::trigger(CustomLog::className(), CustomLog::EVENT_CUSTOM, new CustomLog([
  442. 'sender' => $this,
  443. 'description' => "修改了 用户(uid {$userId}) 的权限: {$str}",
  444. ]));
  445. return true;
  446. }
  447. }