<?php
namespace Nen\Bundle\KennisbankPlatformBundle\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface;
use Nen\Bundle\KennisbankPlatformBundle\Entity\BoltPage;
use App\Entity\Company;
use App\Entity\User;
use Nen\Bundle\KennisbankPlatformBundle\Exceptions\IncompleteTokenRequestException;
use Nen\Bundle\KennisbankPlatformBundle\Exceptions\InvalidPartnerException;
use Nen\Bundle\KennisbankPlatformBundle\Exceptions\TokenRequestException;
use Nen\Bundle\KennisbankPlatformBundle\Form\LoginType;
use Nen\Bundle\KennisbankPlatformBundle\NenConnect\NenConnectException;
use Nen\Bundle\KennisbankPlatformBundle\NenConnect\NenConnectSingleSignOn;
use Nen\Bundle\KennisbankPlatformBundle\Repository\PartnerLoginUserRepository;
use Nen\Bundle\KennisbankPlatformBundle\Repository\UserRepository;
use Nen\Bundle\KennisbankPlatformBundle\Security\GlobalUserLoginFormFactory;
use Nen\Bundle\KennisbankPlatformBundle\Security\ManualUserLogin;
use Nen\Bundle\KennisbankPlatformBundle\Support\CodeGeneratorInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Exception\AccountExpiredException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use function Symfony\Component\Translation\t;
class SecurityController extends AbstractController
{
/**
* @Route("/inloggen", name="login")
*
* @Entity("page", expr="repository.findOneBySystemSectionAndSlug('inloggen')")
*/
public function login(Request $request, BoltPage $page, AuthenticationUtils $utils): Response
{
$data = ['page' => $page];
$form = $this->createForm(LoginType::class, [
'username' => $utils->getLastUsername() ?: $request->cookies->get('wmn_username')
]);
$form->handleRequest($request);
$error = $utils->getLastAuthenticationError();
if ($error !== null) {
if ($error instanceof CustomUserMessageAccountStatusException) {
$data['expired'] = $error->getMessage();
} else {
$form->addError(new FormError('Ongeldige combinatie van e-mailadres en wachtwoord.'));
}
}
$data['form'] = $form->createView();
if ($request->isXmlHttpRequest()) {
return $this->render('@KennisbankPlatform/security/modal/login.html.twig', $data);
}
return $this->render('@KennisbankPlatform/security/login.html.twig', $data);
}
/**
* @Route("/inloggen/partner/token", name="partner_login_token_request")
*
* @param Request $request
* @return Response
*/
public function partnerLoginTokenRequest(
Request $request,
JWTEncoderInterface $JWTEncoder,
PartnerLoginUserRepository $partnerLoginUserRepository
) {
$clientName = null;
$clientId = null;
$secret = null;
$userId = null;
$missingParameters = [];
$parameters = [
'client_name' => 'clientName',
'client_id' => 'clientId',
'secret' => 'secret',
'user_id' => 'userId',
];
foreach ($parameters as $key => $value) {
if (empty(${$value} = $request->query->get($key))) {
$missingParameters[] = $key;
}
}
try {
if (count($missingParameters)) {
throw new IncompleteTokenRequestException(implode(', ', $missingParameters));
}
$partners = $this->getParameter('partner_login');
if (!array_key_exists($clientName, $partners)) {
throw new InvalidPartnerException();
}
if ($partners[$clientName]['id'] !== $clientId || $partners[$clientName]['secret'] !== $secret) {
throw new InvalidPartnerException();
}
//request is valid
$redirect = $this->generateUrl('home', [], UrlGeneratorInterface::ABSOLUTE_URL);
//lookup user
$user = $partnerLoginUserRepository->findOneBy(
[
'partnerName' => $clientName,
'partnerUserId' => $userId,
]
);
$tokenData = [
'exp' => time() + 300
// 5 min expiration. User should be redirected immediately, so no need for long exp time
];
//user not found, set redirect to login page
if (!$user) {
$tokenData['username'] = '';
$tokenData['clientName'] = $clientName;
$tokenData['userId'] = $userId;
$tokenData['exp'] = time() + 3600; // 1 hour expiration so there is enough time to create an account
} else {
$tokenData['username'] = $user->getUser()->getUsername();
}
//create JWT
$token = $JWTEncoder->encode($tokenData);
} catch (TokenRequestException $e) {
return new JsonResponse(['error' => $e->getMessage()], 400);
}
//return JWT
return new JsonResponse(['token' => $token]);
}
/**
* @Route("/nen-connect", name="security_nen_connect_sso")
*
* @IsGranted("ROLE_USER")
*
* @param NenConnectSingleSignOn $sso
* @return RedirectResponse
*/
public function nenConnectSso(NenConnectSingleSignOn $sso)
{
/** @var User $user */
$user = $this->getUser();
try {
$url = $sso->getSingleSignOnUrl($user);
} catch (NenConnectException $e) {
$this->addFlash('error', t('Op dit moment is het niet mogelijk om in te loggen via NEN Connect. Probeer het later nog een keer.'));
return $this->redirectToRoute('home');
}
return $this->redirect($url);
}
}