first impl for api

This commit is contained in:
2021-05-05 20:33:34 +02:00
parent 19fdf2a503
commit f02e33fda7
16 changed files with 849 additions and 87 deletions

View File

@@ -0,0 +1,48 @@
<?php
namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
class AccompanyingCourseApiController extends ApiController
{
public function participationApi($accompanyingPeriodId, Request $request)
{
/** @var AccompanyingPeriod $accompanyingPeriod */
$accompanyingPeriod = $this->getEntity($accompanyingPeriodId);
$person = $this->serializer->deserialize($request->getContent(), Person::class, $_format, []);
if (NULL === $person) {
throw new BadRequestException('person id not found');
}
// TODO add acl
switch ($request->getMethod()) {
case Request::METHOD_POST:
$participation = $accompanyingCours->addPerson($person);
break;
case Request::METHOD_DELETE:
$participation = $accompanyingCours->removePerson($person);
break;
default:
throw new BadRequestException("This method is not supported");
}
$errors = $this->validator->validate($accompanyingCourse);
if ($errors->count() > 0) {
// only format accepted
return $this->json($errors);
}
$this->getDoctrine()->getManager()->flush();
return $this->json($participation);
}
}

View File

@@ -28,6 +28,7 @@ use Chill\MainBundle\DependencyInjection\MissingBundleException;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
use Symfony\Component\HttpFoundation\Request;
/**
* Class ChillPersonExtension
@@ -76,6 +77,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
$loader->load('services/templating.yaml');
$loader->load('services/alt_names.yaml');
$loader->load('services/serializer.yaml');
$loader->load('services/security.yaml');
// load service advanced search only if configure
if ($config['search']['search_by_phone'] != 'never') {
@@ -307,6 +309,34 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
'template' => '@ChillPerson/MaritalStatus/edit.html.twig',
]
]
],
],
'apis' => [
[
'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod::class,
'name' => 'accompanying_course',
'base_path' => '/api/1.0/accompanying_course',
'controller' => \Chill\PersonBundle\Controller\AccompanyingCourseApiController::class,
'actions' => [
'_entity' => [
'roles' => [
Request::METHOD_GET => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
]
],
'/participation' => [
'methods' => [
Request::METHOD_POST => true,
Request::METHOD_DELETE => true,
Request::METHOD_GET => false,
Request::METHOD_HEAD => false,
],
'roles' => [
Request::METHOD_POST => \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE,
Request::METHOD_DELETE=> \Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter::SEE
]
]
]
]
]
]);

View File

@@ -344,50 +344,68 @@ class AccompanyingPeriod
}
/**
* This private function scan Participations Collection,
* searching for a given Person
* Get the participation containing a person
*/
private function participationsContainsPerson(Person $person): ?AccompanyingPeriodParticipation
public function getParticipationsContainsPerson(Person $person): Collection
{
foreach ($this->participations as $participation) {
/** @var AccompanyingPeriodParticipation $participation */
if ($person === $participation->getPerson()) {
return $participation;
}}
return null;
return $this->getParticipations()->filter(
function(AccompanyingPeriodParticipation $participation) use ($person) {
if ($person === $participation->getPerson()) {
return $participation;
}
});
}
/**
* This public function is the same but return only true or false
* Get the opened participation containing a person
*
* "Open" means that the closed date is NULL
*/
public function getOpenParticipationsContainsPerson(Person $person): ?AccompanyingPeriodParticipation
{
$collection = $this->getParticipationsContainsPerson()->filter(
function(AccompanyingPeriodParticipation $participation) use ($person) {
if (NULL === $participation->getClosingDate()) {
return $participation;
}
});
return $collection->count() > 0 ? $collection->first() : NULL;
}
/**
* Return true if the accompanying period contains a person.
*
* **Note**: this participation can be opened or not.
*/
public function containsPerson(Person $person): bool
{
return ($this->participationsContainsPerson($person) === null) ? false : true;
return $this->participationsContainsPerson($person)->count() > 0;
}
/**
* Add Person
*/
public function addPerson(Person $person = null): self
public function addPerson(Person $person = null): AccompanyingPeriodParticipation
{
$participation = new AccompanyingPeriodParticipation($this, $person);
$this->participations[] = $participation;
return $this;
return $participation;
}
/**
* Remove Person
*/
public function removePerson(Person $person): void
public function removePerson(Person $person): ?AccompanyingPeriodParticipation
{
$participation = $this->participationsContainsPerson($person);
$participation = $this->getOpenParticipationContainsPerson($person);
if (! null === $participation) {
$participation->setEndDate(new \DateTimeImmutable('now'));
$this->participations->removeElement($participation);
}
return $participation;
}

View File

@@ -0,0 +1,73 @@
<?php
namespace Chill\PersonBundle\Security\Authorization;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\MainBundle\Entity\Center;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Role\Role;
class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{
protected AuthorizationHelper $helper;
public const SEE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_SEE';
/**
* @param AuthorizationHelper $helper
*/
public function __construct(AuthorizationHelper $helper)
{
$this->helper = $helper;
}
protected function supports($attribute, $subject)
{
return $subject instanceof AccompanyingPeriod;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
if (!$token->getUser() instanceof User) {
return false;
}
// TODO take scopes into account
foreach ($subject->getPersons() as $person) {
// give access as soon as on center is reachable
if ($this->helper->userHasAccess($token->getUser(), $person->getCenter(), $attribute)) {
return true;
}
return false;
}
}
private function getAttributes()
{
return [
self::SEE
];
}
public function getRoles()
{
return $this->getAttributes();
}
public function getRolesWithoutScope()
{
return [];
}
public function getRolesWithHierarchy()
{
return [ 'Person' => $this->getRoles() ];
}
}

View File

@@ -27,14 +27,6 @@ services:
public: true
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 }
- { name: chill.role }
chill.person.birthdate_validation:
class: Chill\PersonBundle\Validator\Constraints\BirthdateValidator

View File

@@ -0,0 +1,16 @@
services:
chill.person.security.authorization.person:
class: Chill\PersonBundle\Security\Authorization\PersonVoter
arguments:
- "@chill.main.security.authorization.helper"
tags:
- { name: security.voter }
- { name: chill.role }
Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter:
arguments:
- "@chill.main.security.authorization.helper"
tags:
- { name: security.voter }
- { name: chill.role }

View File

@@ -190,6 +190,7 @@ CHILL_PERSON_CREATE: Ajouter des personnes
CHILL_PERSON_STATS: Statistiques sur les personnes
CHILL_PERSON_LISTS: Liste des personnes
CHILL_PERSON_DUPLICATE: Gérer les doublons de personnes
CHILL_PERSON_ACCOMPANYING_PERIOD_SEE: Voir les périodes d'accompagnement
#period
Period closed!: Période clôturée!