<?php
namespace App\Controller\Security;
use App\Repository\TManagerRepository;
use App\Utils\Globals;
use App\Utils\ResponseMessage;
use App\Entity\TManager;
use App\Service\DefaultService;
use Exception;
use Swift_Mailer;
use Swift_Message;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Transliterator;
class SecurityController extends AbstractController {
private Globals $globals;
private TManagerRepository $managerRepo;
public function __construct(Globals $globals, TManagerRepository $managerRepo)
{
$this->globals = $globals;
$this->managerRepo = $managerRepo;
}
/**
* @Route("/login", name="security_login")
* @param AuthenticationUtils $helper
* @return Response
*/
public function login(AuthenticationUtils $helper){
return $this->render('security/login.html.twig', [
'last_username' => $helper->getLastUsername(),
'error' => $helper->getLastAuthenticationError(),
]);
}
/**
* @Route("/checklogin", name="security_check_login")
* @param UserPasswordEncoderInterface $passwordEncoder
* @return JsonResponse
*/
public function checklogin(UserPasswordEncoderInterface $passwordEncoder): JsonResponse
{
$data = json_decode(file_get_contents('php://input'), false);
if (!isset($data->username, $data->password))
return new JsonResponse(ResponseMessage::MSG_FORM_INVALID, 200);
$username = $data->username;
$password = $data->password;
$login = $this->managerRepo->findOneBy(['username' => $username, 'active' => true]);
if (!$login)
$login = $this->managerRepo->findBy(array('email' => $username, 'active' => true));
if (!$login)
return new JsonResponse(ResponseMessage::MSG_LOGIN_NOT_FOUND, 200);
if (!$passwordEncoder->isPasswordValid($login, $password))
return new JsonResponse(ResponseMessage::MSG_PASSWORD_NOTMATCH, 200);
$this->authenticateUser($login);
return new JsonResponse(array('status' => 1, 'message' => ResponseMessage::MSG_SUCCESS, 'url' => $this->generateUrl('dashbord')), 200);
}
/**
* @Route("/logout", name="security_logout")
* @throws Exception
*/
public function logout(): void {
throw new Exception('This should never be reached!');
}
/**
* @Route("/invitation/", name="invitation")
*/
public function resetPassword(): Response {
return $this->render('security/password/invitation.html.twig');
}
/**
* @Route("/getinvitation/", name="getInvitation")
* @param Swift_Mailer $mailer
* @param TokenStorageInterface $tokenStorage
* @return JsonResponse
*/
public function getInvitation(Swift_Mailer $mailer): JsonResponse{
$postdata = file_get_contents('php://input');
$request = json_decode($postdata);
if (!isset($request->email)) return new JsonResponse(ResponseMessage::MSG_FORM_INVALID, 200);
$user = $request->email;
$user = $this->managerRepo->findOneBy(['username' => $user]);
if (!$user) return new JsonResponse('email not found', 200);
if ($user->getPasswordState() !== 'tochange' || empty($user->getPasswordToken())){
$user->setPasswordToken(uniqid(mt_rand(), true));
$user->setPasswordState('tochange');
$this->globals->em()->persist($user);
$this->globals->em()->flush();
}
$message = (new Swift_Message('OPAIE - Invitation'))
->setFrom(DefaultService::$EMAIL_FROM)
->setTo($user->getUsername())
->setBody(
$this->renderView(
'email/opaie/passwordToken.html.twig', array('fullname' => $user->getPsoeudo(), 'token' => $user->getPasswordToken())
),
'text/html'
);
$sent = $mailer->send($message);
if ($sent === 0)
return new JsonResponse(ResponseMessage::MSG_MAIL_NOT_SENT, 200);
return new JsonResponse(array('status' => ResponseMessage::MSG_SUCCESS, 'data' => $sent), 200);
}
/**
* @Route("/validChangePassword/", name="validChangePassword")
* @param UserPasswordEncoderInterface $passwordEncoder
* @param TokenStorageInterface $tokenStorage
* @return JsonResponse
*/
public function validChangePassword(UserPasswordEncoderInterface $passwordEncoder): JsonResponse {
$postdata = file_get_contents('php://input');
$request = json_decode($postdata);
if (!isset($request->password1, $request->password2, $request->token)){
return new JsonResponse(ResponseMessage::MSG_FORM_INVALID, 200);
}
$password1 = $request->password1; $password2 = $request->password2; $token = $request->token;
if ($password1 !== $password2) { return new JsonResponse('password not match'); }
if (strlen($password1) < 4) { return new JsonResponse('password too short'); }
$user = $this->managerRepo->findBy(['password_token' => $token, 'password_state' => 'tochange']);
if (!$user) { return new JsonResponse('token invalid', 200); }
$user = $user[0];
$user->setPassword($passwordEncoder->encodePassword($user, $password1));
$user->setPasswordState('changed');
$user->setPasswordToken(null);
$this->globals->em()->persist($user);
$this->globals->em()->flush();
return new JsonResponse(array('status' => ResponseMessage::MSG_SUCCESS, 'data' => null), 200);
}
/**
* @Route("/resetPasword/{token}/", name="security_reset_password")
* @param $token
* @param TokenStorageInterface $tokenStorage
* @return RedirectResponse|Response
*/
public function resetPasword($token) {
if (!$token) return $this->redirectToRoute('dashbord');
$user = $this->managerRepo->findBy(['password_token' => $token]);
if (!$user) return $this->redirectToRoute('dashbord');
$user = $user[0];
return $this->render('security/password/resetPassword.html.twig', array('user' => $user));
}
private function authenticateUser(TManager $user){
$providerKey = 'database_users'; // your firewall name
$token = new UsernamePasswordToken($user, null, $providerKey, $user->getRoles());
$this->get('security.token_storage')->setToken($token);
$this->get('session')->set('_security_main', serialize($token));
}
/**
* @param $string
* @return string|string[]|null
*/
public function slugify($string) {
$rule = 'NFD; [:Nonspacing Mark:] Remove; NFC';
$transliterator = Transliterator::create($rule);
$string = $transliterator->transliterate($string);
return preg_replace(
'/[^a-z0-9]/',
'',
strtolower(trim(strip_tags($string)))
);
}
}