├── assets ├── main.css ├── list-item.css └── animate.css ├── components ├── UserStatus.php ├── GuestRule.php ├── RouteRule.php ├── DbManager.php ├── AccessControl.php ├── ItemController.php ├── Configs.php └── MenuHelper.php ├── mail ├── passwordResetToken-text.php ├── layouts │ ├── text.php │ └── html.php └── passwordResetToken-html.php ├── BaseObject.php ├── AnimateAsset.php ├── views ├── menu │ ├── create.php │ ├── update.php │ ├── _search.php │ ├── view.php │ ├── index.php │ ├── _script.js │ └── _form.php ├── rule │ ├── create.php │ ├── update.php │ ├── _form.php │ ├── index.php │ └── view.php ├── layouts │ ├── top-menu.php │ ├── right-menu.php │ ├── left-menu.php │ └── main.php ├── user │ ├── _form.php │ ├── requestPasswordResetToken.php │ ├── resetPassword.php │ ├── change-password.php │ ├── signup.php │ ├── login.php │ ├── view.php │ └── index.php ├── item │ ├── create.php │ ├── update.php │ ├── index.php │ ├── _form.php │ ├── _script.js │ └── view.php ├── assignment │ ├── index.php │ ├── _script.js │ └── view.php ├── default │ └── index.php └── route │ ├── _script.js │ └── index.php ├── controllers ├── DefaultController.php ├── RoleController.php ├── PermissionController.php ├── RouteController.php ├── RuleController.php ├── MenuController.php ├── AssignmentController.php └── UserController.php ├── AutocompleteAsset.php ├── migrations ├── schema-mssql.sql ├── schema-pgsql.sql ├── schema-oci.sql ├── schema-sqlite.sql ├── schema-mysql.sql ├── m140602_111327_create_menu_table.php └── m160312_050000_create_user.php ├── .travis.yml ├── composer.json ├── models ├── searchs │ ├── User.php │ ├── BizRule.php │ ├── Assignment.php │ ├── Menu.php │ └── AuthItem.php ├── form │ ├── ChangePassword.php │ ├── PasswordResetRequest.php │ ├── Signup.php │ ├── Login.php │ └── ResetPassword.php ├── Assignment.php ├── BizRule.php ├── Menu.php └── User.php ├── messages ├── ja │ └── rbac-admin.php ├── zh-CN │ └── rbac-admin.php ├── zh-TW │ └── rbac-admin.php ├── vi │ └── rbac-admin.php ├── th │ └── rbac-admin.php ├── fa-IR │ └── rbac-admin.php ├── pt-BR │ └── rbac-admin.php ├── it │ └── rbac-admin.php ├── nl │ └── rbac-admin.php ├── pl │ └── rbac-admin.php ├── hr │ └── rbac-admin.php ├── fr │ └── rbac-admin.php ├── de │ └── rbac-admin.php ├── uk │ └── rbac-admin.php ├── ru │ └── rbac-admin.php ├── en │ └── rbac-admin.php ├── id │ └── rbac-admin.php └── es │ └── rbac-admin.php ├── README.md ├── CHANGELOG.md └── Module.php /assets/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 70px; 3 | } 4 | 5 | .footer { 6 | border-top: 1px solid #ddd; 7 | margin-top: 30px; 8 | padding: 15px 0 30px; 9 | } 10 | 11 | .navbar-brand { 12 | padding: 0; 13 | margin: 0; 14 | } -------------------------------------------------------------------------------- /components/UserStatus.php: -------------------------------------------------------------------------------- 1 | 9 | * @since 2.9 10 | */ 11 | class UserStatus 12 | { 13 | const INACTIVE = 0; 14 | const ACTIVE = 10; 15 | } 16 | -------------------------------------------------------------------------------- /assets/list-item.css: -------------------------------------------------------------------------------- 1 | /* 2 | To change this license header, choose License Headers in Project Properties. 3 | To change this template file, choose Tools | Templates 4 | and open the template in the editor. 5 | */ 6 | /* 7 | Created on : Jul 16, 2014, 8:10:29 AM 8 | Author : mdmunirdeb 9 | */ 10 | 11 | #manager-menu .pull-right { 12 | float: right; 13 | } 14 | -------------------------------------------------------------------------------- /mail/passwordResetToken-text.php: -------------------------------------------------------------------------------- 1 | $user->password_reset_token], true); 8 | ?> 9 | Hello username ?>, 10 | 11 | Follow the link below to reset your password: 12 | 13 | 14 | -------------------------------------------------------------------------------- /mail/layouts/text.php: -------------------------------------------------------------------------------- 1 | 7 | beginPage() ?> 8 | beginBody() ?> 9 | 10 | endBody() ?> 11 | endPage() ?> 12 | -------------------------------------------------------------------------------- /BaseObject.php: -------------------------------------------------------------------------------- 1 | 13 | * @since 2.9 14 | */ 15 | class BaseObject extends \yii\base\BaseObject 16 | { 17 | //put your code here 18 | } 19 | -------------------------------------------------------------------------------- /AnimateAsset.php: -------------------------------------------------------------------------------- 1 | 11 | * @since 2.5 12 | */ 13 | class AnimateAsset extends AssetBundle 14 | { 15 | /** 16 | * @inheritdoc 17 | */ 18 | public $sourcePath = '@mdm/admin/assets'; 19 | /** 20 | * @inheritdoc 21 | */ 22 | public $css = [ 23 | 'animate.css', 24 | ]; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /mail/passwordResetToken-html.php: -------------------------------------------------------------------------------- 1 | $user->password_reset_token], true); 9 | ?> 10 |
11 |

Hello username) ?>,

12 | 13 |

Follow the link below to reset your password:

14 | 15 |

16 |
17 | -------------------------------------------------------------------------------- /components/GuestRule.php: -------------------------------------------------------------------------------- 1 | 11 | * @since 2.5 12 | */ 13 | class GuestRule extends Rule 14 | { 15 | /** 16 | * @inheritdoc 17 | */ 18 | public $name = 'guest_rule'; 19 | 20 | /** 21 | * @inheritdoc 22 | */ 23 | public function execute($user, $item, $params) 24 | { 25 | return $user->getIsGuest(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /views/menu/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Create Menu'); 9 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', 'Menus'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 | 23 | -------------------------------------------------------------------------------- /views/rule/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Create Rule'); 9 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', 'Rules'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 |
13 | 14 |

title) ?>

15 | 16 | render('_form', [ 18 | 'model' => $model, 19 | ]); 20 | ?> 21 | 22 |
23 | -------------------------------------------------------------------------------- /views/layouts/top-menu.php: -------------------------------------------------------------------------------- 1 | context; 6 | $menus = $controller->module->menus; 7 | $route = $controller->route; 8 | foreach ($menus as $i => $menu) { 9 | $menus[$i]['active'] = strpos($route, trim((string)$menu['url'][0], '/')) === 0; 10 | } 11 | $this->params['nav-items'] = $menus; 12 | $this->params['top-menu'] = true; 13 | ?> 14 | beginContent($controller->module->mainLayout) ?> 15 |
16 |
17 | 18 |
19 |
20 | endContent(); ?> 21 | -------------------------------------------------------------------------------- /assets/animate.css: -------------------------------------------------------------------------------- 1 | .glyphicon-refresh-animate { 2 | -animation: spin .7s infinite linear; 3 | -ms-animation: spin .7s infinite linear; 4 | -webkit-animation: spinw .7s infinite linear; 5 | -moz-animation: spinm .7s infinite linear; 6 | } 7 | 8 | @keyframes spin { 9 | from { transform: scale(1) rotate(0deg);} 10 | to { transform: scale(1) rotate(360deg);} 11 | } 12 | 13 | @-webkit-keyframes spinw { 14 | from { -webkit-transform: rotate(0deg);} 15 | to { -webkit-transform: rotate(360deg);} 16 | } 17 | 18 | @-moz-keyframes spinm { 19 | from { -moz-transform: rotate(0deg);} 20 | to { -moz-transform: rotate(360deg);} 21 | } -------------------------------------------------------------------------------- /views/user/_form.php: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 | 14 | 15 | field($model, 'status')->textInput() ?> 16 | 17 |
18 | isNewRecord ? Yii::t('rbac-admin', 'Create') : Yii::t('rbac-admin', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> 19 |
20 | 21 | 22 | 23 |
24 | -------------------------------------------------------------------------------- /controllers/DefaultController.php: -------------------------------------------------------------------------------- 1 | 11 | * @since 1.0 12 | */ 13 | class DefaultController extends \yii\web\Controller 14 | { 15 | 16 | /** 17 | * Action index 18 | */ 19 | public function actionIndex($page = 'README.md') 20 | { 21 | if (preg_match('/^docs\/images\/image\d+\.png$/',$page)) { 22 | $file = Yii::getAlias("@mdm/admin/{$page}"); 23 | return Yii::$app->getResponse()->sendFile($file); 24 | } 25 | return $this->render('index', ['page' => $page]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /views/rule/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Update Rule') . ': ' . $model->name; 9 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', 'Rules'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->name]]; 11 | $this->params['breadcrumbs'][] = Yii::t('rbac-admin', 'Update'); 12 | ?> 13 |
14 | 15 |

title) ?>

16 | render('_form', [ 18 | 'model' => $model, 19 | ]); 20 | ?> 21 |
22 | -------------------------------------------------------------------------------- /views/item/create.php: -------------------------------------------------------------------------------- 1 | context; 10 | $labels = $context->labels(); 11 | $this->title = Yii::t('rbac-admin', 'Create ' . $labels['Item']); 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', $labels['Items']), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |
16 |

title) ?>

17 | render('_form', [ 19 | 'model' => $model, 20 | ]); 21 | ?> 22 | 23 |
24 | -------------------------------------------------------------------------------- /views/menu/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Update Menu') . ': ' . ' ' . $model->name; 9 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', 'Menus'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]]; 11 | $this->params['breadcrumbs'][] = Yii::t('rbac-admin', 'Update'); 12 | ?> 13 | 24 | -------------------------------------------------------------------------------- /AutocompleteAsset.php: -------------------------------------------------------------------------------- 1 | 11 | * @since 1.0 12 | */ 13 | class AutocompleteAsset extends AssetBundle 14 | { 15 | /** 16 | * @inheritdoc 17 | */ 18 | public $sourcePath = '@mdm/admin/assets'; 19 | /** 20 | * @inheritdoc 21 | */ 22 | public $css = [ 23 | 'jquery-ui.css', 24 | ]; 25 | /** 26 | * @inheritdoc 27 | */ 28 | public $js = [ 29 | 'jquery-ui.js', 30 | ]; 31 | /** 32 | * @inheritdoc 33 | */ 34 | public $depends = [ 35 | 'yii\web\JqueryAsset', 36 | ]; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /controllers/RoleController.php: -------------------------------------------------------------------------------- 1 | 12 | * @since 1.0 13 | */ 14 | class RoleController extends ItemController 15 | { 16 | /** 17 | * @inheritdoc 18 | */ 19 | public function labels() 20 | { 21 | return[ 22 | 'Item' => 'Role', 23 | 'Items' => 'Roles', 24 | ]; 25 | } 26 | 27 | /** 28 | * @inheritdoc 29 | */ 30 | public function getType() 31 | { 32 | return Item::TYPE_ROLE; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /controllers/PermissionController.php: -------------------------------------------------------------------------------- 1 | 12 | * @since 1.0 13 | */ 14 | class PermissionController extends ItemController 15 | { 16 | 17 | /** 18 | * @inheritdoc 19 | */ 20 | public function labels() 21 | { 22 | return[ 23 | 'Item' => 'Permission', 24 | 'Items' => 'Permissions', 25 | ]; 26 | } 27 | 28 | /** 29 | * @inheritdoc 30 | */ 31 | public function getType() 32 | { 33 | return Item::TYPE_PERMISSION; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /views/rule/_form.php: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | 13 | 14 | 15 | field($model, 'name')->textInput(['maxlength' => 64]) ?> 16 | 17 | field($model, 'className')->textInput() ?> 18 | 19 |
20 | isNewRecord ? Yii::t('rbac-admin', 'Create') : Yii::t('rbac-admin', 'Update'), [ 22 | 'class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) 23 | ?> 24 |
25 | 26 | 27 |
28 | -------------------------------------------------------------------------------- /mail/layouts/html.php: -------------------------------------------------------------------------------- 1 | 8 | beginPage() ?> 9 | 10 | 11 | 12 | 13 | <?= Html::encode($this->title) ?> 14 | head() ?> 15 | 16 | 17 | beginBody() ?> 18 | 19 | endBody() ?> 20 | 21 | 22 | endPage() ?> 23 | -------------------------------------------------------------------------------- /views/item/update.php: -------------------------------------------------------------------------------- 1 | context; 10 | $labels = $context->labels(); 11 | $this->title = Yii::t('rbac-admin', 'Update ' . $labels['Item']) . ': ' . $model->name; 12 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', $labels['Items']), 'url' => ['index']]; 13 | $this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->name]]; 14 | $this->params['breadcrumbs'][] = Yii::t('rbac-admin', 'Update'); 15 | ?> 16 |
17 |

title) ?>

18 | render('_form', [ 20 | 'model' => $model, 21 | ]); 22 | ?> 23 |
24 | -------------------------------------------------------------------------------- /components/RouteRule.php: -------------------------------------------------------------------------------- 1 | 12 | * @since 1.0 13 | */ 14 | class RouteRule extends Rule 15 | { 16 | const RULE_NAME = 'route_rule'; 17 | 18 | /** 19 | * @inheritdoc 20 | */ 21 | public $name = self::RULE_NAME; 22 | 23 | /** 24 | * @inheritdoc 25 | */ 26 | public function execute($user, $item, $params) 27 | { 28 | $routeParams = isset($item->data['params']) ? $item->data['params'] : []; 29 | foreach ($routeParams as $key => $value) { 30 | if (!array_key_exists($key, $params) || $params[$key] != $value) { 31 | return false; 32 | } 33 | } 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /migrations/schema-mssql.sql: -------------------------------------------------------------------------------- 1 | /** 2 | * Database schema required by yii2-admin. 3 | * 4 | * @author Misbahul D Munir 5 | * @since 2.5 6 | */ 7 | 8 | drop table if exists [menu]; 9 | drop table if exists [user]; 10 | 11 | create table [menu] 12 | ( 13 | [id] int IDENTITY PRIMARY KEY, 14 | [name] varchar(128), 15 | [parent] int, 16 | [route] varchar(256), 17 | [order] int, 18 | [data] text, 19 | foreign key (parent) references [menu]([id]) ON DELETE SET NULL ON UPDATE CASCADE 20 | ); 21 | 22 | create table [user] 23 | ( 24 | [id] int IDENTITY PRIMARY KEY, 25 | [username] varchar(32) NOT NULL, 26 | [auth_key] varchar(32) NOT NULL, 27 | [password_hash] varchar(256) NOT NULL, 28 | [password_reset_token] varchar(256), 29 | [email] varchar(256) NOT NULL, 30 | [status] integer not null default 10, 31 | [created_at] integer not null, 32 | [updated_at] integer not null 33 | ); 34 | -------------------------------------------------------------------------------- /views/menu/_search.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 38 | -------------------------------------------------------------------------------- /migrations/schema-pgsql.sql: -------------------------------------------------------------------------------- 1 | /** 2 | * Database schema required by yii2-admin. 3 | * 4 | * @author Misbahul D Munir 5 | * @since 2.5 6 | */ 7 | 8 | drop table if exists "menu"; 9 | drop table if exists "user"; 10 | 11 | create table "menu" 12 | ( 13 | "id" serial NOT NULL PRIMARY KEY, 14 | "name" varchar(128), 15 | "parent" integer, 16 | "route" varchar(256), 17 | "order" integer, 18 | "data" bytea, 19 | foreign key ("parent") references "menu"("id") ON DELETE SET NULL ON UPDATE CASCADE 20 | ); 21 | 22 | create table "user" 23 | ( 24 | "id" serial NOT NULL PRIMARY KEY, 25 | "username" varchar(32) NOT NULL, 26 | "auth_key" varchar(32) NOT NULL, 27 | "password_hash" varchar(256) NOT NULL, 28 | "password_reset_token" varchar(256), 29 | "email" varchar(256) NOT NULL, 30 | "status" integer not null default 10, 31 | "created_at" integer not null, 32 | "updated_at" integer not null 33 | ); 34 | -------------------------------------------------------------------------------- /migrations/schema-oci.sql: -------------------------------------------------------------------------------- 1 | /** 2 | * Database schema required by yii2-admin. 3 | * 4 | * @author Misbahul D Munir 5 | * @since 2.5 6 | */ 7 | 8 | drop table if exists "menu"; 9 | drop table if exists "user"; 10 | 11 | create table "menu" 12 | ( 13 | "id" NUMBER(10) NOT NULL PRIMARY KEY, 14 | "name" varchar(128), 15 | "parent" number(10), 16 | "route" varchar(256), 17 | "order" number(10), 18 | "data" BYTEA, 19 | foreign key (parent) references "menu"("id") ON DELETE SET NULL ON UPDATE CASCADE 20 | ); 21 | 22 | create table "user" 23 | ( 24 | "id" NUMBER(10) NOT NULL PRIMARY KEY, 25 | "username" varchar(32) NOT NULL, 26 | "auth_key" varchar(32) NOT NULL, 27 | "password_hash" varchar(256) NOT NULL, 28 | "password_reset_token" varchar(256), 29 | "email" varchar(256) NOT NULL, 30 | "status" integer not null default 10, 31 | "created_at" number(10) not null, 32 | "updated_at" number(10) not null 33 | ); 34 | -------------------------------------------------------------------------------- /migrations/schema-sqlite.sql: -------------------------------------------------------------------------------- 1 | /** 2 | * Database schema required by yii2-admin. 3 | * 4 | * @author Misbahul D Munir 5 | * @since 2.5 6 | */ 7 | 8 | drop table if exists "menu"; 9 | drop table if exists "user"; 10 | 11 | create table "menu" 12 | ( 13 | "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, 14 | "name" varchar(128), 15 | "parent" int(11), 16 | "route" varchar(256), 17 | "order" int(11), 18 | "data" LONGBLOB, 19 | foreign key ("parent") references "menu"("id") ON DELETE SET NULL ON UPDATE CASCADE 20 | ); 21 | 22 | create table "user" 23 | ( 24 | "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, 25 | "username" varchar(32) NOT NULL, 26 | "auth_key" varchar(32) NOT NULL, 27 | "password_hash" varchar(256) NOT NULL, 28 | "password_reset_token" varchar(256), 29 | "email" varchar(256) NOT NULL, 30 | "status" integer not null default 10, 31 | "created_at" integer not null, 32 | "updated_at" integer not null 33 | ); 34 | -------------------------------------------------------------------------------- /views/user/requestPasswordResetToken.php: -------------------------------------------------------------------------------- 1 | title = 'Request password reset'; 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 |
13 |

title) ?>

14 | 15 |

Please fill out your email. A link to reset password will be sent there.

16 | 17 |
18 |
19 | 'request-password-reset-form']); ?> 20 | field($model, 'email') ?> 21 |
22 | 'btn btn-primary']) ?> 23 |
24 | 25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /views/user/resetPassword.php: -------------------------------------------------------------------------------- 1 | title = 'Reset password'; 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 |
13 |

title) ?>

14 | 15 |

Please choose your new password:

16 | 17 |
18 |
19 | 'reset-password-form']); ?> 20 | field($model, 'password')->passwordInput() ?> 21 | field($model, 'retypePassword')->passwordInput() ?> 22 |
23 | 'btn btn-primary']) ?> 24 |
25 | 26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /migrations/schema-mysql.sql: -------------------------------------------------------------------------------- 1 | /** 2 | * Database schema required by yii2-admin. 3 | * 4 | * @author Misbahul D Munir 5 | * @since 2.5 6 | */ 7 | 8 | drop table if exists `menu`; 9 | drop table if exists `user` cascade; 10 | 11 | create table `menu` 12 | ( 13 | `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 14 | `name` varchar(128), 15 | `parent` int(11), 16 | `route` varchar(256), 17 | `order` int(11), 18 | `data` blob, 19 | foreign key (`parent`) references `menu`(`id`) ON DELETE SET NULL ON UPDATE CASCADE 20 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 21 | 22 | create table `user` 23 | ( 24 | `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 25 | `username` varchar(32) NOT NULL, 26 | `auth_key` varchar(32) NOT NULL, 27 | `password_hash` varchar(256) NOT NULL, 28 | `password_reset_token` varchar(256), 29 | `email` varchar(256) NOT NULL, 30 | `status` integer not null default 10, 31 | `created_at` integer not null, 32 | `updated_at` integer not null 33 | )ENGINE=InnoDB DEFAULT CHARSET=utf8; 34 | -------------------------------------------------------------------------------- /views/rule/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Rules'); 13 | $this->params['breadcrumbs'][] = $this->title; 14 | ?> 15 |
16 | 17 |

