This commit is contained in:
2020-02-01 16:47:12 +07:00
commit 4c619ad6e6
16739 changed files with 3329179 additions and 0 deletions

26
vendor/yii2mod/yii2-rbac/.php_cs vendored Normal file
View File

@@ -0,0 +1,26 @@
<?php
$finder = PhpCsFixer\Finder::create()
->exclude('vendor')
->in([__DIR__]);
$config = PhpCsFixer\Config::create()
->setUsingCache(false)
->setRules([
'@Symfony' => true,
'phpdoc_align' => false,
'phpdoc_summary' => false,
'phpdoc_inline_tag' => false,
'pre_increment' => false,
'heredoc_to_nowdoc' => false,
'cast_spaces' => false,
'include' => false,
'phpdoc_no_package' => false,
'concat_space' => ['spacing' => 'one'],
'ordered_imports' => true,
'array_syntax' => ['syntax' => 'short'],
'yoda_style' => false,
])
->setFinder($finder);
return $config;

View File

@@ -0,0 +1,27 @@
<?php
namespace yii2mod\rbac;
/**
* Class ConsoleModule
*
* Use [[\yii\base\Module::$controllerMap]] to change property of controller.
*
* ```php
* 'controllerMap' => [
* 'migrate' => [
* 'class' => 'yii2mod\rbac\commands\MigrateController',
* 'migrationTable' => '{{%auth_migration}}',
* 'migrationPath' => '@app/rbac/migrations',
* 'templateFile' => 'your own template file'
* ]
* ]
* ```
*/
class ConsoleModule extends Module
{
/**
* @var string the namespace that controller classes are in
*/
public $controllerNamespace = 'yii2mod\rbac\commands';
}

21
vendor/yii2mod/yii2-rbac/LICENSE.txt vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Yii2 modules & extensions
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

41
vendor/yii2mod/yii2-rbac/Module.php vendored Normal file
View File

@@ -0,0 +1,41 @@
<?php
namespace yii2mod\rbac;
/**
* GUI manager for RBAC.
*
* Use [[\yii\base\Module::$controllerMap]] to change property of controller.
*
* ```php
* 'controllerMap' => [
* 'assignment' => [
* 'class' => 'yii2mod\rbac\controllers\AssignmentController',
* 'userIdentityClass' => 'app\models\User',
* 'searchClass' => [
* 'class' => 'yii2mod\rbac\models\search\AssignmentSearch',
* 'pageSize' => 10,
* ],
* 'idField' => 'id',
* 'usernameField' => 'username'
* 'gridViewColumns' => [
* 'id',
* 'username',
* 'email'
* ],
* ],
* ],
* ```php
*/
class Module extends \yii\base\Module
{
/**
* @var string the default route of this module. Defaults to 'default'
*/
public $defaultRoute = 'assignment';
/**
* @var string the namespace that controller classes are in
*/
public $controllerNamespace = 'yii2mod\rbac\controllers';
}

302
vendor/yii2mod/yii2-rbac/README.md vendored Normal file
View File

