Универсальная миграция прав RBAC на Yii2
Часто приходится через миграции на Yii2 добавлять права доступа для пользователей. Естественно, удобней вывести в систему администрирования настройку прав, но стартовые права доступа все же лучше сделать в миграции. Достаточно долго делал универсальный код, т.к. возникали проблемы, например, когда уже права созданы ранее и другие.
Я использую БД для хранения ролей, поэтому в миграции делается проверка на данный факт.
Данный код создает новые права, если они не существуют и присваивает их указанным ролям, если они еще не были присвоены ранее. Все, что нам нужно при данном подходе — заполнить переменную $permissions.
Ключом выступает название прав, а значение — массив из ролей пользователей, которым необходимо присвоить указанные права.
При миграции «вниз» — все указанные права и присвоенные им роли удаляются.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | <?php use app\models\User; use yii\db\Migration; class m150828_110330_add_rbac_permissions extends Migration { protected $permissions = [ 'admin.article.reset-filter' => [User::ROLE_MODERATOR], 'admin.article.batch-publish' => [User::ROLE_MODERATOR], 'admin.article.batch-unpublish' => [User::ROLE_ADMIN] ]; /** * @throws yii\base\InvalidConfigException * @return app\components\DbManager */ protected function getAuthManager() { $authManager = Yii::$app->getAuthManager(); if ($authManager instanceof yii\rbac\DbManager || $authManager instanceof app\components\DbManager) { } else { throw new \yii\base\InvalidConfigException('You should configure "authManager" component to use database before executing this migration.'); } return $authManager; } public function up() { $authManager = $this->getAuthManager(); foreach ($this->permissions as $permissionName => $roles) { if (!$authManager->getPermission($permissionName)) { $permission = $authManager->createPermission($permissionName); $authManager->add($permission); } else { $permission = $authManager->getPermission($permissionName); } foreach ($roles as $role) { if (!$authManager->hasChild($authManager->getRole($role), $permission)) { $authManager->addChild($authManager->getRole($role), $permission); } } } } public function down() { $authManager = $this->getAuthManager(); foreach ($this->permissions as $permissionName => $roles) { if ($permission = $authManager->getPermission($permissionName)) { foreach ($roles as $role) { if ($authManager->getRole($role) && $permission) { $authManager->removeChild($authManager->getRole($role), $permission); } } $authManager->remove($permission); } } } } |
Возможно, возникнет проблема, в случае, если права были уже созданы и присовены к ролям ранее, но это легко обойти сделав проверку перед удалением на наличие присвоения прав к иным ролям:
1 | $authManager->remove($permission); |