mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-12 20:43:25 +00:00
Getting collection calls access_restriction which is not properly cached.
Remove use of cache in AccessRestriction and use instance memory cache instead. Beware static keyword declares variable static for the class, not the instance
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* This file is part of Phraseanet
|
* This file is part of Phraseanet
|
||||||
*
|
*
|
||||||
* (c) 2005-2014 Alchemy
|
* (c) 2005-2016 Alchemy
|
||||||
*
|
*
|
||||||
* For the full copyright and license information, please view the LICENSE
|
* For the full copyright and license information, please view the LICENSE
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
@@ -11,37 +10,63 @@
|
|||||||
|
|
||||||
namespace Alchemy\Phrasea\Core\Configuration;
|
namespace Alchemy\Phrasea\Core\Configuration;
|
||||||
|
|
||||||
use Alchemy\Phrasea\Cache\Cache;
|
|
||||||
use Alchemy\Phrasea\Model\Entities\Collection;
|
|
||||||
use Alchemy\Phrasea\Model\Entities\Databox;
|
|
||||||
use Assert\Assertion;
|
use Assert\Assertion;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
class AccessRestriction
|
class AccessRestriction
|
||||||
{
|
{
|
||||||
private $conf;
|
/**
|
||||||
private $appbox;
|
* @var PropertyAccess
|
||||||
private $logger;
|
*/
|
||||||
private $cache;
|
private $propertyAccess;
|
||||||
|
|
||||||
public function __construct(Cache $cache, PropertyAccess $conf, \appbox $appbox, LoggerInterface $logger)
|
/**
|
||||||
|
* @var \appbox
|
||||||
|
*/
|
||||||
|
private $appbox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $loaded = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $restricted = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $availableDataboxes = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $availableCollections = [];
|
||||||
|
|
||||||
|
public function __construct(PropertyAccess $propertyAccess, \appbox $appbox, LoggerInterface $logger)
|
||||||
{
|
{
|
||||||
$this->conf = $conf;
|
$this->propertyAccess = $propertyAccess;
|
||||||
$this->appbox = $appbox;
|
$this->appbox = $appbox;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->cache = $cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a configuration is set.
|
* Returns true if a configuration is set.
|
||||||
*
|
*
|
||||||
* @return Boolean
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isRestricted()
|
public function isRestricted()
|
||||||
{
|
{
|
||||||
$this->load();
|
$this->load();
|
||||||
|
|
||||||
return $this->cache->fetch('restricted');
|
return $this->restricted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,7 +74,7 @@ class AccessRestriction
|
|||||||
*
|
*
|
||||||
* @param \databox $databox
|
* @param \databox $databox
|
||||||
*
|
*
|
||||||
* @return Boolean
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isDataboxAvailable(\databox $databox)
|
public function isDataboxAvailable(\databox $databox)
|
||||||
{
|
{
|
||||||
@@ -57,7 +82,7 @@ class AccessRestriction
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return in_array($databox->get_sbas_id(), $this->cache->fetch('available_databoxes'), true);
|
return in_array($databox->get_sbas_id(), $this->availableDataboxes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +97,7 @@ class AccessRestriction
|
|||||||
return $databoxes;
|
return $databoxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
$available = array_flip($this->cache->fetch('available_databoxes'));
|
$available = array_flip($this->availableDataboxes);
|
||||||
|
|
||||||
return array_filter($databoxes, function (\databox $databox) use ($available) {
|
return array_filter($databoxes, function (\databox $databox) use ($available) {
|
||||||
return isset($available[$databox->get_sbas_id()]);
|
return isset($available[$databox->get_sbas_id()]);
|
||||||
@@ -84,7 +109,7 @@ class AccessRestriction
|
|||||||
*
|
*
|
||||||
* @param \collection $collection
|
* @param \collection $collection
|
||||||
*
|
*
|
||||||
* @return Boolean
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isCollectionAvailable(\collection $collection)
|
public function isCollectionAvailable(\collection $collection)
|
||||||
{
|
{
|
||||||
@@ -92,30 +117,31 @@ class AccessRestriction
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$availableCollections = $this->cache->fetch('available_collections_'.$collection->get_databox()->get_sbas_id()) ?: [];
|
$availableCollections = isset($this->availableCollections[$collection->get_sbas_id()])
|
||||||
|
? $this->availableCollections[$collection->get_sbas_id()] : [];
|
||||||
|
|
||||||
return in_array($collection->get_base_id(), $availableCollections, true);
|
return in_array($collection->get_base_id(), $availableCollections, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function load()
|
private function load()
|
||||||
{
|
{
|
||||||
if ($this->cache->fetch('loaded')) {
|
if ($this->loaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->cache->save('loaded', true);
|
$this->loaded = true;
|
||||||
|
|
||||||
$allowedDataboxIds = array_map(function ($dbConf) {
|
$allowedDataboxIds = array_map(function ($dbConf) {
|
||||||
return $dbConf['id'];
|
return $dbConf['id'];
|
||||||
}, $this->conf->get('databoxes', []));
|
}, $this->propertyAccess->get('databoxes', []));
|
||||||
|
|
||||||
if (count($allowedDataboxIds) === 0) {
|
if (count($allowedDataboxIds) === 0) {
|
||||||
$this->cache->save('restricted', false);
|
$this->restricted = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->cache->save('restricted', true);
|
$this->restricted = true;
|
||||||
|
|
||||||
$databoxIds = array_map(function (\databox $databox) { return $databox->get_sbas_id(); }, $this->appbox->get_databoxes());
|
$databoxIds = array_map(function (\databox $databox) { return $databox->get_sbas_id(); }, $this->appbox->get_databoxes());
|
||||||
$errors = array_diff($allowedDataboxIds, $databoxIds);
|
$errors = array_diff($allowedDataboxIds, $databoxIds);
|
||||||
@@ -124,18 +150,15 @@ class AccessRestriction
|
|||||||
$this->logger->error(sprintf('Misconfiguration for allowed databoxes : ids %s do not exist', implode(', ', $errors)));
|
$this->logger->error(sprintf('Misconfiguration for allowed databoxes : ids %s do not exist', implode(', ', $errors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$allowedDataboxIds = array_intersect($allowedDataboxIds, $databoxIds);
|
$this->availableDataboxes = array_intersect($allowedDataboxIds, $databoxIds);
|
||||||
$this->cache->save('available_databoxes', $allowedDataboxIds);
|
|
||||||
|
|
||||||
$this->loadCollections();
|
$this->loadCollections();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadCollections()
|
private function loadCollections()
|
||||||
{
|
{
|
||||||
$allowedDataboxIds = $this->cache->fetch('available_databoxes');
|
foreach ($this->propertyAccess->get('databoxes') as $databox) {
|
||||||
|
if (!in_array($databox['id'], $this->availableDataboxes, true)) {
|
||||||
foreach ($this->conf->get('databoxes') as $databox) {
|
|
||||||
if (!in_array($databox['id'], $allowedDataboxIds, true)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,9 +171,7 @@ class AccessRestriction
|
|||||||
$this->logger->error(sprintf('Misconfiguration for allowed collections : ids %s do not exist', implode(', ', $errors)));
|
$this->logger->error(sprintf('Misconfiguration for allowed collections : ids %s do not exist', implode(', ', $errors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$collections = array_intersect($collections, $availableBaseIds);
|
$this->availableCollections[$databox['id']] = array_intersect($collections, $availableBaseIds);
|
||||||
|
|
||||||
$this->cache->save('available_collections_'.$databox['id'], $collections);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -69,7 +69,7 @@ class ConfigurationServiceProvider implements ServiceProviderInterface
|
|||||||
});
|
});
|
||||||
|
|
||||||
$app['conf.restrictions'] = $app->share(function (SilexApplication $app) {
|
$app['conf.restrictions'] = $app->share(function (SilexApplication $app) {
|
||||||
return new AccessRestriction($app['cache'], $app['conf'], $app->getApplicationBox(), $app['monolog']);
|
return new AccessRestriction($app['conf'], $app->getApplicationBox(), $app['monolog']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -730,11 +730,7 @@ class ACL implements cache_cacheableInterface
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
$ret[$base_id] = $collection;
|
||||||
$ret[$base_id] = collection::getByBaseId($this->app, $base_id);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -335,7 +335,7 @@ class appbox extends base
|
|||||||
/**
|
/**
|
||||||
* @return AccessRestriction
|
* @return AccessRestriction
|
||||||
*/
|
*/
|
||||||
private function getAccessRestriction()
|
public function getAccessRestriction()
|
||||||
{
|
{
|
||||||
return $this->app['conf.restrictions'];
|
return $this->app['conf.restrictions'];
|
||||||
}
|
}
|
||||||
|
@@ -188,52 +188,73 @@ class collection implements ThumbnailedElement, cache_cacheableInterface
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$repository = self::getRepository($app, $reference->getDataboxId());
|
return self::getAvailableCollection($app, $reference->getDataboxId(), $reference->getCollectionId());
|
||||||
$collection = $repository->find($reference->getCollectionId());
|
}
|
||||||
|
|
||||||
if (!$collection) {
|
/**
|
||||||
throw new Exception_Databox_CollectionNotFound(sprintf(
|
* @param Application $app
|
||||||
"Collection with base_id %s could not be found",
|
* @param databox $databox
|
||||||
$base_id
|
* @param int $collectionId
|
||||||
));
|
* @return collection
|
||||||
}
|
*/
|
||||||
|
public static function getByCollectionId(Application $app, databox $databox, $collectionId)
|
||||||
|
{
|
||||||
|
assert(is_int($collectionId));
|
||||||
|
|
||||||
if (!$app['conf.restrictions']->isCollectionAvailable($collection)) {
|
return self::getAvailableCollection($app, $databox->get_sbas_id(), $collectionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Application $app
|
||||||
|
* @return \Alchemy\Phrasea\Core\Configuration\AccessRestriction
|
||||||
|
*/
|
||||||
|
private static function getAccessRestriction(Application $app)
|
||||||
|
{
|
||||||
|
return $app['conf.restrictions'];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function assertCollectionIsAvailable(Application $app, collection $collection)
|
||||||
|
{
|
||||||
|
if (!self::getAccessRestriction($app)->isCollectionAvailable($collection)) {
|
||||||
throw new Exception_Databox_CollectionNotFound(sprintf(
|
throw new Exception_Databox_CollectionNotFound(sprintf(
|
||||||
'Collection `%d` is not available here.',
|
'Collection `%d` is not available here.',
|
||||||
$collection->get_base_id()
|
$collection->get_base_id()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Application $app
|
||||||
|
* @param int $databoxId
|
||||||
|
* @param int $collectionId
|
||||||
|
* @return collection
|
||||||
|
*/
|
||||||
|
private static function getByDataboxIdAndCollectionId(Application $app, $databoxId, $collectionId)
|
||||||
|
{
|
||||||
|
$repository = self::getRepository($app, $databoxId);
|
||||||
|
$collection = $repository->find($collectionId);
|
||||||
|
|
||||||
|
if (!$collection) {
|
||||||
|
throw new Exception_Databox_CollectionNotFound(sprintf(
|
||||||
|
"Collection '%d' on databox '%d' could not be found",
|
||||||
|
$collectionId,
|
||||||
|
$databoxId
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return $collection;
|
return $collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Application $app
|
* @param Application $app
|
||||||
* @param databox $databox
|
* @param int $databoxId
|
||||||
* @param int $coll_id
|
* @param int $collectionId
|
||||||
* @return collection
|
* @return collection
|
||||||
*/
|
*/
|
||||||
public static function getByCollectionId(Application $app, databox $databox, $coll_id)
|
private static function getAvailableCollection(Application $app, $databoxId, $collectionId)
|
||||||
{
|
{
|
||||||
assert(is_int($coll_id));
|
$collection = self::getByDataboxIdAndCollectionId($app, $databoxId, $collectionId);
|
||||||
|
self::assertCollectionIsAvailable($app, $collection);
|
||||||
$repository = self::getRepository($app, $databox->get_sbas_id());
|
|
||||||
$collection = $repository->find($coll_id);
|
|
||||||
|
|
||||||
if (!$collection) {
|
|
||||||
throw new Exception_Databox_CollectionNotFound(sprintf(
|
|
||||||
"Collection with collection ID %d could not be found",
|
|
||||||
$coll_id
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$app['conf.restrictions']->isCollectionAvailable($collection)) {
|
|
||||||
throw new Exception_Databox_CollectionNotFound(sprintf(
|
|
||||||
'Collection `%d` is not available here.',
|
|
||||||
$collection->get_base_id()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $collection;
|
return $collection;
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ class AccessRestrictionTest extends \PhraseanetTestCase
|
|||||||
$conf = new MockArrayConf($conf);
|
$conf = new MockArrayConf($conf);
|
||||||
$logger = $this->createLoggerMock();
|
$logger = $this->createLoggerMock();
|
||||||
|
|
||||||
$restriction = new AccessRestriction(new ArrayCache(), new PropertyAccess($conf), self::$DI['app']['phraseanet.appbox'], $logger);
|
$restriction = new AccessRestriction(new PropertyAccess($conf), self::$DI['app']['phraseanet.appbox'], $logger);
|
||||||
$this->assertEquals($restricted, $restriction->isRestricted());
|
$this->assertEquals($restricted, $restriction->isRestricted());
|
||||||
|
|
||||||
foreach ($collAccess as $coll) {
|
foreach ($collAccess as $coll) {
|
||||||
|
Reference in New Issue
Block a user