This commit is contained in:
Björn Fromme
2023-07-07 18:19:15 +02:00
parent 1e9d1c5ac4
commit 305699b1ac
28 changed files with 1428 additions and 63 deletions
+117
View File
@@ -0,0 +1,117 @@
<?php
namespace App\Security;
use App\BusProNet\ApiClient;
use App\BusProNet\ApiClientException;
use App\BusProNet\Model\ErrorResponse;
use App\BusProNet\Model\Profile;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class BpnAuthenticator extends AbstractLoginFormAuthenticator implements AuthenticationEntryPointInterface
{
use TargetPathTrait;
public function __construct(
private readonly UrlGeneratorInterface $urlGenerator,
private readonly EntityManagerInterface $entityManager,
private readonly ApiClient $apiClient,
private readonly LoggerInterface $logger
) {
}
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate('app_security_login');
}
public function authenticate(Request $request): Passport
{
$email = trim($request->request->get('_username', ''));
$password = trim($request->request->get('_password', ''));
$csrfToken = $request->request->get('_csrf_token', '');
return new SelfValidatingPassport(
new UserBadge($email, function () use ($email, $password) {
try {
$response = $this->apiClient->getProfile($email, $password);
} catch (ApiClientException $e) {
return null;
}
if ($response instanceof ErrorResponse) {
return null;
}
return $this->getOrCreateLocalUser($response, $email, $password);
}),
[new CsrfTokenBadge('authenticate', $csrfToken)]
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
/** @var User $user */
$user = $token->getUser();
$user->setLastLoginAt(new \DateTimeImmutable());
$this->entityManager->flush();
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
$url = $this->urlGenerator->generate($user->getDefaultRoute());
return new RedirectResponse($url);
}
private function getOrCreateLocalUser(Profile $profile, string $email, string $password): User
{
$repository = $this->entityManager->getRepository(User::class);
$user = $repository->findOneBy([
'busProAddressId' => $profile->getAddressId(),
'busProPersonId' => $profile->getPersonId(),
]);
if (null !== $user) {
return $user;
}
try {
$response = $this->apiClient->getCrmSelection($email, $password);
} catch (ApiClientException $e) {
}
$user = new User();
$user
->setBusProAddressId($profile->getAddressId())
->setBusProPersonId($profile->getPersonId())
->setRole('ROLE_FOO')
->setEmail($profile->getCommunication()->getEmail())
->setFirstName($profile->getFirstName())
->setLastName($profile->getName())
;
$this->entityManager->persist($user);
$this->entityManager->flush();
return $user;
}
}