Универсальная миграция прав 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); |