From 9567a6086e5feb25225f66330f5467b397a649a3 Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Fri, 23 Aug 2019 07:15:36 -0400 Subject: [PATCH] Make it easier to globally set controller permissions (#1395) --- config/vufind/permissionBehavior.ini | 12 ++++++ .../src/VuFind/Controller/AbstractBase.php | 28 ++++++++++++- .../VuFind/Controller/AbstractBaseFactory.php | 42 ++++++++++++++++++- .../AbstractBaseWithConfigFactory.php | 7 ++-- .../Controller/CartControllerFactory.php | 8 ++-- .../Controller/ChannelsControllerFactory.php | 5 +-- .../Controller/MyResearchController.php | 13 ++++++ .../Controller/UpgradeControllerFactory.php | 8 ++-- 8 files changed, 108 insertions(+), 15 deletions(-) diff --git a/config/vufind/permissionBehavior.ini b/config/vufind/permissionBehavior.ini index 550838fb0c9..3390fd023d8 100644 --- a/config/vufind/permissionBehavior.ini +++ b/config/vufind/permissionBehavior.ini @@ -66,6 +66,18 @@ defaultDeniedControllerBehavior = "promptLogin" ; (False means "use the default behavior defined by the template"). defaultDeniedTemplateBehavior = false +; This setting can be used to override access permissions for controllers. You can +; set a controller class name inside the brackets to explicitly override that +; controller's access permission (and that of any of its children, unless more +; specific permissions are set for those subclasses), whether or not it has a +; default defined in the class. You can use * inside the brackets to set a default +; access permission that is applied to all controllers that do not have an +; internally-defined default (the MyResearchController is also excluded from +; this setting to avoid infinite login redirects). This can be useful if you +; wish to password-protect your entire site. +;controllerAccess[*] = access.VuFindInterface +;controllerAccess[VuFind\Controller\SearchController] = access.SearchResults + ; Example configuration for non-standard favorites permission behavior: ;[feature.Favorites] ;deniedTemplateBehavior = "showMessage:Login for Favorites" diff --git a/module/VuFind/src/VuFind/Controller/AbstractBase.php b/module/VuFind/src/VuFind/Controller/AbstractBase.php index 69fdaf2c5c7..90e9961f4f1 100644 --- a/module/VuFind/src/VuFind/Controller/AbstractBase.php +++ b/module/VuFind/src/VuFind/Controller/AbstractBase.php @@ -51,11 +51,12 @@ class AbstractBase extends AbstractActionController { /** * Permission that must be granted to access this module (false for no - * restriction) + * restriction, null to use configured default (which is usually the same + * as false)). * * @var string|bool */ - protected $accessPermission = false; + protected $accessPermission = null; /** * Behavior when access is denied (used unless overridden through @@ -105,6 +106,29 @@ class AbstractBase extends AbstractActionController } } + /** + * Getter for access permission. + * + * @return string|bool + */ + public function getAccessPermission() + { + return $this->accessPermission; + } + + /** + * Getter for access permission. + * + * @param string $ap Permission to require for access to the controller (false + * for no requirement) + * + * @return void + */ + public function setAccessPermission($ap) + { + $this->accessPermission = empty($ap) ? false : $ap; + } + /** * Register the default events for this controller * diff --git a/module/VuFind/src/VuFind/Controller/AbstractBaseFactory.php b/module/VuFind/src/VuFind/Controller/AbstractBaseFactory.php index 6f3d621cc8a..f16c84b5708 100644 --- a/module/VuFind/src/VuFind/Controller/AbstractBaseFactory.php +++ b/module/VuFind/src/VuFind/Controller/AbstractBaseFactory.php @@ -41,6 +41,46 @@ use Zend\ServiceManager\Factory\FactoryInterface; */ class AbstractBaseFactory implements FactoryInterface { + /** + * Apply permission settings to the controller. + * + * @param ContainerInterface $container Service manager + * @param AbstractBase $controller Controller to configure + * + * @return AbstractBase + */ + protected function applyPermissions($container, $controller) + { + $config = $container->get(\VuFind\Config\PluginManager::class) + ->get('permissionBehavior'); + $permissions = $config->global->controllerAccess ?? []; + + if (!empty($permissions)) { + // Iterate through parent classes until we find the most specific + // class access permission defined (if any): + $class = get_class($controller); + do { + if (isset($permissions[$class])) { + $controller->setAccessPermission($permissions[$class]); + break; + } + $class = get_parent_class($class); + } while ($class); + + // If the controller's current permission is null (as opposed to false + // or a string), that means it has no internally configured default, and + // setAccessPermission was not called above; thus, we should apply the + // default value: + if (isset($permissions['*']) + && $controller->getAccessPermission() === null + ) { + $controller->setAccessPermission($permissions['*']); + } + } + + return $controller; + } + /** * Create an object * @@ -61,6 +101,6 @@ class AbstractBaseFactory implements FactoryInterface if (!empty($options)) { throw new \Exception('Unexpected options sent to factory.'); } - return new $requestedName($container); + return $this->applyPermissions($container, new $requestedName($container)); } } diff --git a/module/VuFind/src/VuFind/Controller/AbstractBaseWithConfigFactory.php b/module/VuFind/src/VuFind/Controller/AbstractBaseWithConfigFactory.php index b6a6f5c731f..f9efa5a7e22 100644 --- a/module/VuFind/src/VuFind/Controller/AbstractBaseWithConfigFactory.php +++ b/module/VuFind/src/VuFind/Controller/AbstractBaseWithConfigFactory.php @@ -28,7 +28,6 @@ namespace VuFind\Controller; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; /** * Generic controller factory (with config injection). @@ -39,7 +38,7 @@ use Zend\ServiceManager\Factory\FactoryInterface; * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ -class AbstractBaseWithConfigFactory implements FactoryInterface +class AbstractBaseWithConfigFactory extends AbstractBaseFactory { /** * Create an object @@ -63,6 +62,8 @@ class AbstractBaseWithConfigFactory implements FactoryInterface } $config = $container->get(\VuFind\Config\PluginManager::class) ->get('config'); - return new $requestedName($container, $config); + return $this->applyPermissions( + $container, new $requestedName($container, $config) + ); } } diff --git a/module/VuFind/src/VuFind/Controller/CartControllerFactory.php b/module/VuFind/src/VuFind/Controller/CartControllerFactory.php index bb56f89a8b9..5e5a908056d 100644 --- a/module/VuFind/src/VuFind/Controller/CartControllerFactory.php +++ b/module/VuFind/src/VuFind/Controller/CartControllerFactory.php @@ -28,7 +28,6 @@ namespace VuFind\Controller; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; /** * Cart controller factory. @@ -39,7 +38,7 @@ use Zend\ServiceManager\Factory\FactoryInterface; * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ -class CartControllerFactory implements FactoryInterface +class CartControllerFactory extends AbstractBaseFactory { /** * Create an object @@ -64,6 +63,9 @@ class CartControllerFactory implements FactoryInterface $session = new \Zend\Session\Container( 'cart_followup', $container->get(\Zend\Session\SessionManager::class) ); - return new $requestedName($container, $session); + return $this->applyPermissions( + $container, + new $requestedName($container, $session) + ); } } diff --git a/module/VuFind/src/VuFind/Controller/ChannelsControllerFactory.php b/module/VuFind/src/VuFind/Controller/ChannelsControllerFactory.php index d3ca628582e..28e3c921706 100644 --- a/module/VuFind/src/VuFind/Controller/ChannelsControllerFactory.php +++ b/module/VuFind/src/VuFind/Controller/ChannelsControllerFactory.php @@ -28,7 +28,6 @@ namespace VuFind\Controller; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; /** * Channels controller factory. @@ -39,7 +38,7 @@ use Zend\ServiceManager\Factory\FactoryInterface; * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ -class ChannelsControllerFactory implements FactoryInterface +class ChannelsControllerFactory extends AbstractBaseFactory { /** * Create an object @@ -62,6 +61,6 @@ class ChannelsControllerFactory implements FactoryInterface throw new \Exception('Unexpected options sent to factory.'); } $loader = $container->get(\VuFind\ChannelProvider\ChannelLoader::class); - return new $requestedName($loader); + return $this->applyPermissions($container, new $requestedName($loader)); } } diff --git a/module/VuFind/src/VuFind/Controller/MyResearchController.php b/module/VuFind/src/VuFind/Controller/MyResearchController.php index 0c3dcad453d..30d7d1e1f18 100644 --- a/module/VuFind/src/VuFind/Controller/MyResearchController.php +++ b/module/VuFind/src/VuFind/Controller/MyResearchController.php @@ -49,6 +49,19 @@ use Zend\View\Model\ViewModel; */ class MyResearchController extends AbstractBase { + /** + * Permission that must be granted to access this module (false for no + * restriction, null to use configured default (which is usually the same + * as false)). + * + * For this controller, we default to false rather than null because + * we don't want a default setting to override the controller's accessibility + * and break the login process! + * + * @var string|bool + */ + protected $accessPermission = false; + /** * ILS Pagination Helper * diff --git a/module/VuFind/src/VuFind/Controller/UpgradeControllerFactory.php b/module/VuFind/src/VuFind/Controller/UpgradeControllerFactory.php index 928b0daeb65..572b9d0c345 100644 --- a/module/VuFind/src/VuFind/Controller/UpgradeControllerFactory.php +++ b/module/VuFind/src/VuFind/Controller/UpgradeControllerFactory.php @@ -28,7 +28,6 @@ namespace VuFind\Controller; use Interop\Container\ContainerInterface; -use Zend\ServiceManager\Factory\FactoryInterface; /** * Upgrade controller factory. @@ -39,7 +38,7 @@ use Zend\ServiceManager\Factory\FactoryInterface; * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ -class UpgradeControllerFactory implements FactoryInterface +class UpgradeControllerFactory extends AbstractBaseFactory { /** * Create an object @@ -65,6 +64,9 @@ class UpgradeControllerFactory implements FactoryInterface $session = new \Zend\Session\Container( 'upgrade', $container->get(\Zend\Session\SessionManager::class) ); - return new $requestedName($container, $cookieManager, $session); + return $this->applyPermissions( + $container, + new $requestedName($container, $cookieManager, $session) + ); } } -- GitLab