diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php index a95f75889e..9f69b17b5e 100644 --- a/lib/Alchemy/Phrasea/Application.php +++ b/lib/Alchemy/Phrasea/Application.php @@ -15,6 +15,7 @@ use Alchemy\Geonames\GeonamesServiceProvider; use Alchemy\Phrasea\Application\Helper\AclAware; use Alchemy\Phrasea\Application\Helper\ApplicationBoxAware; use Alchemy\Phrasea\Application\Helper\AuthenticatorAware; +use Alchemy\Phrasea\Authorization\AuthorizationServiceProvider; use Alchemy\Phrasea\Cache\Factory; use Alchemy\Phrasea\Cache\Manager; use Alchemy\Phrasea\Core\Event\Subscriber\BasketSubscriber; @@ -191,6 +192,7 @@ class Application extends SilexApplication $this->register(new ACLServiceProvider()); $this->register(new APIServiceProvider()); $this->register(new AuthenticationManagerServiceProvider()); + $this->register(new AuthorizationServiceProvider()); $this->register(new BrowserServiceProvider()); $this->register(new ConvertersServiceProvider()); $this->register(new CSVServiceProvider()); diff --git a/lib/Alchemy/Phrasea/Authorization/AuthorizationChecker.php b/lib/Alchemy/Phrasea/Authorization/AuthorizationChecker.php new file mode 100644 index 0000000000..2e434c2500 --- /dev/null +++ b/lib/Alchemy/Phrasea/Authorization/AuthorizationChecker.php @@ -0,0 +1,36 @@ +accessDecisionManager = $accessDecisionManager; + $this->token = $token; + } + + public function isGranted($attributes, $object = null) + { + if (!is_array($attributes)) { + $attributes = [$attributes]; + } + + return $this->accessDecisionManager->decide($this->token, $attributes, $object); + } +} diff --git a/lib/Alchemy/Phrasea/Authorization/AuthorizationServiceProvider.php b/lib/Alchemy/Phrasea/Authorization/AuthorizationServiceProvider.php new file mode 100644 index 0000000000..31b25568c0 --- /dev/null +++ b/lib/Alchemy/Phrasea/Authorization/AuthorizationServiceProvider.php @@ -0,0 +1,52 @@ +share(function (PhraseaApplication $app) { + $user = $app['authentication']->getUser(); + + if ($user instanceof \User_Adapter) { + return new PreAuthenticatedToken((string)$user->get_id(), null, 'fake', ['ROLE_USER']); + } + + return new AnonymousToken('fake', 'anon.', []); + }); + + $app['phraseanet.access_manager'] = $app->share(function (PhraseaApplication $app) { + return new AccessDecisionManager($app['phraseanet.voters']); + }); + $app['phraseanet.voters'] = $app->share(function () { + return []; + }); + + $app['phraseanet.authorization_checker'] = $app->share(function (PhraseaApplication $app) { + return new AuthorizationChecker( + $app['phraseanet.access_manager'], + $app['phraseanet.security_token'] + ); + }); + } + + public function boot(Application $app) + { + // Nothing to do + } +} diff --git a/lib/Alchemy/Phrasea/Authorization/BaseVoter.php b/lib/Alchemy/Phrasea/Authorization/BaseVoter.php new file mode 100644 index 0000000000..19b1f38261 --- /dev/null +++ b/lib/Alchemy/Phrasea/Authorization/BaseVoter.php @@ -0,0 +1,78 @@ +app = $app; + $this->supportedAttributes = $attributes; + $this->supportedClass = $supportedClass; + + if (!is_callable([$this, 'isGranted'])) { + throw new \LogicException('Subclasses should implement a "isGranted" method'); + } + } + + public function supportsAttribute($attribute) + { + return in_array($attribute, $this->supportedAttributes); + } + + public function supportsClass($class) + { + $supportedClass = $this->supportedClass; + if ($class == $supportedClass || is_subclass_of($class, $supportedClass)) { + return true; + } + + return false; + } + + public function vote(TokenInterface $token, $object, array $attributes) + { + if (!$object || !$this->supportsClass(get_class($object))) { + return self::ACCESS_ABSTAIN; + } + + $user = (ctype_digit($token->getUser())) ? new \User_Adapter((int) $token->getUser(), $this->app) : null; + + foreach ($attributes as $attribute) { + $attribute = strtolower($attribute); + + if ($this->supportsAttribute($attribute)) { + $isGranted = call_user_func([$this, 'isGranted'], $attribute, $object, $user); + + return $isGranted ? self::ACCESS_GRANTED : self::ACCESS_DENIED; + } + } + + return self::ACCESS_ABSTAIN; + } + + /** + * @param string $attribute + * @param object $object + * @param \User_Adapter|null $user + * @return bool + */ + //abstract protected function isGranted($attribute, $object, \User_Adapter $user = null); +} diff --git a/templates/web/prod/index.html.twig b/templates/web/prod/index.html.twig index bff5ed5fb2..61207bd585 100644 --- a/templates/web/prod/index.html.twig +++ b/templates/web/prod/index.html.twig @@ -161,6 +161,14 @@ {% block content %} + {% set workzone_plugins = [] %} + {% for plugin in app['plugin.workzone'].keys() %} + {% if app['phraseanet.authorization_checker'].isGranted('VIEW', app['plugin.workzone'][plugin]) %} + {% set workzone_plugins = workzone_plugins|merge({(plugin): app['plugin.workzone'][plugin]}) %} + {% endif %} + {% endfor %} + + {% set search_datas = module_prod.get_search_datas() %}