@@ -0,0 +1,302 @@
<p align="center">
<a href="https://github.com/yiisoft" target="_blank">
<img src="https://avatars0.githubusercontent.com/u/993323" height="100px">
</a>
<h1 align="center">Yii2 RBAC Extension</h1>
<br>
</p>
Yii2-RBAC provides a web interface for advanced access control and includes following features:
- Allows CRUD operations for roles, permissions, rules
- Allows to assign multiple roles or permissions to the user
- Allows to create console migrations
- Integrated with [yii2mod/base](https://github.com/yii2mod/base)
[![Latest Stable Version](https://poser.pugx.org/yii2mod/yii2-rbac/v/stable)](https://packagist.org/packages/yii2mod/yii2-rbac) [![Total Downloads](https://poser.pugx.org/yii2mod/yii2-rbac/downloads)](https://packagist.org/packages/yii2mod/yii2-rbac) [![License](https://poser.pugx.org/yii2mod/yii2-rbac/license)](https://packagist.org/packages/yii2mod/yii2-rbac)
[![Build Status](https://travis-ci.org/yii2mod/yii2-rbac.svg?branch=master)](https://travis-ci.org/yii2mod/yii2-rbac)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yii2mod/yii2-rbac/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yii2mod/yii2-rbac/?branch=master)
Installation
------------
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
Either run
```
php composer.phar require --prefer-dist yii2mod/yii2-rbac "*"
```
or add
```
"yii2mod/yii2-rbac": "*"
```
to the require section of your composer.json.
Usage
------------
Once the extension is installed, simply modify your application configuration as follows:
```php
return [
'modules' => [
'rbac' => [
'class' => 'yii2mod\rbac\Module',
],
],
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
'defaultRoles' => ['guest', 'user'],
],
],
];
```
After you downloaded and configured Yii2-rbac, the last thing you need to do is updating your database schema by
applying the migration:
```bash
$ php yii migrate/up --migrationPath=@yii/rbac/migrations
```
You can then access Auth manager through the following URL:
```
http://localhost/path/to/index.php?r=rbac/
http://localhost/path/to/index.php?r=rbac/route
http://localhost/path/to/index.php?r=rbac/permission
http://localhost/path/to/index.php?r=rbac/role
http://localhost/path/to/index.php?r=rbac/assignment
```
or if you have enabled pretty URLs, you may use the following URL:
```
http://localhost/path/to/index.php/rbac
http://localhost/path/to/index.php/rbac/route
http://localhost/path/to/index.php/rbac/permission
http://localhost/path/to/index.php/rbac/role
http://localhost/path/to/index.php/rbac/assignment
```
**Applying rules:**
1) For applying rules only for `controller` add the following code:
```php
use yii2mod\rbac\filters\AccessControl;
class ExampleController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'allowActions' => [
'index',
// The actions listed here will be allowed to everyone including guests.
]
],
];
}
}
```
2) For applying rules for `module` add the following code:
```php
use Yii;
use yii2mod\rbac\filters\AccessControl;
/**
* Class Module
*/
class Module extends \yii\base\Module
{
/**
* @return array
*/
public function behaviors()
{
return [
AccessControl::class
];
}
}
```
3) Also you can apply rules via main configuration:
```php
// apply for single module
'modules' => [
'rbac' => [
'class' => 'yii2mod\rbac\Module',
'as access' => [
'class' => yii2mod\rbac\filters\AccessControl::class
],
]
]
// or apply globally for whole application
'modules' => [
...
],
'components' => [
...
],
'as access' => [
'class' => yii2mod\rbac\filters\AccessControl::class,
'allowActions' => [
'site/*',
'admin/*',
// The actions listed here will be allowed to everyone including guests.
// So, 'admin/*' should not appear here in the production, of course.
// But in the earlier stages of your development, you may probably want to
// add a lot of actions here until you finally completed setting up rbac,
// otherwise you may not even take a first step.
]
],
```
## Internationalization
All text and messages introduced in this extension are translatable under category 'yii2mod.rbac'.
You may use translations provided within this extension, using following application configuration:
```php
return [
'components' => [
'i18n' => [
'translations' => [
'yii2mod.rbac' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@yii2mod/rbac/messages',
],
// ...
],
],
// ...
],
// ...
];
```
## Migrations
You can create the console migrations for creating/updating RBAC items.
### Module setup
To be able create the migrations, you need to add the following code to your console application configuration:
```php
// console.php
'modules' => [
'rbac' => [
'class' => 'yii2mod\rbac\ConsoleModule'
]
]
```
### Methods
1. `createPermission()`: creating a permission
2. `updatePermission()`: updating a permission
3. `removePermission()`: removing a permission
4. `createRole()`: creating a role
5. `updateRole()`: updating a role
6. `removeRole()`: removing a role
7. `createRule()`: creating a rule
8. `updateRule()`: updating a rule
9. `removeRule()`: removing a rule
10. `addChild()`: creating a child
12. `removeChild()`: removing a child
13. `assign()`: assign a role to a user
### Creating Migrations
To create a new migration, run the following command:
```bash
$ php yii rbac/migrate/create <name>
```
The required `name` argument gives a brief description about the new migration. For example, if the migration is about creating a new role named admin, you may use the name `create_role_admin` and run the following command:
```bash
$ php yii rbac/migrate/create create_role_admin
```
The above command will create a new PHP class file named m160817_085702_create_role_admin.php in the @app/rbac/migrations directory. The file contains the following code which mainly declares a migration class m160817_085702_create_role_admin with the skeleton code:
```php
<?php
use yii2mod\rbac\migrations\Migration;
class m160817_085702_create_role_admin extends Migration
{
public function safeUp()
{
}
public function safeDown()
{
echo "m160817_085702_create_role_admin cannot be reverted.\n";
return false;
}
}
```
The following code shows how you may implement the migration class to create a `admin` role:
```php
<?php
use yii2mod\rbac\migrations\Migration;
class m160817_085702_create_role_admin extends Migration
{
public function safeUp()
{
$this->createRole('admin', 'admin has all available permissions.');
}
public function safeDown()
{
$this->removeRole('admin');
}
}
```
> You can see a complex example of migration [here.](https://github.com/yii2mod/base/blob/master/rbac/migrations/m160722_085418_init.php)
### Applying Migrations
To upgrade a database to its latest structure, you should apply all available new migrations using the following command:
```bash
$ php yii rbac/migrate
```
### Reverting Migrations
To revert (undo) one or multiple migrations that have been applied before, you can run the following command:
```bash
$ php yii rbac/migrate/down # revert the most recently applied migration
$ php yii rbac/migrate/down 3 # revert the most 3 recently applied migrations
```
### Redoing Migrations
Redoing migrations means first reverting the specified migrations and then applying again. This can be done as follows:
```bash
$ php yii rbac/migrate/redo # redo the last applied migration
$ php yii rbac/migrate/redo 3 # redo the last 3 applied migrations
```

36
vendor/yii2mod/yii2-rbac/RbacAsset.php vendored Normal file
View File

@@ -0,0 +1,36 @@
<?php
namespace yii2mod\rbac;
use yii\web\AssetBundle;
/**
* Class RbacAsset
*
* @package yii2mod\rbac
*/
class RbacAsset extends AssetBundle
{
/**
* @var string
*/
public $sourcePath = '@vendor/yii2mod/yii2-rbac/assets';
/**
* @var array
*/
public $js = [
'js/rbac.js',
];
public $css = [
'css/rbac.css',
];
/**
* @var array
*/
public $depends = [
'yii\web\YiiAsset',
];
}

View File

@@ -0,0 +1,18 @@
<?php
namespace yii2mod\rbac;
/**
* Class RbacRouteAsset
*
* @package yii2mod\rbac
*/
class RbacRouteAsset extends RbacAsset
{
/**
* @var array
*/
public $js = [
'js/rbac-route.js',
];
}

View File

@@ -0,0 +1,7 @@
.move-buttons {
margin: 50px;
}
#btn-refresh {
margin-bottom: 10px;
}

View File

@@ -0,0 +1,52 @@
function updateItems(r) {
_opts.items.available = r.available;
_opts.items.assigned = r.assigned;
search('available');
search('assigned');
}
$('.btn-assign').click(function () {
var $this = $(this);
var target = $this.data('target');
var routes = $('select.list[data-target="' + target + '"]').val();
if (routes && routes.length) {
$.post($this.attr('href'), {routes: routes}, function (r) {
updateItems(r);
});
}
return false;
});
$('#btn-refresh').click(function () {
var $btn = $(this);
$btn.attr("disabled", "disabled");
$.post($(this).attr('href'), function (r) {
updateItems(r);
}).always(function () {
$btn.removeAttr("disabled");
});
return false;
});
$('.search[data-target]').keyup(function () {
search($(this).data('target'));
});
function search(target) {
var $list = $('select.list[data-target="' + target + '"]');
$list.html('');
var q = $('.search[data-target="' + target + '"]').val();
$.each(_opts.items[target], function () {
var r = this;
if (r.indexOf(q) >= 0) {
$('<option>').text(r).val(r).appendTo($list);
}
});
}
// initial
search('available');
search('assigned');

View File

@@ -0,0 +1,50 @@
function updateItems(r) {
_opts.items.available = r.available;
_opts.items.assigned = r.assigned;
search('available');
search('assigned');
}
$('.btn-assign').click(function () {
var $this = $(this);
var target = $this.data('target');
var items = $('select.list[data-target="' + target + '"]').val();
if (items && items.length) {
$.post($this.attr('href'), {items: items}, function (r) {
updateItems(r);
});
}
return false;
});
$('.search[data-target]').keyup(function () {
search($(this).data('target'));
});
function search(target) {
var $list = $('select.list[data-target="' + target + '"]');
$list.html('');
var q = $('.search[data-target="' + target + '"]').val();
var groups = {
role: [$('<optgroup label="Roles">'), false],
permission: [$('<optgroup label="Permission">'), false],
route: [$('<optgroup label="Routes">'), false],
};
$.each(_opts.items[target], function (name, group) {
if (name.indexOf(q) >= 0) {
$('<option>').text(name).val(name).appendTo(groups[group][0]);
groups[group][1] = true;
}
});
$.each(groups, function () {
if (this[1]) {
$list.append(this[0]);
}
});
}
// initial
search('available');
search('assigned');

View File

@@ -0,0 +1,236 @@
<?php
namespace yii2mod\rbac\base;
use Yii;
use yii\filters\VerbFilter;
use yii\rbac\Item;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\web\Response;
use yii2mod\rbac\models\AuthItemModel;
use yii2mod\rbac\models\search\AuthItemSearch;
/**
* Class ItemController
*
* @package yii2mod\rbac\base
*/
class ItemController extends Controller
{
/**
* @var string search class name for auth items search
*/
public $searchClass = [
'class' => AuthItemSearch::class,
];
/**
* @var int Type of Auth Item
*/
protected $type;
/**
* @var array labels use in view
*/
protected $labels;
/**
* @inheritdoc
*/
public function behaviors(): array
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'index' => ['get'],
'view' => ['get'],
'create' => ['get', 'post'],
'update' => ['get', 'post'],
'delete' => ['post'],
'assign' => ['post'],
'remove' => ['post'],
],
],
'contentNegotiator' => [
'class' => 'yii\filters\ContentNegotiator',
'only' => ['assign', 'remove'],
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
],
];
}
/**
* Lists of all auth items
*
* @return mixed
*/
public function actionIndex()
{
$searchModel = Yii::createObject($this->searchClass);
$searchModel->type = $this->type;
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
/**
* Displays a single AuthItem model.
*
* @param string $id
*
* @return mixed
*/
public function actionView(string $id)
{
$model = $this->findModel($id);
return $this->render('view', ['model' => $model]);
}
/**
* Creates a new AuthItem model.
*
* If creation is successful, the browser will be redirected to the 'view' page.
*
* @return mixed
*/
public function actionCreate()
{
$model = new AuthItemModel();
$model->type = $this->type;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->session->setFlash('success', Yii::t('yii2mod.rbac', 'Item has been saved.'));
return $this->redirect(['view', 'id' => $model->name]);
}
return $this->render('create', ['model' => $model]);
}
/**
* Updates an existing AuthItem model.
*
* If update is successful, the browser will be redirected to the 'view' page.
*
* @param string $id
*
* @return mixed
*/
public function actionUpdate(string $id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->session->setFlash('success', Yii::t('yii2mod.rbac', 'Item has been saved.'));
return $this->redirect(['view', 'id' => $model->name]);
}
return $this->render('update', ['model' => $model]);
}
/**
* Deletes an existing AuthItem model.
*
* If deletion is successful, the browser will be redirected to the 'index' page.
*
* @param string $id
*
* @return mixed
*/
public function actionDelete(string $id)
{
$model = $this->findModel($id);
Yii::$app->getAuthManager()->remove($model->item);
Yii::$app->session->setFlash('success', Yii::t('yii2mod.rbac', 'Item has been removed.'));
return $this->redirect(['index']);
}
/**
* Assign items
*
* @param string $id
*
* @return array
*/
public function actionAssign(string $id)
{
$items = Yii::$app->getRequest()->post('items', []);
$model = $this->findModel($id);
$model->addChildren($items);
return array_merge($model->getItems());
}
/**
* Remove items
*
* @param string $id
*
* @return array
*/
public function actionRemove(string $id): array
{
$items = Yii::$app->getRequest()->post('items', []);
$model = $this->findModel($id);
$model->removeChildren($items);
return array_merge($model->getItems());
}
/**
* @inheritdoc
*/
public function getViewPath(): string
{
return $this->module->getViewPath() . DIRECTORY_SEPARATOR . 'item';
}
/**
* @return int
*/
public function getType(): int
{
return $this->type;
}
/**
* @return array
*/
public function getLabels(): array
{
return $this->labels;
}
/**
* Finds the AuthItem model based on its primary key value.
*
* If the model is not found, a 404 HTTP exception will be thrown.
*
* @param string $id
*
* @return AuthItemModel the loaded model
*
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel(string $id): AuthItemModel
{
$auth = Yii::$app->getAuthManager();
$item = $this->type === Item::TYPE_ROLE ? $auth->getRole($id) : $auth->getPermission($id);
if (empty($item)) {
throw new NotFoundHttpException(Yii::t('yii2mod.rbac', 'The requested page does not exist.'));
}
return new AuthItemModel($item);
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace yii2mod\rbac\commands;
use yii\console\controllers\BaseMigrateController;
use yii\db\Connection;
use yii\db\Query;
use yii\di\Instance;
use yii\helpers\Console;
/**
* Class MigrateController
*
* Below are some common usages of this command:
*
* ```
* # creates a new migration named 'create_rule'
* yii rbac/migrate/create create_rule
*
* # applies ALL new migrations
* yii rbac/migrate
*
* # reverts the last applied migration
* yii rbac/migrate/down
* ```
*/
class MigrateController extends BaseMigrateController
{
/**
* @var Connection The database connection
*/
public $db = 'db';
/**
* @inheritdoc
*/
public $migrationTable = '{{%auth_migration}}';
/**
* @inheritdoc
*/
public $migrationPath = '@app/rbac/migrations';
/**
* @inheritdoc
*/
public $templateFile = '@vendor/yii2mod/yii2-rbac/views/migration.php';
/**
* @inheritdoc
*/
public function init()
{
$this->db = Instance::ensure($this->db, Connection::class);
parent::init();
}
/**
* @return Connection
*/
public function getDb(): Connection
{
return $this->db;
}
/**
* @inheritdoc
*/
protected function getMigrationHistory($limit)
{
if ($this->db->schema->getTableSchema($this->migrationTable, true) === null) {
$this->createMigrationHistoryTable();
}
$history = (new Query())
->select(['apply_time'])
->from($this->migrationTable)
->orderBy(['apply_time' => SORT_DESC, 'version' => SORT_DESC])
->limit($limit)
->indexBy('version')
->column($this->db);
unset($history[self::BASE_MIGRATION]);
return $history;
}
/**
* @inheritdoc
*/
protected function addMigrationHistory($version)
{
$this->db->createCommand()->insert($this->migrationTable, [
'version' => $version,
'apply_time' => time(),
])->execute();
}
/**
* @inheritdoc
*/
protected function removeMigrationHistory($version)
{
$this->db->createCommand()->delete($this->migrationTable, [
'version' => $version,
])->execute();
}
/**
* Creates the migration history table.
*/
protected function createMigrationHistoryTable()
{
$tableName = $this->db->schema->getRawTableName($this->migrationTable);
$this->stdout("Creating migration history table \"$tableName\"...", Console::FG_YELLOW);
$this->db->createCommand()->createTable($this->migrationTable, [
'version' => 'VARCHAR(180) NOT NULL PRIMARY KEY',
'apply_time' => 'INTEGER',
])->execute();
$this->db->createCommand()->insert($this->migrationTable, [
'version' => self::BASE_MIGRATION,
'apply_time' => time(),
])->execute();
$this->stdout("Done.\n", Console::FG_GREEN);
}
}

45
vendor/yii2mod/yii2-rbac/composer.json vendored Normal file
View File

@@ -0,0 +1,45 @@
{
"name": "yii2mod/yii2-rbac",
"description": "RBAC management module for Yii2",
"keywords": [
"yii2",
"yii2-rbac",
"rbac management",
"rbac gui",
"yii2 rbac",
"rbac module"
],
"type": "yii2-extension",
"license": "MIT",
"authors": [
{
"name": "Dmitry Semenov",
"email": "disemx@gmail.com"
},
{
"name": "Igor Chepurnoi",
"email": "chepurnoi.igor@gmail.com"
}
],
"require": {
"php": ">=7.0.0",
"yiisoft/yii2": "~2.0.13",
"2amigos/yii2-arrayquery-component": "~1.0",
"yiisoft/yii2-jui": "~2.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2.0",
"phpunit/phpunit": "~6.0"
},
"autoload": {
"psr-4": {
"yii2mod\\rbac\\": ""
}
},
"repositories": [
{
"type": "composer",
"url": "https://asset-packagist.org"
}
]
}

View File

