mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-18 07:23:13 +00:00
Add BaseVoter and Authorization Service Provider
PLUG-112
This commit is contained in:
@@ -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());
|
||||
|
36
lib/Alchemy/Phrasea/Authorization/AuthorizationChecker.php
Normal file
36
lib/Alchemy/Phrasea/Authorization/AuthorizationChecker.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Authorization;
|
||||
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
|
||||
|
||||
class AuthorizationChecker
|
||||
{
|
||||
/** @var AccessDecisionManager */
|
||||
private $accessDecisionManager;
|
||||
/** @var TokenInterface */
|
||||
private $token;
|
||||
|
||||
public function __construct(AccessDecisionManager $accessDecisionManager, TokenInterface $token)
|
||||
{
|
||||
$this->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);
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Authorization;
|
||||
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Silex\Application;
|
||||
use Silex\ServiceProviderInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
|
||||
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
|
||||
|
||||
class AuthorizationServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['phraseanet.security_token'] = $app->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
|
||||
}
|
||||
}
|
78
lib/Alchemy/Phrasea/Authorization/BaseVoter.php
Normal file
78
lib/Alchemy/Phrasea/Authorization/BaseVoter.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Authorization;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
||||
|
||||
abstract class BaseVoter implements VoterInterface
|
||||
{
|
||||
private $supportedAttributes;
|
||||
private $supportedClass;
|
||||
|
||||
/** @var Application */
|
||||
private $app;
|
||||
|
||||
public function __construct(Application $app, array $attributes, $supportedClass)
|
||||
{
|
||||
$this->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);
|
||||
}
|
@@ -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() %}
|
||||
<div style="position:absolute; top:0; left:0; right:0; bottom:0; background-color:#1a1a1a; z-index:32766;">
|
||||
<div id="loader" style="top:200px; margin:0 auto; -webkit-border-radius:5px; -moz-border-radius:5px; border-radius:5px; background-color:#CCCCCC; position:relative; margin:0 auto; text-align:center; width:400px; height:100px; padding:20px; z-index:32767;">
|
||||
<div style="margin:0 10px 10px; font-family:Helvetica,Arial,sans-serif; font-size:18px; color:#1A1A1A; text-align:left;">Phraseanet</div>
|
||||
@@ -195,14 +203,9 @@
|
||||
{% include 'prod/tab_thesaurus.html.twig' with {has_access_to_module: app.getAclForUser(app.getAuthenticatedUser()).has_access_to_module('thesaurus')} %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% set workzone_plugins = app['plugin.workzone'] %}
|
||||
{% set workzone_plugins_class = 'single-plugin' %}
|
||||
{% if workzone_plugins.keys()|length > 1 %}
|
||||
{% set workzone_plugins_class = 'multiple-plugin' %}
|
||||
{% endif %}
|
||||
<div id="plugins" class="PNB {{ workzone_plugins_class }}" style="top:52px;">
|
||||
{% for plugin in workzone_plugins.keys() %}
|
||||
{% include workzone_plugins[plugin].getWorkzoneTemplate() with {'app': app, 'plugin_id': plugin} only %}
|
||||
<div id="plugins" class="PNB {{ workzone_plugins|length > 1 ? 'multiple-plugin' : 'single-plugin' }}" style="top:52px;">
|
||||
{% for pluginId, plugin in workzone_plugins %}
|
||||
{% include plugin.getWorkzoneTemplate() with {'app': app, 'plugin_id': pluginId} only %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -16,7 +16,7 @@
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if app['plugin.workzone'].keys() is not empty %}
|
||||
{% if workzone_plugins is not empty %}
|
||||
<li>
|
||||
<a href="#plugins" class="WZplugins">
|
||||
<img src="/skins/icons/plugins.png" title="{{ 'phraseanet:: plugin.workzone' | trans }}"/>
|
||||
|
Reference in New Issue
Block a user