title) ?>

18 | 19 |

20 | 'btn btn-success']) ?> 21 |

22 | 23 | $dataProvider, 26 | 'filterModel' => $searchModel, 27 | 'columns' => [ 28 | ['class' => 'yii\grid\SerialColumn'], 29 | [ 30 | 'attribute' => 'name', 31 | 'label' => Yii::t('rbac-admin', 'Name'), 32 | ], 33 | ['class' => 'yii\grid\ActionColumn',], 34 | ], 35 | ]); 36 | ?> 37 | 38 |
39 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.6 5 | - 7.0 6 | - 7.1 7 | - 7.2 8 | - 7.3 9 | # - hhvm 10 | 11 | # faster builds on new travis setup not using sudo 12 | sudo: false 13 | 14 | services: 15 | - mysql 16 | 17 | # cache vendor dirs 18 | cache: 19 | directories: 20 | - $HOME/.composer/cache 21 | 22 | install: 23 | - travis_retry composer self-update && composer --version 24 | - travis_retry composer global require fxp/composer-asset-plugin --no-plugins 25 | - export PATH="$HOME/.composer/vendor/bin:$PATH" 26 | - travis_retry composer install --dev --prefer-dist --no-interaction 27 | # codeception 28 | - travis_retry composer global require "codeception/codeception=2.0.*" "codeception/specify=*" "codeception/verify=*" 29 | # setup application: 30 | - | 31 | cd tests 32 | codecept build 33 | cd .. 34 | before_install: 35 | - mysql --version 36 | 37 | # initialize databases 38 | - mysql -e 'CREATE DATABASE IF NOT EXISTS mdm_admin_test;' 39 | 40 | script: 41 | - | 42 | cd tests/web 43 | php -S localhost:8080 > /dev/null 2>&1 & 44 | cd .. 45 | codecept run -------------------------------------------------------------------------------- /views/assignment/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Assignments'); 14 | $this->params['breadcrumbs'][] = $this->title; 15 | 16 | $columns = [ 17 | ['class' => 'yii\grid\SerialColumn'], 18 | $usernameField, 19 | ]; 20 | if (!empty($extraColumns)) { 21 | $columns = array_merge($columns, $extraColumns); 22 | } 23 | $columns[] = [ 24 | 'class' => 'yii\grid\ActionColumn', 25 | 'template' => '{view}' 26 | ]; 27 | ?> 28 |
29 | 30 |

title) ?>

31 | 32 | 33 | $dataProvider, 36 | 'filterModel' => $searchModel, 37 | 'columns' => $columns, 38 | ]); 39 | ?> 40 | 41 | 42 |
43 | -------------------------------------------------------------------------------- /views/layouts/right-menu.php: -------------------------------------------------------------------------------- 1 | context; 9 | $menus = $controller->module->menus; 10 | $route = $controller->route; 11 | foreach ($menus as $i => $menu) { 12 | $menus[$i]['active'] = strpos($route, trim((string)$menu['url'][0], '/')) === 0; 13 | } 14 | $this->params['nav-items'] = $menus; 15 | ?> 16 | beginContent($controller->module->mainLayout) ?> 17 |
18 |
19 | 20 |
21 |
22 |
23 | 'list-group-item' . $active, 29 | ]); 30 | } 31 | ?> 32 |
33 |
34 |
35 | endContent(); ?> 36 | -------------------------------------------------------------------------------- /views/rule/view.php: -------------------------------------------------------------------------------- 1 | title = $model->name; 11 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', 'Rules'), 'url' => ['index']]; 12 | $this->params['breadcrumbs'][] = $this->title; 13 | ?> 14 |
15 | 16 |

title) ?>

17 | 18 |

19 | $model->name], ['class' => 'btn btn-primary']) ?> 20 | $model->name], [ 22 | 'class' => 'btn btn-danger', 23 | 'data-confirm' => Yii::t('rbac-admin', 'Are you sure to delete this item?'), 24 | 'data-method' => 'post', 25 | ]); 26 | ?> 27 |

