Преглед на файлове

Merge branch 'feature/BTTF-57' into develop

Vincent GUFFON преди 4 години
родител
ревизия
0669fd7172

+ 1 - 1
config/packages/nelmio_cors.yaml

@@ -3,7 +3,7 @@ nelmio_cors:
         origin_regex: true
         allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
         allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
-        allow_headers: ['Content-Type', 'Authorization', 'x-accessid']
+        allow_headers: ['Content-Type', 'Authorization', 'x-accessid', 'x-switch-user']
         expose_headers: ['Link']
         max_age: 3600
     paths:

+ 3 - 3
config/packages/security.yaml

@@ -156,14 +156,14 @@ security:
             pattern: ^/api/
             stateless: true
             provider: access_provider
+            switch_user:
+                role: CAN_SWITCH_USER
+                parameter: X-Switch-User
 
         main:
             # activate different ways to authenticate
             # https://symfony.com/doc/current/security.html#firewalls-authentication
 
-            # https://symfony.com/doc/current/security/impersonating_user.html
-            # switch_user: true
-
     # Easy way to control access for large sections of your site
     # Note: Only the *first* access control that matches will be used
     access_control:

+ 105 - 13
src/ApiResources/Profile/AccessProfile.php

@@ -5,7 +5,7 @@ namespace App\ApiResources\Profile;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use ApiPlatform\Core\Annotation\ApiResource;
-use App\Entity\Access\Access;
+use Symfony\Component\Serializer\Annotation\Groups;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 
@@ -13,11 +13,12 @@ use Doctrine\Common\Collections\Collection;
  * Classe resource qui contient les champs disponibles lors d'un appel à my_profile.
  *
  * @ApiResource(
- *     collectionOperations={},
  *     itemOperations={
  *          "get"={
+ *             "normalization_context"={"groups"={"access_profile_read"}},
  *             "method"="GET",
- *             "path"="/my_profile/{id}"
+ *             "path"="/my_profile/{id}",
+ *             "defaults"={"id"=0}
  *          }
  *     }
  * )
