Initial commit,修正
This commit is contained in:
+137
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace mdm\admin\components;
|
||||
|
||||
use yii\web\ForbiddenHttpException;
|
||||
use yii\base\Module;
|
||||
use Yii;
|
||||
use yii\web\User;
|
||||
use yii\di\Instance;
|
||||
|
||||
/**
|
||||
* Access Control Filter (ACF) is a simple authorization method that is best used by applications that only need some simple access control.
|
||||
* As its name indicates, ACF is an action filter that can be attached to a controller or a module as a behavior.
|
||||
* ACF will check a set of access rules to make sure the current user can access the requested action.
|
||||
*
|
||||
* To use AccessControl, declare it in the application config as behavior.
|
||||
* For example.
|
||||
*
|
||||
* ```
|
||||
* 'as access' => [
|
||||
* 'class' => 'mdm\admin\components\AccessControl',
|
||||
* 'allowActions' => ['site/login', 'site/error']
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @property User $user
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 1.0
|
||||
*/
|
||||
class AccessControl extends \yii\base\ActionFilter
|
||||
{
|
||||
/**
|
||||
* @var User User for check access.
|
||||
*/
|
||||
private $_user = 'user';
|
||||
/**
|
||||
* @var array List of action that not need to check access.
|
||||
*/
|
||||
public $allowActions = [];
|
||||
|
||||
/**
|
||||
* Get user
|
||||
* @return User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
if (!$this->_user instanceof User) {
|
||||
$this->_user = Instance::ensure($this->_user, User::className());
|
||||
}
|
||||
return $this->_user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user
|
||||
* @param User|string $user
|
||||
*/
|
||||
public function setUser($user)
|
||||
{
|
||||
$this->_user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function beforeAction($action)
|
||||
{
|
||||
$actionId = $action->getUniqueId();
|
||||
$user = $this->getUser();
|
||||
if (Helper::checkRoute('/' . $actionId, Yii::$app->getRequest()->get(), $user)) {
|
||||
return true;
|
||||
}
|
||||
$this->denyAccess($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Denies the access of the user.
|
||||
* The default implementation will redirect the user to the login page if he is a guest;
|
||||
* if the user is already logged, a 403 HTTP exception will be thrown.
|
||||
* @param User $user the current user
|
||||
* @throws ForbiddenHttpException if the user is already logged in.
|
||||
*/
|
||||
protected function denyAccess($user)
|
||||
{
|
||||
if ($user->getIsGuest()) {
|
||||
$user->loginRequired();
|
||||
} else {
|
||||
throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isActive($action)
|
||||
{
|
||||
$uniqueId = $action->getUniqueId();
|
||||
if ($uniqueId === Yii::$app->getErrorHandler()->errorAction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = $this->getUser();
|
||||
if ($user->getIsGuest() && is_array($user->loginUrl) && isset($user->loginUrl[0]) && $uniqueId === trim($user->loginUrl[0], '/')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->owner instanceof Module) {
|
||||
// convert action uniqueId into an ID relative to the module
|
||||
$mid = $this->owner->getUniqueId();
|
||||
$id = $uniqueId;
|
||||
if ($mid !== '' && strpos($id, $mid . '/') === 0) {
|
||||
$id = substr($id, strlen($mid) + 1);
|
||||
}
|
||||
} else {
|
||||
$id = $action->id;
|
||||
}
|
||||
|
||||
foreach ($this->allowActions as $route) {
|
||||
if (substr($route, -1) === '*') {
|
||||
$route = rtrim($route, "*");
|
||||
if ($route === '' || strpos($id, $route) === 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ($id === $route) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($action->controller->hasMethod('allowAction') && in_array($action->id, $action->controller->allowAction())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
namespace mdm\admin\components;
|
||||
|
||||
use Yii;
|
||||
use yii\db\Connection;
|
||||
use yii\caching\Cache;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\di\Instance;
|
||||
|
||||
/**
|
||||
* Configs
|
||||
* Used for configure some value. To set config you can use [[\yii\base\Application::$params]]
|
||||
*
|
||||
* ```
|
||||
* return [
|
||||
*
|
||||
* 'mdm.admin.configs' => [
|
||||
* 'db' => 'customDb',
|
||||
* 'menuTable' => '{{%admin_menu}}',
|
||||
* 'cache' => [
|
||||
* 'class' => 'yii\caching\DbCache',
|
||||
* 'db' => ['dsn' => 'sqlite:@runtime/admin-cache.db'],
|
||||
* ],
|
||||
* ]
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* or use [[\Yii::$container]]
|
||||
*
|
||||
* ```
|
||||
* Yii::$container->set('mdm\admin\components\Configs',[
|
||||
* 'db' => 'customDb',
|
||||
* 'menuTable' => 'admin_menu',
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 1.0
|
||||
*/
|
||||
// class Configs extends \yii\base\Object //更新使用7.2以上版本PHP后,不再可使用Object类 By fm453
|
||||
class Configs extends \yii\base\BaseObject
|
||||
{
|
||||
const CACHE_TAG = 'mdm.admin';
|
||||
|
||||
/**
|
||||
* @var Connection Database connection.
|
||||
*/
|
||||
public $db = 'db';
|
||||
/**
|
||||
* @var Cache Cache component.
|
||||
*/
|
||||
public $cache = 'cache';
|
||||
/**
|
||||
* @var integer Cache duration. Default to a hour.
|
||||
*/
|
||||
public $cacheDuration = 3600;
|
||||
/**
|
||||
* @var string Menu table name.
|
||||
*/
|
||||
public $menuTable = '{{%c_menu}}';
|
||||
/**
|
||||
* @var string Menu table name.
|
||||
*/
|
||||
//public $userTable = '{{%user}}';
|
||||
public $userTable = '{{%c_adminer}}';
|
||||
/**
|
||||
* @var integer Default status user signup. 10 mean active.
|
||||
*/
|
||||
public $defaultUserStatus = 10;
|
||||
/**
|
||||
* @var boolean If true then AccessControl only check if route are registered.
|
||||
*/
|
||||
public $onlyRegisteredRoute = false;
|
||||
/**
|
||||
* @var boolean If false then AccessControl will check without Rule.
|
||||
*/
|
||||
public $strict = true;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $options;
|
||||
/**
|
||||
* @var self Instance of self
|
||||
*/
|
||||
private static $_instance;
|
||||
private static $_classes = [
|
||||
'db' => 'yii\db\Connection',
|
||||
'cache' => 'yii\caching\Cache',
|
||||
];
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
foreach (self::$_classes as $key => $class) {
|
||||
try {
|
||||
$this->{$key} = empty($this->{$key}) ? null : Instance::ensure($this->{$key}, $class);
|
||||
} catch (\Exception $exc) {
|
||||
$this->{$key} = null;
|
||||
Yii::error($exc->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create instance of self
|
||||
* @return static
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if (self::$_instance === null) {
|
||||
$type = ArrayHelper::getValue(Yii::$app->params, 'mdm.admin.configs', []);
|
||||
if (is_array($type) && !isset($type['class'])) {
|
||||
$type['class'] = static::className();
|
||||
}
|
||||
|
||||
return self::$_instance = Yii::createObject($type);
|
||||
}
|
||||
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
public static function __callStatic($name, $arguments)
|
||||
{
|
||||
$instance = static::instance();
|
||||
if ($instance->hasProperty($name)) {
|
||||
return $instance->$name;
|
||||
} else {
|
||||
if (count($arguments)) {
|
||||
$instance->options[$name] = reset($arguments);
|
||||
} else {
|
||||
return array_key_exists($name, $instance->options) ? $instance->options[$name] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Connection
|
||||
*/
|
||||
public static function db()
|
||||
{
|
||||
return static::instance()->db;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Cache
|
||||
*/
|
||||
public static function cache()
|
||||
{
|
||||
return static::instance()->cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public static function cacheDuration()
|
||||
{
|
||||
return static::instance()->cacheDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function menuTable()
|
||||
{
|
||||
return static::instance()->menuTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function userTable()
|
||||
{
|
||||
return static::instance()->userTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function defaultUserStatus()
|
||||
{
|
||||
return static::instance()->defaultUserStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public static function onlyRegisteredRoute()
|
||||
{
|
||||
return static::instance()->onlyRegisteredRoute;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public static function strict()
|
||||
{
|
||||
return static::instance()->strict;
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace mdm\admin\components;
|
||||
|
||||
/**
|
||||
* DbManager represents an authorization manager that stores authorization information in database.
|
||||
*
|
||||
* The database connection is specified by [[$db]]. The database schema could be initialized by applying migration:
|
||||
*
|
||||
* ```
|
||||
* yii migrate --migrationPath=@yii/rbac/migrations/
|
||||
* ```
|
||||
*
|
||||
* If you don't want to use migration and need SQL instead, files for all databases are in migrations directory.
|
||||
*
|
||||
* You may change the names of the three tables used to store the authorization data by setting [[\yii\rbac\DbManager::$itemTable]],
|
||||
* [[\yii\rbac\DbManager::$itemChildTable]] and [[\yii\rbac\DbManager::$assignmentTable]].
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 1.0
|
||||
*/
|
||||
class DbManager extends \yii\rbac\DbManager
|
||||
{
|
||||
/**
|
||||
* Memory cache of assignments
|
||||
* @var array
|
||||
*/
|
||||
private $_assignments = [];
|
||||
private $_childrenList;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getAssignments($userId)
|
||||
{
|
||||
if (!isset($this->_assignments[$userId])) {
|
||||
$this->_assignments[$userId] = parent::getAssignments($userId);
|
||||
}
|
||||
return $this->_assignments[$userId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getChildrenList()
|
||||
{
|
||||
if ($this->_childrenList === null) {
|
||||
$this->_childrenList = parent::getChildrenList();
|
||||
}
|
||||
return $this->_childrenList;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace mdm\admin\components;
|
||||
|
||||
use yii\rbac\Rule;
|
||||
|
||||
/**
|
||||
* Description of GuestRule
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 2.5
|
||||
*/
|
||||
class GuestRule extends Rule
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $name = 'guest_rule';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function execute($user, $item, $params)
|
||||
{
|
||||
return $user->getIsGuest();
|
||||
}
|
||||
}
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
namespace mdm\admin\components;
|
||||
|
||||
use Yii;
|
||||
use yii\web\User;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\caching\TagDependency;
|
||||
|
||||
/**
|
||||
* Description of Helper
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 2.3
|
||||
*/
|
||||
class Helper
|
||||
{
|
||||
private static $_userRoutes = [];
|
||||
private static $_defaultRoutes;
|
||||
private static $_routes;
|
||||
|
||||
public static function getRegisteredRoutes()
|
||||
{
|
||||
if (self::$_routes === null) {
|
||||
self::$_routes = [];
|
||||
$manager = Yii::$app->getAuthManager();
|
||||
foreach ($manager->getPermissions() as $item) {
|
||||
if ($item->name[0] === '/') {
|
||||
self::$_routes[$item->name] = $item->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self::$_routes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assigned routes by default roles
|
||||
* @return array
|
||||
*/
|
||||
protected static function getDefaultRoutes()
|
||||
{
|
||||
if (self::$_defaultRoutes === null) {
|
||||
$manager = Yii::$app->getAuthManager();
|
||||
$roles = $manager->defaultRoles;
|
||||
$cache = Configs::cache();
|
||||
if ($cache && ($routes = $cache->get($roles)) !== false) {
|
||||
self::$_defaultRoutes = $routes;
|
||||
} else {
|
||||
$permissions = self::$_defaultRoutes = [];
|
||||
foreach ($roles as $role) {
|
||||
$permissions = array_merge($permissions, $manager->getPermissionsByRole($role));
|
||||
}
|
||||
foreach ($permissions as $item) {
|
||||
if ($item->name[0] === '/') {
|
||||
self::$_defaultRoutes[$item->name] = true;
|
||||
}
|
||||
}
|
||||
if ($cache) {
|
||||
$cache->set($roles, self::$_defaultRoutes, Configs::cacheDuration(), new TagDependency([
|
||||
'tags' => Configs::CACHE_TAG
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return self::$_defaultRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assigned routes of user.
|
||||
* @param integer $userId
|
||||
* @return array
|
||||
*/
|
||||
public static function getRoutesByUser($userId)
|
||||
{
|
||||
if (!isset(self::$_userRoutes[$userId])) {
|
||||
$cache = Configs::cache();
|
||||
if ($cache && ($routes = $cache->get([__METHOD__, $userId])) !== false) {
|
||||
self::$_userRoutes[$userId] = $routes;
|
||||
} else {
|
||||
$routes = static::getDefaultRoutes();
|
||||
$manager = Yii::$app->getAuthManager();
|
||||
foreach ($manager->getPermissionsByUser($userId) as $item) {
|
||||
if ($item->name[0] === '/') {
|
||||
$routes[$item->name] = true;
|
||||
}
|
||||
}
|
||||
self::$_userRoutes[$userId] = $routes;
|
||||
if ($cache) {
|
||||
$cache->set([__METHOD__, $userId], $routes, Configs::cacheDuration(), new TagDependency([
|
||||
'tags' => Configs::CACHE_TAG
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return self::$_userRoutes[$userId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check access route for user.
|
||||
* @param string|array $route
|
||||
* @param integer|User $user
|
||||
* @return boolean
|
||||
*/
|
||||
public static function checkRoute($route, $params = [], $user = null)
|
||||
{
|
||||
$config = Configs::instance();
|
||||
$r = static::normalizeRoute($route);
|
||||
if ($config->onlyRegisteredRoute && !isset(static::getRegisteredRoutes()[$r])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($user === null) {
|
||||
$user = Yii::$app->getUser();
|
||||
}
|
||||
$userId = $user instanceof User ? $user->getId() : $user;
|
||||
|
||||
if ($config->strict) {
|
||||
if ($user->can($r, $params)) {
|
||||
return true;
|
||||
}
|
||||
while (($pos = strrpos($r, '/')) > 0) {
|
||||
$r = substr($r, 0, $pos);
|
||||
if ($user->can($r . '/*', $params)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $user->can('/*', $params);
|
||||
} else {
|
||||
$routes = static::getRoutesByUser($userId);
|
||||
if (isset($routes[$r])) {
|
||||
return true;
|
||||
}
|
||||
while (($pos = strrpos($r, '/')) > 0) {
|
||||
$r = substr($r, 0, $pos);
|
||||
if (isset($routes[$r . '/*'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return isset($routes['/*']);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function normalizeRoute($route)
|
||||
{
|
||||
if ($route === '') {
|
||||
return '/' . Yii::$app->controller->getRoute();
|
||||
} elseif (strncmp($route, '/', 1) === 0) {
|
||||
return $route;
|
||||
} elseif (strpos($route, '/') === false) {
|
||||
return '/' . Yii::$app->controller->getUniqueId() . '/' . $route;
|
||||
} elseif (($mid = Yii::$app->controller->module->getUniqueId()) !== '') {
|
||||
return '/' . $mid . '/' . $route;
|
||||
}
|
||||
return '/' . $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter menu items
|
||||
* @param array $items
|
||||
* @param integer|User $user
|
||||
*/
|
||||
public static function filter($items, $user = null)
|
||||
{
|
||||
if ($user === null) {
|
||||
$user = Yii::$app->getUser();
|
||||
}
|
||||
return static::filterRecursive($items, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter menu recursive
|
||||
* @param array $items
|
||||
* @param integer|User $user
|
||||
* @return array
|
||||
*/
|
||||
protected static function filterRecursive($items, $user)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($items as $i => $item) {
|
||||
$url = ArrayHelper::getValue($item, 'url', '#');
|
||||
$allow = is_array($url) ? static::checkRoute($url[0], array_slice($url, 1), $user) : true;
|
||||
|
||||
if (isset($item['items']) && is_array($item['items'])) {
|
||||
$subItems = self::filterRecursive($item['items'], $user);
|
||||
if (count($subItems)) {
|
||||
$allow = true;
|
||||
}
|
||||
$item['items'] = $subItems;
|
||||
}
|
||||
if ($allow) {
|
||||
$result[$i] = $item;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter action column button. Use with [[yii\grid\GridView]]
|
||||
* ```php
|
||||
* 'columns' => [
|
||||
* ...
|
||||
* [
|
||||
* 'class' => 'yii\grid\ActionColumn',
|
||||
* 'template' => Helper::filterActionColumn(['view','update','activate'])
|
||||
* ]
|
||||
* ],
|
||||
* ```
|
||||
* @param array|string $buttons
|
||||
* @param integer|User $user
|
||||
* @return string
|
||||
*/
|
||||
public static function filterActionColumn($buttons = [], $user = null)
|
||||
{
|
||||
if (is_array($buttons)) {
|
||||
$result = [];
|
||||
foreach ($buttons as $button) {
|
||||
if (static::checkRoute($button, [], $user)) {
|
||||
$result[] = "{{$button}}";
|
||||
}
|
||||
}
|
||||
return implode(' ', $result);
|
||||
}
|
||||
return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($user) {
|
||||
return static::checkRoute($matches[1], [], $user) ? "{{$matches[1]}}" : '';
|
||||
}, $buttons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to invalidate cache.
|
||||
*/
|
||||
public static function invalidate()
|
||||
{
|
||||
if (Configs::cache() !== null) {
|
||||
TagDependency::invalidate(Configs::cache(), Configs::CACHE_TAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace mdm\admin\components;
|
||||
|
||||
use Yii;
|
||||
use mdm\admin\models\AuthItem;
|
||||
use mdm\admin\models\searchs\AuthItem as AuthItemSearch;
|
||||
use yii\web\Controller;
|
||||
use yii\web\NotFoundHttpException;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\filters\VerbFilter;
|
||||
use yii\rbac\Item;
|
||||
|
||||
/**
|
||||
* AuthItemController implements the CRUD actions for AuthItem model.
|
||||
*
|
||||
* @property integer $type
|
||||
* @property array $labels
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 1.0
|
||||
*/
|
||||
class ItemController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::className(),
|
||||
'actions' => [
|
||||
'delete' => ['post'],
|
||||
'assign' => ['post'],
|
||||
'remove' => ['post'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all AuthItem models.
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionIndex()
|
||||
{
|
||||
$searchModel = new AuthItemSearch(['type' => $this->type]);
|
||||
$dataProvider = $searchModel->search(Yii::$app->request->getQueryParams());
|
||||
|
||||
return $this->render('index', [
|
||||
'dataProvider' => $dataProvider,
|
||||
'searchModel' => $searchModel,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a single AuthItem model.
|
||||
* @param string $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionView($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 AuthItem(null);
|
||||
$model->type = $this->type;
|
||||
if ($model->load(Yii::$app->getRequest()->post()) && $model->save()) {
|
||||
return $this->redirect(['view', 'id' => $model->name]);
|
||||
} else {
|
||||
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($id)
|
||||
{
|
||||
$model = $this->findModel($id);
|
||||
if ($model->load(Yii::$app->getRequest()->post()) && $model->save()) {
|
||||
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($id)
|
||||
{
|
||||
$model = $this->findModel($id);
|
||||
Yii::$app->getAuthManager()->remove($model->item);
|
||||
Helper::invalidate();
|
||||
|
||||
return $this->redirect(['index']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign items
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
public function actionAssign($id)
|
||||
{
|
||||
$items = Yii::$app->getRequest()->post('items', []);
|
||||
$model = $this->findModel($id);
|
||||
$success = $model->addChildren($items);
|
||||
Yii::$app->getResponse()->format = 'json';
|
||||
|
||||
return array_merge($model->getItems(), ['success' => $success]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign or remove items
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
public function actionRemove($id)
|
||||
{
|
||||
$items = Yii::$app->getRequest()->post('items', []);
|
||||
$model = $this->findModel($id);
|
||||
$success = $model->removeChildren($items);
|
||||
Yii::$app->getResponse()->format = 'json';
|
||||
|
||||
return array_merge($model->getItems(), ['success' => $success]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getViewPath()
|
||||
{
|
||||
return $this->module->getViewPath() . DIRECTORY_SEPARATOR . 'item';
|
||||
}
|
||||
|
||||
/**
|
||||
* Label use in view
|
||||
* @throws NotSupportedException
|
||||
*/
|
||||
public function labels()
|
||||
{
|
||||
throw new NotSupportedException(get_class($this) . ' does not support labels().');
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of Auth Item.
|
||||
* @return integer
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 AuthItem the loaded model
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
protected function findModel($id)
|
||||
{
|
||||
$auth = Yii::$app->getAuthManager();
|
||||
$item = $this->type === Item::TYPE_ROLE ? $auth->getRole($id) : $auth->getPermission($id);
|
||||
if ($item) {
|
||||
return new AuthItem($item);
|
||||
} else {
|
||||
throw new NotFoundHttpException('The requested page does not exist.');
|
||||
}
|
||||
}
|
||||
}
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
namespace mdm\admin\components;
|
||||
|
||||
use Yii;
|
||||
use yii\caching\TagDependency;
|
||||
use mdm\admin\models\Menu;
|
||||
|
||||
/**
|
||||
* MenuHelper used to generate menu depend of user role.
|
||||
* Usage
|
||||
*
|
||||
* ```
|
||||
* use mdm\admin\components\MenuHelper;
|
||||
* use yii\bootstrap\Nav;
|
||||
*
|
||||
* echo Nav::widget([
|
||||
* 'items' => MenuHelper::getAssignedMenu(Yii::$app->user->id)
|
||||
* ]);
|
||||
* ```
|
||||
*
|
||||
* To reformat returned, provide callback to method.
|
||||
*
|
||||
* ```
|
||||
* $callback = function ($menu) {
|
||||
* $data = eval($menu['data']);
|
||||
* return [
|
||||
* 'label' => $menu['name'],
|
||||
* 'url' => [$menu['route']],
|
||||
* 'options' => $data,
|
||||
* 'items' => $menu['children']
|
||||
* ]
|
||||
* ]
|
||||
* }
|
||||
*
|
||||
* $items = MenuHelper::getAssignedMenu(Yii::$app->user->id, null, $callback);
|
||||
* ```
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 1.0
|
||||
*/
|
||||
class MenuHelper
|
||||
{
|
||||
/**
|
||||
* Use to get assigned menu of user.
|
||||
* @param mixed $userId
|
||||
* @param integer $root
|
||||
* @param \Closure $callback use to reformat output.
|
||||
* callback should have format like
|
||||
*
|
||||
* ```
|
||||
* function ($menu) {
|
||||
* return [
|
||||
* 'label' => $menu['name'],
|
||||
* 'url' => [$menu['route']],
|
||||
* 'options' => $data,
|
||||
* 'items' => $menu['children']
|
||||
* ]
|
||||
* ]
|
||||
* }
|
||||
* ```
|
||||
* @param boolean $refresh
|
||||
* @return array
|
||||
*/
|
||||
public static function getAssignedMenu($userId, $root = null, $callback = null, $refresh = false)
|
||||
{
|
||||
$config = Configs::instance();
|
||||
|
||||
/* @var $manager \yii\rbac\BaseManager */
|
||||
$manager = Yii::$app->getAuthManager();
|
||||
$menus = Menu::find()->asArray()->indexBy('id')->all();
|
||||
$key = [__METHOD__, $userId, $manager->defaultRoles];
|
||||
$cache = $config->cache;
|
||||
|
||||
if ($refresh || $cache === null || ($assigned = $cache->get($key)) === false) {
|
||||
$routes = $filter1 = $filter2 = [];
|
||||
if ($userId !== null) {
|
||||
foreach ($manager->getPermissionsByUser($userId) as $name => $value) {
|
||||
if ($name[0] === '/') {
|
||||
if (substr($name, -2) === '/*') {
|
||||
$name = substr($name, 0, -1);
|
||||
}
|
||||
$routes[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($manager->defaultRoles as $role) {
|
||||
foreach ($manager->getPermissionsByRole($role) as $name => $value) {
|
||||
if ($name[0] === '/') {
|
||||
if (substr($name, -2) === '/*') {
|
||||
$name = substr($name, 0, -1);
|
||||
}
|
||||
$routes[] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
$routes = array_unique($routes);
|
||||
sort($routes);
|
||||
$prefix = '\\';
|
||||
foreach ($routes as $route) {
|
||||
if (strpos($route, $prefix) !== 0) {
|
||||
if (substr($route, -1) === '/') {
|
||||
$prefix = $route;
|
||||
$filter1[] = $route . '%';
|
||||
} else {
|
||||
$filter2[] = $route;
|
||||
}
|
||||
}
|
||||
}
|
||||
$assigned = [];
|
||||
$query = Menu::find()->select(['id'])->asArray();
|
||||
if (count($filter2)) {
|
||||
$assigned = $query->where(['route' => $filter2])->column();
|
||||
}
|
||||
if (count($filter1)) {
|
||||
$query->where('route like :filter');
|
||||
foreach ($filter1 as $filter) {
|
||||
$assigned = array_merge($assigned, $query->params([':filter' => $filter])->column());
|
||||
}
|
||||
}
|
||||
$assigned = static::requiredParent($assigned, $menus);
|
||||
if ($cache !== null) {
|
||||
$cache->set($key, $assigned, $config->cacheDuration, new TagDependency([
|
||||
'tags' => Configs::CACHE_TAG
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
$key = [__METHOD__, $assigned, $root];
|
||||
if ($refresh || $callback !== null || $cache === null || (($result = $cache->get($key)) === false)) {
|
||||
$result = static::normalizeMenu($assigned, $menus, $callback, $root);
|
||||
if ($cache !== null && $callback === null) {
|
||||
$cache->set($key, $result, $config->cacheDuration, new TagDependency([
|
||||
'tags' => Configs::CACHE_TAG
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure all item menu has parent.
|
||||
* @param array $assigned
|
||||
* @param array $menus
|
||||
* @return array
|
||||
*/
|
||||
private static function requiredParent($assigned, &$menus)
|
||||
{
|
||||
$l = count($assigned);
|
||||
for ($i = 0; $i < $l; $i++) {
|
||||
$id = $assigned[$i];
|
||||
$parent_id = $menus[$id]['parent'];
|
||||
if ($parent_id !== null && !in_array($parent_id, $assigned)) {
|
||||
$assigned[$l++] = $parent_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $assigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse route
|
||||
* @param string $route
|
||||
* @return mixed
|
||||
*/
|
||||
public static function parseRoute($route)
|
||||
{
|
||||
if (!empty($route)) {
|
||||
$url = [];
|
||||
$r = explode('&', $route);
|
||||
$url[0] = $r[0];
|
||||
unset($r[0]);
|
||||
foreach ($r as $part) {
|
||||
$part = explode('=', $part);
|
||||
$url[$part[0]] = isset($part[1]) ? $part[1] : '';
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
return '#';
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize menu
|
||||
* @param array $assigned
|
||||
* @param array $menus
|
||||
* @param Closure $callback
|
||||
* @param integer $parent
|
||||
* @return array
|
||||
*/
|
||||
private static function normalizeMenu(&$assigned, &$menus, $callback, $parent = null)
|
||||
{
|
||||
$result = [];
|
||||
$order = [];
|
||||
foreach ($assigned as $id) {
|
||||
$menu = $menus[$id];
|
||||
if ($menu['parent'] == $parent) {
|
||||
$menu['children'] = static::normalizeMenu($assigned, $menus, $callback, $id);
|
||||
if ($callback !== null) {
|
||||
$item = call_user_func($callback, $menu);
|
||||
} else {
|
||||
$item = [
|
||||
'label' => $menu['name'],
|
||||
'url' => static::parseRoute($menu['route']),
|
||||
];
|
||||
if ($menu['children'] != []) {
|
||||
$item['items'] = $menu['children'];
|
||||
}
|
||||
}
|
||||
$result[] = $item;
|
||||
$order[] = $menu['order'];
|
||||
}
|
||||
}
|
||||
if ($result != []) {
|
||||
array_multisort($order, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace mdm\admin\components;
|
||||
|
||||
use Yii;
|
||||
use yii\rbac\Rule;
|
||||
|
||||
/**
|
||||
* RouteRule Rule for check route with extra params.
|
||||
*
|
||||
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
|
||||
* @since 1.0
|
||||
*/
|
||||
class RouteRule extends Rule
|
||||
{
|
||||
const RULE_NAME = 'route_rule';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $name = self::RULE_NAME;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function execute($user, $item, $params)
|
||||
{
|
||||
$routeParams = isset($item->data['params']) ? $item->data['params'] : [];
|
||||
foreach ($routeParams as $key => $value) {
|
||||
if (!array_key_exists($key, $params) || $params[$key] != $value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user