@@ -0,0 +1,182 @@
<?php
namespace yii2mod\rbac\controllers;
use Yii;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\web\Response;
use yii2mod\rbac\models\AssignmentModel;
use yii2mod\rbac\models\search\AssignmentSearch;
/**
* Class AssignmentController
*
* @package yii2mod\rbac\controllers
*/
class AssignmentController extends Controller
{
/**
* @var \yii\web\IdentityInterface the class name of the [[identity]] object
*/
public $userIdentityClass;
/**
* @var string search class name for assignments search
*/
public $searchClass = [
'class' => AssignmentSearch::class,
];
/**
* @var string id column name
*/
public $idField = 'id';
/**
* @var string username column name
*/
public $usernameField = 'username';
/**
* @var array assignments GridView columns
*/
public $gridViewColumns = [];
/**
* @inheritdoc
*/
public function init()
{
parent::init();
if ($this->userIdentityClass === null) {
$this->userIdentityClass = Yii::$app->user->identityClass;
}
if (empty($this->gridViewColumns)) {
$this->gridViewColumns = [
$this->idField,
$this->usernameField,
];
}
}
/**
* @inheritdoc
*/
public function behaviors(): array
{
return [
'verbs' => [
'class' => 'yii\filters\VerbFilter',
'actions' => [
'index' => ['get'],
'view' => ['get'],
'assign' => ['post'],
'remove' => ['post'],
],
],
'contentNegotiator' => [
'class' => 'yii\filters\ContentNegotiator',
'only' => ['assign', 'remove'],
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
],
];
}
/**
* List of all assignments
*
* @return string
*/
public function actionIndex()
{
/* @var AssignmentSearch */
$searchModel = Yii::createObject($this->searchClass);
if ($searchModel instanceof AssignmentSearch) {
$dataProvider = $searchModel->search(Yii::$app->request->queryParams, $this->userIdentityClass, $this->idField, $this->usernameField);
} else {
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
}
return $this->render('index', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
'gridViewColumns' => $this->gridViewColumns,
]);
}
/**
* Displays a single Assignment model.
*
* @param int $id
*
* @return mixed
*/
public function actionView(int $id)
{
$model = $this->findModel($id);
return $this->render('view', [
'model' => $model,
'usernameField' => $this->usernameField,
]);
}
/**
* Assign items
*
* @param int $id
*
* @return array
*/
public function actionAssign(int $id)
{
$items = Yii::$app->getRequest()->post('items', []);
$assignmentModel = $this->findModel($id);
$assignmentModel->assign($items);
return $assignmentModel->getItems();
}
/**
* Remove items
*
* @param int $id
*
* @return array
*/
public function actionRemove(int $id)
{
$items = Yii::$app->getRequest()->post('items', []);
$assignmentModel = $this->findModel($id);
$assignmentModel->revoke($items);
return $assignmentModel->getItems();
}
/**
* Finds the Assignment model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
*
* @param int $id
*
* @return AssignmentModel the loaded model
*
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel(int $id)
{
$class = $this->userIdentityClass;
if (($user = $class::findIdentity($id)) !== null) {
return new AssignmentModel($user);
}
throw new NotFoundHttpException(Yii::t('yii2mod.rbac', 'The requested page does not exist.'));
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace yii2mod\rbac\controllers;
use yii\rbac\Item;
use yii2mod\rbac\base\ItemController;
/**
* Class PermissionController
*
* @package yii2mod\rbac\controllers
*/
class PermissionController extends ItemController
{
/**
* @var int
*/
protected $type = Item::TYPE_PERMISSION;
/**
* @var array
*/
protected $labels = [
'Item' => 'Permission',
'Items' => 'Permissions',
];
}

View File

@@ -0,0 +1,27 @@
<?php
namespace yii2mod\rbac\controllers;
use yii\rbac\Item;
use yii2mod\rbac\base\ItemController;
/**
* Class RoleController
*
* @package yii2mod\rbac\controllers
*/
class RoleController extends ItemController
{
/**
* @var int
*/
protected $type = Item::TYPE_ROLE;
/**
* @var array
*/
protected $labels = [
'Item' => 'Role',
'Items' => 'Roles',
];
}

View File

@@ -0,0 +1,105 @@
<?php
namespace yii2mod\rbac\controllers;
use Yii;
use yii\filters\VerbFilter;
use yii\web\Controller;
use yii\web\Response;
use yii2mod\rbac\models\RouteModel;
/**
* Class RouteController
*
* @package yii2mod\rbac\controllers
*/
class RouteController extends Controller
{
/**
* @var array route model class
*/
public $modelClass = [
'class' => RouteModel::class,
];
/**
* Returns a list of behaviors that this component should behave as.
*
* @return array
*/
public function behaviors(): array
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'index' => ['get', 'post'],
'create' => ['post'],
'assign' => ['post'],
'remove' => ['post'],
'refresh' => ['post'],
],
],
'contentNegotiator' => [
'class' => 'yii\filters\ContentNegotiator',
'only' => ['assign', 'remove', 'refresh'],
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
],
];
}
/**
* Lists all Route models.
*
* @return mixed
*/
public function actionIndex()
{
$model = Yii::createObject($this->modelClass);
return $this->render('index', ['routes' => $model->getAvailableAndAssignedRoutes()]);
}
/**
* Assign routes
*
* @return array
*/
public function actionAssign(): array
{
$routes = Yii::$app->getRequest()->post('routes', []);
$model = Yii::createObject($this->modelClass);
$model->addNew($routes);
return $model->getAvailableAndAssignedRoutes();
}
/**
* Remove routes
*
* @return array
*/
public function actionRemove(): array
{
$routes = Yii::$app->getRequest()->post('routes', []);
$model = Yii::createObject($this->modelClass);
$model->remove($routes);
return $model->getAvailableAndAssignedRoutes();
}
/**
* Refresh cache of routes
*
* @return array
*/
public function actionRefresh(): array
{
$model = Yii::createObject($this->modelClass);
$model->invalidate();
return $model->getAvailableAndAssignedRoutes();
}
}

View File

