mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Implement user right refs #263
Merge of branch add_acl Squashed commit of the following: commit a3265a71014fc74bcc456aa9436494fc4ed434ea Merge: 2522634 b231b14 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Tue Jun 30 09:58:23 2015 +0200 Merge remote-tracking branch 'origin/master' into add_acl in order to future merging of add_acl into master Conflicts: Tests/Controller/PersonControllerCreateTest.php commit 252263400b1fb54091a0cd36d9ab84812c3a9942 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Mon Jun 29 23:00:25 2015 +0200 check acl on timeline page commit 5f08806585ce4ce1d58c6c507b191221b924d861 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 19 22:24:18 2015 +0200 remove dead code commit 860d62d9c0d9db2186eee725e7ef553ddf1f98f3 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 19 22:19:02 2015 +0200 add access condition for link to person view in person view commit e7b295000dd420309288e83920f6656679d36173 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 19 22:13:04 2015 +0200 add ACL on person view commit 7b1f90a2a28c1aec5ee0eb78206c75a9f1e09c60 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 19 21:47:49 2015 +0200 add autorization for filtering person results in search commit c6669164e2e36b555bed0745d5c7c12b53468b97 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 19 21:47:26 2015 +0200 add fixtures for roles defined by person bundle commit 8f30f5222efe531fb77a2e22b6af8069c5814d00 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 19 20:13:17 2015 +0200 [transfer purpose][ci-skip] commit e8ca4ce4842e619342a90d4343b725c2946f7d70 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 19 17:31:27 2015 +0200 should fix reference problem commit 8c32524a0fd61d504e9640705b97d10bd9b2b993 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 19 17:29:48 2015 +0200 fix test about inheritance commit d93cef2c596aba7fc977cc8db354241d6a77e6e2 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Thu Jun 18 21:38:59 2015 +0200 add role hierarchy + test commit 5066cc5318d67f20e3cff9f91f6d2b6a94d5f9c1 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Thu Jun 18 01:28:40 2015 +0200 add tests for person voter commit cf3359b11b16972db3c55102a3c8b2aae2c27789 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Thu Jun 18 01:07:30 2015 +0200 fix "pass by reference" error commit 94942eb34330813a10124ba58ec814ca685930c5 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Wed Jun 17 22:04:49 2015 +0200 fix syntax error ($this->$is not correct) commit 82d25df6b0e21b4032f4fc82dee203ccd1a067dd Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Wed Jun 17 21:51:41 2015 +0200 add first test for person voter commit 84e0d05be07477175db1ef95f3716a3c420291ce Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Wed Jun 17 21:50:06 2015 +0200 define person voter as a service + CHILL_PERSON_SEE commit bd55e505a179b0df4133903f766d9a8feb469900 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Tue Jun 16 20:57:25 2015 +0200 add test for creating person with user multi center commit d29147c8e70b2ae8313d973fe4b3d45d3f064d9b Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Mon Jun 15 09:11:56 2015 +0200 fix tests - add center to persons since a center is associated with center, people used in tests must be associated with a center. => associate a center to people used in tests commit cfac1ea68aaf615b5f8e9e67388f5407e5095d72 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Mon Jun 15 09:06:24 2015 +0200 remove errors on deprecation commit e1df87df87e831f3827721313603bcf41b3da891 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 12 22:31:03 2015 +0200 fix migration error commit 733fa96a2d874b84d2a0ece6664e4a64eed10b4d Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Wed Jun 10 21:17:15 2015 +0200 add center type on creation forms tests are not adapted yet [ci skip] commit c0d1d1b1c8fd58d9c15bf59d66de28a848df6d35 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Tue Jun 9 23:11:07 2015 +0200 fix bug in migration commit 693abfb7253dfe955beb63de3aebc05a15363cdb Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Tue Jun 9 22:41:21 2015 +0200 add checks on migration check that there are data or not in database and, if there are data, create default center if required. If not required, the default center is the first in the list. commit 8127ea8d49e094c81ce65e838416953bc8d47678 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Mon Jun 8 00:33:39 2015 +0200 add first impl of PersonVoter (not tested) [ci skip] commit 2ea674dbcf8848603f0fefa109abf2412722013f Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Mon Jun 8 00:32:46 2015 +0200 add center to person commit 0b1e3f137ace9eeb959b80cdbdfa3636c75af715 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Sat Jun 6 11:02:49 2015 +0200 add phpunit bridge to handle deprecation msg commit 70a4fd16181badad8ac9b87fd24e1000c7b1a734 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 5 12:42:01 2015 +0200 remove deprecdation warning in phpunit commit b3b8d1deefbdc72505606df7ca217771277e3555 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 5 11:41:36 2015 +0200 fix deprecation of pattern in routing pattern => path in routing.yml commit eea1252d8517ee582c958dc6045f05c1438dd9d1 Author: Julien Fastré <julien.fastre@champs-libres.coop> Date: Fri Jun 5 10:56:02 2015 +0200 switch to symfony 2.7 [ci-skip]
This commit is contained in:
parent
b231b14605
commit
513d9aefbc
@ -51,9 +51,13 @@ class PersonController extends Controller
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
return $this->createNotFoundException("Person with id $person_id not found on this server");
|
||||
return $this->createNotFoundException("Person with id $person_id not"
|
||||
. " found on this server");
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person,
|
||||
"You are not allowed to see this person.");
|
||||
|
||||
return $this->render('ChillPersonBundle:Person:view.html.twig',
|
||||
array("person" => $person,
|
||||
"cFGroup" => $this->getCFGroup()));
|
||||
@ -67,6 +71,9 @@ class PersonController extends Controller
|
||||
return $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_UPDATE', $person,
|
||||
'You are not allowed to edit this person');
|
||||
|
||||
$form = $this->createForm(new PersonType(), $person,
|
||||
array(
|
||||
"action" => $this->generateUrl('chill_person_general_update',
|
||||
@ -87,6 +94,9 @@ class PersonController extends Controller
|
||||
return $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_UPDATE', $person,
|
||||
'You are not allowed to edit this person');
|
||||
|
||||
$form = $this->createForm(new PersonType(), $person,
|
||||
array("cFGroup" => $this->getCFGroup()));
|
||||
|
||||
@ -120,64 +130,6 @@ class PersonController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
public function searchAction()
|
||||
{
|
||||
$q = $this->getRequest()->query->getAlnum('q', '');
|
||||
$q = trim($q);
|
||||
|
||||
if ( $q === '' ) {
|
||||
$this->get('session')
|
||||
->getFlashBag()
|
||||
->add('info',
|
||||
$this->get('translator')
|
||||
->trans('Your query is empty. Be more explicive')
|
||||
);
|
||||
}
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$offset = $this->getRequest()->query->getInt('offet', 0);
|
||||
$limit = $this->getRequest()->query->getInt('limit', 30);
|
||||
|
||||
$dql = 'SELECT p FROM ChillPersonBundle:Person p'
|
||||
. ' WHERE'
|
||||
. ' LOWER(p.firstName) like LOWER(:q)'
|
||||
. ' OR LOWER(p.lastName) like LOWER(:q)';
|
||||
|
||||
if ($this->container->getParameter('cl_chill_person.search.use_double_metaphone')) {
|
||||
$dql .= ' OR DOUBLEMETAPHONE(p.lastName) = DOUBLEMETAPHONE(:qabsolute)';
|
||||
}
|
||||
|
||||
|
||||
$query = $em->createQuery($dql)
|
||||
->setParameter('q', '%'.$q.'%');
|
||||
if ($this->container->getParameter('cl_chill_person.search.use_double_metaphone')) {
|
||||
$query->setParameter('qabsolute', $q);
|
||||
}
|
||||
|
||||
// ->setOffset($offset)
|
||||
// ->setLimit($limit)
|
||||
$persons = $query->getResult() ;
|
||||
|
||||
|
||||
if (count($persons) === 0 ){
|
||||
$this->get('session')
|
||||
->getFlashBag()
|
||||
->add('info',
|
||||
$this->get('translator')
|
||||
->trans('Your query %q% gives no results', array(
|
||||
'%q%' => $q
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
return $this->render('ChillPersonBundle:Person:list.html.twig',
|
||||
array(
|
||||
'persons' => $persons,
|
||||
'pattern' => $q
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a csv file with all the persons
|
||||
*
|
||||
@ -199,10 +151,22 @@ class PersonController extends Controller
|
||||
}
|
||||
|
||||
public function newAction()
|
||||
{
|
||||
{
|
||||
// this is a dummy default center.
|
||||
$defaultCenter = $this->get('security.token_storage')
|
||||
->getToken()
|
||||
->getUser()
|
||||
->getGroupCenters()[0]
|
||||
->getCenter();
|
||||
|
||||
$person = (new Person())
|
||||
->setCenter($defaultCenter);
|
||||
|
||||
$form = $this->createForm(
|
||||
new CreationPersonType(CreationPersonType::FORM_NOT_REVIEWED),
|
||||
null, array('action' => $this->generateUrl('chill_person_review')));
|
||||
array('creation_date' => new \DateTime(), 'center' => $defaultCenter),
|
||||
array('action' => $this->generateUrl('chill_person_review'))
|
||||
);
|
||||
|
||||
return $this->_renderNewForm($form);
|
||||
}
|
||||
@ -232,6 +196,7 @@ class PersonController extends Controller
|
||||
->setLastName($form['lastName']->getData())
|
||||
->setGenre($form['genre']->getData())
|
||||
->setDateOfBirth($form['dateOfBirth']->getData())
|
||||
->setCenter($form['center']->getData())
|
||||
;
|
||||
|
||||
return $person;
|
||||
@ -360,6 +325,9 @@ class PersonController extends Controller
|
||||
|
||||
$errors = $this->_validatePersonAndAccompanyingPeriod($person);
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_CREATE', $person,
|
||||
'You are not allowed to create this person');
|
||||
|
||||
if ($errors->count() === 0) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
|
@ -40,6 +40,8 @@ class TimelinePersonController extends Controller
|
||||
if ($person === NULL) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
|
||||
|
||||
return $this->render('ChillPersonBundle:Timeline:index.html.twig', array
|
||||
(
|
||||
|
@ -118,7 +118,8 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
'FirstName' => $firstName,
|
||||
'LastName' => $lastName,
|
||||
'Genre' => $sex,
|
||||
'Nationality' => (rand(0,100) > 50) ? NULL: 'BE'
|
||||
'Nationality' => (rand(0,100) > 50) ? NULL: 'BE',
|
||||
'center' => (rand(0,1) == 0) ? 'centerA': 'centerB'
|
||||
);
|
||||
|
||||
$this->addAPerson($this->fillWithDefault($person), $manager);
|
||||
@ -151,18 +152,19 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
foreach ($person as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'CountryOfBirth':
|
||||
$p->setCountryOfBirth($this->getCountry($value));
|
||||
$value = $this->getCountry($value);
|
||||
break;
|
||||
case 'Nationality':
|
||||
$p->setNationality($this->getCountry($value));
|
||||
$value = $this->getCountry($value);
|
||||
break;
|
||||
case 'DateOfBirth':
|
||||
$value = new \DateTime($value);
|
||||
|
||||
|
||||
default:
|
||||
call_user_func(array($p, 'set'.$key), $value);
|
||||
break;
|
||||
case 'center':
|
||||
$value = $this->getReference($value);
|
||||
break;
|
||||
}
|
||||
call_user_func(array($p, 'set'.$key), $value);
|
||||
}
|
||||
|
||||
$manager->persist($p);
|
||||
@ -210,7 +212,8 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
'PlaceOfBirth' => "Châteauroux",
|
||||
'Genre' => Person::GENRE_MAN,
|
||||
'CountryOfBirth' => 'FR',
|
||||
'Nationality' => 'RU'
|
||||
'Nationality' => 'RU',
|
||||
'center' => 'centerA'
|
||||
),
|
||||
array(
|
||||
//to have a person with same firstname as Gérard Depardieu
|
||||
@ -218,24 +221,28 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con
|
||||
'LastName' => "Jean",
|
||||
'DateOfBirth' => "1960-10-12",
|
||||
'CountryOfBirth' => 'FR',
|
||||
'Nationality' => 'FR'
|
||||
'Nationality' => 'FR',
|
||||
'center' => 'centerA'
|
||||
),
|
||||
array(
|
||||
//to have a person with same birthdate of Gérard Depardieu
|
||||
'FirstName' => 'Van Snick',
|
||||
'LastName' => 'Bart',
|
||||
'DateOfBirth' => '1948-12-27'
|
||||
'DateOfBirth' => '1948-12-27',
|
||||
'center' => 'centerA'
|
||||
),
|
||||
array(
|
||||
//to have a woman with Depardieu as FirstName
|
||||
'FirstName' => 'Depardieu',
|
||||
'LastName' => 'Charline',
|
||||
'Genre' => Person::GENRE_WOMAN
|
||||
'Genre' => Person::GENRE_WOMAN,
|
||||
'center' => 'centerA'
|
||||
),
|
||||
array(
|
||||
//to have a special character in lastName
|
||||
'FirstName' => 'Manço',
|
||||
'LastName' => 'Étienne'
|
||||
'LastName' => 'Étienne',
|
||||
'center' => 'centerA'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
79
DataFixtures/ORM/LoadPersonACL.php
Normal file
79
DataFixtures/ORM/LoadPersonACL.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadPermissionsGroup;
|
||||
use Chill\MainBundle\Entity\RoleScope;
|
||||
|
||||
/**
|
||||
* Add a role CHILL_PERSON_UPDATE & CHILL_PERSON_CREATE for all groups except administrative,
|
||||
* and a role CHILL_PERSON_SEE for administrative
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class LoadPersonACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
public function getOrder()
|
||||
{
|
||||
return 9600;
|
||||
}
|
||||
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) {
|
||||
$permissionsGroup = $this->getReference($permissionsGroupRef);
|
||||
$scope = $this->getReference('scope_all');
|
||||
|
||||
//create permission group
|
||||
switch ($permissionsGroup->getName()) {
|
||||
case 'social':
|
||||
case 'direction':
|
||||
printf("Adding CHILL_PERSON_UPDATE & CHILL_PERSON_CREATE to %s permission group \n", $permissionsGroup->getName());
|
||||
$roleScopeUpdate = (new RoleScope())
|
||||
->setRole('CHILL_PERSON_UPDATE')
|
||||
->setScope($scope);
|
||||
$permissionsGroup->addRoleScope($roleScopeUpdate);
|
||||
$roleScopeCreate = (new RoleScope())
|
||||
->setRole('CHILL_PERSON_CREATE')
|
||||
->setScope($scope);
|
||||
$permissionsGroup->addRoleScope($roleScopeCreate);
|
||||
$manager->persist($roleScopeUpdate);
|
||||
$manager->persist($roleScopeCreate);
|
||||
break;
|
||||
case 'administrative':
|
||||
printf("Adding CHILL_PERSON_SEE to %s permission group \n", $permissionsGroup->getName());
|
||||
$roleScopeSee = (new RoleScope())
|
||||
->setRole('CHILL_PERSON_SEE')
|
||||
->setScope($scope);
|
||||
$permissionsGroup->addRoleScope($roleScopeSee);
|
||||
$manager->persist($roleScopeSee);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
}
|
@ -49,6 +49,8 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
|
||||
public function prepend(ContainerBuilder $container)
|
||||
{
|
||||
$this->prependRoleHierarchy($container);
|
||||
|
||||
$bundles = $container->getParameter('kernel.bundles');
|
||||
//add ChillMain to assetic-enabled bundles
|
||||
if (!isset($bundles['AsseticBundle'])) {
|
||||
@ -71,4 +73,14 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
protected function prependRoleHierarchy(ContainerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('security', array(
|
||||
'role_hierarchy' => array(
|
||||
'CHILL_PERSON_UPDATE' => array('CHILL_PERSON_SEE'),
|
||||
'CHILL_PERSON_CREATE' => array('CHILL_PERSON_SEE')
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,12 @@ namespace Chill\PersonBundle\Entity;
|
||||
use Symfony\Component\Validator\ExecutionContextInterface;
|
||||
use Chill\MainBundle\Entity\Country;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Chill\MainBundle\Entity\HasCenterInterface;
|
||||
|
||||
/**
|
||||
* Person
|
||||
*/
|
||||
class Person {
|
||||
class Person implements HasCenterInterface {
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
@ -60,6 +61,12 @@ class Person {
|
||||
*/
|
||||
private $genre;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\MainBundle\Entity\Center
|
||||
*/
|
||||
private $center;
|
||||
|
||||
const GENRE_MAN = 'man';
|
||||
const GENRE_WOMAN = 'woman';
|
||||
|
||||
@ -486,7 +493,30 @@ class Person {
|
||||
public function getLabel() {
|
||||
return $this->getFirstName()." ".$this->getLastName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get center
|
||||
*
|
||||
* @return \Chill\MainBundle\Entity\Center
|
||||
*/
|
||||
public function getCenter()
|
||||
{
|
||||
return $this->center;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the center
|
||||
*
|
||||
* @param \Chill\MainBundle\Entity\Center $center
|
||||
* @return \Chill\PersonBundle\Entity\Person
|
||||
*/
|
||||
public function setCenter(\Chill\MainBundle\Entity\Center $center)
|
||||
{
|
||||
$this->center = $center;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set cFData
|
||||
*
|
||||
|
@ -66,6 +66,7 @@ class CreationPersonType extends AbstractType
|
||||
->addModelTransformer($dateToStringTransformer)
|
||||
)
|
||||
->add('form_status', 'hidden')
|
||||
->add('center', 'center')
|
||||
;
|
||||
} else {
|
||||
$builder
|
||||
@ -80,6 +81,7 @@ class CreationPersonType extends AbstractType
|
||||
'widget' => 'single_text', 'format' => 'dd-MM-yyyy',
|
||||
'data' => new \DateTime()))
|
||||
->add('form_status', 'hidden', array('data' => $this->form_status))
|
||||
->add('center', 'center')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,9 @@ Chill\PersonBundle\Entity\Person:
|
||||
targetEntity: Chill\MainBundle\Entity\Country
|
||||
inversedBy: nationals
|
||||
nullable: true
|
||||
center:
|
||||
targetEntity: Chill\MainBundle\Entity\Center
|
||||
nullable: false
|
||||
oneToMany:
|
||||
accompanyingPeriods:
|
||||
targetEntity: AccompanyingPeriod
|
||||
|
@ -1,5 +1,5 @@
|
||||
chill_person_view:
|
||||
pattern: /{_locale}/person/{person_id}/general
|
||||
path: /{_locale}/person/{person_id}/general
|
||||
defaults: { _controller: ChillPersonBundle:Person:view }
|
||||
options:
|
||||
menus:
|
||||
@ -8,15 +8,15 @@ chill_person_view:
|
||||
label: Person details
|
||||
|
||||
chill_person_general_edit:
|
||||
pattern: /{_locale}/person/{person_id}/general/edit
|
||||
path: /{_locale}/person/{person_id}/general/edit
|
||||
defaults: {_controller: ChillPersonBundle:Person:edit }
|
||||
|
||||
chill_person_general_update:
|
||||
pattern: /{_locale}/person/{person_id}/general/update
|
||||
path: /{_locale}/person/{person_id}/general/update
|
||||
defaults: {_controller: ChillPersonBundle:Person:update }
|
||||
|
||||
chill_person_new:
|
||||
pattern: /{_locale}/person/new
|
||||
path: /{_locale}/person/new
|
||||
defaults: {_controller: ChillPersonBundle:Person:new }
|
||||
options:
|
||||
menus:
|
||||
@ -29,15 +29,15 @@ chill_person_new:
|
||||
icons: [plus, male, female]
|
||||
|
||||
chill_person_review:
|
||||
pattern: /{_locale}/person/review
|
||||
path: /{_locale}/person/review
|
||||
defaults: {_controller: ChillPersonBundle:Person:review }
|
||||
|
||||
chill_person_create:
|
||||
pattern: /{_locale}/person/create
|
||||
path: /{_locale}/person/create
|
||||
defaults: {_controller: ChillPersonBundle:Person:create }
|
||||
|
||||
chill_person_search:
|
||||
pattern: /{_locale}/person/search
|
||||
path: /{_locale}/person/search
|
||||
defaults: { _controller: ChillPersonBundle:Person:search }
|
||||
options:
|
||||
menus:
|
||||
@ -46,7 +46,7 @@ chill_person_search:
|
||||
label: Search within persons
|
||||
|
||||
chill_person_accompanying_period_list:
|
||||
pattern: /{_locale}/person/{person_id}/accompanying-period
|
||||
path: /{_locale}/person/{person_id}/accompanying-period
|
||||
defaults: { _controller: ChillPersonBundle:AccompanyingPeriod:list }
|
||||
# options:
|
||||
# menus:
|
||||
@ -55,23 +55,23 @@ chill_person_accompanying_period_list:
|
||||
# label: menu.person.history
|
||||
|
||||
chill_person_accompanying_period_create:
|
||||
pattern: /{_locale}/person/{person_id}/accompanying-period/create
|
||||
path: /{_locale}/person/{person_id}/accompanying-period/create
|
||||
defaults: { _controller: ChillPersonBundle:AccompanyingPeriod:create }
|
||||
|
||||
chill_person_accompanying_period_update:
|
||||
pattern: /{_locale}/person/{person_id}/accompanying-period/{period_id}/update
|
||||
path: /{_locale}/person/{person_id}/accompanying-period/{period_id}/update
|
||||
defaults: { _controller: ChillPersonBundle:AccompanyingPeriod:update }
|
||||
|
||||
chill_person_accompanying_period_close:
|
||||
pattern: /{_locale}/person/{person_id}/accompanying-period/close
|
||||
path: /{_locale}/person/{person_id}/accompanying-period/close
|
||||
defaults: { _controller: ChillPersonBundle:AccompanyingPeriod:close }
|
||||
|
||||
chill_person_accompanying_period_open:
|
||||
pattern: /{_locale}/person/{person_id}/accompanying-period/open
|
||||
path: /{_locale}/person/{person_id}/accompanying-period/open
|
||||
defaults: { _controller: ChillPersonBundle:AccompanyingPeriod:open }
|
||||
|
||||
chill_person_admin:
|
||||
pattern: /{_locale}/admin/person
|
||||
path: /{_locale}/admin/person
|
||||
defaults: { _controller: ChillPersonBundle:Admin:index }
|
||||
options:
|
||||
menus:
|
||||
@ -81,7 +81,7 @@ chill_person_admin:
|
||||
helper: menu.person.admin.helper
|
||||
|
||||
chill_person_export:
|
||||
pattern: /{_locale}/person/export/
|
||||
path: /{_locale}/person/export/
|
||||
defaults: { _controller: ChillPersonBundle:Person:export }
|
||||
options:
|
||||
menus:
|
||||
@ -90,7 +90,7 @@ chill_person_export:
|
||||
label: Export persons
|
||||
|
||||
chill_person_timeline:
|
||||
pattern: /{_locale}/person/{person_id}/timeline
|
||||
path: /{_locale}/person/{person_id}/timeline
|
||||
defaults: { _controller: ChillPersonBundle:TimelinePerson:person }
|
||||
options:
|
||||
menus:
|
||||
|
@ -14,6 +14,8 @@ services:
|
||||
class: Chill\PersonBundle\Search\PersonSearch
|
||||
arguments:
|
||||
- "@doctrine.orm.entity_manager"
|
||||
- "@security.token_storage"
|
||||
- "@chill.main.security.authorization.helper"
|
||||
calls:
|
||||
- ['setContainer', ["@service_container"]]
|
||||
tags:
|
||||
@ -32,3 +34,10 @@ services:
|
||||
- "@doctrine.orm.entity_manager"
|
||||
tags:
|
||||
- { name: chill.timeline, context: 'person' }
|
||||
|
||||
chill.person.security.authorization.person:
|
||||
class: Chill\PersonBundle\Security\Authorization\PersonVoter
|
||||
arguments:
|
||||
- "@chill.main.security.authorization.helper"
|
||||
tags:
|
||||
- { name: security.voter }
|
||||
|
100
Resources/migrations/Version20150607231010.php
Normal file
100
Resources/migrations/Version20150607231010.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Application\Migrations;
|
||||
|
||||
use Doctrine\DBAL\Migrations\AbstractMigration;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
|
||||
/**
|
||||
* Add a center to class person
|
||||
*
|
||||
*/
|
||||
class Version20150607231010 extends AbstractMigration implements ContainerAwareInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
if ($container === NULL) {
|
||||
throw new \RuntimeException('Container is not provided. This migration '
|
||||
. 'need container to set a default center');
|
||||
}
|
||||
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return 'Add a center on the person entity. The default center is the first '
|
||||
. 'recorded.';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function up(Schema $schema)
|
||||
{
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
|
||||
|
||||
// retrieve center for setting a default center
|
||||
$centers = $this->container->get('doctrine.orm.entity_manager')
|
||||
->getRepository('ChillMainBundle:Center')
|
||||
->findAll();
|
||||
|
||||
|
||||
if (count($centers) > 0) {
|
||||
$defaultCenterId = $centers[0]->getId();
|
||||
} else { // if no center, performs other checks
|
||||
//check if there are data in person table
|
||||
$nbPeople = $this->container->get('doctrine.orm.entity_manager')
|
||||
->createQuery('SELECT count(p) FROM ChillPersonBundle:Person p')
|
||||
->getSingleScalarResult();
|
||||
|
||||
if ($nbPeople > 0) {
|
||||
// we have data ! We have to create a center !
|
||||
$center = new Center();
|
||||
$center->setName('Auto-created center');
|
||||
$this->container->get('doctrine.orm.entity_manager')
|
||||
->persist($center)
|
||||
->flush();
|
||||
$defaultCenterId = $center->getId();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->addSql('ALTER TABLE person ADD center_id INT');
|
||||
|
||||
if (isset($defaultCenterId)) {
|
||||
$this->addSql('UPDATE person SET center_id = :id', array('id' => $defaultCenterId));
|
||||
}
|
||||
|
||||
$this->addSql('ALTER TABLE person '
|
||||
. 'ADD CONSTRAINT FK_person_center FOREIGN KEY (center_id) '
|
||||
. 'REFERENCES centers (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE person ALTER center_id SET NOT NULL');
|
||||
$this->addSql('CREATE INDEX IDX_person_center ON person (center_id)');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function down(Schema $schema)
|
||||
{
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE Person DROP CONSTRAINT FK_person_center');
|
||||
$this->addSql('DROP INDEX IDX_person_center');
|
||||
$this->addSql('ALTER TABLE Person DROP center_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -35,8 +35,9 @@ This view should receive those arguments:
|
||||
|
||||
{% block personcontent %}
|
||||
|
||||
|
||||
{% if is_granted('CHILL_PERSON_UPDATE', person) %}
|
||||
{{ include(edit_tmp_name, edit_tmp_args) }}
|
||||
{% endif %}
|
||||
|
||||
<figure>
|
||||
<h2>{{ 'General information'|trans }}</h2>
|
||||
@ -83,7 +84,9 @@ This view should receive those arguments:
|
||||
</dl>
|
||||
</figure>
|
||||
|
||||
{% if is_granted('CHILL_PERSON_UPDATE', person) %}
|
||||
{{ include(edit_tmp_name, edit_tmp_args) }}
|
||||
{% endif %}
|
||||
|
||||
<figure>
|
||||
<h2>{{ 'Administrative information'|trans }}</h2>
|
||||
@ -112,7 +115,9 @@ This view should receive those arguments:
|
||||
</dl>
|
||||
</figure>
|
||||
|
||||
{% if is_granted('CHILL_PERSON_UPDATE', person) %}
|
||||
{{ include(edit_tmp_name, edit_tmp_args) }}
|
||||
{% endif %}
|
||||
|
||||
<figure>
|
||||
<h2>{{ 'Contact information'|trans }}</h2>
|
||||
@ -128,7 +133,9 @@ This view should receive those arguments:
|
||||
|
||||
</figure>
|
||||
|
||||
{% if is_granted('CHILL_PERSON_UPDATE', person) %}
|
||||
{{ include(edit_tmp_name, edit_tmp_args) }}
|
||||
{% endif %}
|
||||
|
||||
{% if cFGroup %}
|
||||
<figure>
|
||||
@ -142,7 +149,9 @@ This view should receive those arguments:
|
||||
{% endfor %}
|
||||
</figure>
|
||||
|
||||
{{ include(edit_tmp_name, edit_tmp_args) }}
|
||||
{% if is_granted('CHILL_PERSON_UPDATE', person) %}
|
||||
{{ include(edit_tmp_name, edit_tmp_args) }}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
@ -23,11 +23,14 @@ use Chill\MainBundle\Search\AbstractSearch;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAware;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
use Chill\MainBundle\Search\ParsingException;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class PersonSearch extends AbstractSearch
|
||||
class PersonSearch extends AbstractSearch implements ContainerAwareInterface
|
||||
{
|
||||
use ContainerAwareTrait;
|
||||
|
||||
@ -37,10 +40,31 @@ class PersonSearch extends AbstractSearch
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\MainBundle\Entity\User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
private $helper;
|
||||
|
||||
|
||||
public function __construct(EntityManagerInterface $em,
|
||||
TokenStorage $tokenStorage, AuthorizationHelper $helper)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->user = $tokenStorage->getToken()->getUser();
|
||||
$this->helper = $helper;
|
||||
|
||||
// throw an error if user is not a valid user
|
||||
if (!$this->user instanceof \Chill\MainBundle\Entity\User) {
|
||||
throw new \LogicException('The user provided must be an instance'
|
||||
. ' of Chill\MainBundle\Entity\User');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -189,6 +213,14 @@ class PersonSearch extends AbstractSearch
|
||||
}
|
||||
}
|
||||
|
||||
//restraint center for security
|
||||
$reachableCenters = $this->helper->getReachableCenters($this->user,
|
||||
new Role('CHILL_PERSON_SEE'));
|
||||
$qb->andWhere($qb->expr()
|
||||
->in('p.center', ':centers'))
|
||||
->setParameter('centers', $reachableCenters)
|
||||
;
|
||||
|
||||
$this->_cacheQuery[$cacheKey] = $qb;
|
||||
|
||||
return $qb;
|
||||
|
67
Security/Authorization/PersonVoter.php
Normal file
67
Security/Authorization/PersonVoter.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PersonVoter extends AbstractChillVoter
|
||||
{
|
||||
const CREATE = 'CHILL_PERSON_CREATE';
|
||||
const UPDATE = 'CHILL_PERSON_UPDATE';
|
||||
const SEE = 'CHILL_PERSON_SEE';
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
protected $helper;
|
||||
|
||||
public function __construct(AuthorizationHelper $helper)
|
||||
{
|
||||
$this->helper = $helper;
|
||||
}
|
||||
|
||||
protected function getSupportedAttributes()
|
||||
{
|
||||
return array(self::CREATE, self::UPDATE, self::SEE);
|
||||
}
|
||||
|
||||
protected function getSupportedClasses()
|
||||
{
|
||||
return array('Chill\PersonBundle\Entity\Person');
|
||||
}
|
||||
|
||||
protected function isGranted($attribute, $person, $user = null)
|
||||
{
|
||||
if (!$user instanceof User) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->helper->userHasAccess($user, $person, $attribute);
|
||||
|
||||
}
|
||||
}
|
@ -77,9 +77,13 @@ class AccompanyingPeriodControllerTest extends WebTestCase
|
||||
'PHP_AUTH_PW' => 'password',
|
||||
));
|
||||
|
||||
$center = static::$em->getRepository('ChillMainBundle:Center')
|
||||
->findOneBy(array('name' => 'Center A'));
|
||||
|
||||
$this->person = (new Person(new \DateTime('2015-01-05')))
|
||||
->setFirstName('Roland')
|
||||
->setLastName('Gallorime')
|
||||
->setCenter($center)
|
||||
->setGenre(Person::GENRE_MAN);
|
||||
|
||||
static::$em->persist($this->person);
|
||||
|
@ -36,6 +36,8 @@ class PersonControllerCreateTest extends WebTestCase
|
||||
const GENRE_INPUT = "chill_personbundle_person_creation[genre]";
|
||||
const DATEOFBIRTH_INPUT = "chill_personbundle_person_creation[dateOfBirth]";
|
||||
const CREATEDATE_INPUT = "chill_personbundle_person_creation[creation_date]";
|
||||
const CENTER_INPUT = "chill_personbundle_person_creation[center]";
|
||||
|
||||
const LONG_TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosq.";
|
||||
|
||||
/**
|
||||
@ -43,10 +45,10 @@ class PersonControllerCreateTest extends WebTestCase
|
||||
*
|
||||
* @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',
|
||||
));
|
||||
}
|
||||
@ -55,10 +57,11 @@ class PersonControllerCreateTest extends WebTestCase
|
||||
*
|
||||
* @param Form $creationForm
|
||||
*/
|
||||
private function fillAValidCreationForm(Form &$creationForm)
|
||||
private function fillAValidCreationForm(Form &$creationForm,
|
||||
$firstname = 'God', $lastname = 'Jesus')
|
||||
{
|
||||
$creationForm->get(self::FIRSTNAME_INPUT)->setValue("God");
|
||||
$creationForm->get(self::LASTNAME_INPUT)->setValue("Jesus");
|
||||
$creationForm->get(self::FIRSTNAME_INPUT)->setValue($firstname);
|
||||
$creationForm->get(self::LASTNAME_INPUT)->setValue($lastname);
|
||||
$creationForm->get(self::GENRE_INPUT)->select("man");
|
||||
$date = new \DateTime('1947-02-01');
|
||||
$creationForm->get(self::DATEOFBIRTH_INPUT)->setValue($date->format('d-m-Y'));
|
||||
@ -203,13 +206,57 @@ class PersonControllerCreateTest extends WebTestCase
|
||||
. "/{_locale}/person/{personID}/general");
|
||||
}
|
||||
|
||||
/**
|
||||
* test adding a person with a user with multi center
|
||||
* is valid
|
||||
*/
|
||||
public function testValidFormWithMultiCenterUser()
|
||||
{
|
||||
$client = $this->getAuthenticatedClient('multi_center');
|
||||
|
||||
$crawler = $client->request('GET', '/fr/person/new');
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful(),
|
||||
"The page is accessible at the URL /{_locale}/person/new");
|
||||
$form = $crawler->selectButton("Ajouter la personne")->form();
|
||||
|
||||
$this->fillAValidCreationForm($form, 'roger', 'rabbit');
|
||||
|
||||
$this->assertTrue($form->has(self::CENTER_INPUT),
|
||||
'The page contains a "center" input');
|
||||
$centerInput = $form->get(self::CENTER_INPUT);
|
||||
$availableValues = $centerInput->availableOptionValues();
|
||||
$lastCenterInputValue = end($availableValues);
|
||||
$centerInput->setValue($lastCenterInputValue);
|
||||
|
||||
$client->submit($form);
|
||||
|
||||
$this->assertTrue($client->getResponse()->isRedirect(),
|
||||
"a valid form redirect to url /{_locale}/person/{personId}/general/edit");
|
||||
$client->followRedirect();
|
||||
$this->assertRegExp('|/fr/person/[1-9][0-9]*/general/edit$|',
|
||||
$client->getHistory()->current()->getUri(),
|
||||
"a valid form redirect to url /{_locale}/person/{personId}/general/edit");
|
||||
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass()
|
||||
{
|
||||
static::bootKernel();
|
||||
$em = static::$kernel->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
//remove two people created during test
|
||||
$jesus = $em->getRepository('ChillPersonBundle:Person')
|
||||
->findOneBy(array('firstName' => 'God'));
|
||||
$em->remove($jesus);
|
||||
if ($jesus !== NULL) {
|
||||
$em->remove($jesus);
|
||||
}
|
||||
|
||||
$jesus2 = $em->getRepository('ChillPersonBundle:Person')
|
||||
->findOneBy(array('firstName' => 'roger'));
|
||||
if ($jesus2 !== NULL) {
|
||||
$em->remove($jesus2);
|
||||
}
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
|
@ -57,13 +57,18 @@ class PersonControllerUpdateTest extends WebTestCase
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$this->em = static::$kernel->getContainer()
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
$center = $this->em->getRepository('ChillMainBundle:Center')
|
||||
->findOneBy(array('name' => 'Center A'));
|
||||
|
||||
$this->person = (new Person())
|
||||
->setLastName("My Beloved")
|
||||
->setFirstName("Jesus")
|
||||
->setCenter($center)
|
||||
->setGenre(Person::GENRE_MAN);
|
||||
|
||||
$this->em = static::$kernel->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
$this->em->persist($this->person);
|
||||
$this->em->flush();
|
||||
|
||||
@ -76,10 +81,6 @@ class PersonControllerUpdateTest extends WebTestCase
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Person
|
||||
*/
|
||||
protected function refreshPerson()
|
||||
{
|
||||
$this->person = $this->em->getRepository('ChillPersonBundle:Person')
|
||||
@ -97,6 +98,30 @@ class PersonControllerUpdateTest extends WebTestCase
|
||||
"The person edit form is accessible");
|
||||
}
|
||||
|
||||
public function testEditPageDeniedForUnauthorized_OutsideCenter()
|
||||
{
|
||||
$client = static::createClient(array(), array(
|
||||
'PHP_AUTH_USER' => 'center b_social',
|
||||
'PHP_AUTH_PW' => 'password',
|
||||
));
|
||||
|
||||
$client->request('GET', $this->editUrl);
|
||||
|
||||
$this->assertEquals(403, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
public function testEditPageDeniedForUnauthorized_InsideCenter()
|
||||
{
|
||||
$client = static::createClient(array(), array(
|
||||
'PHP_AUTH_USER' => 'center a_administrative',
|
||||
'PHP_AUTH_PW' => 'password',
|
||||
));
|
||||
|
||||
$client->request('GET', $this->editUrl);
|
||||
|
||||
$this->assertEquals(403, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* test the edition of a field
|
||||
*
|
||||
|
104
Tests/Controller/PersonControllerViewTest.php
Normal file
104
Tests/Controller/PersonControllerViewTest.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PersonControllerViewTest extends WebTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Doctrine\ORM\EntityManagerInterface
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var Person
|
||||
*/
|
||||
private $person;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$this->em = static::$kernel->getContainer()
|
||||
->get('doctrine.orm.entity_manager');
|
||||
|
||||
$center = $this->em->getRepository('ChillMainBundle:Center')
|
||||
->findOneBy(array('name' => 'Center A'));
|
||||
|
||||
$this->person = (new Person())
|
||||
->setLastName("Tested Person")
|
||||
->setFirstName("Réginald")
|
||||
->setCenter($center)
|
||||
->setGenre(Person::GENRE_MAN);
|
||||
|
||||
$this->em->persist($this->person);
|
||||
$this->em->flush();
|
||||
|
||||
$this->seeUrl = '/en/person/'.$this->person->getId().'/general';
|
||||
}
|
||||
|
||||
public function testViewPerson()
|
||||
{
|
||||
$client = static::createClient(array(), array(
|
||||
'PHP_AUTH_USER' => 'center a_social',
|
||||
'PHP_AUTH_PW' => 'password',
|
||||
));
|
||||
|
||||
$client->request('GET', $this->seeUrl);
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
}
|
||||
|
||||
public function testViewPersonAccessDeniedForUnauthorized()
|
||||
{
|
||||
$client = static::createClient(array(), array(
|
||||
'PHP_AUTH_USER' => 'center b_social',
|
||||
'PHP_AUTH_PW' => 'password',
|
||||
));
|
||||
|
||||
$client->request('GET', $this->seeUrl);
|
||||
|
||||
$this->assertEquals(403, $client->getResponse()->getStatusCode());
|
||||
}
|
||||
|
||||
protected function refreshPerson()
|
||||
{
|
||||
$this->person = $this->em->getRepository('ChillPersonBundle:Person')
|
||||
->find($this->person->getId());
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->refreshPerson();
|
||||
$this->em->remove($this->person);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
}
|
@ -194,9 +194,25 @@ class PersonSearchTest extends WebTestCase
|
||||
$this->assertRegExp('/Étienne/', $crawlerNoSpecial->text());
|
||||
}
|
||||
|
||||
private function generateCrawlerForSearch($pattern)
|
||||
/**
|
||||
* test that person which a user cannot see are not displayed in results
|
||||
*/
|
||||
public function testSearchWithAuthorization()
|
||||
{
|
||||
$client = $this->getAuthenticatedClient();
|
||||
$crawlerCanSee = $this->generateCrawlerForSearch('Gérard', 'center a_social');
|
||||
$crawlerCannotSee = $this->generateCrawlerForSearch('Gérard', 'center b_social');
|
||||
|
||||
$this->assertRegExp('/Gérard/', $crawlerCanSee->text(),
|
||||
'center a_social may see "Gérard" in center a');
|
||||
$this->assertRegExp('/Aucune personne ne correspond aux termes de recherche "gerard"/',
|
||||
$crawlerCannotSee->text(),
|
||||
'center b_social may not see any "Gérard" associated to center b');
|
||||
|
||||
}
|
||||
|
||||
private function generateCrawlerForSearch($pattern, $username = 'center a_social')
|
||||
{
|
||||
$client = $this->getAuthenticatedClient($username);
|
||||
|
||||
$crawler = $client->request('GET', '/fr/search', array(
|
||||
'q' => $pattern
|
||||
@ -211,10 +227,10 @@ class PersonSearchTest extends WebTestCase
|
||||
*
|
||||
* @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',
|
||||
));
|
||||
}
|
||||
|
184
Tests/Security/Authorization/PersonVoterTest.php
Normal file
184
Tests/Security/Authorization/PersonVoterTest.php
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
* Copyright (C) 2015 Champs Libres <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Tests\Security\Authorization;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Entity\PermissionsGroup;
|
||||
use Chill\MainBundle\Entity\GroupCenter;
|
||||
use Chill\MainBundle\Entity\RoleScope;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Test\PrepareUserTrait;
|
||||
use Chill\MainBundle\Test\PrepareCenterTrait;
|
||||
use Chill\MainBundle\Test\PrepareScopeTrait;
|
||||
use Chill\MainBundle\Test\ProphecyTrait;
|
||||
|
||||
/**
|
||||
* Test PersonVoter
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Champs Libres <info@champs-libres.coop>
|
||||
*/
|
||||
class PersonVoterTest extends KernelTestCase
|
||||
{
|
||||
|
||||
use PrepareUserTrait, PrepareCenterTrait, PrepareScopeTrait;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\PersonBundle\Security\Authorization\PersonVoter
|
||||
*/
|
||||
protected $voter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Prophecy\Prophet
|
||||
*/
|
||||
protected $prophet;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
static::bootKernel();
|
||||
$this->voter = static::$kernel->getContainer()
|
||||
->get('chill.person.security.authorization.person');
|
||||
$this->prophet = new \Prophecy\Prophet();
|
||||
}
|
||||
|
||||
public function testNullUser()
|
||||
{
|
||||
$token = $this->prepareToken();
|
||||
$center = $this->prepareCenter(1, 'center');
|
||||
$person = $this->preparePerson($center);
|
||||
|
||||
$this->assertEquals(
|
||||
VoterInterface::ACCESS_DENIED,
|
||||
$this->voter->vote($token, $person, array('CHILL_PERSON_SEE')),
|
||||
"assert that a null user is not allowed to see"
|
||||
);
|
||||
}
|
||||
|
||||
public function testUserCanNotReachCenter()
|
||||
{
|
||||
$centerA = $this->prepareCenter(1, 'centera');
|
||||
$centerB = $this->prepareCenter(2, 'centerb');
|
||||
$scope = $this->prepareScope(1, 'default');
|
||||
$token = $this->prepareToken(array(
|
||||
array(
|
||||
'center' => $centerA, 'permissionsGroup' => array(
|
||||
['scope' => $scope, 'role' => 'CHILL_PERSON_UPDATE']
|
||||
)
|
||||
)
|
||||
));
|
||||
$person = $this->preparePerson($centerB);
|
||||
|
||||
$this->assertEquals(
|
||||
VoterInterface::ACCESS_DENIED,
|
||||
$this->voter->vote($token, $person, array('CHILL_PERSON_UPDATE')),
|
||||
'assert that a user with right not in the good center has access denied'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* test a user with sufficient right may see the person
|
||||
*/
|
||||
public function testUserAllowed()
|
||||
{
|
||||
$center = $this->prepareCenter(1, 'center');
|
||||
$scope = $this->prepareScope(1, 'default');
|
||||
$token = $this->prepareToken(array(
|
||||
array(
|
||||
'center' => $center, 'permissionsGroup' => array(
|
||||
['scope' => $scope, 'role' => 'CHILL_PERSON_SEE']
|
||||
)
|
||||
)
|
||||
));
|
||||
$person = $this->preparePerson($center);
|
||||
|
||||
$this->assertEquals(
|
||||
VoterInterface::ACCESS_GRANTED,
|
||||
$this->voter->vote($token, $person, array('CHILL_PERSON_SEE')),
|
||||
'assert that a user with correct rights may is granted access'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* test a user with sufficient right may see the person.
|
||||
* hierarchy between role is required
|
||||
*/
|
||||
public function testUserAllowedWithInheritance()
|
||||
{
|
||||
$center = $this->prepareCenter(1, 'center');
|
||||
$scope = $this->prepareScope(1, 'default');
|
||||
$token = $this->prepareToken(array(
|
||||
array(
|
||||
'center' => $center, 'permissionsGroup' => array(
|
||||
['scope' => $scope, 'role' => 'CHILL_PERSON_UPDATE']
|
||||
)
|
||||
)
|
||||
));
|
||||
$person = $this->preparePerson($center);
|
||||
$this->assertEquals(
|
||||
VoterInterface::ACCESS_GRANTED,
|
||||
$this->voter->vote($token, $person, array('CHILL_PERSON_SEE')),
|
||||
'assert that a user with correct role is granted on inherited roles'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare a person
|
||||
*
|
||||
* The only properties set is the center, others properties are ignored.
|
||||
*
|
||||
* @param Center $center
|
||||
* @return Person
|
||||
*/
|
||||
protected function preparePerson(Center $center)
|
||||
{
|
||||
return (new Person())
|
||||
->setCenter($center)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare a token interface with correct rights
|
||||
*
|
||||
* if $permissions = null, user will be null (no user associated with token
|
||||
*
|
||||
* @param array $permissions an array of permissions, with key 'center' for the center and 'permissions' for an array of permissions
|
||||
* @return \Symfony\Component\Security\Core\Authentication\Token\TokenInterface
|
||||
*/
|
||||
protected function prepareToken(array $permissions = null)
|
||||
{
|
||||
$token = $this->prophet->prophesize();
|
||||
$token
|
||||
->willImplement('\Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
|
||||
if ($permissions === NULL) {
|
||||
$token->getUser()->willReturn(null);
|
||||
} else {
|
||||
$token->getUser()->willReturn($this->prepareUser($permissions));
|
||||
}
|
||||
|
||||
return $token->reveal();
|
||||
}
|
||||
}
|
@ -20,15 +20,15 @@
|
||||
"twig/extensions": "~1.0",
|
||||
"symfony/assetic-bundle": "~2.3",
|
||||
"symfony/monolog-bundle": "~2.4",
|
||||
"symfony/framework-bundle": "2.5.*",
|
||||
"symfony/yaml": "2.5.*",
|
||||
"symfony/symfony": "~2.5",
|
||||
"symfony/framework-bundle": "~2.7",
|
||||
"symfony/yaml": "~2.7",
|
||||
"symfony/symfony": "~2.7",
|
||||
"doctrine/dbal": "~2.5",
|
||||
"doctrine/orm": "~2.4",
|
||||
"doctrine/common": "~2.4",
|
||||
"doctrine/doctrine-bundle": "~1.2",
|
||||
"chill-project/main": "*@dev",
|
||||
"chill-project/custom-fields": "*@dev",
|
||||
"chill-project/main": "dev-add_acl@dev",
|
||||
"chill-project/custom-fields": "dev-add_acl@dev",
|
||||
"doctrine/doctrine-fixtures-bundle": "~2.2",
|
||||
"champs-libres/composer-bundle-migration": "~1.0",
|
||||
"doctrine/doctrine-migrations-bundle": "dev-master@dev",
|
||||
@ -36,7 +36,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/dom-crawler": "2.5",
|
||||
"symfony/security": "~2.5"
|
||||
"symfony/security": "~2.5",
|
||||
"symfony/phpunit-bridge": "^2.7"
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
|
@ -19,5 +19,6 @@
|
||||
</filter>
|
||||
<php>
|
||||
<server name="KERNEL_DIR" value="/Tests/Fixtures/App/app/" />
|
||||
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
|
||||
</php>
|
||||
</phpunit>
|
||||
</phpunit>
|
||||
|
Loading…
x
Reference in New Issue
Block a user