From a16a097550f72139ddb060f924441010dd2f1935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 30 Jun 2015 00:19:10 +0200 Subject: [PATCH] add acl on report search --- Resources/config/services.yml | 2 ++ Search/ReportSearch.php | 57 ++++++++++++++++++++++++++++++- Tests/Search/ReportSearchTest.php | 27 +++++++++++++-- 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 82310bc37..4d8b4b625 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -8,6 +8,8 @@ services: class: Chill\ReportBundle\Search\ReportSearch arguments: - '@doctrine.orm.entity_manager' + - '@chill.main.security.authorization.helper' + - '@security.token_storage' calls: - [setContainer, ["@service_container"]] tags: diff --git a/Search/ReportSearch.php b/Search/ReportSearch.php index ef5b53965..e5a80716a 100644 --- a/Search/ReportSearch.php +++ b/Search/ReportSearch.php @@ -24,6 +24,11 @@ use Chill\MainBundle\Search\AbstractSearch; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Chill\MainBundle\Search\ParsingException; +use Doctrine\ORM\QueryBuilder; +use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Role\Role; +use Chill\MainBundle\Entity\Scope; /** * Search amongst reports @@ -39,9 +44,28 @@ class ReportSearch extends AbstractSearch implements ContainerAwareInterface */ private $em; - public function __construct(EntityManagerInterface $em) + /** + * + * @var AuthorizationHelper + */ + private $helper; + + /** + * + * @var \Chill\MainBundle\Entity\User + */ + private $user; + + public function __construct(EntityManagerInterface $em, + AuthorizationHelper $helper, TokenStorageInterface $tokenStorage) { $this->em = $em; + $this->helper = $helper; + + if(! $tokenStorage->getToken()->getUser() instanceof \Chill\MainBundle\Entity\User) { + throw new \RuntimeException('an user must be associated with token'); + } + $this->user = $tokenStorage->getToken()->getUser(); } public function getOrder() @@ -120,8 +144,39 @@ class ReportSearch extends AbstractSearch implements ContainerAwareInterface ; } + $query->andWhere($this->addACL($query)); + return $query; } + + private function addACL(QueryBuilder $qb) + { + //adding join + $qb->join('r.person', 'p'); + + $role = new Role('CHILL_REPORT_SEE'); + $reachableCenters = $this->helper->getReachableCenters($this->user, $role); + + $whereElement = $qb->expr()->orX(); + $i = 0; + foreach ($reachableCenters as $center) { + $reachableScopesId = array_map( + function (Scope $scope) { return $scope->getId(); }, + $this->helper->getReachableScopes($this->user, $role, $center) + ); + $whereElement->add( + $qb->expr()->andX( + $qb->expr()->eq('p.center', ':center_'.$i), + $qb->expr()->in('r.scope', ':reachable_scopes_'.$i) + ) + ) + ; + $qb->setParameter('center_'.$i, $center); + $qb->setParameter('reachable_scopes_'.$i, $reachableScopesId); + } + + return $whereElement; + } public function supports($domain) { diff --git a/Tests/Search/ReportSearchTest.php b/Tests/Search/ReportSearchTest.php index 60008e0cd..b650c7cea 100644 --- a/Tests/Search/ReportSearchTest.php +++ b/Tests/Search/ReportSearchTest.php @@ -90,17 +90,38 @@ class ReportSearchTest extends WebTestCase $this->assertGreaterThan(0, $crawler->filter('.error')->count()); } - + /** + * Test that the user do not see unauthorized results + * + * We test for that that : + * - we do not see any unauthorized scope mention + */ + public function testUsersDoNotSeeUnauthorizedResults() + { + $clientSocial = $this->getAuthenticatedClient(); + $clientAdministrative = $this->getAuthenticatedClient('center a_administrative'); + + $params = array('q' => '@report date:2015-01-05'); + + $crawlerSocial = $clientSocial->request('GET', '/fr/search', $params); + $crawlerAdministrative = $clientAdministrative->request('GET', '/fr/search', $params); + + + $this->assertNotContains('social', $crawlerAdministrative->filter('.content') + ->text()); + $this->assertNotContains('administrative', $crawlerAdministrative->filter('.content') + ->text()); + } /** * * @return \Symfony\Component\BrowserKit\Client */ - private function getAuthenticatedClient() + private function getAuthenticatedClient($username = 'center a_social') { return static::createClient(array(), array( - 'PHP_AUTH_USER' => 'center a_social', + 'PHP_AUTH_USER' => $username, 'PHP_AUTH_PW' => 'password', )); }