<?php
namespace App\EventListener\OAuth2;
use App\Entity\Commons\OAuth2\User;
use App\Oauth2\Grant\AuthCodeGrant;
use Doctrine\ORM\EntityManagerInterface;
use Cdp\Users\Transverse\Entity\Commons\Accounts;
use Nyholm\Psr7\Response;
use Symfony\Component\HttpFoundation\RequestStack;
use Trikoder\Bundle\OAuth2Bundle\Event\AuthorizationRequestResolveEvent;
use Twig\Environment;
class AuthorizationCodeListener
{
protected RequestStack $requestStack;
protected Environment $templating;
protected EntityManagerInterface $commonsEm;
public function __construct(RequestStack $requestStack, Environment $templating, EntityManagerInterface $commonsEm)
{
$this->requestStack = $requestStack;
$this->templating = $templating;
$this->commonsEm = $commonsEm;
}
public function onAuthorizationRequestResolve(AuthorizationRequestResolveEvent $event)
{
// Si personne n'est loggué
// -> Ne devrait jamais arriver car le security va rerouter sur oauth2_auth_login si pas de user en session
if (null === $event->getUser()) {
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED);
return;
}
$user = $event->getUser();
$request = $this->requestStack->getMasterRequest();
// Si on a déjà sélectionné un account précedement, on skip
if ($request->getSession()->has(AuthCodeGrant::PARAMETER_ACCOUNT)) {
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED);
return;
}
$account = null;
// Depuis le template de selection l'account est simplement passé en GET
if ($accountId = $request->query->get(AuthCodeGrant::PARAMETER_ACCOUNT)) {
$account = $this->commonsEm->find(Accounts::class, $accountId);
if (!$account) {
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED);
return;
}
if ($account->getUser() != $user) {
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED);
return;
}
}
if (null === $account) {
// $accounts = $this->commonsEm->getRepository(Accounts::class)->findBy([
// 'user' => $user,
// ]);
$qb = $this->commonsEm->createQueryBuilder();
$qb
->select('a')
->from(Accounts::class, 'a')
->andWhere('a.user = :user')
->setParameter("user", $user)
->innerJoin('a.fond', 'fond')
->orderBy('fond.libelle', 'ASC')
;
$accounts = $qb->getQuery()->getResult();
// Si le user n'a qu'un seul account, on passe l'étape de selection
if (1 === count($accounts)) {
return $this->onSuccessAccountSelection($event, $accounts[0]);
}
$content = $this->templating->render('sso/choose_account.html.twig', [
'accounts' => $accounts,
]);
$response = new Response(200, [], $content);
$event->setResponse($response);
return;
} else {
return $this->onSuccessAccountSelection($event, $account);
}
}
protected function onSuccessAccountSelection(AuthorizationRequestResolveEvent $event, Accounts $account)
{
$request = $this->requestStack->getMasterRequest();
// On set en $_SESSION pour pouvoir l'integrer dans l'authorization_code
$request->getSession()->set(AuthCodeGrant::PARAMETER_ACCOUNT, $account->getId());
$event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED);
return;
}
}