@@ -0,0 +1,158 @@
<?php
namespace yii2mod\rbac\controllers;
use Yii;
use yii\filters\VerbFilter;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii2mod\rbac\models\BizRuleModel;
use yii2mod\rbac\models\search\BizRuleSearch;
/**
* Class RuleController
*
* @package yii2mod\rbac\controllers
*/
class RuleController extends Controller
{
/**
* @var string search class name for rules search
*/
public $searchClass = [
'class' => BizRuleSearch::class,
];
/**
* Returns a list of behaviors that this component should behave as.
*
* @return array
*/
public function behaviors(): array
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'index' => ['get'],
'view' => ['get'],
'create' => ['get', 'post'],
'update' => ['get', 'post'],
'delete' => ['post'],
],
],
];
}
/**
* List of all rules
*
* @return mixed
*/
public function actionIndex()
{
$searchModel = Yii::createObject($this->searchClass);
$dataProvider = $searchModel->search(Yii::$app->request->getQueryParams());
return $this->render('index', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
/**
* Displays a single Rule item.
*
* @param string $id
*
* @return mixed
*/
public function actionView(string $id)
{
$model = $this->findModel($id);
return $this->render('view', ['model' => $model]);
}
/**
* Creates a new Rule item.
*
* If creation is successful, the browser will be redirected to the 'view' page.
*
* @return mixed
*/
public function actionCreate()
{
$model = new BizRuleModel();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->session->setFlash('success', Yii::t('yii2mod.rbac', 'Rule has been saved.'));
return $this->redirect(['view', 'id' => $model->name]);
}
return $this->render('create', ['model' => $model]);
}
/**
* Updates an existing Rule item.
*
* If update is successful, the browser will be redirected to the 'view' page.
*
* @param string $id
*
* @return mixed
*/
public function actionUpdate(string $id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->session->setFlash('success', Yii::t('yii2mod.rbac', 'Rule has been saved.'));
return $this->redirect(['view', 'id' => $model->name]);
}
return $this->render('update', ['model' => $model]);
}
/**
* Deletes an existing Rule item.
*
* If deletion is successful, the browser will be redirected to the 'index' page.
*
* @param string $id
*
* @return mixed
*/
public function actionDelete(string $id)
{
$model = $this->findModel($id);
Yii::$app->authManager->remove($model->item);
Yii::$app->session->setFlash('success', Yii::t('yii2mod.rbac', 'Rule has been deleted.'));
return $this->redirect(['index']);
}
/**
* Finds the BizRuleModel based on its primary key value.
*
* If the model is not found, a 404 HTTP exception will be thrown.
*
* @param string $id
*
* @return BizRuleModel the loaded model
*
* @throws \yii\web\NotFoundHttpException
*/
protected function findModel(string $id)
{
$item = Yii::$app->authManager->getRule($id);
if (!empty($item)) {
return new BizRuleModel($item);
}
throw new NotFoundHttpException(Yii::t('yii2mod.rbac', 'The requested page does not exist.'));
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace yii2mod\rbac\filters;
use Yii;
use yii\base\Action;
use yii\base\Module;
use yii\helpers\ArrayHelper;
use yii\helpers\Url;
/**
* Class AccessControl
*
* @package yii2mod\rbac\filters
*/
class AccessControl extends \yii\filters\AccessControl
{
/**
* @var array
*/
public $params = [];
/**
* @var array list of actions that not need to check access
*/
public $allowActions = [];
/**
* @inheritdoc
*/
public function beforeAction($action): bool
{
$controller = $action->controller;
$params = ArrayHelper::getValue($this->params, $action->id, []);
if (Yii::$app->user->can('/' . $action->getUniqueId(), $params)) {
return true;
}
do {
if (Yii::$app->user->can('/' . ltrim($controller->getUniqueId() . '/*', '/'))) {
return true;
}
$controller = $controller->module;
} while ($controller !== null);
return parent::beforeAction($action);
}
/**
* @inheritdoc
*/
protected function isActive($action): bool
{
if ($this->isErrorPage($action) || $this->isLoginPage($action) || $this->isAllowedAction($action)) {
return false;
}
return parent::isActive($action);
}
/**
* Returns a value indicating whether a current url equals `errorAction` property of the ErrorHandler component
*
* @param Action $action
*
* @return bool
*/
private function isErrorPage(Action $action): bool
{
if ($action->getUniqueId() === Yii::$app->getErrorHandler()->errorAction) {
return true;
}
return false;
}
/**
* Returns a value indicating whether a current url equals `loginUrl` property of the User component
*
* @param Action $action
*
* @return bool
*/
private function isLoginPage(Action $action): bool
{
$loginUrl = trim(Url::to(Yii::$app->user->loginUrl), '/');
if (Yii::$app->user->isGuest && $action->getUniqueId() === $loginUrl) {
return true;
}
return false;
}
/**
* Returns a value indicating whether a current url exists in the `allowActions` list.
*
* @param Action $action
*
* @return bool
*/
private function isAllowedAction(Action $action): bool
{
if ($this->owner instanceof Module) {
$ownerId = $this->owner->getUniqueId();
$id = $action->getUniqueId();
if (!empty($ownerId) && strpos($id, $ownerId . '/') === 0) {
$id = substr($id, strlen($ownerId) + 1);
}
} else {
$id = $action->id;
}
foreach ($this->allowActions as $route) {
if (substr($route, -1) === '*') {
$route = rtrim($route, '*');
if ($route === '' || strpos($id, $route) === 0) {
return true;
}
} else {
if ($id === $route) {
return true;
}
}
}
return false;
}
}

View File

@@ -0,0 +1,58 @@
<?php
return [
// string, required, root directory of all source files
'sourcePath' => __DIR__ . DIRECTORY_SEPARATOR . '..',
// array, required, list of language codes that the extracted messages
// should be translated to. For example, ['zh-CN', 'de'].
'languages' => ['en'],
// string, the name of the function for translating messages.
// Defaults to 'Yii::t'. This is used as a mark to find the messages to be
// translated. You may use a string for single function name or an array for
// multiple function names.
'translator' => 'Yii::t',
// boolean, whether to sort messages by keys when merging new messages
// with the existing ones. Defaults to false, which means the new (untranslated)
// messages will be separated from the old (translated) ones.
'sort' => true,
// boolean, whether to remove messages that no longer appear in the source code.
// Defaults to false, which means each of these messages will be enclosed with a pair of '@@' marks.
'removeUnused' => false,
// array, list of patterns that specify which files (not directories) should be processed.
// If empty or not set, all files will be processed.
// Please refer to "except" for details about the patterns.
'only' => ['*.php'],
// array, list of patterns that specify which files/directories should NOT be processed.
// If empty or not set, all files/directories will be processed.
// A path matches a pattern if it contains the pattern string at its end. For example,
// '/a/b' will match all files and directories ending with '/a/b';
// the '*.svn' will match all files and directories whose name ends with '.svn'.
// and the '.svn' will match all files and directories named exactly '.svn'.
// Note, the '/' characters in a pattern matches both '/' and '\'.
// See helpers/FileHelper::findFiles() description for more details on pattern matching rules.
// If a file/directory matches both a pattern in "only" and "except", it will NOT be processed.
'except' => [
'.svn',
'.git',
'.gitignore',
'.gitkeep',
'.hgignore',
'.hgkeep',
'/messages',
'/tests',
'/runtime',
'/vendor',
],
// 'php' output format is for saving messages to php files.
'format' => 'php',
// Root directory containing message translations.
'messagePath' => __DIR__,
// boolean, whether the message file should be overwritten with the merged messages
'overwrite' => true,
// Message categories to ignore
'ignoreCategories' => [
'yii',
],
];

View File

@@ -0,0 +1,62 @@
<?php
/**
* Message translations.
*
* This file is automatically generated by 'yii message/extract' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'\'{class}\' must extend from \'yii\\rbac\\Rule\' or its child class' => '\'{class}\' must extend from \'yii\\rbac\\Rule\' or its child class',
'Action' => 'Action',
'Are you sure to delete this item?' => 'Are you sure to delete this item?',
'Assign' => 'Assign',
'Assignment : {0}' => 'Assignment : {0}',
'Assignments' => 'Assignments',
'Class Name' => 'Class Name',
'Create' => 'Create',
'Create Rule' => 'Create Rule',
'Create Role' => 'Create Role',
'Data' => 'Data',
'Delete' => 'Delete',
'Description' => 'Description',
'Invalid rule "{value}"' => 'Invalid rule "{value}"',
'Item has been removed.' => 'Item has been removed.',
'Item has been saved.' => 'Item has been saved.',
'Name' => 'Name',
'Permissions' => 'Permissions',
'Refresh' => 'Refresh',
'Remove' => 'Remove',
'Roles' => 'Roles',
'Role : {0}' => 'Role : {0}',
'Permission : {0}' => 'Permission : {0}',
'Create Permission' => 'Create Permission',
'Routes' => 'Routes',
'Rule' => 'Rule',
'Rule "{value}" does not exists' => 'Rule "{value}" does not exists',
'Rule : {0}' => 'Rule : {0}',
'Rule Name' => 'Rule Name',
'Rule has been deleted.' => 'Rule has been deleted.',
'Rule has been saved.' => 'Rule has been saved.',
'Rules' => 'Rules',
'Search for assigned' => 'Search for assigned',
'Search for available' => 'Search for available',
'The requested page does not exist.' => 'The requested page does not exist.',
'Type' => 'Type',
'Unknown class \'{class}\'' => 'Unknown class \'{class}\'',
'Update' => 'Update',
'Update Rule : {0}' => 'Update Rule : {0}',
'Update Role : {0}' => 'Update Role : {0}',
'Update Permission : {0}' => 'Update Permission : {0}',
'Select Rule' => 'Select Rule',
];

View File

@@ -0,0 +1,62 @@
<?php
/**
* Message translations.
*
* This file is automatically generated by 'yii message/extract' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'\'{class}\' must extend from \'yii\\rbac\\Rule\' or its child class' => 'Класс должен быть унаследован от \'yii\\rbac\\Rule\' или его дочерних классов',
'Action' => 'Действие',
'Are you sure to delete this item?' => 'Вы действительно хотите удалить этот элемент?',
'Assign' => 'Назначить',
'Assignment : {0}' => 'Назначение : {0}',
'Assignments' => 'Назначения',
'Class Name' => 'Имя класса',
'Create' => 'Создать',
'Create Rule' => 'Создать правило',
'Create Role' => 'Создать роль',
'Data' => 'Данные',
'Delete' => 'Удалить',
'Description' => 'Описание',
'Invalid rule "{value}"' => 'Некорректное правило "{value}"',
'Item has been removed.' => 'Элемент был удален.',
'Item has been saved.' => 'Элемент сохранен.',
'Name' => 'Имя',
'Permissions' => 'Разрешения',
'Refresh' => 'Обновить',
'Remove' => 'Удалить',
'Roles' => 'Роли',
'Role : {0}' => 'Роль : {0}',
'Permission : {0}' => 'Разрешение : {0}',
'Create Permission' => 'Создать разрешение',
'Routes' => 'Маршруты',
'Rule' => 'Правило',
'Rule "{value}" does not exists' => 'Правило "{value}" не существует',
'Rule : {0}' => 'Правило : {0}',
'Rule Name' => 'Имя правила',
'Rule has been deleted.' => 'Правило было удалено.',
'Rule has been saved.' => 'Правило сохранено.',
'Rules' => 'Правила',
'Search for assigned' => 'Поиск по присвоенным',
'Search for available' => 'Поиск по доступным',
'The requested page does not exist.' => 'Ошибка 404 - страница не найдена!',
'Type' => 'Тип',
'Unknown class \'{class}\'' => 'Неизвестный класс \'{class}\'',
'Update' => 'Обновить',
'Update Rule : {0}' => 'Обновить правило : {0}',
'Update Role : {0}' => 'Обновить роль : {0}',
'Update Permission : {0}' => 'Обновить разрешение : {0}',
'Select Rule' => 'Выберите правило',
];

View File

@@ -0,0 +1,423 @@
<?php
namespace yii2mod\rbac\migrations;
use yii\base\Component;
use yii\base\InvalidParamException;
use yii\db\MigrationInterface;
use yii\di\Instance;
use yii\rbac\DbManager;
use yii\rbac\Item;
use yii\rbac\Permission;
use yii\rbac\Role;
use yii\rbac\Rule;
/**
* Class Migration
*
* @package yii2mod\rbac\migrations
*/
class Migration extends Component implements MigrationInterface
{
/**
* @var string|DbManager The auth manager component ID that this migration should work with
*/
public $authManager = 'authManager';
/**
* Initializes the migration.
* This method will set [[authManager]] to be the 'authManager' application component, if it is `null`.
*/
public function init()
{
$this->authManager = Instance::ensure($this->authManager, DbManager::class);
parent::init();
}
/**
* @inheritdoc
*/
public function up()
{
$transaction = $this->authManager->db->beginTransaction();
try {
if ($this->safeUp() === false) {
$transaction->rollBack();
return false;
}
$transaction->commit();
$this->authManager->invalidateCache();
return true;
} catch (\Exception $e) {
echo "Rolling transaction back\n";
echo 'Exception: ' . $e->getMessage() . ' (' . $e->getFile() . ':' . $e->getLine() . ")\n";
echo $e->getTraceAsString() . "\n";
$transaction->rollBack();
return false;
}
}
/**
* @inheritdoc
*/
public function down()
{
$transaction = $this->authManager->db->beginTransaction();
try {
if ($this->safeDown() === false) {
$transaction->rollBack();
return false;
}
$transaction->commit();
$this->authManager->invalidateCache();
return true;
} catch (\Exception $e) {
echo "Rolling transaction back\n";
echo 'Exception: ' . $e->getMessage() . ' (' . $e->getFile() . ':' . $e->getLine() . ")\n";
echo $e->getTraceAsString() . "\n";
$transaction->rollBack();
return false;
}
}
/**
* This method contains the logic to be executed when applying this migration.
*
* @return bool return a false value to indicate the migration fails
* and should not proceed further. All other return values mean the migration succeeds
*/
public function safeUp()
{
}
/**
* This method contains the logic to be executed when removing this migration.
*
* @return bool return a false value to indicate the migration fails
* and should not proceed further. All other return values mean the migration succeeds
*/
public function safeDown()
{
}
/**
* Creates new permission.
*
* @param string $name The name of the permission
* @param string $description The description of the permission
* @param string|null $ruleName The rule associated with the permission
* @param mixed|null $data The additional data associated with the permission
*
* @return Permission
*/
protected function createPermission($name, $description = '', $ruleName = null, $data = null)
{
echo " > create permission $name ...";
$time = microtime(true);
$permission = $this->authManager->createPermission($name);
$permission->description = $description;
$permission->ruleName = $ruleName;
$permission->data = $data;
$this->authManager->add($permission);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
return $permission;
}
/**
* Creates new role.
*
* @param string $name The name of the role
* @param string $description The description of the role
* @param string|null $ruleName The rule associated with the role
* @param mixed|null $data The additional data associated with the role
*
* @return Role
*/
protected function createRole($name, $description = '', $ruleName = null, $data = null)
{
echo " > create role $name ...";
$time = microtime(true);
$role = $this->authManager->createRole($name);
$role->description = $description;
$role->ruleName = $ruleName;
$role->data = $data;
$this->authManager->add($role);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
return $role;
}
/**
* Creates new rule.
*
* @param string $ruleName The name of the rule
* @param string|array $definition The class of the rule
*
* @return Rule
*/
protected function createRule($ruleName, $definition)
{
echo " > create rule $ruleName ...";
$time = microtime(true);
if (is_array($definition)) {
$definition['name'] = $ruleName;
} else {
$definition = [
'class' => $definition,
'name' => $ruleName,
];
}
/** @var Rule $rule */
$rule = \Yii::createObject($definition);
$this->authManager->add($rule);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
return $rule;
}
/**
* Finds either role or permission or throws an exception if it is not found.
*
* @param string $name
*
* @return Permission|Role|null
*/
protected function findItem($name)
{
$item = $this->authManager->getRole($name);
if ($item instanceof Role) {
return $item;
}
$item = $this->authManager->getPermission($name);
if ($item instanceof Permission) {
return $item;
}
return null;
}
/**
* Finds the role or throws an exception if it is not found.
*
* @param string $name
*
* @return Role|null
*/
protected function findRole($name)
{
$role = $this->authManager->getRole($name);
if ($role instanceof Role) {
return $role;
}
return null;
}
/**
* Finds the permission or throws an exception if it is not found.
*
* @param string $name
*
* @return Permission|null
*/
protected function findPermission($name)
{
$permission = $this->authManager->getPermission($name);
if ($permission instanceof Permission) {
return $permission;
}
return null;
}
/**
* Adds child.
*
* @param Item|string $parent Either name or Item instance which is parent
* @param Item|string $child Either name or Item instance which is child
*/
protected function addChild($parent, $child)
{
if (is_string($parent)) {
$parent = $this->findItem($parent);
}
if (is_string($child)) {
$child = $this->findItem($child);
}
echo " > adding $child->name as child to $parent->name ...";
$time = microtime(true);
$this->authManager->addChild($parent, $child);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
}
/**
* Removes child.
*
* @param Item|string $parent Either name or Item instance which is parent
* @param Item|string $child Either name or Item instance which is child
*/
protected function removeChild($parent, $child)
{
if (is_string($parent)) {
$parent = $this->findItem($parent);
}
if (is_string($child)) {
$child = $this->findItem($child);
}
echo " > removing $child->name from $parent->name ...";
$time = microtime(true);
$this->authManager->removeChild($parent, $child);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
}
/**
* Assigns a role to a user.
*
* @param string|Role $role
* @param string|int $userId
*/
protected function assign($role, $userId)
{
if (is_string($role)) {
$role = $this->findRole($role);
}
echo " > assigning $role->name to user $userId ...";
$time = microtime(true);
$this->authManager->assign($role, $userId);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
}
/**
* Updates role.
*
* @param string|Role $role
* @param string $description
* @param string $ruleName
* @param mixed $data
*
* @return Role
*/
protected function updateRole($role, $description = '', $ruleName = null, $data = null)
{
if (is_string($role)) {
$role = $this->findRole($role);
}
echo " > update role $role->name ...";
$time = microtime(true);
$role->description = $description;
$role->ruleName = $ruleName;
$role->data = $data;
$this->authManager->update($role->name, $role);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
return $role;
}
/**
* Remove role.
*
* @param string $name
*/
protected function removeRole($name)
{
$role = $this->authManager->getRole($name);
if (empty($role)) {
throw new InvalidParamException("Role '{$role}' does not exists");
}
echo " > removing role $role->name ...";
$time = microtime(true);
$this->authManager->remove($role);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
}
/**
* Updates permission.
*
* @param string|Permission $permission
* @param string $description
* @param string $ruleName
* @param mixed $data
*
* @return Permission
*/
protected function updatePermission($permission, $description = '', $ruleName = null, $data = null)
{
if (is_string($permission)) {
$permission = $this->findPermission($permission);
}
echo " > update permission $permission->name ...";
$time = microtime(true);
$permission->description = $description;
$permission->ruleName = $ruleName;
$permission->data = $data;
$this->authManager->update($permission->name, $permission);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
return $permission;
}
/**
* Remove permission.
*
* @param string $name
*/
protected function removePermission($name)
{
$permission = $this->authManager->getPermission($name);
if (empty($permission)) {
throw new InvalidParamException("Permission '{$permission}' does not exists");
}
echo " > removing permission $permission->name ...";
$time = microtime(true);
$this->authManager->remove($permission);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
}
/**
* Updates rule.
*
* @param string $ruleName
* @param string $className
*
* @return Rule
*/
protected function updateRule($ruleName, $className)
{
echo " > update rule $ruleName ...";
$time = microtime(true);
/** @var Rule $rule */
$rule = \Yii::createObject([
'class' => $className,
'name' => $ruleName,
]);
$this->authManager->update($ruleName, $rule);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
return $rule;
}
/**
* Remove rule.
*
* @param string $ruleName
*/
protected function removeRule($ruleName)
{
$rule = $this->authManager->getRule($ruleName);
if (empty($rule)) {
throw new InvalidParamException("Rule '{$ruleName}' does not exists");
}
echo " > removing rule $rule->name ...";
$time = microtime(true);
$this->authManager->remove($rule);
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
}
}

View File

@@ -0,0 +1,119 @@
<?php
namespace yii2mod\rbac\models;
use Yii;
use yii\base\BaseObject;
use yii\base\InvalidConfigException;
use yii\web\IdentityInterface;
/**
* Class AssignmentModel
*
* @package yii2mod\rbac\models
*/
class AssignmentModel extends BaseObject
{
/**
* @var IdentityInterface
*/
public $user;
/**
* @var int User id
*/
public $userId;
/**
* @var \yii\rbac\ManagerInterface
*/
protected $manager;
/**
* AssignmentModel constructor.
*
* @param IdentityInterface $user
* @param array $config
*
* @throws InvalidConfigException
*/
public function __construct(IdentityInterface $user, $config = [])
{
$this->user = $user;
$this->userId = $user->getId();
$this->manager = Yii::$app->authManager;
if ($this->userId === null) {
throw new InvalidConfigException('The "userId" property must be set.');
}
parent::__construct($config);
}
/**
* Assign a roles and permissions to the user.
*
* @param array $items
*
* @return bool
*/
public function assign(array $items): bool
{
foreach ($items as $name) {
$item = $this->manager->getRole($name);
$item = $item ?: $this->manager->getPermission($name);
$this->manager->assign($item, $this->userId);
}
return true;
}
/**
* Revokes a roles and permissions from the user.
*
* @param array $items
*
* @return bool
*/
public function revoke(array $items): bool
{
foreach ($items as $name) {
$item = $this->manager->getRole($name);
$item = $item ?: $this->manager->getPermission($name);
$this->manager->revoke($item, $this->userId);
}
return true;
}
/**
* Get all available and assigned roles and permissions
*
* @return array
*/
public function getItems(): array
{
$available = [];
$assigned = [];
foreach (array_keys($this->manager->getRoles()) as $name) {
$available[$name] = 'role';
}
foreach (array_keys($this->manager->getPermissions()) as $name) {
if ($name[0] != '/') {
$available[$name] = 'permission';
}
}
foreach ($this->manager->getAssignments($this->userId) as $item) {
$assigned[$item->roleName] = $available[$item->roleName];
unset($available[$item->roleName]);
}
return [
'available' => $available,
'assigned' => $assigned,
];
}
}

View File

@@ -0,0 +1,320 @@
<?php
namespace yii2mod\rbac\models;
use Yii;
use yii\base\Model;
use yii\helpers\Json;
use yii\rbac\Item;
use yii\rbac\Rule;
/**
* Class AuthItemModel
*
* @property string $name
* @property int $type
* @property string $description
* @property string $ruleName
* @property string $data
* @property Item $item
*/
class AuthItemModel extends Model
{
/**
* @var string auth item name
*/
public $name;
/**
* @var int auth item type
*/
public $type;
/**
* @var string auth item description
*/
public $description;
/**
* @var string biz rule name
*/
public $ruleName;
/**
* @var null|string additional data
*/
public $data;
/**
* @var \yii\rbac\ManagerInterface
*/
protected $manager;
/**
* @var Item
*/
private $_item;
/**
* AuthItemModel constructor.
*
* @param Item|null $item
* @param array $config
*/
public function __construct($item = null, $config = [])
{
$this->_item = $item;
$this->manager = Yii::$app->authManager;
if ($item !== null) {
$this->name = $item->name;
$this->type = $item->type;
$this->description = $item->description;
$this->ruleName = $item->ruleName;
$this->data = $item->data === null ? null : Json::encode($item->data);
}
parent::__construct($config);
}
/**
* @inheritdoc
*/
public function rules(): array
{
return [
[['name', 'description', 'data', 'ruleName'], 'trim'],
[['name', 'type'], 'required'],
['ruleName', 'checkRule'],
['name', 'validateName', 'when' => function () {
return $this->getIsNewRecord() || ($this->_item->name != $this->name);
}],
['type', 'integer'],
[['description', 'data', 'ruleName'], 'default'],
['name', 'string', 'max' => 64],
];
}
/**
* Validate item name
*/
public function validateName()
{
$value = $this->name;
if ($this->manager->getRole($value) !== null || $this->manager->getPermission($value) !== null) {
$message = Yii::t('yii', '{attribute} "{value}" has already been taken.');
$params = [
'attribute' => $this->getAttributeLabel('name'),
'value' => $value,
];
$this->addError('name', Yii::$app->getI18n()->format($message, $params, Yii::$app->language));
}
}
/**
* Check for rule
*/
public function checkRule()
{
$name = $this->ruleName;
if (!$this->manager->getRule($name)) {
try {
$rule = Yii::createObject($name);
if ($rule instanceof Rule) {
$rule->name = $name;
$this->manager->add($rule);
} else {
$this->addError('ruleName', Yii::t('yii2mod.rbac', 'Invalid rule "{value}"', ['value' => $name]));
}
} catch (\Exception $exc) {
$this->addError('ruleName', Yii::t('yii2mod.rbac', 'Rule "{value}" does not exists', ['value' => $name]));
}
}
}
/**
* @inheritdoc
*/
public function attributeLabels(): array
{
return [
'name' => Yii::t('yii2mod.rbac', 'Name'),
'type' => Yii::t('yii2mod.rbac', 'Type'),
'description' => Yii::t('yii2mod.rbac', 'Description'),
'ruleName' => Yii::t('yii2mod.rbac', 'Rule Name'),
'data' => Yii::t('yii2mod.rbac', 'Data'),
];
}
/**
* Check if is new record.
*
* @return bool
*/
public function getIsNewRecord(): bool
{
return $this->_item === null;
}
/**
* Find role
*
* @param string $id
*
* @return null|\self
*/
public static function find(string $id)
{
$item = Yii::$app->authManager->getRole($id);
if ($item !== null) {
return new self($item);
}
return null;
}
/**
* Save role to [[\yii\rbac\authManager]]
*
* @return bool
*/
public function save(): bool
{
if ($this->validate()) {
if ($this->_item === null) {
if ($this->type == Item::TYPE_ROLE) {
$this->_item = $this->manager->createRole($this->name);
} else {
$this->_item = $this->manager->createPermission($this->name);
}
$isNew = true;
$oldName = false;
} else {
$isNew = false;
$oldName = $this->_item->name;
}
$this->_item->name = $this->name;
$this->_item->description = $this->description;
$this->_item->ruleName = $this->ruleName;
$this->_item->data = Json::decode($this->data);
if ($isNew) {
$this->manager->add($this->_item);
} else {
$this->manager->update($oldName, $this->_item);
}
return true;
}
return false;
}
/**
* Add child to Item
*
* @param array $items
*
* @return bool
*/
public function addChildren(array $items): bool
{
if ($this->_item) {
foreach ($items as $name) {
$child = $this->manager->getPermission($name);
if (empty($child) && $this->type == Item::TYPE_ROLE) {
$child = $this->manager->getRole($name);
}
$this->manager->addChild($this->_item, $child);
}
}
return true;
}
/**
* Remove child from an item
*
* @param array $items
*
* @return bool
*/
public function removeChildren(array $items): bool
{
if ($this->_item !== null) {
foreach ($items as $name) {
$child = $this->manager->getPermission($name);
if (empty($child) && $this->type == Item::TYPE_ROLE) {
$child = $this->manager->getRole($name);
}
$this->manager->removeChild($this->_item, $child);
}
}
return true;
}
/**
* Get all available and assigned roles, permission and routes
*
* @return array
*/
public function getItems(): array
{
$available = [];
$assigned = [];
if ($this->type == Item::TYPE_ROLE) {
foreach (array_keys($this->manager->getRoles()) as $name) {
$available[$name] = 'role';
}
}
foreach (array_keys($this->manager->getPermissions()) as $name) {
$available[$name] = $name[0] == '/' ? 'route' : 'permission';
}
foreach ($this->manager->getChildren($this->_item->name) as $item) {
$assigned[$item->name] = $item->type == 1 ? 'role' : ($item->name[0] == '/' ? 'route' : 'permission');
unset($available[$item->name]);
}
unset($available[$this->name]);
return [
'available' => $available,
'assigned' => $assigned,
];
}
/**
* @return null|Item
*/
public function getItem()
{
return $this->_item;
}
/**
* Get type name
*
* @param mixed $type
*
* @return string|array
*/
public static function getTypeName($type = null)
{
$result = [
Item::TYPE_PERMISSION => 'Permission',
Item::TYPE_ROLE => 'Role',
];
if ($type === null) {
return $result;
}
return $result[$type];
}
}

View File

@@ -0,0 +1,176 @@
<?php
namespace yii2mod\rbac\models;
use Yii;
use yii\base\Model;
use yii\rbac\Rule;
/**
* Class BizRuleModel
*
* @package yii2mod\rbac\models
*/
class BizRuleModel extends Model
{
/**
* @var string name of the rule
*/
public $name;
/**
* @var int UNIX timestamp representing the rule creation time
*/
public $createdAt;
/**
* @var int UNIX timestamp representing the rule updating time
*/
public $updatedAt;
/**
* @var string Rule className
*/
public $className;
/**
* @var \yii\rbac\ManagerInterface
*/
protected $manager;
/**
* @var Rule
*/
private $_item;
/**
* BizRuleModel constructor.
*
* @param \yii\rbac\Rule $item
* @param array $config
*/
public function __construct($item = null, $config = [])
{
$this->_item = $item;
$this->manager = Yii::$app->authManager;
if ($item !== null) {
$this->name = $item->name;
$this->className = get_class($item);
}
parent::__construct($config);
}
/**
* @inheritdoc
*/
public function rules(): array
{
return [
[['name', 'className'], 'trim'],
[['name', 'className'], 'required'],
['className', 'string'],
['name', 'string', 'max' => 64],
['className', 'classExists'],
];
}
/**
* Validate className
*/
public function classExists()
{
if (!class_exists($this->className)) {
$message = Yii::t('yii2mod.rbac', "Unknown class '{class}'", ['class' => $this->className]);
$this->addError('className', $message);
return;
}
if (!is_subclass_of($this->className, Rule::class)) {
$message = Yii::t('yii2mod.rbac', "'{class}' must extend from 'yii\\rbac\\Rule' or its child class", [
'class' => $this->className, ]);
$this->addError('className', $message);
}
}
/**
* @inheritdoc
*/
public function attributeLabels(): array
{
return [
'name' => Yii::t('yii2mod.rbac', 'Name'),
'className' => Yii::t('yii2mod.rbac', 'Class Name'),
];
}
/**
* Check if record is new
*
* @return bool
*/
public function getIsNewRecord(): bool
{
return $this->_item === null;
}
/**
* Create object
*
* @param $id
*
* @return BizRuleModel|null
*/
public static function find(int $id)
{
$item = Yii::$app->authManager->getRule($id);
if ($item !== null) {
return new static($item);
}
return null;
}
/**
* Save rule
*
* @return bool
*/
public function save(): bool
{
if ($this->validate()) {
$class = $this->className;
if ($this->_item === null) {
$this->_item = new $class();
$isNew = true;
$oldName = false;
} else {
$isNew = false;
$oldName = $this->_item->name;
}
$this->_item->name = $this->name;
if ($isNew) {
$this->manager->add($this->_item);
} else {
$this->manager->update($oldName, $this->_item);
}
return true;
}
return false;
}
/**
* @return null|Rule
*/
public function getItem()
{
return $this->_item;
}
}

View File

@@ -0,0 +1,293 @@
<?php
namespace yii2mod\rbac\models;
use Yii;
use yii\base\BaseObject;
use yii\base\Controller;
use yii\base\Module;
use yii\caching\TagDependency;
use yii\helpers\VarDumper;
/**
* Class RouteModel
*
* @package yii2mod\rbac\models
*/
class RouteModel extends BaseObject
{
/**
* @var string cache tag
*/
const CACHE_TAG = 'yii2mod.rbac.route';
/**
* @var \yii\caching\Cache
*/
public $cache;
/**
* @var int cache duration
*/
public $cacheDuration = 3600;
/**
* @var array list of module IDs that will be excluded
*/
public $excludeModules = [];
/**
* @var \yii\rbac\ManagerInterface
*/
protected $manager;
/**
* RouteModel constructor.
*
* @param array $config
*/
public function __construct(array $config = [])
{
$this->cache = Yii::$app->cache;
$this->manager = Yii::$app->authManager;
parent::__construct($config);
}
/**
* Assign items
*
* @param array $routes
*
* @return bool
*/
public function addNew(array $routes): bool
{
foreach ($routes as $route) {
$this->manager->add($this->manager->createPermission('/' . trim($route, ' /')));
}
$this->invalidate();
return true;
}
/**
* Remove items
*
* @param array $routes
*
* @return bool
*/
public function remove(array $routes): bool
{
foreach ($routes as $route) {
$item = $this->manager->createPermission('/' . trim($route, '/'));
$this->manager->remove($item);
}
$this->invalidate();
return true;
}
/**
* Get available and assigned routes
*
* @return array
*/
public function getAvailableAndAssignedRoutes(): array
{
$routes = $this->getAppRoutes();
$exists = [];
foreach (array_keys($this->manager->getPermissions()) as $name) {
if ($name[0] !== '/') {
continue;
}
$exists[] = $name;
unset($routes[$name]);
}
return [
'available' => array_keys($routes),
'assigned' => $exists,
];
}
/**
* Get list of application routes
*
* @param null|string $module
*
* @return array
*/
public function getAppRoutes(string $module = null): array
{
if ($module === null) {
$module = Yii::$app;
} else {
$module = Yii::$app->getModule($module);
}
$key = [__METHOD__, $module->getUniqueId()];
$result = (($this->cache !== null) ? $this->cache->get($key) : false);
if ($result === false) {
$result = [];
$this->getRouteRecursive($module, $result);
if ($this->cache !== null) {
$this->cache->set($key, $result, $this->cacheDuration, new TagDependency([
'tags' => self::CACHE_TAG,
]));
}
}
return $result;
}
/**
* Invalidate the cache
*/
public function invalidate()
{
if ($this->cache !== null) {
TagDependency::invalidate($this->cache, self::CACHE_TAG);
}
}
/**
* Get route(s) recursive
*
* @param Module $module
* @param array $result
*/
protected function getRouteRecursive(Module $module, &$result)
{
if (!in_array($module->id, $this->excludeModules)) {
$token = "Get Route of '" . get_class($module) . "' with id '" . $module->uniqueId . "'";
Yii::beginProfile($token, __METHOD__);
try {
foreach ($module->getModules() as $id => $child) {
if (($child = $module->getModule($id)) !== null) {
$this->getRouteRecursive($child, $result);
}
}
foreach ($module->controllerMap as $id => $type) {
$this->getControllerActions($type, $id, $module, $result);
}
$namespace = trim($module->controllerNamespace, '\\') . '\\';
$this->getControllerFiles($module, $namespace, '', $result);
$all = '/' . ltrim($module->uniqueId . '/*', '/');
$result[$all] = $all;
} catch (\Exception $exc) {
Yii::error($exc->getMessage(), __METHOD__);
}
Yii::endProfile($token, __METHOD__);
}
}
/**
* Get list controllers under module
*
* @param Module $module
* @param string $namespace
* @param string $prefix
* @param mixed $result
*/
protected function getControllerFiles(Module $module, string $namespace, string $prefix, &$result)
{
$path = Yii::getAlias('@' . str_replace('\\', '/', $namespace), false);
$token = "Get controllers from '$path'";
Yii::beginProfile($token, __METHOD__);
try {
if (!is_dir($path)) {
return;
}
foreach (scandir($path) as $file) {
if ($file == '.' || $file == '..') {
continue;
}
if (is_dir($path . '/' . $file) && preg_match('%^[a-z0-9_/]+$%i', $file . '/')) {
$this->getControllerFiles($module, $namespace . $file . '\\', $prefix . $file . '/', $result);
} elseif (strcmp(substr($file, -14), 'Controller.php') === 0) {
$baseName = substr(basename($file), 0, -14);
$name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $baseName));
$id = ltrim(str_replace(' ', '-', $name), '-');
$className = $namespace . $baseName . 'Controller';
if (strpos($className, '-') === false && class_exists($className) && is_subclass_of($className, 'yii\base\Controller')) {
$this->getControllerActions($className, $prefix . $id, $module, $result);
}
}
}
} catch (\Exception $exc) {
Yii::error($exc->getMessage(), __METHOD__);
}
Yii::endProfile($token, __METHOD__);
}
/**
* Get list actions of controller
*
* @param mixed $type
* @param string $id
* @param Module $module
* @param mixed $result
*/
protected function getControllerActions($type, $id, Module $module, &$result)
{
$token = 'Create controller with config=' . VarDumper::dumpAsString($type) . " and id='$id'";
Yii::beginProfile($token, __METHOD__);
try {
/* @var $controller Controller */
$controller = Yii::createObject($type, [$id, $module]);
$this->getActionRoutes($controller, $result);
$all = "/{$controller->uniqueId}/*";
$result[$all] = $all;
} catch (\Exception $exc) {
Yii::error($exc->getMessage(), __METHOD__);
}
Yii::endProfile($token, __METHOD__);
}
/**
* Get route of action
*
* @param Controller $controller
* @param array $result all controller action
*/
protected function getActionRoutes(Controller $controller, &$result)
{
$token = "Get actions of controller '" . $controller->uniqueId . "'";
Yii::beginProfile($token, __METHOD__);
try {
$prefix = '/' . $controller->uniqueId . '/';
foreach ($controller->actions() as $id => $value) {
$result[$prefix . $id] = $prefix . $id;
}
$class = new \ReflectionClass($controller);
foreach ($class->getMethods() as $method) {
$name = $method->getName();
if ($method->isPublic() && !$method->isStatic() && strpos($name, 'action') === 0 && $name !== 'actions') {
$name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', substr($name, 6)));
$id = $prefix . ltrim(str_replace(' ', '-', $name), '-');
$result[$id] = $id;
}
}
} catch (\Exception $exc) {
Yii::error($exc->getMessage(), __METHOD__);
}
Yii::endProfile($token, __METHOD__);
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace yii2mod\rbac\models\search;
use yii\base\Model;
use yii\data\ActiveDataProvider;
/**
* Class AssignmentSearch
*
* @package yii2mod\rbac\models\search
*/
class AssignmentSearch extends Model
{
/**
* @var string user id
*/
public $id;
/**
* @var string username
*/
public $username;
/**
* @var int the default page size
*/
public $pageSize = 25;
/**
* @inheritdoc
*/
public function rules(): array
{
return [
[['id', 'username'], 'safe'],
];
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
* @param \yii\db\ActiveRecord $class
* @param $idField
* @param string $usernameField
*
* @return ActiveDataProvider
*/
public function search(array $params, $class, string $idField, string $usernameField): ActiveDataProvider
{
$query = $class::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => $this->pageSize,
],
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
$query->andFilterWhere([$idField => $this->id]);
$query->andFilterWhere(['like', $usernameField, $this->username]);
return $dataProvider;
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace yii2mod\rbac\models\search;
use dosamigos\arrayquery\ArrayQuery;
use Yii;
use yii\base\Model;
use yii\data\ArrayDataProvider;
use yii\rbac\Item;
/**
* Class AuthItemSearch
*
* @package yii2mod\rbac\models\search
*/
class AuthItemSearch extends Model
{
/**
* @var string auth item name
*/
public $name;
/**
* @var int auth item type
*/
public $type;
/**
* @var string auth item description
*/
public $description;
/**
* @var string auth item rule name
*/
public $ruleName;
/**
* @var int the default page size
*/
public $pageSize = 25;
/**
* @inheritdoc
*/
public function rules(): array
{
return [
[['name', 'ruleName', 'description'], 'trim'],
[['type'], 'integer'],
[['name', 'ruleName', 'description'], 'safe'],
];
}
/**
* @inheritdoc
*/
public function attributeLabels(): array
{
return [
'name' => Yii::t('yii2mod.rbac', 'Name'),
'type' => Yii::t('yii2mod.rbac', 'Type'),
'description' => Yii::t('yii2mod.rbac', 'Description'),
'rule' => Yii::t('yii2mod.rbac', 'Rule'),
'data' => Yii::t('yii2mod.rbac', 'Data'),
];
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return \yii\data\ArrayDataProvider
*/
public function search(array $params): ArrayDataProvider
{
$authManager = Yii::$app->getAuthManager();
if ($this->type == Item::TYPE_ROLE) {
$items = $authManager->getRoles();
} else {
$items = array_filter($authManager->getPermissions(), function ($item) {
return strpos($item->name, '/') !== 0;
});
}
$query = new ArrayQuery($items);
$this->load($params);
if ($this->validate()) {
$query->addCondition('name', $this->name ? "~{$this->name}" : null)
->addCondition('ruleName', $this->ruleName ? "~{$this->ruleName}" : null)
->addCondition('description', $this->description ? "~{$this->description}" : null);
}
return new ArrayDataProvider([
'allModels' => $query->find(),
'sort' => [
'attributes' => ['name'],
],
'pagination' => [
'pageSize' => $this->pageSize,
],
]);
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace yii2mod\rbac\models\search;
use dosamigos\arrayquery\ArrayQuery;
use Yii;
use yii\base\Model;
use yii\data\ArrayDataProvider;
/**
* Class BizRuleSearch
*
* @package yii2mod\rbac\models\search
*/
class BizRuleSearch extends Model
{
/**
* @var string name of the rule
*/
public $name;
/**
* @var int the default page size
*/
public $pageSize = 25;
/**
* @inheritdoc
*/
public function rules(): array
{
return [
['name', 'trim'],
['name', 'safe'],
];
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ArrayDataProvider
*/
public function search(array $params): ArrayDataProvider
{
$query = new ArrayQuery(Yii::$app->authManager->getRules());
if ($this->load($params) && $this->validate()) {
$query->addCondition('name', $this->name ? "~{$this->name}" : null);
}
return new ArrayDataProvider([
'allModels' => $query->find(),
'sort' => [
'attributes' => ['name'],
],
'pagination' => [
'pageSize' => $this->pageSize,
],
]);
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace yii2mod\rbac\rules;
use Yii;
use yii\rbac\Rule;
/**
* Class GuestRule
*
* @package yii2mod\rbac\rules
*/
class GuestRule extends Rule
{
/**
* @inheritdoc
*/
public $name = 'guestRule';
/**
* @param int|string $user
* @param \yii\rbac\Item $item
* @param array $params
*
* @return mixed
*/
public function execute($user, $item, $params)
{
return Yii::$app->user->isGuest;
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace yii2mod\rbac\rules;
use Yii;
use yii\rbac\Rule;
/**
* Class UserRule
*
* @package yii2mod\rbac\rules
*/
class UserRule extends Rule
{
/**
* @inheritdoc
*/
public $name = 'userRule';
/**
* @param int|string $user
* @param \yii\rbac\Item $item
* @param array $params
*
* @return mixed
*/
public function execute($user, $item, $params)
{
return !Yii::$app->user->isGuest;
}
}

View File

@@ -0,0 +1,42 @@
<?php
use yii\helpers\Html;
use yii\web\View;
/* @var $this yii\web\View */
/* @var $assignUrl array */
/* @var $removeUrl array */
/* @var $opts string */
$this->registerJs("var _opts = {$opts};", View::POS_BEGIN);
?>
<div class="row">
<div class="col-lg-5">
<input class="form-control search" data-target="available"
placeholder="<?php echo Yii::t('yii2mod.rbac', 'Search for available'); ?>">
<br/>
<select multiple size="20" class="form-control list" data-target="available"></select>
</div>
<div class="col-lg-2">
<div class="move-buttons">
<br><br>
<?php echo Html::a('&gt;&gt;', $assignUrl, [
'class' => 'btn btn-success btn-assign',
'data-target' => 'available',
'title' => Yii::t('yii2mod.rbac', 'Assign'),
]); ?>
<br/><br/>
<?php echo Html::a('&lt;&lt;', $removeUrl, [
'class' => 'btn btn-danger btn-assign',
'data-target' => 'assigned',
'title' => Yii::t('yii2mod.rbac', 'Remove'),
]); ?>
</div>
</div>
<div class="col-lg-5">
<input class="form-control search" data-target="assigned"
placeholder="<?php echo Yii::t('yii2mod.rbac', 'Search for assigned'); ?>">
<br/>
<select multiple size="20" class="form-control list" data-target="assigned"></select>
</div>
</div>

View File

@@ -0,0 +1,35 @@
<?php
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\widgets\Pjax;
/* @var $this \yii\web\View */
/* @var $gridViewColumns array */
/* @var $dataProvider \yii\data\ArrayDataProvider */
/* @var $searchModel \yii2mod\rbac\models\search\AssignmentSearch */
$this->title = Yii::t('yii2mod.rbac', 'Assignments');
$this->params['breadcrumbs'][] = $this->title;
$this->render('/layouts/_sidebar');
?>
<div class="assignment-index">
<h1><?php echo Html::encode($this->title); ?></h1>
<?php Pjax::begin(['timeout' => 5000]); ?>
<?php echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => ArrayHelper::merge($gridViewColumns, [
[
'class' => 'yii\grid\ActionColumn',
'template' => '{view}',
],
]),
]); ?>
<?php Pjax::end(); ?>
</div>

View File

@@ -0,0 +1,31 @@
<?php
use yii\helpers\Html;
use yii\helpers\Json;
use yii2mod\rbac\RbacAsset;
RbacAsset::register($this);
/* @var $this yii\web\View */
/* @var $model \yii2mod\rbac\models\AssignmentModel */
/* @var $usernameField string */
$userName = $model->user->{$usernameField};
$this->title = Yii::t('yii2mod.rbac', 'Assignment : {0}', $userName);
$this->params['breadcrumbs'][] = ['label' => Yii::t('yii2mod.rbac', 'Assignments'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $userName;
$this->render('/layouts/_sidebar');
?>
<div class="assignment-index">
<h1><?php echo Html::encode($this->title); ?></h1>
<?php echo $this->render('../_dualListBox', [
'opts' => Json::htmlEncode([
'items' => $model->getItems(),
]),
'assignUrl' => ['assign', 'id' => $model->userId],
'removeUrl' => ['remove', 'id' => $model->userId],
]); ?>
</div>

View File

@@ -0,0 +1,34 @@
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model yii2mod\rbac\models\AuthItemModel */
?>
<div class="auth-item-form">
<?php $form = ActiveForm::begin(); ?>
<?php echo $form->field($model, 'name')->textInput(['maxlength' => 64]); ?>
<?php echo $form->field($model, 'description')->textarea(['rows' => 2]); ?>
<?php echo $form->field($model, 'ruleName')->widget('yii\jui\AutoComplete', [
'options' => [
'class' => 'form-control',
],
'clientOptions' => [
'source' => array_keys(Yii::$app->authManager->getRules()),
],
]);
?>
<?php echo $form->field($model, 'data')->textarea(['rows' => 6]); ?>
<div class="form-group">
<?php echo Html::submitButton($model->getIsNewRecord() ? Yii::t('yii2mod.rbac', 'Create') : Yii::t('yii2mod.rbac', 'Update'), ['class' => $model->getIsNewRecord() ? 'btn btn-success' : 'btn btn-primary']); ?>
</div>
<?php ActiveForm::end(); ?>
</div>

View File

@@ -0,0 +1,19 @@
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model \yii2mod\rbac\models\AuthItemModel */
$labels = $this->context->getLabels();
$this->title = Yii::t('yii2mod.rbac', 'Create ' . $labels['Item']);
$this->params['breadcrumbs'][] = ['label' => Yii::t('yii2mod.rbac', $labels['Items']), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
$this->render('/layouts/_sidebar');
?>
<div class="auth-item-create">
<h1><?php echo Html::encode($this->title); ?></h1>
<?php echo $this->render('_form', [
'model' => $model,
]); ?>
</div>

View File

@@ -0,0 +1,52 @@
<?php
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\widgets\Pjax;
/* @var $this yii\web\View */
/* @var $dataProvider \yii\data\ArrayDataProvider */
/* @var $searchModel \yii2mod\rbac\models\search\AuthItemSearch */
$labels = $this->context->getLabels();
$this->title = Yii::t('yii2mod.rbac', $labels['Items']);
$this->params['breadcrumbs'][] = $this->title;
$this->render('/layouts/_sidebar');
?>
<div class="item-index">
<h1><?php echo Html::encode($this->title); ?></h1>
<p>
<?php echo Html::a(Yii::t('yii2mod.rbac', 'Create ' . $labels['Item']), ['create'], ['class' => 'btn btn-success']); ?>
</p>
<?php Pjax::begin(['timeout' => 5000, 'enablePushState' => false]); ?>
<?php echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'attribute' => 'name',
'label' => Yii::t('yii2mod.rbac', 'Name'),
],
[
'attribute' => 'ruleName',
'label' => Yii::t('yii2mod.rbac', 'Rule Name'),
'filter' => ArrayHelper::map(Yii::$app->getAuthManager()->getRules(), 'name', 'name'),
'filterInputOptions' => ['class' => 'form-control', 'prompt' => Yii::t('yii2mod.rbac', 'Select Rule')],
],
[
'attribute' => 'description',
'format' => 'ntext',
'label' => Yii::t('yii2mod.rbac', 'Description'),
],
[
'header' => Yii::t('yii2mod.rbac', 'Action'),
'class' => 'yii\grid\ActionColumn',
],
],
]); ?>
<?php Pjax::end(); ?>
</div>

View File

@@ -0,0 +1,21 @@
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model \yii2mod\rbac\models\AuthItemModel */
$context = $this->context;
$labels = $this->context->getLabels();
$this->title = Yii::t('yii2mod.rbac', 'Update ' . $labels['Item'] . ' : {0}', $model->name);
$this->params['breadcrumbs'][] = ['label' => Yii::t('yii2mod.rbac', $labels['Items']), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->name]];
$this->params['breadcrumbs'][] = Yii::t('yii2mod.rbac', 'Update');
$this->render('/layouts/_sidebar');
?>
<div class="auth-item-update">
<h1><?php echo Html::encode($this->title); ?></h1>
<?php echo $this->render('_form', [
'model' => $model,
]); ?>
</div>

View File

@@ -0,0 +1,50 @@
<?php
use yii\helpers\Html;
use yii\helpers\Json;
use yii\widgets\DetailView;
use yii2mod\rbac\RbacAsset;
RbacAsset::register($this);
/* @var $this yii\web\View */
/* @var $model \yii2mod\rbac\models\AuthItemModel */
$labels = $this->context->getLabels();
$this->title = Yii::t('yii2mod.rbac', $labels['Item'] . ' : {0}', $model->name);
$this->params['breadcrumbs'][] = ['label' => Yii::t('yii2mod.rbac', $labels['Items']), 'url' => ['index']];
$this->params['breadcrumbs'][] = $model->name;
$this->render('/layouts/_sidebar');
?>
<div class="auth-item-view">
<h1><?php echo Html::encode($this->title); ?></h1>
<p>
<?php echo Html::a(Yii::t('yii2mod.rbac', 'Update'), ['update', 'id' => $model->name], ['class' => 'btn btn-primary']); ?>
<?php echo Html::a(Yii::t('yii2mod.rbac', 'Delete'), ['delete', 'id' => $model->name], [
'class' => 'btn btn-danger',
'data-confirm' => Yii::t('yii2mod.rbac', 'Are you sure to delete this item?'),
'data-method' => 'post',
]); ?>
<?php echo Html::a(Yii::t('yii2mod.rbac', 'Create'), ['create'], ['class' => 'btn btn-success']); ?>
</p>
<div class="row">
<div class="col-sm-12">
<?php echo DetailView::widget([
'model' => $model,
'attributes' => [
'name',
'description:ntext',
'ruleName',
'data:ntext',
],
]); ?>
</div>
</div>
<?php echo $this->render('../_dualListBox', [
'opts' => Json::htmlEncode([
'items' => $model->getItems(),
]),
'assignUrl' => ['assign', 'id' => $model->name],
'removeUrl' => ['remove', 'id' => $model->name],
]); ?>
</div>

View File

@@ -0,0 +1,26 @@
<?php
/* @var $this \yii\web\View */
$this->params['sidebar'] = [
[
'label' => Yii::t('yii2mod.rbac', 'Assignments'),
'url' => ['assignment/index'],
],
[
'label' => Yii::t('yii2mod.rbac', 'Roles'),
'url' => ['role/index'],
],
[
'label' => Yii::t('yii2mod.rbac', 'Permissions'),
'url' => ['permission/index'],
],
[
'label' => Yii::t('yii2mod.rbac', 'Routes'),
'url' => ['route/index'],
],
[
'label' => Yii::t('yii2mod.rbac', 'Rules'),
'url' => ['rule/index'],
],
];

View File

@@ -0,0 +1,23 @@
<?php
/**
* @var string the new migration class name
*/
echo "<?php\n";
?>
use yii2mod\rbac\migrations\Migration;
class <?= $className; ?> extends Migration
{
public function safeUp()
{
}
public function safeDown()
{
echo "<?= $className; ?> cannot be reverted.\n";
return false;
}
}

View File

@@ -0,0 +1,27 @@
<?php
use yii\helpers\Html;
use yii\helpers\Json;
use yii2mod\rbac\RbacRouteAsset;
RbacRouteAsset::register($this);
/* @var $this yii\web\View */
/* @var $routes array */
$this->title = Yii::t('yii2mod.rbac', 'Routes');
$this->params['breadcrumbs'][] = $this->title;
$this->render('/layouts/_sidebar');
?>
<h1><?php echo Html::encode($this->title); ?></h1>
<?php echo Html::a(Yii::t('yii2mod.rbac', 'Refresh'), ['refresh'], [
'class' => 'btn btn-primary',
'id' => 'btn-refresh',
]); ?>
<?php echo $this->render('../_dualListBox', [
'opts' => Json::htmlEncode([
'items' => $routes,
]),
'assignUrl' => ['assign'],
'removeUrl' => ['remove'],
]); ?>

View File

@@ -0,0 +1,29 @@
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model \yii2mod\rbac\models\BizRuleModel */
/* @var $form ActiveForm */
?>
<div class="rule-item-form">
<?php $form = ActiveForm::begin(); ?>
<?php echo $form->field($model, 'name')->textInput(['maxlength' => 64]); ?>
<?php echo $form->field($model, 'className')->textInput(); ?>
<div class="form-group">
<?php echo Html::submitButton(
$model->getIsNewRecord() ? Yii::t('yii2mod.rbac', 'Create') : Yii::t('yii2mod.rbac', 'Update'),
[
'class' => $model->getIsNewRecord() ? 'btn btn-success' : 'btn btn-primary',
]
); ?>
</div>
<?php ActiveForm::end(); ?>
</div>

View File

@@ -0,0 +1,21 @@
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model \yii2mod\rbac\models\BizRuleModel */
$this->title = Yii::t('yii2mod.rbac', 'Create Rule');
$this->params['breadcrumbs'][] = ['label' => Yii::t('yii2mod.rbac', 'Rules'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
$this->render('/layouts/_sidebar');
?>
<div class="rule-item-create">
<h1><?php echo Html::encode($this->title); ?></h1>
<?php echo $this->render('_form', [
'model' => $model,
]); ?>
</div>

View File

@@ -0,0 +1,43 @@
<?php
use yii\grid\GridView;
use yii\helpers\Html;
use yii\widgets\Pjax;
/* @var $this yii\web\View */
/* @var $dataProvider \yii\data\ArrayDataProvider */
/* @var $searchModel yii2mod\rbac\models\search\BizRuleSearch */
$this->title = Yii::t('yii2mod.rbac', 'Rules');
$this->params['breadcrumbs'][] = $this->title;
$this->render('/layouts/_sidebar');
?>
<div class="role-index">
<h1><?php echo Html::encode($this->title); ?></h1>
<p>
<?php echo Html::a(Yii::t('yii2mod.rbac', 'Create Rule'), ['create'], ['class' => 'btn btn-success']); ?>
</p>
<?php Pjax::begin(['timeout' => 5000]); ?>
<?php echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'attribute' => 'name',
'label' => Yii::t('yii2mod.rbac', 'Name'),
],
[
'header' => Yii::t('yii2mod.rbac', 'Action'),
'class' => 'yii\grid\ActionColumn',
],
],
]);
?>
<?php Pjax::end(); ?>
</div>

View File

@@ -0,0 +1,21 @@
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model \yii2mod\rbac\models\BizRuleModel */
$this->title = Yii::t('yii2mod.rbac', 'Update Rule : {0}', $model->name);
$this->params['breadcrumbs'][] = ['label' => Yii::t('yii2mod.rbac', 'Rules'), 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->name]];
$this->params['breadcrumbs'][] = Yii::t('yii2mod.rbac', 'Update');
$this->render('/layouts/_sidebar');
?>
<div class="rule-item-update">
<h1><?php echo Html::encode($this->title); ?></h1>
<?php echo $this->render('_form', [
'model' => $model,
]); ?>
</div>

View File

@@ -0,0 +1,35 @@
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
/* @var $this yii\web\View */
/* @var $model \yii2mod\rbac\models\BizRuleModel */
$this->title = Yii::t('yii2mod.rbac', 'Rule : {0}', $model->name);
$this->params['breadcrumbs'][] = ['label' => Yii::t('yii2mod.rbac', 'Rules'), 'url' => ['index']];
$this->params['breadcrumbs'][] = $model->name;
$this->render('/layouts/_sidebar');
?>
<div class="rule-item-view">
<h1><?php echo Html::encode($this->title); ?></h1>
<p>
<?php echo Html::a(Yii::t('yii2mod.rbac', 'Update'), ['update', 'id' => $model->name], ['class' => 'btn btn-primary']); ?>
<?php echo Html::a(Yii::t('yii2mod.rbac', 'Delete'), ['delete', 'id' => $model->name], [
'class' => 'btn btn-danger',
'data-confirm' => Yii::t('yii2mod.rbac', 'Are you sure to delete this item?'),
'data-method' => 'post',
]); ?>
</p>
<?php echo DetailView::widget([
'model' => $model,
'attributes' => [
'name',
'className',
],
]); ?>
</div>