tao-test/app/funcAcl/controller/Admin.php

394 lines
12 KiB
PHP
Raw Permalink Normal View History

2022-08-29 20:14:13 +02:00
<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2002-2008 (original work) Public Research Centre Henri Tudor & University of Luxembourg (under the project TAO & TAO2);
* 2008-2010 (update and modification) Deutsche Institut für Internationale Pädagogische Forschung (under the project TAO-TRANSFER);
* 2009-2012 (update and modification) Public Research Centre Henri Tudor (under the project TAO-SUSTAIN & TAO-DEV);
* 2012-2018 (update and modification) Open Assessment Technologies SA;
*
*/
namespace oat\funcAcl\controller;
use oat\generis\model\GenerisRdf;
use oat\tao\helpers\ControllerHelper;
use oat\funcAcl\models\AccessService;
use oat\funcAcl\models\ActionAccessService;
use oat\funcAcl\models\ExtensionAccessService;
use oat\funcAcl\models\ModuleAccessService;
use oat\funcAcl\helpers\CacheHelper;
use oat\funcAcl\helpers\MapHelper;
use common_exception_BadRequest;
use oat\tao\model\service\ApplicationService;
use oat\tao\model\accessControl\func\FuncAccessControl;
use oat\funcAcl\models\FuncAcl;
use oat\tao\model\accessControl\func\AclProxy;
/**
* This controller provide the actions to manage the ACLs
*
* @author CRP Henri Tudor - TAO Team - {@link http://www.tao.lu}
* @license GPLv2 http://www.opensource.org/licenses/gpl-2.0.php
* @package tao
*
*/
class Admin extends \tao_actions_CommonModule
{
/**
* Access to this functionality is inherited from
* an included role
*
* @var string
*/
const ACCESS_INHERITED = 'inherited';
/**
* Full access to this functionalities and children
*
* @var string
*/
const ACCESS_FULL = 'full';
/**
* Partial access to thie functionality means
* some children are at least partial accessible
*
* @var string
*/
const ACCESS_PARTIAL = 'partial';
/**
* No access to this functionality or any of its children
*
* @var string
*/
const ACCESS_NONE = 'none';
/**
* Show the list of roles
* @return void
*/
public function index()
{
$this->defaultData();
$rolesc = new \core_kernel_classes_Class(GenerisRdf::CLASS_ROLE);
$roles = [];
foreach ($rolesc->getInstances(true) as $id => $r) {
$roles[] = ['id' => $id, 'label' => $r->getLabel()];
}
usort($roles, function ($a, $b) {
return strcmp($a['label'], $b['label']);
});
$this->setData('roles', $roles);
$this->setView('list.tpl');
}
/**
* @throws \common_exception_Error
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
public function getModules()
{
$this->beforeAction();
$role = new \core_kernel_classes_Class($this->getRequestParameter('role'));
$included = [];
foreach (\tao_models_classes_RoleService::singleton()->getIncludedRoles($role) as $includedRole) {
$included[$includedRole->getUri()] = $includedRole->getLabel();
}
$extManager = \common_ext_ExtensionsManager::singleton();
$extData = [];
foreach ($extManager->getInstalledExtensions() as $extension) {
if ($extension->getId() != 'generis') {
$extData[] = $this->buildExtensionData($extension, $role->getUri(), array_keys($included));
}
}
usort($extData, function ($a, $b) {
return strcmp($a['label'], $b['label']);
});
$this->returnJson([
'extensions' => $extData,
'includedRoles' => $included,
'locked' => $this->isLocked(),
]);
}
protected function buildExtensionData(\common_ext_Extension $extension, $roleUri, $includedRoleUris)
{
$extAccess = CacheHelper::getExtensionAccess($extension->getId());
$extAclUri = AccessService::singleton()->makeEMAUri($extension->getId());
$atLeastOneAccess = false;
$allAccess = in_array($roleUri, $extAccess);
$inherited = count(array_intersect($includedRoleUris, $extAccess)) > 0;
$controllers = [];
foreach (ControllerHelper::getControllers($extension->getId()) as $controllerClassName) {
$controllerData = $this->buildControllerData($controllerClassName, $roleUri, $includedRoleUris);
$atLeastOneAccess = $atLeastOneAccess || $controllerData['access'] != self::ACCESS_NONE;
$controllers[] = $controllerData;
}
usort($controllers, function ($a, $b) {
return strcmp($a['label'], $b['label']);
});
$access = $inherited ? 'inherited'
: ($allAccess ? 'full'
: ($atLeastOneAccess ? 'partial' : 'none'));
return [
'uri' => $extAclUri,
'label' => $extension->getName(),
'access' => $access,
'modules' => $controllers
];
}
protected function buildControllerData($controllerClassName, $roleUri, $includedRoleUris)
{
$modUri = MapHelper::getUriForController($controllerClassName);
$moduleAccess = CacheHelper::getControllerAccess($controllerClassName);
$uri = explode('#', $modUri);
list($type, $extId, $modId) = explode('_', $uri[1]);
$access = self::ACCESS_NONE;
if (count(array_intersect($includedRoleUris, $moduleAccess['module'])) > 0) {
$access = self::ACCESS_INHERITED;
} elseif (true === in_array($roleUri, $moduleAccess['module'])) {
$access = self::ACCESS_FULL;
} else {
// have a look at actions.
foreach ($moduleAccess['actions'] as $roles) {
if (in_array($roleUri, $roles) || count(array_intersect($includedRoleUris, $roles)) > 0) {
$access = self::ACCESS_PARTIAL;
break;
}
}
}
return [
'uri' => $modUri,
'label' => $modId,
'access' => $access,
];
}
/**
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
private function beforeAction()
{
$this->defaultData();
if (!\tao_helpers_Request::isAjax()) {
throw new common_exception_BadRequest('wrong request mode');
}
}
/**
* @return bool
*/
private function isLocked()
{
$locked = !$this->getServiceLocator()->get(AclProxy::SERVICE_ID) instanceof FuncAcl;
$locked = $locked || !$this->getServiceLocator()->get(ApplicationService::SERVICE_ID)->isDebugMode();
return $locked;
}
/**
* @throws \common_exception_NotFound
*/
private function prodLocker()
{
if ($this->isLocked()) {
throw new \common_exception_NotFound();
}
}
/**
* Shows the access to the actions of a controller for a specific role
*
* @throws \common_exception_Error
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
public function getActions()
{
$this->beforeAction();
$role = new \core_kernel_classes_Resource($this->getRequestParameter('role'));
$included = [];
foreach (\tao_models_classes_RoleService::singleton()->getIncludedRoles($role) as $includedRole) {
$included[] = $includedRole->getUri();
}
$module = new \core_kernel_classes_Resource($this->getRequestParameter('module'));
$controllerClassName = MapHelper::getControllerFromUri($module->getUri());
$controllerAccess = CacheHelper::getControllerAccess($controllerClassName);
$actions = [];
foreach (ControllerHelper::getActions($controllerClassName) as $actionName) {
$uri = MapHelper::getUriForAction($controllerClassName, $actionName);
$part = explode('#', $uri);
list($type, $extId, $modId, $actId) = explode('_', $part[1]);
$allowedRoles = isset($controllerAccess['actions'][$actionName])
? array_merge($controllerAccess['module'], $controllerAccess['actions'][$actionName])
: $controllerAccess['module'];
$access = count(array_intersect($included, $allowedRoles)) > 0
? self::ACCESS_INHERITED
: (in_array($role->getUri(), $allowedRoles)
? self::ACCESS_FULL
: self::ACCESS_NONE);
$actions[$actId] = [
'uri' => $uri,
'access' => $access,
'locked' => $this->isLocked(),
];
}
ksort($actions);
$this->returnJson($actions);
}
/**
* @throws \common_exception_NotFound
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
public function removeExtensionAccess()
{
$this->beforeAction();
$this->prodLocker();
$role = $this->getRequestParameter('role');
$uri = $this->getRequestParameter('uri');
$extensionService = ExtensionAccessService::singleton();
$extensionService->remove($role, $uri);
$this->returnJson([
'uri' => $uri,
]);
}
/**
* @throws \common_exception_NotFound
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
public function addExtensionAccess()
{
$this->beforeAction();
$this->prodLocker();
$role = $this->getRequestParameter('role');
$uri = $this->getRequestParameter('uri');
$extensionService = ExtensionAccessService::singleton();
$extensionService->add($role, $uri);
$this->returnJson([
'uri' => $uri,
]);
}
/**
* @throws \common_exception_NotFound
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
public function removeModuleAccess()
{
$this->beforeAction();
$this->prodLocker();
$role = $this->getRequestParameter('role');
$uri = $this->getRequestParameter('uri');
$moduleService = ModuleAccessService::singleton();
$moduleService->remove($role, $uri);
$this->returnJson([
'uri' => $uri,
]);
}
/**
* @throws \common_exception_NotFound
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
public function addModuleAccess()
{
$this->beforeAction();
$this->prodLocker();
$role = $this->getRequestParameter('role');
$uri = $this->getRequestParameter('uri');
$moduleService = ModuleAccessService::singleton();
$moduleService->add($role, $uri);
$this->returnJson([
'uri' => $uri,
]);
}
/**
* @throws \common_exception_NotFound
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
public function removeActionAccess()
{
$this->beforeAction();
$this->prodLocker();
$role = $this->getRequestParameter('role');
$uri = $this->getRequestParameter('uri');
$actionService = ActionAccessService::singleton();
$actionService->remove($role, $uri);
$this->returnJson([
'uri' => $uri,
]);
}
/**
* @throws \common_exception_NotFound
* @throws \common_ext_ExtensionException
* @throws common_exception_BadRequest
*/
public function addActionAccess()
{
$this->beforeAction();
$this->prodLocker();
$role = $this->getRequestParameter('role');
$uri = $this->getRequestParameter('uri');
$actionService = ActionAccessService::singleton();
$actionService->add($role, $uri);
$this->returnJson([
'uri' => $uri,
]);
}
}