<?php
namespace App\Controller;
use App\Model\DataObject\User;
use App\Security\AppAuthenticator;
use Carbon\Carbon;
use Exception;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Pimcore\Controller\FrontendController;
use Pimcore\Log\Simple;
use Pimcore\Mail;
use Pimcore\Model\DataObject;
use Pimcore\Model\DataObject\Folder;
use Pimcore\Model\Element\Service;
use Pimcore\Model\WebsiteSetting;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use App\Form\RecaptchaFormType;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security as FrontSecurity;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class AuthController extends FrontendController
{
/**
* @Template
* @param Request $request
* @param AuthenticationUtils $authenticationUtils
* @return array
* @Route(
* "/{_locale}/login",
* name="login"
* )
*/
public function loginAction(Request $request, AuthenticationUtils $authenticationUtils, FrontSecurity $security)
{
$lang = $request->getLocale();
$securityUser = $security->getUser();
if ($securityUser) {
$user = User::getByUsername($securityUser->getUserIdentifier())->load()[0];
return $this->redirect($this->getDefaultRoute($user));
}
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
//dd($error);
return [
'_username' => $lastUsername,
'error' => $error,
'_target_path' => $request->get('_target_path') ?? null,
];
}
/**
* @Route(
* "/is-connected",
* name="isConnected",
* methods={"GET"}
* )
*/
public function isConnected(FrontSecurity $security)
{
if ($security->getUser()) {
return $this->json(['res' => true]);
}
return $this->json(['res' => false]);
}
/**
* @Route("/{_locale}/login/after", name="afterLogin")
*/
public function afterLogin(Request $request, FrontSecurity $security)
{
return $this->redirect('/' . $request->getLocale());
}
/**
* Link to this controller to start the "connect" process
*
* @Route("/connect/{service}", name="connect_oauth")
*/
public function connectWithOauth(Request $request, ClientRegistry $clientRegistry)
{
$orderId = $request->get("orderid");
if($orderId){
$order = DataObject\Order::getById($orderId);
if($order){
$url = $clientRegistry
->getClient($request->get('service'))
->redirect(['email'], [])->getTargetUrl();
$query_str = parse_url($url, PHP_URL_QUERY);
parse_str($query_str, $query_params);
if(isset($query_params["state"])){
$order->setOauthState($query_params["state"]);
}
}
}
return $clientRegistry
->getClient($request->get('service'))
->redirect(['email'], []);
}
/**
* @Template
*
* @Route("/oauth/check/{service}", name="oauth_check")
*/
public function checkOauth(Request $request, FrontSecurity $security)
{
return [];
}
private function getDefaultRoute(User $user)
{
return '/' . $user->getLang();
}
/**
* @Template
* @param Request $request
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
* @throws \Exception
* @Route(
* "/{_locale}/reset/password/{renew_token}",
* name="reset_password",
* methods={"GET","POST"}
* )
*/
public function resetPasswordAction(Request $request)
{
if ($request->isMethod('POST') && $request->get("new_password")) {
$user = User::getById($request->get('user_id'));
if (!$user) {
return ['error' => "Impossible de trouver l'utilisateur"];
}
$user->setPassword($request->get('new_password'));
$user->setRenewToken(null);
$user->setRenewExpire(null);
$user->save();
return $this->redirect($this->generateUrl("login"));
} elseif ($request->get("renew_token")) {
$user = User::getByRenewToken($request->get("renew_token"))->load()[0];
if (!$user) {
return $this->redirect($this->generateUrl('login'));
}
$expired = false;
if ($user->getRenewExpire()->lt(Carbon::now())) {
$expired = true;
}
return ["user" => $user, "expired" => $expired];
} else {
return $this->redirect($this->generateUrl('login'));
}
}
/**
* @Template
* @param Request $request
* @return \Symfony\Component\HttpFoundation\JsonResponse
* @throws \Exception
* @Route(
* "/{_locale}/reset/password",
* name="ask_reset_password",
* methods={"GET","POST"}
* )
*/
public function askResetPasswordAction(Request $request, FrontSecurity $security, \Pimcore\Config\Config $websiteConfig)
{
$lang = $request->getLocale();
if ($request->isMethod('POST') && $request->get('username')) {
$user = User::getByUsername($request->get('username'))->load()[0];
if (!$user) {
return ["error" => "Le compte n'existe pas"];
}
$token = md5(time() * 10000);
$user->setRenewToken($token);
$nbrDays = intval($websiteConfig->get('expirationDays')) === 0 ? 1 : intval($websiteConfig->get('expirationDays'));
$user->setRenewExpire(Carbon::now()->addDay($nbrDays));
$user->save();
$mail = new Mail();
$mail->setDocument('/emails/' . $lang . "/reset-password");
$mail->to($user->getUsername());
$mail->setParam('renewLink', $this->generateUrl("reset_password", ['renew_token' => $token], UrlGeneratorInterface::ABSOLUTE_URL));
$mail->send();
return ["message" => "Vous avez reçu un lien pour modifier votre mot de passe par email."];
}
}
/**
* @Template
* @Route(
* "/{_locale}/register",
* name="register",
* methods={"GET","POST"}
* )
*/
public function registerAction(Request $request, FrontSecurity $security, \Pimcore\Config\Config $websiteConfig, ValidatorInterface $validator)
{
$formStatus = false;
$honeypotValue = "Waterloo";
// initialize form and handle request data
$formContact = $this->createForm(RecaptchaFormType::class, null);
$formContact->handleRequest($request);
Simple::log('apk_register', 'Start new user');
$securityUser = $security->getUser();
if ($securityUser) {
$user = User::getByUsername($securityUser->getUserIdentifier())->load()[0];
return $this->redirect($this->getDefaultRoute($user));
}
/** @var Pimcore\Model\DataObject */
$countries = DataObject\Service::getOptionsForSelectField("Pimcore\Model\DataObject\User", "country");
if ($request->isMethod('POST')) {
$orderid = $request->get("orderid");
foreach (['email', 'password', 'confirm-password'] as $required_field) {
$isSet = false;
if (is_array($required_field)) {
foreach ($required_field as $field) {
if ($request->get($field)) {
$isSet = true;
}
}
} else {
$isSet = $request->get($required_field);
}
if (!$isSet) {
return ["error" => "Vous devez remplir tous les champs.","countries" => $countries, "previousValues" => $request->request->all(), 'form' => $formContact->createView(), "formStatus" => $formStatus, "honeypotValue" => $honeypotValue];
}
}
$email = $request->get('email');
$password = $request->get('password');
$confirmPassword = $request->get('confirm-password');
if ($password !== $confirmPassword) {
return ["error" => "Les 2 mots de passe ne sont pas identiques","countries" => $countries, "previousValues" => $request->request->all(), 'form' => $formContact->createView(), "formStatus" => $formStatus, "honeypotValue" => $honeypotValue];
}
/** @var Symfony\Component\Validator\Constraints as Assert */
$emailConstraint = new Assert\Email();
$errors = $validator->validate($email, $emailConstraint);
if (count($errors) > 0) {
return ["error" => $errors[0]->getMessage(),"countries" => $countries, "previousValues" => $request->request->all(), 'form' => $formContact->createView(), "formStatus" => $formStatus, "honeypotValue" => $honeypotValue];
}
$checkUser = User::getByUsername($email, ['limit' => 1, 'unpublished' => true]);
if ($checkUser) {
$now = Carbon::now();
if($checkUser->getPublished()){
return ["message" => 'Le compte existe déjà, <a href="' . $this->generateUrl('login') . '">connectez-vous</a> ou <a href="' . $this->generateUrl('ask_reset_password') . '">cliquez ici</a> pour réinitialiser votre mot de passe',"countries" => $countries, "previousValues" => $request->request->all(), 'form' => $formContact->createView(), "formStatus" => $formStatus, "honeypotValue" => $honeypotValue];
}else{
if($checkUser->getStatus() == "unverified"){
if(($now->timestamp - $checkUser->getCreationDate()) > 60){
$token = md5(uniqid('renew_token', true));
$checkUser->setRenewToken($token);
$nbrDays = intval($websiteConfig->get('expirationDays')) === 0 ? 1 : intval($websiteConfig->get('expirationDays'));
$checkUser->setRenewExpire(Carbon::now()->addDays($nbrDays));
$checkUser->save();
if($orderid){
$order = DataObject\Order::getById($orderid);
if($order && !$order->getLinkedUser()){
$order->setLinkedUser($checkUser);
$order->save();
}
}
/*$mail = new Mail();
$mail->setDocument('/emails/' . $request->getLocale() . "/verify-email");
$mail->to($checkUser->getUsername());
$mail->setParam('Link', $this->generateUrl('verify_email_itsme', ['renew_token' => $checkUser->getRenewToken()], UrlGeneratorInterface::ABSOLUTE_URL));
$mail->send();*/
}else{
Simple::log('apk_register', 'less that 60seconds since first register mail');
}
return $this->redirectToRoute('verify_email_itsme', ['renew_token' => $checkUser->getRenewToken()]);
//return ["message" => "Votre adresse email doit être confirmée, vous allez recevoir un email de confirmation", "message_title" => "You've got mail!"];
}else{
return ["message" => 'Il semblerait que votre compte soit désactivé. Veuillez nous contacter.',"countries" => $countries, "previousValues" => ["gender" => "", "firstname" => "", "lastname" => "", "email" => "", "password" => "", "confirm-email" => "", "phone" => "", 'street' => '', 'zip' => '', 'country' => '', 'city' => '', 'prefix' => '+32'], 'form' => $formContact->createView(), "formStatus" => $formStatus, "honeypotValue" => $honeypotValue];
}
}
}
$data = $formContact->getData();
// fake variable
$address = $_POST["address"];
// reCaptcha verification
$recaptchaKeyPrivate = WebsiteSetting::getByName('recaptchaKeyPrivate');
$recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
$recaptcha_response = $data['recaptcha'];
$recaptcha = file_get_contents($recaptcha_url . '?secret=' . $recaptchaKeyPrivate->getData() . '&response=' . $recaptcha_response);
$recaptcha = json_decode($recaptcha);
if ($recaptcha->success && isset($recaptcha->score) && $recaptcha->score >= 0.3 && $address == $honeypotValue)
{
$user = new User();
$user->setUsername($email);
$user->setEmail($email);
$user->setLang($request->getLocale());
$user->setRecaptchaScore($recaptcha->score);
$user->setPassword($password);
$user->setRoles(["ROLE_USER"]);
$user->setStatus("unverified");
$keyname = Service::getValidKey($email, 'object');
$user->setKey($keyname);
$user->setParent(Folder::getByPath('/users') ?? Folder::create(['o_parentId' => 1, 'o_key' => 'users']));
$user->setPublished(false);
$token = md5(uniqid('renew_token', true));
$user->setRenewToken($token);
$nbrDays = intval($websiteConfig->get('expirationDays')) === 0 ? 1 : intval($websiteConfig->get('expirationDays'));
$user->setRenewExpire(Carbon::now()->addDays($nbrDays));
if (WebsiteSetting::getByName("parrainage")) {
if ($request->get('parrain')) {
$parrain = User::getByParrainageToken($request->get('parrain'))->load();
if ($parrain) {
$parrain = $parrain[0];
} else {
return ["error" => "Ce code de parrainage n'existe pas.", "countries" => $countries, "previousValues" => ["gender" => "", "firstname" => "", "lastname" => "", "email" => $email, "password" => $password, "confirm-email" => "", "phone" => "", 'street' => '', 'zip' => '', 'country' => '', 'city' => '', 'prefix' => '+32'], 'form' => $formContact->createView(), "formStatus" => $formStatus, "honeypotValue" => $honeypotValue];
}
$user->setParrain($parrain);
}
}
$user->save();
if($orderid){
$order = DataObject\Order::getById($orderid);
if($order && !$order->getLinkedUser()){
$order->setLinkedUser($user);
$order->save();
}
}
/*$mail = new Mail();
$mail->setDocument('/emails/' . $request->getLocale() . "/verify-email");
$mail->to($user->getUsername());
$mail->setParam('Link', $this->generateUrl('verify_email_itsme', ['renew_token' => $user->getRenewToken()], UrlGeneratorInterface::ABSOLUTE_URL));
$mail->send();*/
return $this->redirectToRoute('verify_email_itsme', ['renew_token' => $user->getRenewToken()]);
//return ["message" => "Votre adresse email doit être confirmée, vous allez recevoir un email de confirmation", "message_title" => "You've got mail!", 'form' => $formContact->createView(), "formStatus" => $formStatus];
}else{
$formStatus = 'robot';
}
}
return ["countries" => $countries, "previousValues" => ["gender" => "", "firstname" => "", "lastname" => "", "email" => "", "password" => "", "confirm-email" => "", "phone" => "", 'street' => '', 'zip' => '', 'country' => '', 'city' => '', 'prefix' => '+32'], 'form' => $formContact->createView(), "formStatus" => $formStatus, "honeypotValue" => $honeypotValue];
}
/**
* @Template
* @Route(
* "{_locale}/verify-email/itsme/{renew_token}",
* name="verify_email_itsme",
* methods={"GET"}
* )
*/
public function verifyEmailItsmeAction(Request $request, \Pimcore\Config\Config $websiteConfig,
GuardAuthenticatorHandler $guard,
AppAuthenticator $formAuthenticator)
{
if ($request->get('renew_token')) {
$user = User::getByRenewToken($request->get("renew_token"), ['limit' => 1, 'unpublished' => true]);
if (!$user) {
return ["error" => "Vous devez définir un token valide", "message" => false];
}
$user->setPublished(true);
$user->save();
//login automatique du user
$guard->authenticateUserAndHandleSuccess(
$user,
$request,
$formAuthenticator,
'app_admin'
);
return ["userid" => $user->getId()];
} else {
return ["error" => "Vous devez définir un token valide", "message" => false];
}
}
/**
* @Template
* @Route(
* "{_locale}/verify-email/{renew_token}",
* name="verify_email",
* methods={"GET"}
* )
*/
public function verifyEmailAction(Request $request, \Pimcore\Config\Config $websiteConfig)
{
if ($request->get('renew_token')) {
$user = User::getByRenewToken($request->get("renew_token"), ['limit' => 1, 'unpublished' => true]);
if (!$user) {
return ["error" => "Vous devez définir un token valide", "message" => false];
}
$user->setRenewToken(null);
$user->setRenewExpire(null);
$user->setStatus("verified");
$user->save();
$countries = DataObject\Service::getOptionsForSelectField("Pimcore\Model\DataObject\User", "country");
return $this->render('user/details.html.twig',
["user" => $user, "countries" => $countries, "message" => "You have been verified."]
);
} else {
return ["error" => "Vous devez définir un token valide", "message" => false];
}
}
/**
* @Route("/before-logout", name="beforeLogout", methods={"GET"})
*/
public function beforeLogout()
{
// \Pimcore\Cache::clearTag("pimcore_viewcache_header_cache");
return $this->redirectToRoute("logout");
}
/**
* @Route("/logout", name="logout", methods={"GET"})
*/
public function logout()
{
// controller can be blank: it will never be executed!
throw new \Exception('Don\'t forget to activate logout in security.yaml');
}
}