28 | 29 | $model, 32 | 'attributes' => [ 33 | 'name', 34 | 'className', 35 | ], 36 | ]); 37 | ?> 38 |
39 | -------------------------------------------------------------------------------- /views/user/change-password.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Change Password'); 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 | 30 | -------------------------------------------------------------------------------- /views/menu/view.php: -------------------------------------------------------------------------------- 1 | title = $model->name; 10 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', 'Menus'), 'url' => ['index']]; 11 | $this->params['breadcrumbs'][] = $this->title; 12 | ?> 13 | 43 | -------------------------------------------------------------------------------- /views/user/signup.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Signup'); 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 | 31 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mdmsoft/yii2-admin", 3 | "description": "RBAC Auth manager for Yii2 ", 4 | "keywords": ["yii", "admin", "auth", "rbac"], 5 | "type": "yii2-extension", 6 | "license": "BSD-3-Clause", 7 | "support": { 8 | "issues": "https://github.com/mdmsoft/yii2-admin/issues", 9 | "source": "https://github.com/mdmsoft/yii2-admin" 10 | }, 11 | "authors": [ 12 | { 13 | "name": "Misbahul Munir", 14 | "email": "misbahuldmunir@gmail.com" 15 | } 16 | ], 17 | "minimum-stability": "dev", 18 | "require": { 19 | "yiisoft/yii2": "~2.0.7" 20 | }, 21 | "require-dev": { 22 | "yiisoft/yii2-codeception": "~2.0" 23 | }, 24 | "suggest": { 25 | "yiisoft/yii2-bootstrap": "Used when using layout 'left-menu', 'right-menu' or 'top-menu'" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "mdm\\admin\\": "" 30 | } 31 | }, 32 | "extra": { 33 | "branch-alias": { 34 | "dev-1.0.master": "1.0.x-dev", 35 | "dev-master": "2.x-dev" 36 | }, 37 | "asset-installer-paths": { 38 | "npm-asset-library": "vendor/npm", 39 | "bower-asset-library": "vendor/bower" 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /migrations/m140602_111327_create_menu_table.php: -------------------------------------------------------------------------------- 1 | 9 | * @since 1.0 10 | */ 11 | class m140602_111327_create_menu_table extends \yii\db\Migration 12 | { 13 | 14 | /** 15 | * @inheritdoc 16 | */ 17 | public function up() 18 | { 19 | $menuTable = Configs::instance()->menuTable; 20 | $tableOptions = null; 21 | if ($this->db->driverName === 'mysql') { 22 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB'; 23 | } 24 | 25 | $this->createTable($menuTable, [ 26 | 'id' => $this->primaryKey(), 27 | 'name' => $this->string(128)->notNull(), 28 | 'parent' => $this->integer(), 29 | 'route' => $this->string(), 30 | 'order' => $this->integer(), 31 | 'data' => $this->binary(), 32 | "FOREIGN KEY ([[parent]]) REFERENCES {$menuTable}([[id]]) ON DELETE SET NULL ON UPDATE CASCADE", 33 | ], $tableOptions); 34 | } 35 | 36 | /** 37 | * @inheritdoc 38 | */ 39 | public function down() 40 | { 41 | $this->dropTable(Configs::instance()->menuTable); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /views/layouts/left-menu.php: -------------------------------------------------------------------------------- 1 | context; 9 | $menus = $controller->module->menus; 10 | $route = $controller->route; 11 | foreach ($menus as $i => $menu) { 12 | $menus[$i]['active'] = strpos($route, trim((string)$menu['url'][0], '/')) === 0; 13 | } 14 | $this->params['nav-items'] = $menus; 15 | ?> 16 | beginContent($controller->module->mainLayout) ?> 17 |
18 |
19 |
20 | 'glyphicon glyphicon-chevron-right pull-right']) . 23 | Html::tag('span', Html::encode($menu['label']), []); 24 | $active = $menu['active'] ? ' active' : ''; 25 | echo Html::a($label, $menu['url'], [ 26 | 'class' => 'list-group-item' . $active, 27 | ]); 28 | } 29 | ?> 30 |
31 |
32 |
33 | 34 |
35 |
36 | assetManager->publish('@mdm/admin/assets'); 38 | $this->registerCssFile($url . '/list-item.css'); 39 | ?> 40 | 41 | endContent(); ?> 42 | -------------------------------------------------------------------------------- /views/user/login.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Login'); 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 | 34 | -------------------------------------------------------------------------------- /views/menu/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('rbac-admin', 'Menus'); 12 | $this->params['breadcrumbs'][] = $this->title; 13 | ?> 14 | 47 | -------------------------------------------------------------------------------- /views/menu/_script.js: -------------------------------------------------------------------------------- 1 | $('#parent_name').autocomplete({ 2 | source: function (request, response) { 3 | var result = []; 4 | var limit = 10; 5 | var term = request.term.toLowerCase(); 6 | $.each(_opts.menus, function () { 7 | var menu = this; 8 | if (term == '' || menu.name.toLowerCase().indexOf(term) >= 0 || 9 | (menu.parent_name && menu.parent_name.toLowerCase().indexOf(term) >= 0) || 10 | (menu.route && menu.route.toLowerCase().indexOf(term) >= 0)) { 11 | result.push(menu); 12 | limit--; 13 | if (limit <= 0) { 14 | return false; 15 | } 16 | } 17 | }); 18 | response(result); 19 | }, 20 | focus: function (event, ui) { 21 | $('#parent_name').val(ui.item.name); 22 | return false; 23 | }, 24 | select: function (event, ui) { 25 | $('#parent_name').val(ui.item.name); 26 | $('#parent_id').val(ui.item.id); 27 | return false; 28 | }, 29 | search: function () { 30 | $('#parent_id').val(''); 31 | } 32 | }).autocomplete("instance")._renderItem = function (ul, item) { 33 | return $("
  • ") 34 | .append($('').append($('').text(item.name)).append('
    ') 35 | .append($('').text(item.parent_name + ' | ' + item.route))) 36 | .appendTo(ul); 37 | }; 38 | 39 | $('#route').autocomplete({ 40 | source: _opts.routes, 41 | }); -------------------------------------------------------------------------------- /views/default/index.php: -------------------------------------------------------------------------------- 1 | title = substr($page, 0, strrpos($page, '.')); 12 | } else { 13 | $baseDir = substr($page, 0, $pos) . '/'; 14 | $this->title = substr($page, $pos + 1, strrpos($page, '.') - $pos - 1); 15 | } 16 | 17 | if ($page == 'README.md') { 18 | $this->params['breadcrumbs'][] = 'Readme'; 19 | $menus = $this->context->module->getMenus(); 20 | $links = []; 21 | foreach ($menus as $menu) { 22 | $url = Url::to($menu['url'], true); 23 | $links[] = "[**{$menu['label']}**]({$url})"; 24 | } 25 | $body = str_replace(':smile:.', ".\n\n" . implode(' ', $links) . "\n", file_get_contents(Url::to('@mdm/admin/README.md'))); 26 | } elseif(preg_match('/^docs\/guide\/[\w-]+\.md$/', $page)) { 27 | $body = file_get_contents(Url::to("@mdm/admin/{$page}")); 28 | } else{ 29 | $body = ''; 30 | } 31 | 32 | $body = preg_replace_callback('/\]\((.*?)\)/', function($matches) use($baseDir) { 33 | $link = $matches[1]; 34 | if (strpos($link, '://') === false) { 35 | if ($link[0] == '/') { 36 | $link = Url::current(['page' => ltrim((string)$link, '/')], true); 37 | } else { 38 | $link = Url::current(['page' => $baseDir . $link], true); 39 | } 40 | } 41 | return "]($link)"; 42 | }, $body); 43 | 44 | echo Markdown::process($body, 'gfm'); 45 | -------------------------------------------------------------------------------- /models/searchs/User.php: -------------------------------------------------------------------------------- 1 | getUser()->identityClass ? : 'mdm\admin\models\User'; 41 | $query = $class::find(); 42 | 43 | $dataProvider = new ActiveDataProvider([ 44 | 'query' => $query, 45 | ]); 46 | 47 | $this->load($params); 48 | if (!$this->validate()) { 49 | $query->where('1=0'); 50 | return $dataProvider; 51 | } 52 | 53 | $query->andFilterWhere([ 54 | 'id' => $this->id, 55 | 'status' => $this->status, 56 | ]); 57 | 58 | $query->andFilterWhere(['like', 'username', $this->username]) 59 | ->andFilterWhere(['like', 'email', $this->email]); 60 | 61 | return $dataProvider; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /views/menu/_form.php: -------------------------------------------------------------------------------- 1 | Menu::getMenuSource(), 15 | 'routes' => Menu::getSavedRoutes(), 16 | ]); 17 | $this->registerJs("var _opts = $opts;"); 18 | $this->registerJs($this->render('_script.js')); 19 | ?> 20 | 21 | 47 | -------------------------------------------------------------------------------- /components/DbManager.php: -------------------------------------------------------------------------------- 1 | 20 | * @since 1.0 21 | */ 22 | class DbManager extends \yii\rbac\DbManager 23 | { 24 | /** 25 | * Memory cache of assignments 26 | * @var array 27 | */ 28 | private $_assignments = []; 29 | private $_childrenList; 30 | 31 | /** 32 | * @inheritdoc 33 | */ 34 | public function getAssignments($userId) 35 | { 36 | if (!isset($this->_assignments[$userId])) { 37 | $this->_assignments[$userId] = parent::getAssignments($userId); 38 | } 39 | return $this->_assignments[$userId]; 40 | } 41 | 42 | /** 43 | * @inheritdoc 44 | */ 45 | protected function getChildrenList() 46 | { 47 | if ($this->_childrenList === null) { 48 | $this->_childrenList = parent::getChildrenList(); 49 | } 50 | return $this->_childrenList; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /models/searchs/BizRule.php: -------------------------------------------------------------------------------- 1 | 16 | * @since 1.0 17 | */ 18 | class BizRule extends Model 19 | { 20 | /** 21 | * @var string name of the rule 22 | */ 23 | public $name; 24 | 25 | public function rules() 26 | { 27 | return [ 28 | [['name'], 'safe'] 29 | ]; 30 | } 31 | 32 | /** 33 | * @inheritdoc 34 | */ 35 | public function attributeLabels() 36 | { 37 | return [ 38 | 'name' => Yii::t('rbac-admin', 'Name'), 39 | ]; 40 | } 41 | 42 | /** 43 | * Search BizRule 44 | * @param array $params 45 | * @return \yii\data\ActiveDataProvider|\yii\data\ArrayDataProvider 46 | */ 47 | public function search($params) 48 | { 49 | /* @var \yii\rbac\Manager $authManager */ 50 | $authManager = Configs::authManager(); 51 | $models = []; 52 | $included = !($this->load($params) && $this->validate() && trim((string)$this->name) !== ''); 53 | foreach ($authManager->getRules() as $name => $item) { 54 | if ($name != RouteRule::RULE_NAME && ($included || stripos($item->name, $this->name) !== false)) { 55 | $models[$name] = new MBizRule($item); 56 | } 57 | } 58 | 59 | return new ArrayDataProvider([ 60 | 'allModels' => $models, 61 | ]); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /views/assignment/_script.js: -------------------------------------------------------------------------------- 1 | $('i.glyphicon-refresh-animate').hide(); 2 | function updateItems(r) { 3 | _opts.items.available = r.available; 4 | _opts.items.assigned = r.assigned; 5 | search('available'); 6 | search('assigned'); 7 | } 8 | 9 | $('.btn-assign').click(function () { 10 | var $this = $(this); 11 | var target = $this.data('target'); 12 | var items = $('select.list[data-target="' + target + '"]').val(); 13 | 14 | if (items && items.length) { 15 | $this.children('i.glyphicon-refresh-animate').show(); 16 | $.post($this.attr('href'), {items: items}, function (r) { 17 | updateItems(r); 18 | }).always(function () { 19 | $this.children('i.glyphicon-refresh-animate').hide(); 20 | }); 21 | } 22 | return false; 23 | }); 24 | 25 | $('.search[data-target]').keyup(function () { 26 | search($(this).data('target')); 27 | }); 28 | 29 | function search(target) { 30 | var $list = $('select.list[data-target="' + target + '"]'); 31 | $list.html(''); 32 | var q = $('.search[data-target="' + target + '"]').val(); 33 | 34 | var groups = { 35 | role: [$(''), false], 36 | permission: [$(''), false], 37 | }; 38 | $.each(_opts.items[target], function (name, group) { 39 | if (name.indexOf(q) >= 0) { 40 | $('
    ${user.username}`; 73 | }); 74 | users.push('
    '); 75 | if (_opts.users.prev) { 76 | users.push(`«`); 77 | } 78 | if (_opts.users.next) { 79 | users.push(`»`); 80 | } 81 | $list.html(users.join(' ')); 82 | } 83 | 84 | // initial 85 | search('available'); 86 | search('assigned'); 87 | listUsers(); 88 | -------------------------------------------------------------------------------- /messages/en/rbac-admin.php: -------------------------------------------------------------------------------- 1 | 'Activate', 21 | 'Add' => 'Add', 22 | 'Assignments' => 'Assignments', 23 | 'Users' => 'Users', 24 | 'User' => 'User', 25 | 'Change' => 'Change', 26 | 'Change Password' => 'Change Password', 27 | 'Signup' => 'Signup', 28 | 'Login' => 'Login', 29 | 'Send' => 'Send', 30 | 'Available' => 'Available', 31 | 'Assigned' => 'Assigned', 32 | 'Create' => 'Create', 33 | 'Update' => 'Update', 34 | 'Roles' => 'Roles', 35 | 'Create New' => 'Create New', 36 | 'Create Role' => 'Create Role', 37 | 'Name' => 'Name', 38 | 'Type' => 'Type', 39 | 'Description' => 'Description', 40 | 'Rule Name' => 'Rule Name', 41 | 'Data' => 'Data', 42 | 'Update Role' => 'Update Role', 43 | 'Delete' => 'Delete', 44 | 'Are you sure to delete this item?' => 'Are you sure to delete this item?', 45 | 'Are you sure you want to activate this user?' => 'Are you sure you want to activate this user?', 46 | 'ID' => 'ID', 47 | 'Parent' => 'Parent', 48 | 'Parent Name' => 'Parent Name', 49 | 'Route' => 'Route', 50 | 'Username' => 'Username', 51 | 'Update Permission' => 'Update Permission', 52 | 'Permissions' => 'Permissions', 53 | 'Permission' => 'Permission', 54 | 'Create Permission' => 'Create Permission', 55 | 'Create Permissions' => 'Create Permissions', 56 | 'Routes' => 'Routes', 57 | 'Create route' => 'Create route', 58 | 'New' => 'New', 59 | 'New route(s)' => 'New route(s)', 60 | 'Generate Routes' => 'Generate Routes', 61 | 'Append' => 'Append', 62 | 'Create Rule' => 'Create Rule', 63 | 'Rules' => 'Rules', 64 | 'Rules' => 'Rules', 65 | 'Select Rule' => 'Select Rule', 66 | 'Update Rule' => 'Update Rule', 67 | 'Create Menu' => 'Create Menu', 68 | 'Menus' => 'Menus', 69 | 'Search' => 'Search', 70 | 'Search for available' => 'Search for available', 71 | 'Search for assigned' => 'Search for assigned', 72 | 'Reset' => 'Reset', 73 | 'Update Menu' => 'Update Menu', 74 | 'Menus' => 'Menus', 75 | 'Order' => 'Order', 76 | 'Class Name' => 'Class Name', 77 | 'Assignment' => 'Assignment', 78 | 'Role' => 'Role', 79 | 'Rule' => 'Rule', 80 | 'Menu' => 'Menu', 81 | 'Help' => 'Help', 82 | 'Application' => 'Application', 83 | ]; 84 | -------------------------------------------------------------------------------- /messages/id/rbac-admin.php: -------------------------------------------------------------------------------- 1 | 'Mengaktifkan', 21 | 'Add' => 'Tambah', 22 | 'Assignments' => 'Penugasan', 23 | 'Users' => 'Pengguna', 24 | 'User' => 'Pemakai', 25 | 'Change' => 'Ganti', 26 | 'Change Password' => 'Ganti Kata Sandi', 27 | 'Signup' => 'Daftar', 28 | 'Login' => 'Masuk', 29 | 'Send' => 'Kirim', 30 | 'Available' => 'Tersedia', 31 | 'Assigned' => 'Ditugaskan', 32 | 'Create' => 'Buat', 33 | 'Update' => 'Perbarui', 34 | 'Roles' => 'Peran', 35 | 'Create New' => 'Buat Baru', 36 | 'Create Role' => 'Buat Peran', 37 | 'Name' => 'Nama', 38 | 'Type' => 'Tipe', 39 | 'Description' => 'Deskripsi', 40 | 'Rule Name' => 'Nama Aturan', 41 | 'Data' => 'Data', 42 | 'Update Role' => 'Perbarui Peran', 43 | 'Delete' => 'Hapus', 44 | 'Are you sure to delete this item?' => 'Apakah Anda yakin menghapus item ini?', 45 | 'Are you sure you want to activate this user?' => 'Apakah Anda yakin ingin mengaktifkan pengguna ini?', 46 | 'ID' => 'ID', 47 | 'Parent' => 'Induk', 48 | 'Parent Name' => 'Nama Induk', 49 | 'Route' => 'Rute', 50 | 'Username' => 'Nama Pengguna', 51 | 'Update Permission' => 'Perbarui Ijin', 52 | 'Permissions' => 'Perizinan', 53 | 'Permission' => 'Izin', 54 | 'Create Permission' => 'Buat Izin', 55 | 'Create Permissions' => 'Buat perizinan', 56 | 'Routes' => 'Rute', 57 | 'Create route' => 'Buat Rute', 58 | 'New' => 'Baru', 59 | 'New route(s)' => 'Rute Baru', 60 | 'Generate Routes' => 'Hasilkan Rute', 61 | 'Append' => 'Menambahkan', 62 | 'Create Rule' => 'Buat Peraturan', 63 | 'Rules' => 'Peraturan', 64 | 'Rules' => 'Peraturan', 65 | 'Select Rule' => 'Pilih Pengaturan', 66 | 'Update Rule' => 'Perbarui Peraturan', 67 | 'Create Menu' => 'Buat Menu', 68 | 'Menus' => 'Menu', 69 | 'Search' => 'Cari', 70 | 'Search for available' => 'Cari yang tersedia', 71 | 'Search for assigned' => 'Cari yang sudah ditugaskan', 72 | 'Reset' => 'Atur Ulang', 73 | 'Update Menu' => 'Perbarui Menu', 74 | 'Menus' => 'Menu', 75 | 'Order' => 'Urutan', 76 | 'Class Name' => 'Nama Kelas', 77 | 'Assignment' => 'Penugasan', 78 | 'Role' => 'Peran', 79 | 'Rule' => 'Peraturan', 80 | 'Menu' => 'Menu', 81 | 'Help' => 'Bantuan', 82 | 'Application' => 'Aplikasi', 83 | ]; 84 | -------------------------------------------------------------------------------- /messages/es/rbac-admin.php: -------------------------------------------------------------------------------- 1 | 'Activar', 21 | 'Add' => 'Agregar', 22 | 'Assignments' => 'Asignaciones', 23 | 'Users' => 'Usuarios', 24 | 'User' => 'Usuario', 25 | 'Change' => 'Cambiar', 26 | 'Change Password' => 'Cambiar Contraseña', 27 | 'Signup' => 'Regístrate', 28 | 'Login' => 'Iniciar Sesión', 29 | 'Send' => 'Enviar', 30 | 'Available' => 'Disponible(s)', 31 | 'Assigned' => 'Asignado', 32 | 'Create' => 'Crear', 33 | 'Update' => 'Actualizar', 34 | 'Roles' => 'Roles', 35 | 'Create New' => 'Crear Nuevo', 36 | 'Create Role' => 'Crear Rol', 37 | 'Name' => 'Nombre', 38 | 'Type' => 'Tipo', 39 | 'Description' => 'Descripción', 40 | 'Rule Name' => 'Nombre de regla', 41 | 'Data' => 'Datos', 42 | 'Update Role' => 'Actualizar Rol', 43 | 'Delete' => 'Borrar', 44 | 'Are you sure to delete this item?' => '¿Está seguro de querer borrar este item?', 45 | 'Are you sure you want to activate this user?' => '¿Esta seguro de querer actualizar este usuario?', 46 | 'ID' => 'ID', 47 | 'Parent' => 'Padre', 48 | 'Parent Name' => 'Nombre del Padre', 49 | 'Route' => 'Ruta', 50 | 'Username' => 'Nombre de usuario', 51 | 'Update Permission' => 'Actualizar Permiso', 52 | 'Permissions' => 'Permisos', 53 | 'Permission' => 'Permiso', 54 | 'Create Permission' => 'Crear Permiso', 55 | 'Create Permissions' => 'Crear Permisos', 56 | 'Routes' => 'Rutas', 57 | 'Create route' => 'Crear Ruta', 58 | 'New' => 'Nuevo(a)', 59 | 'New route(s)' => 'Nueva Ruta(s)', 60 | 'Generate Routes' => 'Generar Rutas', 61 | 'Append' => 'Añadir', 62 | 'Create Rule' => 'Crear Regla', 63 | 'Rules' => 'Reglas', 64 | 'Select Rule' => 'Seleccione la Regla', 65 | 'Update Rule' => 'Actualizar Regla', 66 | 'Create Menu' => 'Crear Menú', 67 | 'Menus' => 'Menús', 68 | 'Search' => 'Buscar', 69 | 'Search for available' => 'Buscar Disponible', 70 | 'Search for assigned' => 'Buscar Asignado', 71 | 'Reset' => 'Reiniciar', 72 | 'Update Menu' => 'Actualizar Menú', 73 | 'Menus' => 'Menús', 74 | 'Order' => 'Orden', 75 | 'Class Name' => 'Nombre de la Clase', 76 | 'Assignment' => 'Asignación', 77 | 'Role' => 'Rol', 78 | 'Rule' => 'Regla', 79 | 'Menu' => 'Menú', 80 | 'Help' => 'Ayuda', 81 | 'Application' => 'Aplicación', 82 | ]; 83 | -------------------------------------------------------------------------------- /models/searchs/AuthItem.php: -------------------------------------------------------------------------------- 1 | 15 | * @since 1.0 16 | */ 17 | class AuthItem extends Model 18 | { 19 | const TYPE_ROUTE = 101; 20 | 21 | public $name; 22 | public $type; 23 | public $description; 24 | public $ruleName; 25 | public $data; 26 | 27 | /** 28 | * @inheritdoc 29 | */ 30 | public function rules() 31 | { 32 | return [ 33 | [['name', 'ruleName', 'description'], 'safe'], 34 | [['type'], 'integer'], 35 | ]; 36 | } 37 | 38 | /** 39 | * @inheritdoc 40 | */ 41 | public function attributeLabels() 42 | { 43 | return [ 44 | 'name' => Yii::t('rbac-admin', 'Name'), 45 | 'item_name' => Yii::t('rbac-admin', 'Name'), 46 | 'type' => Yii::t('rbac-admin', 'Type'), 47 | 'description' => Yii::t('rbac-admin', 'Description'), 48 | 'ruleName' => Yii::t('rbac-admin', 'Rule Name'), 49 | 'data' => Yii::t('rbac-admin', 'Data'), 50 | ]; 51 | } 52 | 53 | /** 54 | * Search authitem 55 | * @param array $params 56 | * @return \yii\data\ActiveDataProvider|\yii\data\ArrayDataProvider 57 | */ 58 | public function search($params) 59 | { 60 | /* @var \yii\rbac\Manager $authManager */ 61 | $authManager = Configs::authManager(); 62 | $advanced = Configs::instance()->advanced; 63 | if ($this->type == Item::TYPE_ROLE) { 64 | $items = $authManager->getRoles(); 65 | } else { 66 | $items = array_filter($authManager->getPermissions(), function($item) use ($advanced){ 67 | $isPermission = $this->type == Item::TYPE_PERMISSION; 68 | if ($advanced) { 69 | return $isPermission xor (strncmp($item->name, '/', 1) === 0 or strncmp($item->name, '@', 1) === 0); 70 | } 71 | else { 72 | return $isPermission xor strncmp($item->name, '/', 1) === 0; 73 | } 74 | }); 75 | } 76 | $this->load($params); 77 | if ($this->validate()) { 78 | 79 | $search = mb_strtolower(trim((string)$this->name)); 80 | $desc = mb_strtolower(trim((string)$this->description)); 81 | $ruleName = $this->ruleName; 82 | foreach ($items as $name => $item) { 83 | $f = (empty($search) || mb_strpos(mb_strtolower($item->name), $search) !== false) && 84 | (empty($desc) || mb_strpos(mb_strtolower($item->description), $desc) !== false) && 85 | (empty($ruleName) || $item->ruleName == $ruleName); 86 | if (!$f) { 87 | unset($items[$name]); 88 | } 89 | } 90 | } 91 | 92 | return new ArrayDataProvider([ 93 | 'allModels' => $items, 94 | ]); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RBAC Manager for Yii 2 2 | ====================== 3 | GUI manager for RBAC (Role Base Access Control) Yii2. Easy to manage authorization of user :smile:. 4 | 5 | [![Latest Unstable Version](https://poser.pugx.org/mdmsoft/yii2-admin/v/unstable)](https://packagist.org/packages/mdmsoft/yii2-admin) 6 | [![Total Downloads](https://poser.pugx.org/mdmsoft/yii2-admin/downloads.png)](https://packagist.org/packages/mdmsoft/yii2-admin) 7 | [![Daily Downloads](https://poser.pugx.org/mdmsoft/yii2-admin/d/daily)](https://packagist.org/packages/mdmsoft/yii2-admin) 8 | [![License](https://poser.pugx.org/mdmsoft/yii2-admin/license)](https://packagist.org/packages/mdmsoft/yii2-admin) 9 | [![Reference Status](https://www.versioneye.com/php/mdmsoft:yii2-admin/reference_badge.svg)](https://www.versioneye.com/php/mdmsoft:yii2-admin/references) 10 | [![Build Status](https://img.shields.io/travis/mdmsoft/yii2-admin.svg)](http://travis-ci.org/mdmsoft/yii2-admin) 11 | [![Dependency Status](https://www.versioneye.com/php/mdmsoft:yii2-admin/dev-master/badge.png)](https://www.versioneye.com/php/mdmsoft:yii2-admin/dev-master) 12 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/mdmsoft/yii2-admin/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/mdmsoft/yii2-admin/?branch=master) 13 | [![Code Climate](https://img.shields.io/codeclimate/github/mdmsoft/yii2-admin.svg)](https://codeclimate.com/github/mdmsoft/yii2-admin) 14 | 15 | Documentation 16 | ------------- 17 | > **Important: If you install version 3.x, please see [this readme](https://github.com/mdmsoft/yii2-admin/blob/3.master/README.md#upgrade-from-2x).** 18 | 19 | 20 | - [Change Log](CHANGELOG.md). 21 | - [Authorization Guide](http://www.yiiframework.com/doc-2.0/guide-security-authorization.html). Important, read this first before you continue. 22 | - [Basic Configuration](docs/guide/configuration.md) 23 | - [Basic Usage](docs/guide/basic-usage.md). 24 | - [User Management](docs/guide/user-management.md). 25 | - [Using Menu](docs/guide/using-menu.md). 26 | - [Api](https://mdmsoft.github.io/yii2-admin/index.html). 27 | 28 | Installation 29 | ------------ 30 | 31 | ### Install With Composer 32 | 33 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 34 | 35 | Either run 36 | 37 | ``` 38 | php composer.phar require mdmsoft/yii2-admin "~1.0" 39 | or 40 | php composer.phar require mdmsoft/yii2-admin "~2.0" 41 | ``` 42 | 43 | or for the dev-master 44 | 45 | ``` 46 | php composer.phar require mdmsoft/yii2-admin "2.x-dev" 47 | ``` 48 | 49 | Or, you may add 50 | 51 | ``` 52 | "mdmsoft/yii2-admin": "~2.0" 53 | ``` 54 | 55 | to the require section of your `composer.json` file and execute `php composer.phar update`. 56 | 57 | ### Install From the Archive 58 | 59 | Download the latest release from here [releases](https://github.com/mdmsoft/yii2-admin/releases), then extract it to your project. 60 | In your application config, add the path alias for this extension. 61 | 62 | ```php 63 | return [ 64 | ... 65 | 'aliases' => [ 66 | '@mdm/admin' => 'path/to/your/extracted', 67 | // for example: '@mdm/admin' => '@app/extensions/mdm/yii2-admin-2.0.0', 68 | ... 69 | ] 70 | ]; 71 | ``` 72 | 73 | [**More...**](docs/guide/configuration.md) 74 | 75 | [screenshots](https://goo.gl/r8RizT) 76 | -------------------------------------------------------------------------------- /models/Assignment.php: -------------------------------------------------------------------------------- 1 | 13 | * @since 2.5 14 | */ 15 | class Assignment extends \mdm\admin\BaseObject 16 | { 17 | /** 18 | * @var integer User id 19 | */ 20 | public $id; 21 | /** 22 | * @var \yii\web\IdentityInterface User 23 | */ 24 | public $user; 25 | 26 | /** 27 | * @inheritdoc 28 | */ 29 | public function __construct($id, $user = null, $config = array()) 30 | { 31 | $this->id = $id; 32 | $this->user = $user; 33 | parent::__construct($config); 34 | } 35 | 36 | /** 37 | * Grands a roles from a user. 38 | * @param array $items 39 | * @return integer number of successful grand 40 | */ 41 | public function assign($items) 42 | { 43 | $manager = Configs::authManager(); 44 | $success = 0; 45 | foreach ($items as $name) { 46 | try { 47 | $item = $manager->getRole($name); 48 | $item = $item ?: $manager->getPermission($name); 49 | $manager->assign($item, $this->id); 50 | $success++; 51 | } catch (\Exception $exc) { 52 | Yii::error($exc->getMessage(), __METHOD__); 53 | } 54 | } 55 | Helper::invalidate(); 56 | return $success; 57 | } 58 | 59 | /** 60 | * Revokes a roles from a user. 61 | * @param array $items 62 | * @return integer number of successful revoke 63 | */ 64 | public function revoke($items) 65 | { 66 | $manager = Configs::authManager(); 67 | $success = 0; 68 | foreach ($items as $name) { 69 | try { 70 | $item = $manager->getRole($name); 71 | $item = $item ?: $manager->getPermission($name); 72 | $manager->revoke($item, $this->id); 73 | $success++; 74 | } catch (\Exception $exc) { 75 | Yii::error($exc->getMessage(), __METHOD__); 76 | } 77 | } 78 | Helper::invalidate(); 79 | return $success; 80 | } 81 | 82 | /** 83 | * Get all available and assigned roles/permission 84 | * @return array 85 | */ 86 | public function getItems() 87 | { 88 | $manager = Configs::authManager(); 89 | $available = []; 90 | foreach (array_keys($manager->getRoles()) as $name) { 91 | $available[$name] = 'role'; 92 | } 93 | 94 | foreach (array_keys($manager->getPermissions()) as $name) { 95 | if ($name[0] != '/') { 96 | $available[$name] = 'permission'; 97 | } 98 | } 99 | 100 | $assigned = []; 101 | foreach ($manager->getAssignments($this->id) as $item) { 102 | $assigned[$item->roleName] = $available[$item->roleName]; 103 | unset($available[$item->roleName]); 104 | } 105 | 106 | ksort($available); 107 | ksort($assigned); 108 | return [ 109 | 'available' => $available, 110 | 'assigned' => $assigned, 111 | ]; 112 | } 113 | 114 | /** 115 | * @inheritdoc 116 | */ 117 | public function __get($name) 118 | { 119 | if ($this->user) { 120 | return $this->user->$name; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Yii2 Admin Change Log 2 | ========================== 3 | 4 | 2.5 5 | ----- 6 | 7 | - Enh: Add code testing (mdmunir). 8 | - Enh: Add more documentation (mdmunir). 9 | 10 | 2.0 11 | --------------------- 12 | 13 | - Chg: Remove dependenci to `yiisoft/yii2-jui` (mdmunir). 14 | - Chg: Add asset bundle for jui autocomplete (mdmunir). 15 | 16 | 17 | 1.0.4 18 | ----------------------- 19 | 20 | - Bug: #102: Unique validation of the permission and role (mdmunir). 21 | - Enh: Clear cache when menu change (mdmunir). 22 | - Enh: Ensure get latest state of `user` component (mdmunir). 23 | 24 | 25 | 1.0.3 26 | ------ 27 | 28 | 29 | 1.0.2 30 | ------ 31 | 32 | - Enh: Add Portuguese language to translation message (iforme). 33 | - Enh: configurable Navbar defined in module config (Stefano Mtangoo). 34 | - Enh: Add Italian language to translation message (realtebo). 35 | 36 | 1.0.1 37 | ----- 38 | 39 | - Enh: Add Persian language to translation message (jafaripur). 40 | - Enh: Add French language to translation message (marsuboss). 41 | 42 | 43 | 1.0.0 44 | ----- 45 | 46 | - Enh: Internationalization (sosojni). 47 | - Enh: Add Russian language to translation message (m0zart89). 48 | 49 | 50 | 1.0.0-rc 51 | -------- 52 | 53 | - Bug #12: Allow another module name (mdmunir). 54 | - Bug: #19: Added table prefix to table `menu` for some query (mdmunir, liu0472). 55 | - Bug: #24: change `$cache === null` to `isset($cache)` (mdmunir). 56 | - Bug: Bug fix. Ensure array has index before check `in_array()` (mdmunir). 57 | - Bug: Typo fix, replace `AssigmentController` to `AssignmentController` (mdmunir). 58 | - Enh: Custom side menu via `mdm\admin\Module::items` (mdmunir). 59 | - Enh: Added menu manager (mdmunir). 60 | - Enh: Migration for table menu (mdmunir). 61 | - Enh: Added Menu order (mdmunir). 62 | - Enh: Add `db` and `cache` configuration (mdmunir). 63 | - Enh: Add comment docs for entire class (mdmunir). 64 | - Enh: Add documentation (mdmunir). 65 | - Enh #57: Allow user to assign permission directly (mdmunir). 66 | - Chg #10: `cache` is not used anymore (mdmunir). 67 | - Chg #11: Only use required style sheet (mdmunir). 68 | - Chg: Using `VarDumper::export` to save `data` of `mdm\models\AuthItem` (mdmunir). 69 | - Chg: Allow using another `yii\rbac\Rule` instance (mdmunir). 70 | - Chg: Remove prefix `menu_` from column name of table `menu` (mdmunir). 71 | - Chg: Added column `data` to table `menu` (mdmunir). 72 | - Chg: Can customize return of `mdm\admin\components\AccessHelper::getAssignedMenu()` with provide a callback to method (mdmunir). 73 | - Chg: Add require "yiisoft/yii2-jui" to composer.json (mdmunir, hashie5). 74 | - Chg: #21: Force set allow `null` to column `parent` in database migration (mdmunir). 75 | - Chg: Remove `mdm\admin\components\BizRule` (mdmunir). 76 | - Chg: Change convert string to `yii\rbac\Item::$data` with `Json::decode()` (mdmunir). 77 | - Chg: Add extra param to route (mdmunir). 78 | - Chg: Add ability to get sparated menu. See [Using Menu](docs/guide/using-menu.md) (mdmunir). 79 | - Chg: Refactor layout (mdmunir). 80 | - Chg: Change `AccessHelper` to `MenuHelper` (mdmunir). 81 | - Chg: Change migration path name (mdmunir). 82 | - Chg: `db` and `cache` configuration via `$app->params['mdm.admin.configs']` (mdmunir). 83 | - Chg: #29: Change `yii\caching\GroupDependency` to `yii\caching\TagDependency` (mdmunir). 84 | - Chg: Remove `mdm\admin\Module::allowActions`. Set access control directly with `mdm\admin\components\AccessControl` (mdmunir). 85 | - Chg: Change cache strategy (mdmunir). 86 | - Chg: `mdm\admin\components\DbManager` now inherited from `yii\rbac\DbManager` (mdmunir). 87 | - Chg: Change module default layout (mdmunir). 88 | - Chg: Change back items to controllers (mdmunir). 89 | - Chg: Set default layout to `null` (mdmunir). 90 | - Chg #53: Fixed typo. Change Role to Permission (mdmunir). 91 | - Chg: Simplify using layout (mdmunir). 92 | -------------------------------------------------------------------------------- /controllers/RuleController.php: -------------------------------------------------------------------------------- 1 | 18 | * @since 1.0 19 | */ 20 | class RuleController extends Controller 21 | { 22 | 23 | /** 24 | * @inheritdoc 25 | */ 26 | public function behaviors() 27 | { 28 | return [ 29 | 'verbs' => [ 30 | 'class' => VerbFilter::className(), 31 | 'actions' => [ 32 | 'delete' => ['post'], 33 | ], 34 | ], 35 | ]; 36 | } 37 | 38 | /** 39 | * Lists all AuthItem models. 40 | * @return mixed 41 | */ 42 | public function actionIndex() 43 | { 44 | $searchModel = new BizRuleSearch(); 45 | $dataProvider = $searchModel->search(Yii::$app->request->getQueryParams()); 46 | 47 | return $this->render('index', [ 48 | 'dataProvider' => $dataProvider, 49 | 'searchModel' => $searchModel, 50 | ]); 51 | } 52 | 53 | /** 54 | * Displays a single AuthItem model. 55 | * @param string $id 56 | * @return mixed 57 | */ 58 | public function actionView($id) 59 | { 60 | $model = $this->findModel($id); 61 | 62 | return $this->render('view', ['model' => $model]); 63 | } 64 | 65 | /** 66 | * Creates a new AuthItem model. 67 | * If creation is successful, the browser will be redirected to the 'view' page. 68 | * @return mixed 69 | */ 70 | public function actionCreate() 71 | { 72 | $model = new BizRule(null); 73 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 74 | Helper::invalidate(); 75 | 76 | return $this->redirect(['view', 'id' => $model->name]); 77 | } else { 78 | return $this->render('create', ['model' => $model,]); 79 | } 80 | } 81 | 82 | /** 83 | * Updates an existing AuthItem model. 84 | * If update is successful, the browser will be redirected to the 'view' page. 85 | * @param string $id 86 | * @return mixed 87 | */ 88 | public function actionUpdate($id) 89 | { 90 | $model = $this->findModel($id); 91 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 92 | Helper::invalidate(); 93 | 94 | return $this->redirect(['view', 'id' => $model->name]); 95 | } 96 | 97 | return $this->render('update', ['model' => $model,]); 98 | } 99 | 100 | /** 101 | * Deletes an existing AuthItem model. 102 | * If deletion is successful, the browser will be redirected to the 'index' page. 103 | * @param string $id 104 | * @return mixed 105 | */ 106 | public function actionDelete($id) 107 | { 108 | $model = $this->findModel($id); 109 | Configs::authManager()->remove($model->item); 110 | Helper::invalidate(); 111 | 112 | return $this->redirect(['index']); 113 | } 114 | 115 | /** 116 | * Finds the AuthItem model based on its primary key value. 117 | * If the model is not found, a 404 HTTP exception will be thrown. 118 | * @param string $id 119 | * @return AuthItem the loaded model 120 | * @throws HttpException if the model cannot be found 121 | */ 122 | protected function findModel($id) 123 | { 124 | $item = Configs::authManager()->getRule($id); 125 | if ($item) { 126 | return new BizRule($item); 127 | } else { 128 | throw new NotFoundHttpException('The requested page does not exist.'); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /controllers/MenuController.php: -------------------------------------------------------------------------------- 1 | 17 | * @since 1.0 18 | */ 19 | class MenuController extends Controller 20 | { 21 | 22 | /** 23 | * @inheritdoc 24 | */ 25 | public function behaviors() 26 | { 27 | return [ 28 | 'verbs' => [ 29 | 'class' => VerbFilter::className(), 30 | 'actions' => [ 31 | 'delete' => ['post'], 32 | ], 33 | ], 34 | ]; 35 | } 36 | 37 | /** 38 | * Lists all Menu models. 39 | * @return mixed 40 | */ 41 | public function actionIndex() 42 | { 43 | $searchModel = new MenuSearch; 44 | $dataProvider = $searchModel->search(Yii::$app->request->getQueryParams()); 45 | 46 | return $this->render('index', [ 47 | 'dataProvider' => $dataProvider, 48 | 'searchModel' => $searchModel, 49 | ]); 50 | } 51 | 52 | /** 53 | * Displays a single Menu model. 54 | * @param integer $id 55 | * @return mixed 56 | */ 57 | public function actionView($id) 58 | { 59 | return $this->render('view', [ 60 | 'model' => $this->findModel($id), 61 | ]); 62 | } 63 | 64 | /** 65 | * Creates a new Menu model. 66 | * If creation is successful, the browser will be redirected to the 'view' page. 67 | * @return mixed 68 | */ 69 | public function actionCreate() 70 | { 71 | $model = new Menu; 72 | 73 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 74 | Helper::invalidate(); 75 | return $this->redirect(['view', 'id' => $model->id]); 76 | } else { 77 | return $this->render('create', [ 78 | 'model' => $model, 79 | ]); 80 | } 81 | } 82 | 83 | /** 84 | * Updates an existing Menu model. 85 | * If update is successful, the browser will be redirected to the 'view' page. 86 | * @param integer $id 87 | * @return mixed 88 | */ 89 | public function actionUpdate($id) 90 | { 91 | $model = $this->findModel($id); 92 | if ($model->menuParent) { 93 | $model->parent_name = $model->menuParent->name; 94 | } 95 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 96 | Helper::invalidate(); 97 | return $this->redirect(['view', 'id' => $model->id]); 98 | } else { 99 | return $this->render('update', [ 100 | 'model' => $model, 101 | ]); 102 | } 103 | } 104 | 105 | /** 106 | * Deletes an existing Menu model. 107 | * If deletion is successful, the browser will be redirected to the 'index' page. 108 | * @param integer $id 109 | * @return mixed 110 | */ 111 | public function actionDelete($id) 112 | { 113 | $this->findModel($id)->delete(); 114 | Helper::invalidate(); 115 | 116 | return $this->redirect(['index']); 117 | } 118 | 119 | /** 120 | * Finds the Menu model based on its primary key value. 121 | * If the model is not found, a 404 HTTP exception will be thrown. 122 | * @param integer $id 123 | * @return Menu the loaded model 124 | * @throws NotFoundHttpException if the model cannot be found 125 | */ 126 | protected function findModel($id) 127 | { 128 | if (($model = Menu::findOne($id)) !== null) { 129 | return $model; 130 | } else { 131 | throw new NotFoundHttpException('The requested page does not exist.'); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /models/BizRule.php: -------------------------------------------------------------------------------- 1 | 13 | * @since 1.0 14 | */ 15 | class BizRule extends \yii\base\Model 16 | { 17 | /** 18 | * @var string name of the rule 19 | */ 20 | public $name; 21 | 22 | /** 23 | * @var integer UNIX timestamp representing the rule creation time 24 | */ 25 | public $createdAt; 26 | 27 | /** 28 | * @var integer UNIX timestamp representing the rule updating time 29 | */ 30 | public $updatedAt; 31 | 32 | /** 33 | * @var string Rule classname. 34 | */ 35 | public $className; 36 | 37 | /** 38 | * @var Rule 39 | */ 40 | private $_item; 41 | 42 | /** 43 | * Initialize object 44 | * @param \yii\rbac\Rule $item 45 | * @param array $config 46 | */ 47 | public function __construct($item, $config = []) 48 | { 49 | $this->_item = $item; 50 | if ($item !== null) { 51 | $this->name = $item->name; 52 | $this->className = get_class($item); 53 | } 54 | parent::__construct($config); 55 | } 56 | 57 | /** 58 | * @inheritdoc 59 | */ 60 | public function rules() 61 | { 62 | return [ 63 | [['name', 'className'], 'required'], 64 | [['className'], 'string'], 65 | [['className'], 'classExists'] 66 | ]; 67 | } 68 | 69 | /** 70 | * Validate class exists 71 | */ 72 | public function classExists() 73 | { 74 | if (!class_exists($this->className)) { 75 | $message = Yii::t('rbac-admin', "Unknown class '{class}'", ['class' => $this->className]); 76 | $this->addError('className', $message); 77 | return; 78 | } 79 | if (!is_subclass_of($this->className, Rule::className())) { 80 | $message = Yii::t('rbac-admin', "'{class}' must extend from 'yii\rbac\Rule' or its child class", [ 81 | 'class' => $this->className]); 82 | $this->addError('className', $message); 83 | } 84 | } 85 | 86 | /** 87 | * @inheritdoc 88 | */ 89 | public function attributeLabels() 90 | { 91 | return [ 92 | 'name' => Yii::t('rbac-admin', 'Name'), 93 | 'className' => Yii::t('rbac-admin', 'Class Name'), 94 | ]; 95 | } 96 | 97 | /** 98 | * Check if new record. 99 | * @return boolean 100 | */ 101 | public function getIsNewRecord() 102 | { 103 | return $this->_item === null; 104 | } 105 | 106 | /** 107 | * Find model by id 108 | * @param type $id 109 | * @return null|static 110 | */ 111 | public static function find($id) 112 | { 113 | $item = Configs::authManager()->getRule($id); 114 | if ($item !== null) { 115 | return new static($item); 116 | } 117 | 118 | return null; 119 | } 120 | 121 | /** 122 | * Save model to authManager 123 | * @return boolean 124 | */ 125 | public function save() 126 | { 127 | if ($this->validate()) { 128 | $manager = Configs::authManager(); 129 | $class = $this->className; 130 | if ($this->_item === null) { 131 | $this->_item = new $class(); 132 | $isNew = true; 133 | } else { 134 | $isNew = false; 135 | $oldName = $this->_item->name; 136 | } 137 | $this->_item->name = $this->name; 138 | 139 | if ($isNew) { 140 | $manager->add($this->_item); 141 | } else { 142 | $manager->update($oldName, $this->_item); 143 | } 144 | 145 | return true; 146 | } else { 147 | return false; 148 | } 149 | } 150 | 151 | /** 152 | * Get item 153 | * @return Item 154 | */ 155 | public function getItem() 156 | { 157 | return $this->_item; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /views/item/view.php: -------------------------------------------------------------------------------- 1 | context; 18 | $labels = $context->labels(); 19 | $this->title = $model->name; 20 | $this->params['breadcrumbs'][] = ['label' => Yii::t('rbac-admin', $labels['Items']), 'url' => ['index']]; 21 | $this->params['breadcrumbs'][] = $this->title; 22 | 23 | AnimateAsset::register($this); 24 | YiiAsset::register($this); 25 | $opts = Json::htmlEncode([ 26 | 'items' => $model->getItems(), 27 | 'users' => $model->getUsers(), 28 | 'getUserUrl' => Url::to(['get-users', 'id' => $model->name]) 29 | ]); 30 | $this->registerJs("var _opts = {$opts};"); 31 | $this->registerJs($this->render('_script.js')); 32 | $animateIcon = ' '; 33 | ?> 34 |
    35 |

    title); ?>

    36 |

    37 | $model->name], ['class' => 'btn btn-primary']); ?> 38 | $model->name], [ 40 | 'class' => 'btn btn-danger', 41 | 'data-confirm' => Yii::t('rbac-admin', 'Are you sure to delete this item?'), 42 | 'data-method' => 'post', 43 | ]); 44 | ?> 45 | 'btn btn-success']); ?> 46 |

    47 |
    48 |
    49 | $model, 52 | 'attributes' => [ 53 | 'name', 54 | 'description:ntext', 55 | 'ruleName', 56 | 'data:ntext', 57 | ], 58 | 'template' => '{label}{value}', 59 | ]); 60 | ?> 61 |
    62 |
    63 |
    64 |
    65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
    75 |
    76 |
    77 |
    78 |
    79 | 81 | 82 |
    83 |
    84 |

    85 | $model->name], [ 87 | 'class' => 'btn btn-success btn-assign', 88 | 'data-target' => 'available', 89 | 'title' => Yii::t('rbac-admin', 'Assign'), 90 | ]); 91 | ?>

    92 | $model->name], [ 94 | 'class' => 'btn btn-danger btn-assign', 95 | 'data-target' => 'assigned', 96 | 'title' => Yii::t('rbac-admin', 'Remove'), 97 | ]); 98 | ?> 99 |
    100 |
    101 | 103 | 104 |
    105 |
    106 |
    107 | -------------------------------------------------------------------------------- /controllers/AssignmentController.php: -------------------------------------------------------------------------------- 1 | 16 | * @since 1.0 17 | */ 18 | class AssignmentController extends Controller 19 | { 20 | public $userClassName; 21 | public $idField = 'id'; 22 | public $usernameField = 'username'; 23 | public $fullnameField; 24 | public $searchClass; 25 | public $extraColumns = []; 26 | 27 | /** 28 | * @inheritdoc 29 | */ 30 | public function init() 31 | { 32 | parent::init(); 33 | if ($this->userClassName === null) { 34 | $this->userClassName = Yii::$app->getUser()->identityClass; 35 | $this->userClassName = $this->userClassName ? : 'mdm\admin\models\User'; 36 | } 37 | } 38 | 39 | /** 40 | * @inheritdoc 41 | */ 42 | public function behaviors() 43 | { 44 | return [ 45 | 'verbs' => [ 46 | 'class' => VerbFilter::className(), 47 | 'actions' => [ 48 | 'assign' => ['post'], 49 | 'revoke' => ['post'], 50 | ], 51 | ], 52 | ]; 53 | } 54 | 55 | /** 56 | * Lists all Assignment models. 57 | * @return mixed 58 | */ 59 | public function actionIndex() 60 | { 61 | 62 | if ($this->searchClass === null) { 63 | $searchModel = new AssignmentSearch; 64 | $dataProvider = $searchModel->search(Yii::$app->getRequest()->getQueryParams(), $this->userClassName, $this->usernameField); 65 | } else { 66 | $class = $this->searchClass; 67 | $searchModel = new $class; 68 | $dataProvider = $searchModel->search(Yii::$app->getRequest()->getQueryParams()); 69 | } 70 | 71 | return $this->render('index', [ 72 | 'dataProvider' => $dataProvider, 73 | 'searchModel' => $searchModel, 74 | 'idField' => $this->idField, 75 | 'usernameField' => $this->usernameField, 76 | 'extraColumns' => $this->extraColumns, 77 | ]); 78 | } 79 | 80 | /** 81 | * Displays a single Assignment model. 82 | * @param integer $id 83 | * @return mixed 84 | */ 85 | public function actionView($id) 86 | { 87 | $model = $this->findModel($id); 88 | 89 | return $this->render('view', [ 90 | 'model' => $model, 91 | 'idField' => $this->idField, 92 | 'usernameField' => $this->usernameField, 93 | 'fullnameField' => $this->fullnameField, 94 | ]); 95 | } 96 | 97 | /** 98 | * Assign items 99 | * @param string $id 100 | * @return array 101 | */ 102 | public function actionAssign($id) 103 | { 104 | $items = Yii::$app->getRequest()->post('items', []); 105 | $model = new Assignment($id); 106 | $success = $model->assign($items); 107 | Yii::$app->getResponse()->format = 'json'; 108 | return array_merge($model->getItems(), ['success' => $success]); 109 | } 110 | 111 | /** 112 | * Assign items 113 | * @param string $id 114 | * @return array 115 | */ 116 | public function actionRevoke($id) 117 | { 118 | $items = Yii::$app->getRequest()->post('items', []); 119 | $model = new Assignment($id); 120 | $success = $model->revoke($items); 121 | Yii::$app->getResponse()->format = 'json'; 122 | return array_merge($model->getItems(), ['success' => $success]); 123 | } 124 | 125 | /** 126 | * Finds the Assignment model based on its primary key value. 127 | * If the model is not found, a 404 HTTP exception will be thrown. 128 | * @param integer $id 129 | * @return Assignment the loaded model 130 | * @throws NotFoundHttpException if the model cannot be found 131 | */ 132 | protected function findModel($id) 133 | { 134 | $class = $this->userClassName; 135 | if (($user = $class::findIdentity($id)) !== null) { 136 | return new Assignment($id, $user); 137 | } else { 138 | throw new NotFoundHttpException('The requested page does not exist.'); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /models/Menu.php: -------------------------------------------------------------------------------- 1 | 23 | * @since 1.0 24 | */ 25 | class Menu extends \yii\db\ActiveRecord 26 | { 27 | public $parent_name; 28 | 29 | /** 30 | * @inheritdoc 31 | */ 32 | public static function tableName() 33 | { 34 | return Configs::instance()->menuTable; 35 | } 36 | 37 | /** 38 | * @inheritdoc 39 | */ 40 | public static function getDb() 41 | { 42 | if (Configs::instance()->db !== null) { 43 | return Configs::instance()->db; 44 | } else { 45 | return parent::getDb(); 46 | } 47 | } 48 | 49 | /** 50 | * @inheritdoc 51 | */ 52 | public function rules() 53 | { 54 | return [ 55 | [['name'], 'required'], 56 | [['parent_name'], 'in', 57 | 'range' => static::find()->select(['name'])->column(), 58 | 'message' => 'Menu "{value}" not found.'], 59 | [['parent', 'route', 'data', 'order'], 'default'], 60 | [['parent'], 'filterParent', 'when' => function() { 61 | return !$this->isNewRecord; 62 | }], 63 | [['order'], 'integer'], 64 | [['route'], 'in', 65 | 'range' => static::getSavedRoutes(), 66 | 'message' => 'Route "{value}" not found.'] 67 | ]; 68 | } 69 | 70 | /** 71 | * Use to loop detected. 72 | */ 73 | public function filterParent() 74 | { 75 | $parent = $this->parent; 76 | $db = static::getDb(); 77 | $query = (new Query)->select(['parent']) 78 | ->from(static::tableName()) 79 | ->where('[[id]]=:id'); 80 | while ($parent) { 81 | if ($this->id == $parent) { 82 | $this->addError('parent_name', 'Loop detected.'); 83 | return; 84 | } 85 | $parent = $query->params([':id' => $parent])->scalar($db); 86 | } 87 | } 88 | 89 | /** 90 | * @inheritdoc 91 | */ 92 | public function attributeLabels() 93 | { 94 | return [ 95 | 'id' => Yii::t('rbac-admin', 'ID'), 96 | 'name' => Yii::t('rbac-admin', 'Name'), 97 | 'parent' => Yii::t('rbac-admin', 'Parent'), 98 | 'parent_name' => Yii::t('rbac-admin', 'Parent Name'), 99 | 'route' => Yii::t('rbac-admin', 'Route'), 100 | 'order' => Yii::t('rbac-admin', 'Order'), 101 | 'data' => Yii::t('rbac-admin', 'Data'), 102 | ]; 103 | } 104 | 105 | /** 106 | * Get menu parent 107 | * @return \yii\db\ActiveQuery 108 | */ 109 | public function getMenuParent() 110 | { 111 | return $this->hasOne(Menu::className(), ['id' => 'parent']); 112 | } 113 | 114 | /** 115 | * Get menu children 116 | * @return \yii\db\ActiveQuery 117 | */ 118 | public function getMenus() 119 | { 120 | return $this->hasMany(Menu::className(), ['parent' => 'id']); 121 | } 122 | private static $_routes; 123 | 124 | /** 125 | * Get saved routes. 126 | * @return array 127 | */ 128 | public static function getSavedRoutes() 129 | { 130 | if (self::$_routes === null) { 131 | self::$_routes = []; 132 | foreach (Configs::authManager()->getPermissions() as $name => $value) { 133 | if ($name[0] === '/' && substr($name, -1) != '*') { 134 | self::$_routes[] = $name; 135 | } 136 | } 137 | } 138 | return self::$_routes; 139 | } 140 | 141 | public static function getMenuSource() 142 | { 143 | $tableName = static::tableName(); 144 | return (new \yii\db\Query()) 145 | ->select(['m.id', 'm.name', 'm.route', 'parent_name' => 'p.name']) 146 | ->from(['m' => $tableName]) 147 | ->leftJoin(['p' => $tableName], '[[m.parent]]=[[p.id]]') 148 | ->all(static::getDb()); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /components/AccessControl.php: -------------------------------------------------------------------------------- 1 | [ 21 | * 'class' => 'mdm\admin\components\AccessControl', 22 | * 'allowActions' => ['site/login', 'site/error'] 23 | * ] 24 | * ``` 25 | * 26 | * @property User $user 27 | * 28 | * @author Misbahul D Munir 29 | * @since 1.0 30 | */ 31 | class AccessControl extends \yii\base\ActionFilter 32 | { 33 | /** 34 | * @var User User for check access. 35 | */ 36 | private $_user = 'user'; 37 | /** 38 | * @var array List of action that not need to check access. 39 | */ 40 | public $allowActions = []; 41 | 42 | /** 43 | * Get user 44 | * @return User 45 | */ 46 | public function getUser() 47 | { 48 | if (!$this->_user instanceof User) { 49 | $this->_user = Instance::ensure($this->_user, User::className()); 50 | } 51 | return $this->_user; 52 | } 53 | 54 | /** 55 | * Set user 56 | * @param User|string $user 57 | */ 58 | public function setUser($user) 59 | { 60 | $this->_user = $user; 61 | } 62 | 63 | /** 64 | * @inheritdoc 65 | */ 66 | public function beforeAction($action) 67 | { 68 | $actionId = $action->getUniqueId(); 69 | $user = $this->getUser(); 70 | if (Helper::checkRoute('/' . $actionId, Yii::$app->getRequest()->get(), $user)) { 71 | return true; 72 | } 73 | $this->denyAccess($user); 74 | } 75 | 76 | /** 77 | * Denies the access of the user. 78 | * The default implementation will redirect the user to the login page if he is a guest; 79 | * if the user is already logged, a 403 HTTP exception will be thrown. 80 | * @param User $user the current user 81 | * @throws ForbiddenHttpException if the user is already logged in. 82 | */ 83 | protected function denyAccess($user) 84 | { 85 | if ($user->getIsGuest()) { 86 | $user->loginRequired(); 87 | } else { 88 | throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.')); 89 | } 90 | } 91 | 92 | /** 93 | * @inheritdoc 94 | */ 95 | protected function isActive($action) 96 | { 97 | $uniqueId = $action->getUniqueId(); 98 | if ($uniqueId === Yii::$app->getErrorHandler()->errorAction) { 99 | return false; 100 | } 101 | 102 | $user = $this->getUser(); 103 | if($user->getIsGuest()) 104 | { 105 | $loginUrl = null; 106 | if(is_array($user->loginUrl) && isset($user->loginUrl[0])){ 107 | $loginUrl = $user->loginUrl[0]; 108 | }else if(is_string($user->loginUrl)){ 109 | $loginUrl = $user->loginUrl; 110 | } 111 | if(!is_null($loginUrl) && trim((string)$loginUrl,'/') === $uniqueId) 112 | { 113 | return false; 114 | } 115 | } 116 | 117 | if ($this->owner instanceof Module) { 118 | // convert action uniqueId into an ID relative to the module 119 | $mid = $this->owner->getUniqueId(); 120 | $id = $uniqueId; 121 | if ($mid !== '' && strpos($id, $mid . '/') === 0) { 122 | $id = substr($id, strlen($mid) + 1); 123 | } 124 | } else { 125 | $id = $action->id; 126 | } 127 | 128 | foreach ($this->allowActions as $route) { 129 | if (substr($route, -1) === '*') { 130 | $route = rtrim((string)$route, "*"); 131 | if ($route === '' || strpos($id, $route) === 0) { 132 | return false; 133 | } 134 | } else { 135 | if ($id === $route) { 136 | return false; 137 | } 138 | } 139 | } 140 | 141 | if ($action->controller->hasMethod('allowAction') && in_array($action->id, $action->controller->allowAction())) { 142 | return false; 143 | } 144 | 145 | return true; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /models/User.php: -------------------------------------------------------------------------------- 1 | userTable; 40 | } 41 | 42 | /** 43 | * @inheritdoc 44 | */ 45 | public function behaviors() 46 | { 47 | return [ 48 | TimestampBehavior::className(), 49 | ]; 50 | } 51 | 52 | /** 53 | * @inheritdoc 54 | */ 55 | public function rules() 56 | { 57 | return [ 58 | ['status', 'in', 'range' => [UserStatus::ACTIVE, UserStatus::INACTIVE]], 59 | ]; 60 | } 61 | 62 | /** 63 | * @inheritdoc 64 | */ 65 | public static function findIdentity($id) 66 | { 67 | return static::findOne(['id' => $id, 'status' => UserStatus::ACTIVE]); 68 | } 69 | 70 | /** 71 | * @inheritdoc 72 | */ 73 | public static function findIdentityByAccessToken($token, $type = null) 74 | { 75 | throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.'); 76 | } 77 | 78 | /** 79 | * Finds user by username 80 | * 81 | * @param string $username 82 | * @return static|null 83 | */ 84 | public static function findByUsername($username) 85 | { 86 | return static::findOne(['username' => $username, 'status' => UserStatus::ACTIVE]); 87 | } 88 | 89 | /** 90 | * Finds user by password reset token 91 | * 92 | * @param string $token password reset token 93 | * @return static|null 94 | */ 95 | public static function findByPasswordResetToken($token) 96 | { 97 | if (!static::isPasswordResetTokenValid($token)) { 98 | return null; 99 | } 100 | 101 | return static::findOne([ 102 | 'password_reset_token' => $token, 103 | 'status' => UserStatus::ACTIVE, 104 | ]); 105 | } 106 | 107 | /** 108 | * Finds out if password reset token is valid 109 | * 110 | * @param string $token password reset token 111 | * @return boolean 112 | */ 113 | public static function isPasswordResetTokenValid($token) 114 | { 115 | if (empty($token)) { 116 | return false; 117 | } 118 | $expire = Yii::$app->params['user.passwordResetTokenExpire']; 119 | $parts = explode('_', $token); 120 | $timestamp = (int) end($parts); 121 | return $timestamp + $expire >= time(); 122 | } 123 | 124 | /** 125 | * @inheritdoc 126 | */ 127 | public function getId() 128 | { 129 | return $this->getPrimaryKey(); 130 | } 131 | 132 | /** 133 | * @inheritdoc 134 | */ 135 | public function getAuthKey() 136 | { 137 | return $this->auth_key; 138 | } 139 | 140 | /** 141 | * @inheritdoc 142 | */ 143 | public function validateAuthKey($authKey) 144 | { 145 | return $this->getAuthKey() === $authKey; 146 | } 147 | 148 | /** 149 | * Validates password 150 | * 151 | * @param string $password password to validate 152 | * @return boolean if password provided is valid for current user 153 | */ 154 | public function validatePassword($password) 155 | { 156 | return Yii::$app->security->validatePassword($password, $this->password_hash); 157 | } 158 | 159 | /** 160 | * Generates password hash from password and sets it to the model 161 | * 162 | * @param string $password 163 | */ 164 | public function setPassword($password) 165 | { 166 | $this->password_hash = Yii::$app->security->generatePasswordHash($password); 167 | } 168 | 169 | /** 170 | * Generates "remember me" authentication key 171 | */ 172 | public function generateAuthKey() 173 | { 174 | $this->auth_key = Yii::$app->security->generateRandomString(); 175 | } 176 | 177 | /** 178 | * Generates new password reset token 179 | */ 180 | public function generatePasswordResetToken() 181 | { 182 | $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time(); 183 | } 184 | 185 | /** 186 | * Removes password reset token 187 | */ 188 | public function removePasswordResetToken() 189 | { 190 | $this->password_reset_token = null; 191 | } 192 | 193 | public static function getDb() 194 | { 195 | return Configs::userDb(); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /components/ItemController.php: -------------------------------------------------------------------------------- 1 | 21 | * @since 1.0 22 | */ 23 | class ItemController extends Controller 24 | { 25 | 26 | /** 27 | * @inheritdoc 28 | */ 29 | public function behaviors() 30 | { 31 | return [ 32 | 'verbs' => [ 33 | 'class' => VerbFilter::className(), 34 | 'actions' => [ 35 | 'delete' => ['post'], 36 | 'assign' => ['post'], 37 | 'remove' => ['post'], 38 | ], 39 | ], 40 | ]; 41 | } 42 | 43 | /** 44 | * Lists all AuthItem models. 45 | * @return mixed 46 | */ 47 | public function actionIndex() 48 | { 49 | $searchModel = new AuthItemSearch(['type' => $this->type]); 50 | $dataProvider = $searchModel->search(Yii::$app->request->getQueryParams()); 51 | 52 | return $this->render('index', [ 53 | 'dataProvider' => $dataProvider, 54 | 'searchModel' => $searchModel, 55 | ]); 56 | } 57 | 58 | /** 59 | * Displays a single AuthItem model. 60 | * @param string $id 61 | * @return mixed 62 | */ 63 | public function actionView($id) 64 | { 65 | $model = $this->findModel($id); 66 | 67 | return $this->render('view', ['model' => $model]); 68 | } 69 | 70 | /** 71 | * Creates a new AuthItem model. 72 | * If creation is successful, the browser will be redirected to the 'view' page. 73 | * @return mixed 74 | */ 75 | public function actionCreate() 76 | { 77 | $model = new AuthItem(null); 78 | $model->type = $this->type; 79 | if ($model->load(Yii::$app->getRequest()->post()) && $model->save()) { 80 | return $this->redirect(['view', 'id' => $model->name]); 81 | } else { 82 | return $this->render('create', ['model' => $model]); 83 | } 84 | } 85 | 86 | /** 87 | * Updates an existing AuthItem model. 88 | * If update is successful, the browser will be redirected to the 'view' page. 89 | * @param string $id 90 | * @return mixed 91 | */ 92 | public function actionUpdate($id) 93 | { 94 | $model = $this->findModel($id); 95 | if ($model->load(Yii::$app->getRequest()->post()) && $model->save()) { 96 | return $this->redirect(['view', 'id' => $model->name]); 97 | } 98 | 99 | return $this->render('update', ['model' => $model]); 100 | } 101 | 102 | /** 103 | * Deletes an existing AuthItem model. 104 | * If deletion is successful, the browser will be redirected to the 'index' page. 105 | * @param string $id 106 | * @return mixed 107 | */ 108 | public function actionDelete($id) 109 | { 110 | $model = $this->findModel($id); 111 | Configs::authManager()->remove($model->item); 112 | Helper::invalidate(); 113 | 114 | return $this->redirect(['index']); 115 | } 116 | 117 | /** 118 | * Assign items 119 | * @param string $id 120 | * @return array 121 | */ 122 | public function actionAssign($id) 123 | { 124 | $items = Yii::$app->getRequest()->post('items', []); 125 | $model = $this->findModel($id); 126 | $success = $model->addChildren($items); 127 | Yii::$app->getResponse()->format = 'json'; 128 | 129 | return array_merge($model->getItems(), ['success' => $success]); 130 | } 131 | 132 | /** 133 | * Assign items 134 | * @param string $id 135 | * @return array 136 | */ 137 | public function actionGetUsers($id) 138 | { 139 | $page = Yii::$app->getRequest()->get('page', 0); 140 | $model = $this->findModel($id); 141 | Yii::$app->getResponse()->format = 'json'; 142 | 143 | return array_merge($model->getUsers($page)); 144 | } 145 | 146 | /** 147 | * Assign or remove items 148 | * @param string $id 149 | * @return array 150 | */ 151 | public function actionRemove($id) 152 | { 153 | $items = Yii::$app->getRequest()->post('items', []); 154 | $model = $this->findModel($id); 155 | $success = $model->removeChildren($items); 156 | Yii::$app->getResponse()->format = 'json'; 157 | 158 | return array_merge($model->getItems(), ['success' => $success]); 159 | } 160 | 161 | /** 162 | * @inheritdoc 163 | */ 164 | public function getViewPath() 165 | { 166 | return $this->module->getViewPath() . DIRECTORY_SEPARATOR . 'item'; 167 | } 168 | 169 | /** 170 | * Label use in view 171 | * @throws NotSupportedException 172 | */ 173 | public function labels() 174 | { 175 | throw new NotSupportedException(get_class($this) . ' does not support labels().'); 176 | } 177 | 178 | /** 179 | * Type of Auth Item. 180 | * @return integer 181 | */ 182 | public function getType() 183 | { 184 | 185 | } 186 | 187 | /** 188 | * Finds the AuthItem model based on its primary key value. 189 | * If the model is not found, a 404 HTTP exception will be thrown. 190 | * @param string $id 191 | * @return AuthItem the loaded model 192 | * @throws NotFoundHttpException if the model cannot be found 193 | */ 194 | protected function findModel($id) 195 | { 196 | $auth = Configs::authManager(); 197 | $item = $this->type === Item::TYPE_ROLE ? $auth->getRole($id) : $auth->getPermission($id); 198 | if ($item) { 199 | return new AuthItem($item); 200 | } else { 201 | throw new NotFoundHttpException('The requested page does not exist.'); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /Module.php: -------------------------------------------------------------------------------- 1 | 'left-menu', // default to null mean use application layout. 16 | * 'controllerMap' => [ 17 | * 'assignment' => [ 18 | * 'class' => 'mdm\admin\controllers\AssignmentController', 19 | * 'userClassName' => 'app\models\User', 20 | * 'idField' => 'id' 21 | * ] 22 | * ], 23 | * 'menus' => [ 24 | * 'assignment' => [ 25 | * 'label' => 'Grand Access' // change label 26 | * ], 27 | * 'route' => null, // disable menu 28 | * ], 29 | * ``` 30 | * 31 | * @property string $mainLayout Main layout using for module. Default to layout of parent module. 32 | * Its used when `layout` set to 'left-menu', 'right-menu' or 'top-menu'. 33 | * @property array $menus List available menu of module. 34 | * It generated by module items . 35 | * 36 | * @author Misbahul D Munir 37 | * @since 1.0 38 | */ 39 | class Module extends \yii\base\Module 40 | { 41 | /** 42 | * @inheritdoc 43 | */ 44 | public $defaultRoute = 'assignment'; 45 | /** 46 | * @var array Nav bar items. 47 | */ 48 | public $navbar; 49 | /** 50 | * @var string Main layout using for module. Default to layout of parent module. 51 | * Its used when `layout` set to 'left-menu', 'right-menu' or 'top-menu'. 52 | */ 53 | public $mainLayout = '@mdm/admin/views/layouts/main.php'; 54 | /** 55 | * @var array 56 | * @see [[menus]] 57 | */ 58 | private $_menus = []; 59 | /** 60 | * @var array 61 | * @see [[menus]] 62 | */ 63 | private $_coreItems = [ 64 | 'user' => 'Users', 65 | 'assignment' => 'Assignments', 66 | 'role' => 'Roles', 67 | 'permission' => 'Permissions', 68 | 'route' => 'Routes', 69 | 'rule' => 'Rules', 70 | 'menu' => 'Menus', 71 | ]; 72 | /** 73 | * @var array 74 | * @see [[items]] 75 | */ 76 | private $_normalizeMenus; 77 | 78 | /** 79 | * @var string Default url for breadcrumb 80 | */ 81 | public $defaultUrl; 82 | 83 | /** 84 | * @var string Default url label for breadcrumb 85 | */ 86 | public $defaultUrlLabel; 87 | 88 | /** 89 | * @inheritdoc 90 | */ 91 | public function init() 92 | { 93 | parent::init(); 94 | if (!isset(Yii::$app->i18n->translations['rbac-admin'])) { 95 | Yii::$app->i18n->translations['rbac-admin'] = [ 96 | 'class' => 'yii\i18n\PhpMessageSource', 97 | 'sourceLanguage' => 'en', 98 | 'basePath' => '@mdm/admin/messages', 99 | ]; 100 | } 101 | 102 | //user did not define the Navbar? 103 | if ($this->navbar === null && Yii::$app instanceof \yii\web\Application) { 104 | $this->navbar = [ 105 | ['label' => Yii::t('rbac-admin', 'Help'), 'url' => ['default/index']], 106 | ['label' => Yii::t('rbac-admin', 'Application'), 'url' => Yii::$app->homeUrl], 107 | ]; 108 | } 109 | if (class_exists('yii\jui\JuiAsset')) { 110 | Yii::$container->set('mdm\admin\AutocompleteAsset', 'yii\jui\JuiAsset'); 111 | } 112 | } 113 | 114 | /** 115 | * Get available menu. 116 | * @return array 117 | */ 118 | public function getMenus() 119 | { 120 | if ($this->_normalizeMenus === null) { 121 | $mid = '/' . $this->getUniqueId() . '/'; 122 | // resolve core menus 123 | $this->_normalizeMenus = []; 124 | 125 | $config = components\Configs::instance(); 126 | $conditions = [ 127 | 'user' => $config->db && $config->db->schema->getTableSchema($config->userTable), 128 | 'assignment' => ($userClass = Yii::$app->getUser()->identityClass) && is_subclass_of($userClass, 'yii\db\BaseActiveRecord'), 129 | 'menu' => $config->db && $config->db->schema->getTableSchema($config->menuTable), 130 | ]; 131 | foreach ($this->_coreItems as $id => $lable) { 132 | if (!isset($conditions[$id]) || $conditions[$id]) { 133 | $this->_normalizeMenus[$id] = ['label' => Yii::t('rbac-admin', $lable), 'url' => [$mid . $id]]; 134 | } 135 | } 136 | foreach (array_keys($this->controllerMap) as $id) { 137 | $this->_normalizeMenus[$id] = ['label' => Yii::t('rbac-admin', Inflector::humanize($id)), 'url' => [$mid . $id]]; 138 | } 139 | 140 | // user configure menus 141 | foreach ($this->_menus as $id => $value) { 142 | if (empty($value)) { 143 | unset($this->_normalizeMenus[$id]); 144 | continue; 145 | } 146 | if (is_string($value)) { 147 | $value = ['label' => $value]; 148 | } 149 | $this->_normalizeMenus[$id] = isset($this->_normalizeMenus[$id]) ? array_merge($this->_normalizeMenus[$id], $value) 150 | : $value; 151 | if (!isset($this->_normalizeMenus[$id]['url'])) { 152 | $this->_normalizeMenus[$id]['url'] = [$mid . $id]; 153 | } 154 | } 155 | } 156 | return $this->_normalizeMenus; 157 | } 158 | 159 | /** 160 | * Set or add available menu. 161 | * @param array $menus 162 | */ 163 | public function setMenus($menus) 164 | { 165 | $this->_menus = array_merge($this->_menus, $menus); 166 | $this->_normalizeMenus = null; 167 | } 168 | 169 | /** 170 | * @inheritdoc 171 | */ 172 | public function beforeAction($action) 173 | { 174 | if (parent::beforeAction($action)) { 175 | /* @var $action \yii\base\Action */ 176 | $view = $action->controller->getView(); 177 | 178 | $view->params['breadcrumbs'][] = [ 179 | 'label' => ($this->defaultUrlLabel ?: Yii::t('rbac-admin', 'Admin')), 180 | 'url' => ['/' . ($this->defaultUrl ?: $this->uniqueId)], 181 | ]; 182 | return true; 183 | } 184 | return false; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /components/Configs.php: -------------------------------------------------------------------------------- 1 | [ 20 | * 'db' => 'customDb', 21 | * 'menuTable' => '{{%admin_menu}}', 22 | * 'cache' => [ 23 | * 'class' => 'yii\caching\DbCache', 24 | * 'db' => ['dsn' => 'sqlite:@runtime/admin-cache.db'], 25 | * ], 26 | * ] 27 | * ]; 28 | * ``` 29 | * 30 | * or use [[\Yii::$container]] 31 | * 32 | * ``` 33 | * Yii::$container->set('mdm\admin\components\Configs',[ 34 | * 'db' => 'customDb', 35 | * 'menuTable' => 'admin_menu', 36 | * ]); 37 | * ``` 38 | * 39 | * @author Misbahul D Munir 40 | * @since 1.0 41 | */ 42 | 43 | class Configs extends \mdm\admin\BaseObject 44 | { 45 | const CACHE_TAG = 'mdm.admin'; 46 | 47 | /** 48 | * @var ManagerInterface . 49 | */ 50 | public $authManager = 'authManager'; 51 | 52 | /** 53 | * @var Connection Database connection. 54 | */ 55 | public $db = 'db'; 56 | 57 | /** 58 | * @var Connection Database connection. 59 | */ 60 | public $userDb = 'db'; 61 | 62 | /** 63 | * @var Cache Cache component. 64 | */ 65 | public $cache = 'cache'; 66 | 67 | /** 68 | * @var integer Cache duration. Default to a hour. 69 | */ 70 | public $cacheDuration = 3600; 71 | 72 | /** 73 | * @var string Menu table name. 74 | */ 75 | public $menuTable = '{{%menu}}'; 76 | 77 | /** 78 | * @var string Menu table name. 79 | */ 80 | public $userTable = '{{%user}}'; 81 | 82 | /** 83 | * @var integer Default status user signup. 10 mean active. 84 | */ 85 | public $defaultUserStatus = 10; 86 | 87 | /** 88 | * @var integer Number of user role. 89 | */ 90 | public $userRolePageSize = 100; 91 | 92 | /** 93 | * @var boolean If true then AccessControl only check if route are registered. 94 | */ 95 | public $onlyRegisteredRoute = false; 96 | 97 | /** 98 | * @var boolean If false then AccessControl will check without Rule. 99 | */ 100 | public $strict = true; 101 | 102 | /** 103 | * @var array 104 | */ 105 | public $options; 106 | 107 | /** 108 | * @var array|false Used for multiple application 109 | * ```php 110 | * [ 111 | * 'frontend' => [ 112 | * '@common/config/main.php', 113 | * '@common/config/main-local.php', 114 | * '@frontend/config/main.php', 115 | * '@frontend/config/main-local.php', 116 | * ], 117 | * 'backend' => [ 118 | * '@common/config/main.php', 119 | * '@common/config/main-local.php', 120 | * '@backend/config/main.php', 121 | * '@backend/config/main-local.php', 122 | * ], 123 | * ] 124 | * ``` * 125 | */ 126 | public $advanced; 127 | 128 | /** 129 | * @var self Instance of self 130 | */ 131 | private static $_instance; 132 | private static $_classes = [ 133 | 'db' => 'yii\db\Connection', 134 | 'userDb' => 'yii\db\Connection', 135 | 'cache' => 'yii\caching\Cache', 136 | 'authManager' => 'yii\rbac\ManagerInterface', 137 | ]; 138 | 139 | /** 140 | * @inheritdoc 141 | */ 142 | public function init() 143 | { 144 | foreach (self::$_classes as $key => $class) { 145 | try { 146 | $this->{$key} = empty($this->{$key}) ? null : Instance::ensure($this->{$key}, $class); 147 | } catch (\Exception $exc) { 148 | $this->{$key} = null; 149 | Yii::error($exc->getMessage()); 150 | } 151 | } 152 | } 153 | 154 | /** 155 | * Create instance of self 156 | * @return static 157 | */ 158 | public static function instance() 159 | { 160 | if (self::$_instance === null) { 161 | $type = ArrayHelper::getValue(Yii::$app->params, 'mdm.admin.configs', []); 162 | if (is_array($type) && !isset($type['class'])) { 163 | $type['class'] = static::className(); 164 | } 165 | 166 | return self::$_instance = Yii::createObject($type); 167 | } 168 | 169 | return self::$_instance; 170 | } 171 | 172 | public static function __callStatic($name, $arguments) 173 | { 174 | $instance = static::instance(); 175 | if ($instance->hasProperty($name)) { 176 | return $instance->$name; 177 | } else { 178 | if (count($arguments)) { 179 | $instance->options[$name] = reset($arguments); 180 | } else { 181 | return array_key_exists($name, $instance->options) ? $instance->options[$name] : null; 182 | } 183 | } 184 | } 185 | 186 | /** 187 | * @return Connection 188 | */ 189 | public static function db() 190 | { 191 | return static::instance()->db; 192 | } 193 | 194 | /** 195 | * @return Connection 196 | */ 197 | public static function userDb() 198 | { 199 | return static::instance()->userDb; 200 | } 201 | 202 | /** 203 | * @return Cache 204 | */ 205 | public static function cache() 206 | { 207 | return static::instance()->cache; 208 | } 209 | 210 | /** 211 | * @return ManagerInterface 212 | */ 213 | public static function authManager() 214 | { 215 | return static::instance()->authManager; 216 | } 217 | /** 218 | * @return integer 219 | */ 220 | public static function cacheDuration() 221 | { 222 | return static::instance()->cacheDuration; 223 | } 224 | 225 | /** 226 | * @return string 227 | */ 228 | public static function menuTable() 229 | { 230 | return static::instance()->menuTable; 231 | } 232 | 233 | /** 234 | * @return string 235 | */ 236 | public static function userTable() 237 | { 238 | return static::instance()->userTable; 239 | } 240 | 241 | /** 242 | * @return string 243 | */ 244 | public static function defaultUserStatus() 245 | { 246 | return static::instance()->defaultUserStatus; 247 | } 248 | 249 | /** 250 | * @return boolean 251 | */ 252 | public static function onlyRegisteredRoute() 253 | { 254 | return static::instance()->onlyRegisteredRoute; 255 | } 256 | 257 | /** 258 | * @return boolean 259 | */ 260 | public static function strict() 261 | { 262 | return static::instance()->strict; 263 | } 264 | 265 | /** 266 | * @return int 267 | */ 268 | public static function userRolePageSize() 269 | { 270 | return static::instance()->userRolePageSize; 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /components/MenuHelper.php: -------------------------------------------------------------------------------- 1 | MenuHelper::getAssignedMenu(Yii::$app->user->id) 19 | * ]); 20 | * ``` 21 | * 22 | * To reformat returned, provide callback to method. 23 | * 24 | * ``` 25 | * $callback = function ($menu) { 26 | * $data = eval($menu['data']); 27 | * return [ 28 | * 'label' => $menu['name'], 29 | * 'url' => [$menu['route']], 30 | * 'options' => $data, 31 | * 'items' => $menu['children'] 32 | * ] 33 | * ] 34 | * } 35 | * 36 | * $items = MenuHelper::getAssignedMenu(Yii::$app->user->id, null, $callback); 37 | * ``` 38 | * 39 | * @author Misbahul D Munir 40 | * @since 1.0 41 | */ 42 | class MenuHelper 43 | { 44 | /** 45 | * Use to get assigned menu of user. 46 | * @param mixed $userId 47 | * @param integer $root 48 | * @param \Closure $callback use to reformat output. 49 | * callback should have format like 50 | * 51 | * ``` 52 | * function ($menu) { 53 | * return [ 54 | * 'label' => $menu['name'], 55 | * 'url' => [$menu['route']], 56 | * 'options' => $data, 57 | * 'items' => $menu['children'] 58 | * ] 59 | * ] 60 | * } 61 | * ``` 62 | * @param boolean $refresh 63 | * @return array 64 | */ 65 | public static function getAssignedMenu($userId, $root = null, $callback = null, $refresh = false) 66 | { 67 | $config = Configs::instance(); 68 | 69 | /* @var $manager \yii\rbac\BaseManager */ 70 | $manager = Configs::authManager(); 71 | $menus = Menu::find()->asArray()->indexBy('id')->all(); 72 | $key = [__METHOD__, $userId, $manager->defaultRoles]; 73 | $cache = $config->cache; 74 | 75 | if ($refresh || $cache === null || ($assigned = $cache->get($key)) === false) { 76 | $routes = $filter1 = $filter2 = []; 77 | if ($userId !== null) { 78 | foreach ($manager->getPermissionsByUser($userId) as $name => $value) { 79 | if ($name[0] === '/') { 80 | if (substr($name, -2) === '/*') { 81 | $name = substr($name, 0, -1); 82 | } 83 | $routes[] = $name; 84 | } 85 | } 86 | } 87 | foreach ($manager->defaultRoles as $role) { 88 | foreach ($manager->getPermissionsByRole($role) as $name => $value) { 89 | if ($name[0] === '/') { 90 | if (substr($name, -2) === '/*') { 91 | $name = substr($name, 0, -1); 92 | } 93 | $routes[] = $name; 94 | } 95 | } 96 | } 97 | $routes = array_unique($routes); 98 | sort($routes); 99 | $prefix = '\\'; 100 | foreach ($routes as $route) { 101 | if (strpos($route, $prefix) !== 0) { 102 | if (substr($route, -1) === '/') { 103 | $prefix = $route; 104 | $filter1[] = $route . '%'; 105 | } else { 106 | $filter2[] = $route; 107 | } 108 | } 109 | } 110 | $assigned = []; 111 | $query = Menu::find()->select(['id'])->asArray(); 112 | if (count($filter2)) { 113 | $assigned = $query->where(['route' => $filter2])->column(); 114 | } 115 | if (count($filter1)) { 116 | $query->where('route like :filter'); 117 | foreach ($filter1 as $filter) { 118 | $assigned = array_merge($assigned, $query->params([':filter' => $filter])->column()); 119 | } 120 | } 121 | $assigned = static::requiredParent($assigned, $menus); 122 | if ($cache !== null) { 123 | $cache->set($key, $assigned, $config->cacheDuration, new TagDependency([ 124 | 'tags' => Configs::CACHE_TAG 125 | ])); 126 | } 127 | } 128 | 129 | $key = [__METHOD__, $assigned, $root]; 130 | if ($refresh || $callback !== null || $cache === null || (($result = $cache->get($key)) === false)) { 131 | $result = static::normalizeMenu($assigned, $menus, $callback, $root); 132 | if ($cache !== null && $callback === null) { 133 | $cache->set($key, $result, $config->cacheDuration, new TagDependency([ 134 | 'tags' => Configs::CACHE_TAG 135 | ])); 136 | } 137 | } 138 | 139 | return $result; 140 | } 141 | 142 | /** 143 | * Ensure all item menu has parent. 144 | * @param array $assigned 145 | * @param array $menus 146 | * @return array 147 | */ 148 | private static function requiredParent($assigned, &$menus) 149 | { 150 | $l = count($assigned); 151 | for ($i = 0; $i < $l; $i++) { 152 | $id = $assigned[$i]; 153 | $parent_id = $menus[$id]['parent']; 154 | if ($parent_id !== null && !in_array($parent_id, $assigned)) { 155 | $assigned[$l++] = $parent_id; 156 | } 157 | } 158 | 159 | return $assigned; 160 | } 161 | 162 | /** 163 | * Parse route 164 | * @param string $route 165 | * @return mixed 166 | */ 167 | public static function parseRoute($route) 168 | { 169 | if (!empty($route)) { 170 | $url = []; 171 | $r = explode('&', $route); 172 | $url[0] = $r[0]; 173 | unset($r[0]); 174 | foreach ($r as $part) { 175 | $part = explode('=', $part); 176 | $url[$part[0]] = isset($part[1]) ? $part[1] : ''; 177 | } 178 | 179 | return $url; 180 | } 181 | 182 | return '#'; 183 | } 184 | 185 | /** 186 | * Normalize menu 187 | * @param array $assigned 188 | * @param array $menus 189 | * @param Closure $callback 190 | * @param integer $parent 191 | * @return array 192 | */ 193 | private static function normalizeMenu(&$assigned, &$menus, $callback, $parent = null) 194 | { 195 | $result = []; 196 | $order = []; 197 | foreach ($assigned as $id) { 198 | $menu = $menus[$id]; 199 | if ($menu['parent'] == $parent) { 200 | $menu['children'] = static::normalizeMenu($assigned, $menus, $callback, $id); 201 | if ($callback !== null) { 202 | $item = call_user_func($callback, $menu); 203 | } else { 204 | $item = [ 205 | 'label' => $menu['name'], 206 | 'url' => static::parseRoute($menu['route']), 207 | ]; 208 | if ($menu['children'] != []) { 209 | $item['items'] = $menu['children']; 210 | } 211 | } 212 | $result[] = $item; 213 | $order[] = $menu['order']; 214 | } 215 | } 216 | if ($result != []) { 217 | array_multisort($order, $result); 218 | } 219 | 220 | return $result; 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /controllers/UserController.php: -------------------------------------------------------------------------------- 1 | [ 36 | 'class' => VerbFilter::className(), 37 | 'actions' => [ 38 | 'delete' => ['post'], 39 | 'logout' => ['post'], 40 | 'activate' => ['post'], 41 | ], 42 | ], 43 | ]; 44 | } 45 | 46 | /** 47 | * @inheritdoc 48 | */ 49 | public function beforeAction($action) 50 | { 51 | if (parent::beforeAction($action)) { 52 | if (Yii::$app->has('mailer') && ($mailer = Yii::$app->getMailer()) instanceof BaseMailer) { 53 | /* @var $mailer BaseMailer */ 54 | $this->_oldMailPath = $mailer->getViewPath(); 55 | $mailer->setViewPath('@mdm/admin/mail'); 56 | } 57 | return true; 58 | } 59 | return false; 60 | } 61 | 62 | /** 63 | * @inheritdoc 64 | */ 65 | public function afterAction($action, $result) 66 | { 67 | if ($this->_oldMailPath !== null) { 68 | Yii::$app->getMailer()->setViewPath($this->_oldMailPath); 69 | } 70 | return parent::afterAction($action, $result); 71 | } 72 | 73 | /** 74 | * Lists all User models. 75 | * @return mixed 76 | */ 77 | public function actionIndex() 78 | { 79 | $searchModel = new UserSearch(); 80 | $dataProvider = $searchModel->search(Yii::$app->request->queryParams); 81 | 82 | return $this->render('index', [ 83 | 'searchModel' => $searchModel, 84 | 'dataProvider' => $dataProvider, 85 | ]); 86 | } 87 | 88 | /** 89 | * Displays a single User model. 90 | * @param integer $id 91 | * @return mixed 92 | */ 93 | public function actionView($id) 94 | { 95 | return $this->render('view', [ 96 | 'model' => $this->findModel($id), 97 | ]); 98 | } 99 | 100 | /** 101 | * Deletes an existing User model. 102 | * If deletion is successful, the browser will be redirected to the 'index' page. 103 | * @param integer $id 104 | * @return mixed 105 | */ 106 | public function actionDelete($id) 107 | { 108 | $this->findModel($id)->delete(); 109 | 110 | return $this->redirect(['index']); 111 | } 112 | 113 | /** 114 | * Login 115 | * @return string 116 | */ 117 | public function actionLogin() 118 | { 119 | if (!Yii::$app->getUser()->isGuest) { 120 | return $this->goHome(); 121 | } 122 | 123 | $model = new Login(); 124 | if ($model->load(Yii::$app->getRequest()->post()) && $model->login()) { 125 | return $this->goBack(); 126 | } else { 127 | return $this->render('login', [ 128 | 'model' => $model, 129 | ]); 130 | } 131 | } 132 | 133 | /** 134 | * Logout 135 | * @return string 136 | */ 137 | public function actionLogout() 138 | { 139 | Yii::$app->getUser()->logout(); 140 | 141 | return $this->goHome(); 142 | } 143 | 144 | /** 145 | * Signup new user 146 | * @return string 147 | */ 148 | public function actionSignup() 149 | { 150 | $model = new Signup(); 151 | if ($model->load(Yii::$app->getRequest()->post())) { 152 | if ($user = $model->signup()) { 153 | return $this->goHome(); 154 | } 155 | } 156 | 157 | return $this->render('signup', [ 158 | 'model' => $model, 159 | ]); 160 | } 161 | 162 | /** 163 | * Request reset password 164 | * @return string 165 | */ 166 | public function actionRequestPasswordReset() 167 | { 168 | $model = new PasswordResetRequest(); 169 | if ($model->load(Yii::$app->getRequest()->post()) && $model->validate()) { 170 | if ($model->sendEmail()) { 171 | Yii::$app->getSession()->setFlash('success', 'Check your email for further instructions.'); 172 | 173 | return $this->goHome(); 174 | } else { 175 | Yii::$app->getSession()->setFlash('error', 'Sorry, we are unable to reset password for email provided.'); 176 | } 177 | } 178 | 179 | return $this->render('requestPasswordResetToken', [ 180 | 'model' => $model, 181 | ]); 182 | } 183 | 184 | /** 185 | * Reset password 186 | * @return string 187 | */ 188 | public function actionResetPassword($token) 189 | { 190 | try { 191 | $model = new ResetPassword($token); 192 | } catch (InvalidParamException $e) { 193 | throw new BadRequestHttpException($e->getMessage()); 194 | } 195 | 196 | if ($model->load(Yii::$app->getRequest()->post()) && $model->validate() && $model->resetPassword()) { 197 | Yii::$app->getSession()->setFlash('success', 'New password was saved.'); 198 | 199 | return $this->goHome(); 200 | } 201 | 202 | return $this->render('resetPassword', [ 203 | 'model' => $model, 204 | ]); 205 | } 206 | 207 | /** 208 | * Reset password 209 | * @return string 210 | */ 211 | public function actionChangePassword() 212 | { 213 | $model = new ChangePassword(); 214 | if ($model->load(Yii::$app->getRequest()->post()) && $model->change()) { 215 | return $this->goHome(); 216 | } 217 | 218 | return $this->render('change-password', [ 219 | 'model' => $model, 220 | ]); 221 | } 222 | 223 | /** 224 | * Activate new user 225 | * @param integer $id 226 | * @return type 227 | * @throws UserException 228 | * @throws NotFoundHttpException 229 | */ 230 | public function actionActivate($id) 231 | { 232 | /* @var $user User */ 233 | $user = $this->findModel($id); 234 | if ($user->status == UserStatus::INACTIVE) { 235 | $user->status = UserStatus::ACTIVE; 236 | if ($user->save()) { 237 | return $this->goHome(); 238 | } else { 239 | $errors = $user->firstErrors; 240 | throw new UserException(reset($errors)); 241 | } 242 | } 243 | return $this->goHome(); 244 | } 245 | 246 | /** 247 | * Finds the User model based on its primary key value. 248 | * If the model is not found, a 404 HTTP exception will be thrown. 249 | * @param integer $id 250 | * @return User the loaded model 251 | * @throws NotFoundHttpException if the model cannot be found 252 | */ 253 | protected function findModel($id) 254 | { 255 | if (($model = User::findOne($id)) !== null) { 256 | return $model; 257 | } else { 258 | throw new NotFoundHttpException('The requested page does not exist.'); 259 | } 260 | } 261 | } 262 | --------------------------------------------------------------------------------