diff --git a/src/Module.php b/src/Module.php index af39541..89d5a6d 100644 --- a/src/Module.php +++ b/src/Module.php @@ -28,6 +28,8 @@ class Module extends \yii\base\Module */ public $modulesDashboardBlacklist = []; + public $rbacDiagramExcludeRoles = ['Master']; + /** * @param $label * diff --git a/src/controllers/CacheController.php b/src/controllers/CacheController.php new file mode 100644 index 0000000..6e9224b --- /dev/null +++ b/src/controllers/CacheController.php @@ -0,0 +1,35 @@ +cache->flush()) { + \Yii::$app->session->addFlash('success', Yii::t('backend-module','Cache cleared')); + } else { + \Yii::$app->session->addFlash('error', Yii::t('backend-module','Cannot clear cache')); + } + return $this->redirect(['default/index']); + } +} \ No newline at end of file diff --git a/src/controllers/ConfigController.php b/src/controllers/ConfigController.php new file mode 100644 index 0000000..688a37e --- /dev/null +++ b/src/controllers/ConfigController.php @@ -0,0 +1,44 @@ + $loadedModules]); + $loadedModulesDataProvider->pagination->pageSize = 100; + + $components = Yii::$app->getComponents(); + ksort($components); + $modules = Yii::$app->getModules(); + ksort($modules); + $env = $_ENV; + ksort($env); + + + return $this->render( + 'view', + [ + 'params' => Yii::$app->params, + 'components' => $components, + 'modules' => $modules, + 'env' => $env, + 'loadedModulesDataProvider' => $loadedModulesDataProvider, + ] + ); + } +} diff --git a/src/controllers/DefaultController.php b/src/controllers/DefaultController.php index 1b4b857..5a94263 100644 --- a/src/controllers/DefaultController.php +++ b/src/controllers/DefaultController.php @@ -2,15 +2,12 @@ namespace dmstr\modules\backend\controllers; -use dmstr\helpers\Metadata; use dmstr\modules\backend\Module; use dmstr\widgets\Menu; use insolita\wgadminlte\InfoBox; use Yii; -use yii\data\ArrayDataProvider; use yii\helpers\ArrayHelper; use yii\helpers\Html; -use yii\helpers\Url; use yii\web\Controller; /** @@ -38,96 +35,6 @@ public function actionIndex() return $this->render('index', ['items' => $items]); } - /** - * Application configuration. - * - * @return string - */ - public function actionViewConfig() - { - $loadedModules = Metadata::getModules(); - $loadedModulesDataProvider = new ArrayDataProvider(['allModels' => $loadedModules]); - $loadedModulesDataProvider->pagination->pageSize = 100; - - $components = Yii::$app->getComponents(); - ksort($components); - $modules = Yii::$app->getModules(); - ksort($modules); - - return $this->render( - 'view-config', - [ - 'params' => Yii::$app->params, - 'components' => $components, - 'modules' => $modules, - 'loadedModulesDataProvider' => $loadedModulesDataProvider, - ] - ); - } - - /** - * @return string - */ - public function actionShowAuth() - { - $allPermissions = Yii::$app->authManager->getPermissions(); - $allRoles = Yii::$app->authManager->getRoles(); - $userPermissions = []; - $userRoles = []; - - foreach ($allPermissions AS $item) { - if (Yii::$app->user->can($item->name)) { - $userPermissions[] = [ - 'description' => $item->description, - 'name' => $item->name, - ]; - } - } - foreach ($allRoles AS $item) { - if (Yii::$app->user->can($item->name)) { - $userRoles[] = [ - 'description' => $item->description, - 'name' => $item->name, - ]; - } - } - - return $this->render('show-auth', - [ - 'permissions' => new ArrayDataProvider([ - 'allModels' => $userPermissions, - 'pagination' => [ - 'pageSize' => 100, - ], - ]), - 'roles' => new ArrayDataProvider([ - 'allModels' => $userRoles, - 'pagination' => [ - 'pageSize' => 100, - ], - ]), - ]); - } - - - - /** - * flush cache - * - * if APCu is used as cache we cannot flush cache from cli command - * see: https://github.com/yiisoft/yii2/issues/8647 - * - * @return \yii\web\Response - */ - public function actionCacheFlush() - { - if (Yii::$app->cache->flush()) { - Yii::$app->session->addFlash('success', Yii::t('backend-module','Cache cleared')); - } else { - Yii::$app->session->addFlash('error', Yii::t('backend-module','Cannot clear cache')); - } - return $this->redirect(!empty(Yii::$app->request->referrer) ? Yii::$app->request->referrer : Url::to(['index'])); - } /** @@ -167,4 +74,5 @@ public function renderDashboardMenu($item = []) return $menuItems; } + } diff --git a/src/controllers/RbacController.php b/src/controllers/RbacController.php new file mode 100644 index 0000000..5910928 --- /dev/null +++ b/src/controllers/RbacController.php @@ -0,0 +1,205 @@ +_manager = \Yii::$app->authManager; + + } + + /** + * @return string + */ + public function actionAssignments() + { + $allPermissions = Yii::$app->authManager->getPermissions(); + $allRoles = Yii::$app->authManager->getRoles(); + $userPermissions = []; + $userRoles = []; + + foreach ($allPermissions AS $item) { + if (Yii::$app->user->can($item->name)) { + $userPermissions[] = [ + 'description' => $item->description, + 'name' => $item->name, + ]; + } + } + foreach ($allRoles AS $item) { + if (Yii::$app->user->can($item->name)) { + $userRoles[] = [ + 'description' => $item->description, + 'name' => $item->name, + ]; + } + } + + return $this->render('show-auth', + [ + 'permissions' => new ArrayDataProvider([ + 'allModels' => $userPermissions, + 'pagination' => [ + 'pageSize' => 100, + ], + ]), + 'roles' => new ArrayDataProvider([ + 'allModels' => $userRoles, + 'pagination' => [ + 'pageSize' => 100, + ], + ]), + ]); + } + + public function actionDiagram() + { + $this->renderDiagram(); + + $mmd = file_get_contents(\Yii::getAlias($this->_mmdFile)); + return $this->render('index.twig', ['mmd' => $mmd]); + } + + + private function renderDiagram() + { + + $mermaid = 'flowchart LR' . PHP_EOL . PHP_EOL; + + $assignmentsMmd = ''; + $permissionMmd = ''; + + $rolesMmd = $this->renderRoles(); + $permissionMmd .= $this->renderPermissions(); + + foreach ($this->_manager->getRoles() as $role) { + $assignmentsMmd .= $this->renderAssignments($role); + } + $assignmentsMmd .= PHP_EOL . PHP_EOL; + foreach ($this->_manager->getPermissions() as $permission) { + $assignmentsMmd .= $this->renderAssignments($permission); + } + + #$mermaid .= $this->renderAsSubgraph('roles',$rolesMmd) . PHP_EOL; + $mermaid .= $rolesMmd . PHP_EOL; + #$mermaid .= $permissionMmd . PHP_EOL; + $mermaid .= $permissionMmd . PHP_EOL; + $mermaid .= $assignmentsMmd . PHP_EOL; + + $filename = \Yii::getAlias($this->_mmdFile); + FileHelper::createDirectory(dirname($filename)); + file_put_contents($filename, $mermaid); + + } + + private function renderRoles() + { + $roles = $this->_manager->getRoles(); + $rolesMmd = ''; + $assignmentsMmd = ''; + + $_gs = []; + + foreach ($roles as $role) { + #var_dump($this->module->rbacDiagramExcludeRoles);exit; + if (in_array($role->name, $this->module->rbacDiagramExcludeRoles)) continue; + + $group = $role->ruleName ?? '__NONE__'; + $group = '__NONE__'; + + if ($role->ruleName) { + $_gs[$group][] = $this->renderItem($role) . PHP_EOL; + $arrow = '-.->'; + } else { + $_gs[$group][] = $this->renderItem($role) . PHP_EOL; + $arrow = '-->'; + } + + #$assignmentsMmd .= $this->renderAssignments($role); + + } + + foreach ($_gs as $groupName => $g) { + $groupMmd = implode("\n", $g); + if ($groupName != '__NONE__') { + $rolesMmd .= $this->renderAsSubgraph($groupName, $groupMmd); + } else { + $rolesMmd .= $groupMmd; + } + #$rolesMmd .= $groupMmd; + } + + + return $rolesMmd . $assignmentsMmd; + } + + private function renderAssignments($item) + { + if (in_array($item->name, $this->module->rbacDiagramExcludeRoles)) return; + + $assignmentsMmd = ''; + foreach ($this->_manager->getChildren($item->name) as $child) { + $arrow = ($item->ruleName) ? '-.->' : '-->'; + $assignmentsMmd .= $this->renderItem($item, true) . $arrow . $this->renderItem($child, true) . PHP_EOL; + } + return $assignmentsMmd; + } + + private function renderPermissions() + { + $permissionGroups = []; + $permissionMmd = '' . PHP_EOL; + foreach ($this->_manager->getPermissions() as $permission) { + $group = explode('_', $permission->name)[0]; + $group = explode('.', $group)[0]; + $group = explode('-', $group)[0]; + $permissionGroups[$group][] = $this->renderItem($permission) . PHP_EOL; + } + + foreach ($permissionGroups as $group => $items) { + $g = ''; + foreach ($items as $line) { + $g .= $line; + } + $permissionMmd .= $this->renderAsSubgraph("__$group", $g); + } + return $permissionMmd; + } + + private function renderAsSubgraph($name, $diagram) + { + $subgraph = 'subgraph ' . $name . PHP_EOL; + $subgraph .= $diagram . PHP_EOL; + $subgraph .= 'end' . PHP_EOL; + + return $subgraph; + } + + private function renderItem($item, $compact = false) + { + if ($compact) { + $node = md5($item->name); + } else { + $symbols = ($item->type == 1) ? ["(",")"] : ["[","]"]; + $node = md5($item->name) . $symbols[0]. '"' . $item->name . '

' . $item->description . '"'.$symbols[1]; + + $node .= ';' . PHP_EOL; + $routePart = $item->type == 1 ? 'role' : 'permission'; + $node .= 'click ' . md5($item->name) . ' "/user/' . $routePart . '/update?name=' . $item->name . '" "TT";'; + } + return $node; + } +} diff --git a/src/views/default/_controller.php b/src/views/config/_controller.php similarity index 100% rename from src/views/default/_controller.php rename to src/views/config/_controller.php diff --git a/src/views/default/_module.php b/src/views/config/_module.php similarity index 100% rename from src/views/default/_module.php rename to src/views/config/_module.php diff --git a/src/views/default/view-config.php b/src/views/config/view.php similarity index 91% rename from src/views/default/view-config.php rename to src/views/config/view.php index 7f91ba1..f503d52 100644 --- a/src/views/default/view-config.php +++ b/src/views/config/view.php @@ -89,6 +89,14 @@ endBlock('modules') ?> +beginBlock('env') ?> +
+
+
+endBlock('env') ?> + + + diff --git a/src/views/default/index.php b/src/views/default/index.php index 2059d8e..69ee379 100644 --- a/src/views/default/index.php +++ b/src/views/default/index.php @@ -3,7 +3,7 @@ $this->title = Yii::t('backend-module', 'Dashboard'); ?> -

Backend

+

@@ -11,14 +11,15 @@
-
+

- +

- + +

@@ -33,7 +34,7 @@
-
+

-
+

getModules()) ?> @@ -75,7 +76,7 @@
- +

@@ -103,6 +104,71 @@
+ + +
+ +
+
+

+ +

+

+ +

+
+
+ +
+ + + +
+
+ + +
+ +
+
+

+ +

+ +

+ +

+
+
+ +
+ + + +
+
+ + +
+ +
+
+

+ +

+ +

+ +

+
+
+ +
+ + + +
+
diff --git a/src/views/rbac/index.twig b/src/views/rbac/index.twig new file mode 100644 index 0000000..2fce36e --- /dev/null +++ b/src/views/rbac/index.twig @@ -0,0 +1,19 @@ +{# register_asset_bundle('dmstr/web/MermaidAsset') #} + + + +
+
+ Roles and Permissions +
+
+ {{ mmd }} +
+
+ +{# +

Debug

+

+ {{ mmd }}
+
+#} diff --git a/src/views/default/show-auth.php b/src/views/rbac/show-auth.php similarity index 100% rename from src/views/default/show-auth.php rename to src/views/rbac/show-auth.php