<?php
namespace App\Controller;
use App\Entity\Usuario;
use App\Form\CadastroCandidatoType;
use App\Form\ChangeEmailSelfType;
use App\Form\ChangePasswordType;
use App\Form\DadosCandidatoType;
use App\Form\ForgotChangeFormType;
use App\Form\ForgotCpfFormType;
use App\Form\ForgotFormType;
use App\Form\ForgotPassportFormType;
use App\Form\LoginFormType;
use App\Form\Model\ChangePassword;
use App\Repository\EditalRepository;
use App\Repository\UsuarioRepository;
use App\Service\Comunicador;
use App\Service\CpfValidator;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
class MainController extends AppController
{
/**
* @Route("/", name="index")
*/
public function index(EditalRepository $editalRepository): Response
{
$editaisDisponiveis = $editalRepository->findEditaisDisponiveis();
$editaisFuturos = $editalRepository->findEditaisFuturos();
return $this->render('main/index.html.twig', [
'editaisDisponiveis' => $editaisDisponiveis,
'editaisFuturos' => $editaisFuturos,
]);
}
/**
* @Route("/cadastro", name="cadastro")
*/
public function cadastroAction(Request $request, EntityManagerInterface $em, Comunicador $comunicador): Response
{
$candidato = new Usuario();
if ($request->query->has('cpf')) {
$candidato->setCpf($request->query->get('cpf'));
}
if ($request->query->has('email')) {
$candidato->setEmail($request->query->get('email'));
}
if ($request->query->has('pp')) {
list($pais, $pass) = explode('/', $request->query->get('pp'));
$candidato->setNacionalidade($pais);
$candidato->setPassaporte($pass);
}
else {
$candidato->setNacionalidade('BR');
}
$candidato->setRoles(['ROLE_USER', 'ROLE_CANDIDATO']);
$form = $this->createForm(CadastroCandidatoType::class, $candidato, ['repository' => $em->getRepository(Usuario::class)]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
/** @var Usuario $candidato */
$candidato = $form->getData();
$em->persist($candidato);
$em->flush();
$this->addFlash('success', 'Cadastro realizado com sucesso! Um email de verificação foi enviado para você.');
$comunicador->sendCadastroRealizado($candidato);
return $this->redirectToRoute('login');
} catch (UniqueConstraintViolationException $e) {
$this->addFlash('error', 'Email ou CPF / passaporte já cadastrados no sistema!');
return $this->redirectToRoute('cadastro');
}
}
return $this->render(
'main/cadastro.html.twig', [
'form' => $form->createView(),
]
);
}
/**
* @Route("/entrar", name="login")
*/
public function loginAction(AuthenticationUtils $authenticationUtils, Request $request): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError(false);
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
$form = $this->createForm(LoginFormType::class, [
'_username' => $lastUsername,
]);
return $this->render(
'main/login.html.twig',
array(
'form' => $form->createView(),
'error' => $error,
)
);
}
/**
* @Route("/esqueci", name="forgot")
*/
public function forgotAction(Request $request, Comunicador $comunicador, UsuarioRepository $repository, EntityManagerInterface $em): Response
{
$form = $this->createForm(ForgotFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$usuario = $repository->findOneBy(['email' => $formData['email']]);
if (!$usuario) {
$this->addFlash('error', 'Não foi possível localizar um cadastro com este e-mail. Faça um novo cadastro.');
return $this->redirectToRoute('cadastro', ['email' => $formData['email']]);
}
$token = $usuario->generateResetToken(\DateInterval::createFromDateString('1 hour'));
if ($comunicador->sendEsqueceuSenha($usuario, $token)) {
$em->persist($usuario);
$em->flush();
$this->addFlash('success', 'Email para alteração de senha enviado!');
}
else {
$this->addFlash('error', 'A funcionalidade de recuperação de senha está temporariamente desativada no sistema!');
}
return $this->redirectToRoute('forgot');
}
return $this->render('main/forgot.html.twig', [
'form' => $form->createView()
]);
}
/**
* @Route("/esqueci-cpf", name="forgot_cpf")
*/
public function forgotCpf(Request $request, Comunicador $comunicador, UsuarioRepository $repository, EntityManagerInterface $em): Response
{
$form = $this->createForm(ForgotCpfFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$cpf = CpfValidator::prettyfy($formData['cpf']);
$usuario = $repository->findOneBy(['cpf' => $cpf]);
if (!$usuario) {
$this->addFlash('error', 'Não foi possível localizar um cadastro com este CPF. Faça um novo cadastro.');
return $this->redirectToRoute('cadastro', ['cpf' => $cpf]);
}
$token = $usuario->generateResetToken(\DateInterval::createFromDateString('1 hour'));
$comunicador->sendEsqueceuSenha($usuario, $token);
$em->persist($usuario);
$em->flush();
$this->addFlash('success', 'Email para alteração de senha enviado!');
return $this->render('main/forgot_cpf.html.twig', [
'usuario' => $usuario,
'obfuscated' => $usuario->getObfuscatedEmail(),
'first_name' => $usuario->getFirstName(),
]);
}
return $this->render('main/forgot_cpf.html.twig', [
'form' => $form->createView()
]);
}
/**
* @Route("/esqueci-passaporte", name="forgot_passport")
*/
public function forgotPassaporte(Request $request, Comunicador $comunicador, UsuarioRepository $repository, EntityManagerInterface $em): Response
{
$form = $this->createForm(ForgotPassportFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$pass = $formData['passaporte'];
$nac = $formData['nacionalidade'];
$usuario = $repository->findOneBy(['passaporte' => $pass, 'nacionalidade' => $nac]);
if (!$usuario) {
$this->addFlash('error', 'Não foi possível localizar um cadastro com este Passaporte. Faça um novo cadastro.');
return $this->redirectToRoute('cadastro', ['pp' => "$nac/$pass"]);
}
$token = $usuario->generateResetToken(\DateInterval::createFromDateString('1 hour'));
$comunicador->sendEsqueceuSenha($usuario, $token);
$em->persist($usuario);
$em->flush();
$this->addFlash('success', 'Email para alteração de senha enviado!');
return $this->render('main/forgot_passport.html.twig', [
'usuario' => $usuario,
'obfuscated' => $usuario->getObfuscatedEmail(),
'first_name' => $usuario->getFirstName(),
]);
}
return $this->render('main/forgot_passport.html.twig', [
'form' => $form->createView()
]);
}
/**
* @Route("/esqueci/{resetToken}", name="forgot_change")
*/
public function forgotChangeAction(Usuario $usuario, Request $request, Comunicador $comunicador, EntityManagerInterface $em): Response
{
if ($usuario->isResetTokenValid()) {
$form = $this->createForm(ForgotChangeFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$usuario->setPlainPassword($formData['senha']);
$usuario->clearResetToken();
$comunicador->sendSenhaRecuperada($usuario);
$em->persist($usuario);
$em->flush();
$this->addFlash('success', "Senha de {$usuario->getFirstName()} alterada com sucesso!");
return $this->redirectToRoute('login');
}
return $this->render('main/forgot_change.html.twig', [
'form' => $form->createView(),
'usuario' => $usuario,
]);
} else {
$this->addFlash('error', 'Solicitação inválida ou expirada.');
return $this->redirectToRoute('forgot');
}
}
/**
* @Route("/trocar-senha", name="change_pass")
* @IsGranted("ROLE_USER")
*/
public function trocarSenhaAction(Request $request, EntityManagerInterface $em, Comunicador $comunicador): Response
{
/** @var Usuario $usuario */
$usuario = $this->getUser();
$form = $this->createForm(ChangePasswordType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var ChangePassword $formData */
$formData = $form->getData();
$usuario->setPlainPassword($formData->getNewPassword());
$usuario->clearResetToken();
$em->persist($usuario);
$em->flush();
$comunicador->sendSenhaTrocada($usuario, $formData->getNewPassword());
$this->addFlash('success', 'Senha alterada com sucesso!');
return $this->redirectToRoute('inscricao');
}
return $this->render('main/change_pass.html.twig', [
'trocarSenhaForm' => $form->createView(),
'usuario' => $usuario,
]);
}
/**
* @Route("/sair", name="logout")
*/
public function logoutAction(): Response
{
throw new \Exception('this should not be reached!');
}
/**
* @Route("/trocar-email", name="trocar_email")
* @IsGranted("ROLE_USER")
*/
public function trocarEmail(Request $request, Comunicador $comunicador, UsuarioRepository $repository, EntityManagerInterface $em): Response
{
/** @var Usuario $usuario */
$usuario = $this->getUser();
$form = $this->createForm(ChangeEmailSelfType::class, null, [
'repository' => $repository,
'user' => $usuario,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$email = $data['email'];
$token = $usuario->generateEmailResetToken($email, \DateInterval::createFromDateString('1 hour'));
$comunicador->sendTrocarEmail($usuario, $token);
$em->persist($usuario);
$em->flush();
$this->addFlash('success', 'Email para alteração de e-mail enviado!');
return $this->redirectToRoute('trocar_email');
}
return $this->render('main/email.html.twig', [
'form' => $form->createView()
]);
}
/**
* @Route("/trocar-email/{resetToken}", name="email_change")
* @IsGranted("ROLE_USER")
*/
public function confirmarTrocaEmail($resetToken, Usuario $usuario, Request $request, Comunicador $comunicador, EntityManagerInterface $em, UsuarioRepository $usuarioRepository): Response
{
if ($usuario->isEmailResetTokenValid($this->getUser()->getId())) {
if ($request->isXmlHttpRequest() && $request->isMethod('patch')) {
// Cancelamento da requisição
$email = $usuario->getResetEmail();
$usuario->clearResetToken();
$em->persist($usuario);
$em->flush();
return $this->json([
'message' => "Trocar de e-mail para {$email} cancelada com sucesso.",
'url' => $this->generateUrl('trocar_email'),
], 200);
}
$form = $this->createForm(ChangeEmailSelfType::class, ['email' => $usuario->getResetEmail()], [
'locked' => true,
'user' => $usuario,
'repository' => $usuarioRepository,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData = $form->getData();
$antigo = $usuario->getEmail();
$usuario->setEmail($usuario->getResetEmail());
$usuario->clearResetToken();
$comunicador->sendEmailTrocado($usuario, $antigo);
$em->persist($usuario);
$em->flush();
$this->addFlash('success', 'E-mail alterado!');
return $this->redirectToRoute('trocar_email');
}
return $this->render('main/email_change.html.twig', [
'form' => $form->createView(),
'usuario' => $usuario,
'token' => $resetToken,
]);
} else {
if ($request->isXmlHttpRequest()) {
return $this->json([
'message' => 'Solicitação inválida ou expirada!'
], 409);
}
else {
$this->addFlash('error', 'Solicitação inválida ou expirada!');
return $this->redirectToRoute('trocar_email');
}
}
}
/**
* @Route("/meus-dados", name="account")
* @IsGranted("ROLE_USER")
*/
public function meusDados(Request $request, EntityManagerInterface $em, UsuarioRepository $repository): Response
{
/** @var Usuario $usuario */
$usuario = $this->getUser();
$form = $this->createForm(DadosCandidatoType::class, $usuario, [
'candidato' => $usuario,
'repository' => $repository,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$usuario = $form->getData();
$em->persist($usuario);
$em->flush();
$this->addFlash('success', 'Cadastro de Usuário Atualizado!');
return $this->redirectToRoute('account');
}
return $this->render('main/account.html.twig', [
'form' => $form->createView()
]);
}
}