@@ -26,18 +27,54 @@ class AccessProfile
 {
     /**
      * @ApiProperty(identifier=true)
+     * @Groups({"access_profile_read"})
      */
     public $id;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $isAdminAccess;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $name;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $givenName;
+    /**
+     * @Groups({"access_profile_read"})
+     */
+    private $gender;
+    /**
+     * @Groups({"access_profile_read"})
+     */
+    private $avatarId;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $roles = [];
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $organization;
-    private $accesses;
+    /**
+     * @Groups({"access_profile_read"})
+     */
+    private $multiAccesses;
+    /**
+     * @Groups({"access_profile_read"})
+     */
+    private $familyAccesses;
+    /**
+     * @Groups({"access_profile_read"})
+     */
+    private $originalAccess;
 
     public function __construct()
     {
-        $this->accesses = new ArrayCollection();
+        $this->multiAccesses = new ArrayCollection();
+        $this->familyAccesses = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -100,6 +137,28 @@ class AccessProfile
         return $this;
     }
 
+    public function getGender(): ?string
+    {
+        return $this->gender;
+    }
+
+    public function setGender($gender): self
+    {
+        $this->gender = $gender;
+        return $this;
+    }
+
+    public function getAvatarId(): ?int
+    {
+        return $this->avatarId;
+    }
+
+    public function setAvatarId(int $avatarId): self
+    {
+        $this->avatarId = $avatarId;
+        return $this;
+    }
+
     public function getRoles(): array
     {
         $roles = $this->roles;
@@ -114,24 +173,57 @@ class AccessProfile
     }
 
     /**
-     * @return Collection|AccessProfile[]
+     * @return Collection|OrganizationProfile[]
      */
-    public function getAccesses(): Collection
+    public function getMultiAccesses(): Collection
     {
-        return $this->accesses;
+        return $this->multiAccesses;
     }
 
-    public function addAccess(AccessProfile $accessProfile): self
+    public function addMultiAccess(OrganizationProfile $organizationProfile): self
     {
-        if (!$this->accesses->contains($accessProfile)) {
-            $this->accesses[] = $accessProfile;
+        if (!$this->multiAccesses->contains($organizationProfile)) {
+            $this->multiAccesses[] = $organizationProfile;
         }
         return $this;
     }
 
-    public function removeAccess(AccessProfile $accessProfile): self
+    public function removeMultiAccess(OrganizationProfile $organizationProfile): self
+    {
+        $this->multiAccesses->removeElement($organizationProfile);
+        return $this;
+    }
+
+    /**
+     * @return Collection|OrganizationProfile[]
+     */
+    public function getFamilyAccesses(): Collection
+    {
+        return $this->familyAccesses;
+    }
+
+    public function addFamilyAccess(AccessProfile $accessProfile): self
+    {
+        if (!$this->familyAccesses->contains($accessProfile)) {
+            $this->familyAccesses[] = $accessProfile;
+        }
+        return $this;
+    }
+
+    public function removeFamilyAccess(AccessProfile $accessProfile): self
+    {
+        $this->familyAccesses->removeElement($accessProfile);
+        return $this;
+    }
+
+    public function getOriginalAccess(): ?AccessProfile
+    {
+        return $this->originalAccess;
+    }
+
+    public function setOriginalAccess(?AccessProfile $originalAccess): self
     {
-        $this->accesses->removeElement($accessProfile);
+        $this->originalAccess = $originalAccess;
         return $this;
     }
 }

+ 29 - 0
src/ApiResources/Profile/OrganizationProfile.php

@@ -4,24 +4,53 @@ declare(strict_types=1);
 namespace App\ApiResources\Profile;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
+use Symfony\Component\Serializer\Annotation\Groups;
+use ApiPlatform\Core\Annotation\ApiResource;
 
 /**
  * Classe resource qui contient les champs relatifs aux organizations présentent dans la requete my_profile.
  * @package App\ApiResources\Profile
+ *
+ *  @ApiResource()
  */
 class OrganizationProfile
 {
     /**
      * @ApiProperty(identifier=true)
+     * @Groups({"access_profile_read"})
      */
     public $id;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $name;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $product;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $subDomain;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $networks = [];
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $website;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $modules = [];
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $hasChildren = false;
+    /**
+     * @Groups({"access_profile_read"})
+     */
     private $parents = [];
 
     public function __construct()

+ 14 - 1
src/DataProvider/Access/AccessProfileDataProvider.php

@@ -9,6 +9,8 @@ use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
 use App\ApiResources\Profile\AccessProfile;
 use App\Entity\Access\Access;
 use App\Service\Access\AccessProfileCreator;
+use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
+use Symfony\Component\Security\Core\Exception\AuthenticationException;
 use Symfony\Component\Security\Core\Security;
 
 /**
@@ -38,6 +40,17 @@ final class AccessProfileDataProvider implements ItemDataProviderInterface, Rest
     {
         /** @var Access $access */
         $access = $this->security->getUser();
-        return $this->accessProfileCreator->getAccessProfile($access);
+        $originalAccess = null;
+
+        $token = $this->security->getToken();
+        if($token instanceof SwitchUserToken){
+            $originalAccess = $token->getOriginalToken()->getUser();
+        }
+
+        try {
+            return $this->accessProfileCreator->getAccessProfile($access, $originalAccess);
+        } catch (\Exception $e) {
+            return null;
+        }
     }
 }

+ 68 - 0
src/Entity/Access/Access.php

@@ -85,15 +85,33 @@ class Access implements UserInterface
     private $organizationFunction;
 
     /**
+     * @var ArrayCollection<OrganizationLicence>
      * @ORM\OneToMany(targetEntity=OrganizationLicence::class, mappedBy="licensee", orphanRemoval=true)
      */
     private $organizationLicences;
 
+    /**
+     * @var ArrayCollection<Access>
+     * @ORM\ManyToMany(targetEntity=Access::class, mappedBy="children", cascade={"persist"})
+     */
+    private $guardians;
+    /**
+     * @var ArrayCollection<Access>
+     * @ORM\ManyToMany(targetEntity=Access::class, inversedBy="guardians", cascade={"persist"})
+     * @ORM\JoinTable(name="children_guardians",
+     *      joinColumns={@ORM\JoinColumn(name="guardians_id", referencedColumnName="id")},
+     *      inverseJoinColumns={@ORM\JoinColumn(name="children_id", referencedColumnName="id")}
+     *     )
+     */
+    private $children;
+
     public function __construct()
     {
         $this->personActivity = new ArrayCollection();
         $this->organizationFunction = new ArrayCollection();
         $this->organizationLicences = new ArrayCollection();
+        $this->guardians = new ArrayCollection();
+        $this->children = new ArrayCollection();
     }
 
     public function getId(): ?int
