src/Security/User/EmailLinkingTeamMateProvider.php line 57

Open in your IDE?
  1. <?php
  2. namespace App\Security\User;
  3. use BigIdea\IdentityBundle\Entity\TeamMate;
  4. use BigIdea\IdentityBundle\Repository\TeamMateRepository;
  5. use BigIdea\IdentityBundle\Security\Factory\SsoUserFactoryInterface;
  6. use Drenso\OidcBundle\Model\OidcUserData;
  7. use Drenso\OidcBundle\Security\UserProvider\OidcUserProviderInterface;
  8. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  9. use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
  10. use Symfony\Component\Security\Core\Exception\UserNotFoundException;
  11. use Symfony\Component\Security\Core\User\UserInterface;
  12. /**
  13.  * TeamMate provider that re-links legacy/fixture users by email on first SSO login.
  14.  */
  15. final class EmailLinkingTeamMateProvider implements OidcUserProviderInterface
  16. {
  17.     public function __construct(
  18.         private SsoUserFactoryInterface $factory,
  19.         private TeamMateRepository $repository,
  20.     ) {
  21.     }
  22.     public function refreshUser(UserInterface $user): UserInterface
  23.     {
  24.         if (!$user instanceof TeamMate) {
  25.             throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.'get_debug_type($user)));
  26.         }
  27.         return $this->loadOidcUser($user->getUserIdentifier());
  28.     }
  29.     public function supportsClass(string $class): bool
  30.     {
  31.         return $class === TeamMate::class;
  32.     }
  33.     public function loadUserByIdentifier(string $identifier): UserInterface
  34.     {
  35.         $user $this->repository->findByEmail($identifier);
  36.         $this->assertUserFound($user$identifier);
  37.         if (!$user->isAllowedPasswordAuthentication()) {
  38.             throw new AccessDeniedException();
  39.         }
  40.         return $user;
  41.     }
  42.     public function loadUserByUsername(string $username): UserInterface
  43.     {
  44.         return $this->loadUserByIdentifier($username);
  45.     }
  46.     public function ensureUserExists(string $userIdentifierOidcUserData $userData): void
  47.     {
  48.         $user $this->repository->findBySsoIdentifier($userIdentifier);
  49.         if (null === $user) {
  50.             $email $userData->getEmail();
  51.             if (is_string($email) && '' !== $email) {
  52.                 $user $this->repository->findByEmail($email);
  53.             }
  54.             if (null === $user) {
  55.                 $user $this->factory->create($userIdentifier$userData);
  56.             } else {
  57.                 $this->relinkSsoIdentifier($user$userIdentifier);
  58.                 $this->factory->update($user$userData);
  59.             }
  60.         } else {
  61.             $this->factory->update($user$userData);
  62.         }
  63.         $this->repository->save($user);
  64.     }
  65.     public function loadOidcUser(string $userIdentifier): UserInterface
  66.     {
  67.         $user $this->repository->findBySsoIdentifier($userIdentifier);
  68.         $this->assertUserFound($user$userIdentifier);
  69.         return $user;
  70.     }
  71.     private function relinkSsoIdentifier(TeamMate $userstring $ssoIdentifier): void
  72.     {
  73.         $property = new \ReflectionProperty(TeamMate::class, 'ssoIdentifier');
  74.         $property->setValue($user$ssoIdentifier);
  75.     }
  76.     private function assertUserFound(?UserInterface $userint|string $identifier): void
  77.     {
  78.         if (null === $user) {
  79.             $ex = new UserNotFoundException();
  80.             $ex->setUserIdentifier((string) $identifier);
  81.             throw $ex;
  82.         }
  83.     }
  84. }