diff --git a/front/itemright.form.php b/front/itemright.form.php new file mode 100644 index 0000000..ede1891 --- /dev/null +++ b/front/itemright.form.php @@ -0,0 +1,125 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2018-2023 by Metabase plugin team. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/metabase + * ------------------------------------------------------------------------- + * + * CUSTOM FORK NOTICE: added to handle per Group / per User dashboard rights. + * ------------------------------------------------------------------------- + */ + +function plugin_metabase_check_itemright_access($itemtype) +{ + if (!in_array($itemtype, PluginMetabaseItemright::SUPPORTED_ITEMTYPES, true)) { + Session::addMessageAfterRedirect( + __s('Invalid request.', 'metabase'), + false, + ERROR, + ); + Html::back(); + } + + if ($itemtype === Group::class) { + Session::checkRight('group', UPDATE); + } else { + Session::checkRight('user', UPDATE); + } +} + +if (isset($_REQUEST['update'])) { + if ( + !array_key_exists('itemtype', $_REQUEST) + || empty($_REQUEST['itemtype']) + || !array_key_exists('items_id', $_REQUEST) + || empty($_REQUEST['items_id']) + || !array_key_exists('dashboard', $_REQUEST) + || !is_array($_REQUEST['dashboard']) + ) { + Session::addMessageAfterRedirect( + __s('Invalid request.', 'metabase'), + false, + ERROR, + ); + Html::back(); + } + + plugin_metabase_check_itemright_access($_REQUEST['itemtype']); + + $viewableDashboardsUuids = []; + foreach ($_REQUEST['dashboard'] as $dashboardUuid => $rights) { + PluginMetabaseItemright::setDashboardRightsForItem( + $_REQUEST['itemtype'], + $_REQUEST['items_id'], + $dashboardUuid, + $rights, + ); + + if (($rights & READ) !== 0) { + $viewableDashboardsUuids[] = $dashboardUuid; + } + } + + if (!empty($viewableDashboardsUuids)) { + $apiclient = new PluginMetabaseAPIClient(); + $apiclient->enableDashboardsEmbeddedDisplay($viewableDashboardsUuids); + } +} elseif (isset($_REQUEST['set_rights_to_all'])) { + if ( + !array_key_exists('itemtype', $_REQUEST) + || empty($_REQUEST['itemtype']) + || !array_key_exists('items_id', $_REQUEST) + || empty($_REQUEST['items_id']) + ) { + Session::addMessageAfterRedirect( + __s('Invalid request.', 'metabase'), + false, + ERROR, + ); + Html::back(); + } + + plugin_metabase_check_itemright_access($_REQUEST['itemtype']); + + $apiclient = new PluginMetabaseAPIClient(); + + $viewableDashboardsUuids = []; + foreach ($apiclient->getDashboards() as $dashboard) { + PluginMetabaseItemright::setDashboardRightsForItem( + $_REQUEST['itemtype'], + $_REQUEST['items_id'], + $dashboard['id'], + $_REQUEST['set_rights_to_all'], + ); + + $viewableDashboardsUuids[] = $dashboard['id']; + } + + if ((int) $_REQUEST['set_rights_to_all'] !== 0) { + $apiclient->enableDashboardsEmbeddedDisplay($viewableDashboardsUuids); + } +} + +Html::back(); diff --git a/inc/dashboard.class.php b/inc/dashboard.class.php index 1a90775..5995f17 100644 --- a/inc/dashboard.class.php +++ b/inc/dashboard.class.php @@ -43,6 +43,58 @@ public static function getTypeName($nb = 0) return __s('Metabase dashboard', 'metabase'); } + /** + * Check if the currently logged-in user is able to view at least one + * dashboard, combining profile, group and user based rights. + * + * CUSTOM FORK: rights are additive (OR) across profile / groups / user. + * + * @return boolean + */ + public static function canCurrentUserViewDashboards(): bool + { + if (PluginMetabaseProfileright::canProfileViewDashboards($_SESSION['glpiactiveprofile']['id'])) { + return true; + } + + if (PluginMetabaseItemright::canItemViewDashboards(User::class, Session::getLoginUserID())) { + return true; + } + + if (PluginMetabaseItemright::canGroupsViewDashboards($_SESSION['glpigroups'] ?? [])) { + return true; + } + + return false; + } + + /** + * Check if the currently logged-in user is able to view the given + * dashboard, combining profile, group and user based rights. + * + * rights are additive (OR) across profile / groups / user. + * + * @param integer $dashboardUuid + * + * @return boolean + */ + public static function canCurrentUserViewDashboard(int $dashboardUuid): bool + { + if (PluginMetabaseProfileright::canProfileViewDashboard($_SESSION['glpiactiveprofile']['id'], $dashboardUuid)) { + return true; + } + + if (PluginMetabaseItemright::canItemViewDashboard(User::class, Session::getLoginUserID(), $dashboardUuid)) { + return true; + } + + if (PluginMetabaseItemright::canGroupsViewDashboard($_SESSION['glpigroups'] ?? [], $dashboardUuid)) { + return true; + } + + return false; + } + /** * {@inheritDoc} * @see CommonGLPI::getTabNameForItem() @@ -51,7 +103,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { switch ($item->getType()) { case 'Central': - if (PluginMetabaseProfileright::canProfileViewDashboards($_SESSION['glpiactiveprofile']['id'])) { + if (self::canCurrentUserViewDashboards()) { return self::createTabEntry(self::getTypeName(), 0, $item::getType(), PluginMetabaseConfig::getIcon()); } @@ -69,7 +121,7 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $ { switch (get_class($item)) { case Central::class: - if (PluginMetabaseProfileright::canProfileViewDashboards($_SESSION['glpiactiveprofile']['id'])) { + if (self::canCurrentUserViewDashboards()) { self::showForCentral($item, $withtemplate); } @@ -99,10 +151,7 @@ public static function showForCentral(Central $item, $withtemplate = 0, $is_help $dashboards, function ($dashboard) { $isEmbeddingEnabled = $dashboard['enable_embedding']; - $canView = PluginMetabaseProfileright::canProfileViewDashboard( - $_SESSION['glpiactiveprofile']['id'], - $dashboard['id'], - ); + $canView = self::canCurrentUserViewDashboard($dashboard['id']); return $isEmbeddingEnabled && $canView; }, diff --git a/inc/itemright.class.php b/inc/itemright.class.php new file mode 100644 index 0000000..72a882a --- /dev/null +++ b/inc/itemright.class.php @@ -0,0 +1,405 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2018-2023 by Metabase plugin team. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/metabase + * ------------------------------------------------------------------------- + * + * CUSTOM FORK NOTICE + * ------------------------------------------------------------------------- + * This class was added in a local fork to allow defining dashboard access + * rights per Group and per User, in addition to the native per Profile + * rights handled by PluginMetabaseProfileright. + * ------------------------------------------------------------------------- + */ + +class PluginMetabaseItemright extends CommonDBTM +{ + /** + * Itemtypes supported by this "generic" right holder. + */ + public const SUPPORTED_ITEMTYPES = [Group::class, User::class]; + + /** + * {@inheritDoc} + * @see CommonGLPI::getTypeName() + */ + public static function getTypeName($nb = 0) + { + return __s('Metabase', 'metabase'); + } + + /** + * Returns the GLPI right (and value) required to manage metabase + * dashboard rights for the given itemtype. + * + * @param string $itemtype Group::class or User::class + * + * @return array{0: string, 1: int} [rightname, right value] + */ + private static function getRequiredRight(string $itemtype): array + { + return match ($itemtype) { + Group::class => ['group', UPDATE], + User::class => ['user', UPDATE], + default => ['profile', UPDATE], + }; + } + + /** + * {@inheritDoc} + * @see CommonGLPI::getTabNameForItem() + */ + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { + $itemtype = $item::getType(); + + if (!in_array($itemtype, self::SUPPORTED_ITEMTYPES, true)) { + return ''; + } + + [$rightname, $rightvalue] = self::getRequiredRight($itemtype); + if (Session::haveRight($rightname, $rightvalue)) { + return self::createTabEntry(self::getTypeName(), 0, $itemtype, PluginMetabaseConfig::getIcon()); + } + + return ''; + } + + /** + * {@inheritDoc} + * @see CommonGLPI::displayTabContentForItem() + */ + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + $itemtype = $item::getType(); + + if (!in_array($itemtype, self::SUPPORTED_ITEMTYPES, true)) { + return true; + } + + [$rightname, $rightvalue] = self::getRequiredRight($itemtype); + if (Session::haveRight($rightname, $rightvalue)) { + $itemright = new self(); + $itemright->showRightsForm($itemtype, $item->fields['id']); + } + + return true; + } + + /** + * Display item (group/user) rights form. + * + * @param string $itemtype Group::class or User::class + * @param integer $itemsId Group or User id + * @param array $options + * + * @return bool + */ + public function showRightsForm($itemtype, $itemsId, $options = []) + { + if (!in_array($itemtype, self::SUPPORTED_ITEMTYPES, true)) { + return false; + } + + [$rightname, $rightvalue] = self::getRequiredRight($itemtype); + if (!Session::haveRight($rightname, $rightvalue)) { + return false; + } + + $apiclient = new PluginMetabaseAPIClient(); + $dashboards = $apiclient->getDashboards(); + + if (!$dashboards) { + echo '