@@ -286,4 +304,54 @@ class Access implements UserInterface
 
         return $this;
     }
+
+    /**
+     * @return Collection|Access[]
+     */
+    public function getChildren(): Collection
+    {
+        return $this->children;
+    }
+
+    public function addChild (Access $access): self
+    {
+        if (!$this->children->contains($access)) {
+            $this->children[] = $access;
+            $access->addGuardian($this);
+        }
+        return $this;
+    }
+
+    public function removeChild(Access $access): self
+    {
+        if ($this->children->removeElement($access)) {
+            $access->removeGuardian($this);
+        }
+        return $this;
+    }
+
+    /**
+     * @return Collection|Access[]
+     */
+    public function getGuardians(): Collection
+    {
+        return $this->guardians;
+    }
+
+    public function addGuardian(Access $access): self
+    {
+        if (!$this->guardians->contains($access)) {
+            $this->guardians[] = $access;
+            $access->addChild($this);
+        }
+        return $this;
+    }
+
+    public function removeGuardian(Access $access): self
+    {
+        if ($this->guardians->removeElement($access)) {
+            $access->removeChild($this);
+        }
+        return $this;
+    }
 }

+ 137 - 0
src/Entity/Core/File.php

@@ -0,0 +1,137 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Entity\Core;
+
+use App\Entity\Person\Person;
+use App\Repository\Core\FileRepository;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity(repositoryClass=FileRepository::class)
+ */
+class File
+{
+    /**
+     * @ORM\Id
+     * @ORM\GeneratedValue
+     * @ORM\Column(type="integer")
+     */
+    private $id;
+
+    /**
+     * @ORM\Column(type="string", length=255)
+     *
+     */
+    private $slug;
+    /**
+     * @var string
+     *
+     * @ORM\Column(type="string", length=255)
+     *
+     */
+    private $path;
+    /**
+     * @var string
+     *
+     * @ORM\Column(type="string", length=255)
+     */
+    private $name;
+    /**
+     * @ORM\Column(type="string", length=255, nullable=true)
+     */
+    private $mimeType;
+
+    /**
+     * @var ArrayCollection<Person>
+     * @ORM\OneToMany(targetEntity=Person::class, mappedBy="image", orphanRemoval=true)
+     */
+    private $personImages;
+
+    public function __construct()
+    {
+        $this->personImages = new ArrayCollection();
+    }
+
+    public function getId(): ?int
+    {
+        return $this->id;
+    }
+
+    public function getSlug(): string
+    {
+        return $this->slug;
+    }
+
+    public function setSlug(string $slug): self
+    {
+        $this->slug = $slug;
+        return $this;
+    }
+
+    public function getPath(): string
+    {
+        return $this->path;
+    }
+
+    public function setPath(string $path): self
+    {
+        $this->path = $path;
+        return $this;
+
+    }
+
+    public function getName(): string
+    {
+        return $this->name;
+    }
+
+    public function setName(string $name): self
+    {
+        $this->name = $name;
+        return $this;
+    }
+
+    public function getMimeType(): ?string
+    {
+        return $this->mimeType;
+    }
+
+    public function setMimeType(string $mimeType): self
+    {
+        $this->mimeType = $mimeType;
+        return $this;
+    }
+
+    /**
+     * @return Collection|Person[]
+     */
+    public function getPersonImages(): Collection
+    {
+        return $this->personImages;
+    }
+
+    public function addPersonImage (Person $person): self
+    {
+        if (!$this->personImages->contains($person)) {
+            $this->personImages[] = $person;
+            $person->setImage($this);
+        }
+
+        return $this;
+    }
+
+    public function removePersonImage(Person $person): self
+    {
+        if ($this->personImages->removeElement($person)) {
+            // set the owning side to null (unless already changed)
+            if ($person->getImage() === $this) {
+                $person->setImage(null);
+            }
+        }
+
+        return $this;
+    }
+}

+ 27 - 16
src/Entity/Person/Person.php

@@ -5,12 +5,13 @@ namespace App\Entity\Person;
 
 use ApiPlatform\Core\Annotation\ApiResource;
 use App\Entity\Core\ContactPoint;
+use App\Entity\Core\File;
 use App\Repository\Person\PersonRepository;
-use AppBundle\Entity\AccessAndFunction\Access;
 use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Validator\Constraints as Assert;
 
 /**
  * Personne physique ou morale
@@ -59,11 +60,17 @@ class Person implements UserInterface
     private $contactPoints;
 
     /**
-     * @ORM\Column(type="integer", nullable=true)
-     * @var int
+     * @var string Gender of the person.
+     * @ORM\Column(type="string", nullable=true)
+     * @Assert\Choice(callback={"App\Enum\Person\GenderEnum", "toArray"})
      */
-    private $accessFavorite;
+    private $gender;
 
+    /**
+     * @ORM\ManyToOne(targetEntity=File::class, inversedBy="personImages")
+     * @ORM\JoinColumn(referencedColumnName="id", nullable=true, onDelete="SET NULL")
+     */
+    private $image;
 
     public function __construct()
     {
@@ -177,6 +184,17 @@ class Person implements UserInterface
         return $this;
     }
 
+    public function setGender($gender): self
+    {
+        $this->gender = $gender;
+        return $this;
+    }
+
+    public function getGender(): ?string
+    {
+        return $this->gender;
+    }
+
     /**
      * @return Collection|ContactPoint[]
      */
@@ -204,21 +222,14 @@ class Person implements UserInterface
         return $this;
     }
 
-    /**
-     * @return int
-     */
-    public function getAccessFavorite() : int
+    public function setImage(File $image):self
     {
-        return $this->accessFavorite;
+        $this->image = $image;
+        return $this;
     }
 
-    /**
-     * @param $accessFavorite
-     * @return $this
-     */
-    public function setAccessFavorite($accessFavorite) : self
+    public function getImage(): File
     {
-        $this->accessFavorite = $accessFavorite;
-        return $this;
+        return $this->image;
     }
 }

+ 4 - 4
src/Entity/Traits/ActivityPeriodTrait.php

@@ -29,8 +29,8 @@ trait ActivityPeriodTrait
      *
      * @return \DateTime
      */
-    public function getStartDate(): string {
-        return $this->startDate ? $this->startDate->format('Y-m-d') : '';
+    public function getStartDate(): ?string {
+        return $this->startDate ? $this->startDate->format('Y-m-d') : null;
     }
 
     /**
@@ -49,8 +49,8 @@ trait ActivityPeriodTrait
      *
      * @return \DateTime
      */
-    public function getEndDate(): string {
-        return $this->endDate ? $this->endDate->format('Y-m-d') : '';
+    public function getEndDate(): ?string {
+        return $this->endDate ? $this->endDate->format('Y-m-d') : null;
     }
 
     /**

+ 27 - 7
src/Repository/Access/AccessRepository.php

@@ -14,11 +14,11 @@ use Symfony\Component\HttpFoundation\RequestStack;
  * @method Access|null findOneBy(array $criteria, array $orderBy = null)
  * @method Access[]    findAll()
  * @method Access[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
- * @method null loadUserByIdentifier(string $identifier)
  */
 class AccessRepository extends ServiceEntityRepository implements UserLoaderInterface
 {
     const ACCESS_NAME_HEADER = 'X-AccessId';
+    const HTTP_X_SWITCH_USER = 'X-Switch-User';
 
     private RequestStack $requestStack;
 
@@ -29,17 +29,37 @@ class AccessRepository extends ServiceEntityRepository implements UserLoaderInte
     }
 
     /**
-     * Méthode permettant de fournir un userProvider custom (voir config provider : access_provider)
+     * @deprecated  in symfony 6.0, replace by loadUserByIdentifier
      * @param string $username
-     * @return mixed|\Symfony\Component\Security\Core\User\UserInterface|null
-     * @throws \Doctrine\ORM\NonUniqueResultException
+     * @return \Symfony\Component\Security\Core\User\UserInterface|void|null
      */
     public function loadUserByUsername(string $username)
-    {
-        $entityManager = $this->getEntityManager();
+    {}
+
+    /**
+     * Méthode permettant de fournir un userProvider custom (voir config provider : access_provider)
+     * @param string $username
+     * @return Access|mixed|object|\Symfony\Component\Security\Core\User\UserInterface|null
+     * @throws \Doctrine\ORM\ORMException
+     * @throws \Doctrine\ORM\OptimisticLockException
+     * @throws \Doctrine\ORM\TransactionRequiredException
+     */
+    public function loadUserByIdentifier($identifier){
+        if($this->requestStack->getMainRequest()->headers->get(self::HTTP_X_SWITCH_USER) == $identifier)
+            return $this->getEntityManager()->find(Access::class, $identifier);
 
-        $id = $this->requestStack->getMasterRequest()->headers->get(self::ACCESS_NAME_HEADER);
+        return $this->findAccessByUsernameAndAccessId($identifier, $this->requestStack->getMainRequest()->headers->get(self::ACCESS_NAME_HEADER));
+    }
 
+    /**
+     * Récupère un access grâce à son username et son ID
+     * @param string $username
+     * @param $id
+     * @return mixed
+     * @throws \Doctrine\ORM\NonUniqueResultException
+     */
+    private function findAccessByUsernameAndAccessId(string $username, $id){
+        $entityManager = $this->getEntityManager();
         return $entityManager->createQuery(
             'SELECT a
                 FROM App\Entity\Access\Access a

+ 15 - 0
src/Repository/Core/FileRepository.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Repository\Core;
+
+use App\Entity\Core\File;
+use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Doctrine\Persistence\ManagerRegistry;
+
+class FileRepository extends ServiceEntityRepository
+{
+    public function __construct(ManagerRegistry $registry)
+    {
+        parent::__construct($registry, File::class);
+    }
+}

+ 49 - 0
src/Security/Voter/SwitchUserVoter.php

@@ -0,0 +1,49 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Security\Voter;
+
+use App\Service\Security\SwitchUser;
+use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\Security\Core\Authorization\Voter\Voter;
+use Symfony\Component\Security\Core\Security;
+use Symfony\Component\Security\Core\User\UserInterface;
+
+class SwitchUserVoter extends Voter
+{
+    private Security $security;
+    private SwitchUser $switchUser;
+
+    public function __construct(Security $security, SwitchUser $switchUser)
+    {
+        $this->security = $security;
+        $this->switchUser = $switchUser;
+    }
+
+    protected function supports($attribute, $subject): bool
+    {
+        return in_array($attribute, ['CAN_SWITCH_USER'])
+            && $subject instanceof UserInterface;
+    }
+
+    protected function voteOnAttribute($attribute, $user_to_switch, TokenInterface $token): bool
+    {
+        $user = $token->getUser();
+
+        // if the user is anonymous or if the subject is not a user, do not grant access
+        if (!$user instanceof UserInterface || !$user_to_switch instanceof UserInterface) {
+            return false;
+        }
+
+        // check for ROLE_ALLOWED_TO_SWITCH
+        if ($this->security->isGranted('ROLE_ALLOWED_TO_SWITCH')) {
+            return true;
+        }
+
+        if ($this->switchUser->isAllowedToSwitch($user, $user_to_switch)) {
+            return true;
+        }
+
+        return true;
+    }
+}

+ 26 - 13
src/Service/Access/AccessProfileCreator.php

@@ -38,22 +38,34 @@ class AccessProfileCreator
     /**
      * On récupère l'accessProfile complet correspondant à l'Access
      * @param Access $access
+     * @param Access $originalAccess
      * @return AccessProfile
      * @throws \Exception
      * @see AccessProfileCreatorTest::testGetAccessProfileFailed
      */
-    public function getAccessProfile(Access $access): AccessProfile{
+    public function getAccessProfile(Access $access, Access $originalAccess = null): AccessProfile{
         $validAccesses = $this->accessRepository->findAllValidAccesses($access);
         if(empty($validAccesses))
             throw new AuthenticationException('no_valid_access', 401);
 
         //L'Access en paramètre est celui de la connexion
-        $mainAccessProfile = $this->createAccessProfile($access);
+        $mainAccessProfile = $this->createCompleteAccessProfile($access);
 
-        //On remplit les autres Accesses (multi comptes)
-        $otherAccesses = $this->accessUtils->filterAccesses($validAccesses, $access);
-        foreach ($otherAccesses as $otherAccess){
-            $mainAccessProfile->addAccess($this->createLightAccessProfile($otherAccess));
+        //On remplit les accesses multi-compte
+        $multiAccesses = $this->accessUtils->filterAccesses($validAccesses, $access);
+        foreach ($multiAccesses as $multiAccess){
+            $mainAccessProfile->addMultiAccess($this->organizationProfileCreator->createLightOrganizationProfile($multiAccess->getOrganization()));
+        }
+
+        //On remplit les accesses famille
+        $familyAccesses = $access->getChildren();
+        foreach ($familyAccesses as $familyAccess){
+            $mainAccessProfile->addFamilyAccess($this->createLightAccessProfile($familyAccess));
+        }
+
+        //Dans le cas où nous sommes dans une connexion switch
+        if($originalAccess){
+            $mainAccessProfile->setOriginalAccess($this->createLightAccessProfile($originalAccess));
         }
 
         return $mainAccessProfile;
@@ -65,15 +77,12 @@ class AccessProfileCreator
      * @return AccessProfile
      * @see AccessProfileCreatorTest::testCreateAccessProfile
      */
-    public function createAccessProfile(Access $access): AccessProfile{
-        $accessProfile = new AccessProfile();
+    public function createCompleteAccessProfile(Access $access): AccessProfile{
+        $accessProfile = $this->createLightAccessProfile($access);
         return $accessProfile
-            ->setId($access->getId())
             ->setIsAdminAccess($access->getAdminAccess())
-            ->setName($access->getPerson()->getName())
-            ->setGivenName($access->getPerson()->getGivenName())
             ->setRoles($this->roleHierarchy->getReachableRoleNames($access->getRoles()))
-            ->setOrganization($this->organizationProfileCreator->getOrganizationProfile($access->getOrganization()));
+            ->setOrganization($this->organizationProfileCreator->createCompleteOrganizationProfile($access->getOrganization()));
     }
 
     /**
@@ -86,6 +95,10 @@ class AccessProfileCreator
         $accessProfile = new AccessProfile();
         return $accessProfile
             ->setId($access->getId())
-            ->setOrganization($this->organizationProfileCreator->setCommonElements($access->getOrganization()));
+            ->setName($access->getPerson()->getName())
+            ->setGivenName($access->getPerson()->getGivenName())
+            ->setGender($access->getPerson()->getGender())
+            ->setAvatarId($access->getPerson()->getImage()->getId())
+        ;
     }
 }

+ 5 - 5
src/Service/Organization/OrganizationProfileCreator.php

@@ -31,10 +31,10 @@ class OrganizationProfileCreator
      * Classe permettant de créer le profile d'une organisation à partir d'une entité Organization
      * @param Organization $organization
      * @return OrganizationProfile
-     * @see OrganizationProfileCreatorTest::testGetOrganizationProfile()
+     * @see OrganizationProfileCreatorTest::testCreateCompleteOrganizationProfile()
      */
-    public function getOrganizationProfile(Organization $organization): OrganizationProfile{
-        $organizationProfile = $this->setCommonElements($organization);
+    public function createCompleteOrganizationProfile(Organization $organization): OrganizationProfile{
+        $organizationProfile = $this->createLightOrganizationProfile($organization);
         $organizationProfile->setModules($this->module->getOrganizationModules($organization));
         $organizationProfile->setProduct($organization->getSettings()->getProduct());
         $organizationProfile->setHasChildren($organization->getNetworkOrganizationChildren()->count() > 1);
@@ -45,7 +45,7 @@ class OrganizationProfileCreator
 
         /** @var \App\Entity\Organization\Organization $parent */
         foreach ($this->tree->findAllParentsAndSortByType($organization) as $parent){
-            $parentProfile = $this->setCommonElements($parent);
+            $parentProfile = $this->createLightOrganizationProfile($parent);
             $organizationProfile->addParent($parentProfile);
         }
         return $organizationProfile;
@@ -56,7 +56,7 @@ class OrganizationProfileCreator
      * @param Organization $organization
      * @return OrganizationProfile
      */
-    public function setCommonElements(Organization $organization): OrganizationProfile{
+    public function createLightOrganizationProfile(Organization $organization): OrganizationProfile{
         $organizationProfile = new OrganizationProfile();
         $organizationProfile
             ->setId($organization->getId())

+ 28 - 0
src/Service/Security/SwitchUser.php

@@ -0,0 +1,28 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Service\Security;
+
+use App\Test\Service\Security\SwitchUserTest;
+use Symfony\Component\Security\Core\User\UserInterface;
+
+/**
+ * Class SwitchUser : Classe gérant la possibilité de Switcher entre utilisateurs.
+ * @package App\Service\Security
+ */
+class SwitchUser
+{
+    public function __construct()
+    {
+    }
+
+    /**
+     * @param UserInterface $user
+     * @param UserInterface $user_to_switch
+     * @return bool
+     * @see SwitchUserTest::testIsAllowedToSwitch()
+     */
+    public function isAllowedToSwitch(UserInterface $user, UserInterface $user_to_switch):bool{
+        return $user->getChildren()->contains($user_to_switch);
+    }
+}

+ 3 - 3
tests/Service/Access/AccessProfileCreatorTest.php

@@ -71,10 +71,10 @@ class AccessProfileCreatorTest extends TestCase
     }
 
     /**
-     * @see AccessProfileCreator::createAccessProfile()
+     * @see AccessProfileCreator::createCompleteAccessProfile()
      */
-    public function testCreateAccessProfile(){
-        $accessProfile = $this->accessProfileCreator->createAccessProfile($this->access);
+    public function testCreateCompleteAccessProfile(){
+        $accessProfile = $this->accessProfileCreator->createCompleteAccessProfile($this->access);
         $this->assertInstanceOf(AccessProfile::class, $accessProfile);
     }
 

+ 3 - 3
tests/Service/Organization/OrganizationProfileCreatorTest.php

@@ -25,9 +25,9 @@ class OrganizationProfileCreatorTest extends TestCase
     }
 
     /**
-     * @see OrganizationProfileCreator::getOrganizationProfile()
+     * @see OrganizationProfileCreator::createCompleteOrganizationProfile()
      */
-    public function testGetOrganizationProfile(){
+    public function testCreateCompleteOrganizationProfile(){
         $moduleMock = $this->getMockBuilder(Module::class)->disableOriginalConstructor()->getMock();
         $moduleMock
             ->method('getOrganizationModules')
@@ -43,7 +43,7 @@ class OrganizationProfileCreatorTest extends TestCase
             ->willReturn([$parent, $parent]);
 
         $organizationProfileCreator = new OrganizationProfileCreator($moduleMock,$treeMock);
-        $organizationProfile = $organizationProfileCreator->getOrganizationProfile($this->organization);
+        $organizationProfile = $organizationProfileCreator->createCompleteOrganizationProfile($this->organization);
 
         $this->assertInstanceOf(OrganizationProfile::class, $organizationProfile);
     }

+ 48 - 0
tests/Service/Security/SwitchUserTest.php

@@ -0,0 +1,48 @@
+<?php
+namespace App\Test\Service\Security;
+
+use App\Entity\Access\Access;
+use App\Service\Security\SwitchUser;
+use Doctrine\Common\Collections\ArrayCollection;
+use PHPUnit\Framework\TestCase;
+
+class SwitchUserTest extends TestCase
+{
+    public function setUp():void
+    {
+    }
+
+    /**
+     * @see SwitchUser::isAllowedToSwitch()
+     */
+    public function testIsAllowedToSwitch(){
+        $childrenMockMock = $this->getMockBuilder(Access::class)->getMock();
+
+        $children = new ArrayCollection();
+        $children->add($childrenMockMock);
+
+        $userMockMock = $this->getMockBuilder(Access::class)->getMock();
+        $userMockMock
+            ->expects($this->once())
+            ->method('getChildren')
+            ->willReturn($children);
+
+        $switchUser = new SwitchUser();
+        $this->assertTrue($switchUser->isAllowedToSwitch($userMockMock, $childrenMockMock));
+    }
+
+    /**
+     * @see SwitchUser::isAllowedToSwitch()
+     */
+    public function testIsNotAllowedToSwitch(){
+        $childrenMockMock = $this->getMockBuilder(Access::class)->getMock();
+        $userMockMock = $this->getMockBuilder(Access::class)->getMock();
+        $userMockMock
+            ->expects($this->once())
+            ->method('getChildren')
+            ->willReturn(new ArrayCollection());
+
+        $switchUser = new SwitchUser();
+        $this->assertFalse($switchUser->isAllowedToSwitch($userMockMock, $childrenMockMock));
+    }
+}