<?php namespace App\Controller; use App\Entity\AccountComptoir; use App\Entity\AccountGroupe; use App\Entity\AccountPrestataire; use App\Entity\AccountSiege; use App\Entity\Comptoir; use App\Entity\Geoloc; use App\Entity\GlobalParameter; use App\Entity\Groupe; use App\Entity\Prestataire; use App\Entity\Siege; use App\Entity\User; use App\Entity\Usergroup; use App\Enum\CurrencyEnum; use App\Form\Type\InstallFormType; use App\Security\LoginAuthenticator; use Doctrine\ORM\EntityManagerInterface; use FOS\UserBundle\Event\FilterUserResponseEvent; use FOS\UserBundle\FOSUserEvents; use FOS\UserBundle\Model\UserManagerInterface; use Geocoder\Provider\Nominatim\Nominatim; use Geocoder\Query\GeocodeQuery; use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Security as Secur; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Guard\GuardAuthenticatorHandler; use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; use Symfony\Component\Security\Core\Security; class IndexController extends AbstractController { private $eventDispatcher; private $em; private $userManager; private $tokenManager; private $guard; private $authenticator; private $session; private $tokenStorage; private $router; private $security; public function __construct( EventDispatcherInterface $eventDispatcher, EntityManagerInterface $em, UserManagerInterface $userManager, CsrfTokenManagerInterface $tokenManager = null, GuardAuthenticatorHandler $guard, SessionInterface $session, LoginAuthenticator $authenticator, TokenStorageInterface $tokenStorage, RouterInterface $router, Security $security ) { $this->eventDispatcher = $eventDispatcher; $this->em = $em; $this->userManager = $userManager; $this->tokenManager = $tokenManager; $this->guard = $guard; $this->authenticator = $authenticator; $this->session = $session; $this->tokenStorage = $tokenStorage; $this->router = $router; $this->security = $security; } /** * @Route("/", name="index") */ public function index(Request $request) { /* Pour la première installation */ $siege = $this->em->getRepository(Siege::class)->findAll(); if (null == $siege || empty($siege)) { return $this->redirectToRoute('installation'); } /* Pour la modale de login => SecurityController loginAction */ $session = $request->getSession(); $lastUsernameKey = Secur::LAST_USERNAME; // last username entered by the user $lastUsername = (null === $session) ? '' : $session->get($lastUsernameKey); $csrfToken = $this->tokenManager ? $this->tokenManager->getToken('authenticate')->getValue() : null; $isWordpress = 'false' != $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::USE_WORDPRESS); $template = 'index.html.twig'; if ($isWordpress) { $template = 'index_wordpress.html.twig'; } if ( isset($_GET["upswd"]) && $_GET["upswd"] == "success" && $this->security->isGranted('ROLE_ADHERENT') && $this->getParameter('tav_env') == true ) { $this->addFlash( 'warning', 'Suite à la modification de votre mot de passe, pensez à mettre à jour votre code de paiment pour pouvoir effectuer des achats.' ); } return $this->render('@kohinos/' . $template, [ 'news' => [], 'last_username' => $lastUsername, 'csrf_token' => $csrfToken, ]); } /** * @Route("/manifest.json", name="manifest") */ public function manifest(Request $request) { return new JsonResponse(json_decode($this->renderView('@kohinos/common/manifest.json.twig'))); } /** * @Route("/cotisation/invalid", name="cotisation_invalid") */ public function cotisationInvalidAction(Request $request) { return $this->render('@kohinos/index_cotisation_invalid.html.twig', []); } /** * @Route("/installation", name="installation") */ public function installationAction(Request $request) { $siege = $this->em->getRepository(Siege::class)->findAll(); if (!empty($siege) && count($siege) > 0) { // Installation déjà effectuée ! return $this->redirectToRoute('index'); } $repogroup = $this->em->getRepository(Usergroup::class); $group = $repogroup->findOneBy(['name' => 'Super Admin']); if (empty($group)) { return new Response('ERREUR !<br><br>Avant de pouvoir installer le kohinos, il faut charger les fixtures : <br>Soit charger les fixtures standards :<br><em>php bin/console hautelook:fixtures:load --purge-with-truncate</em><br/><br/>Soit charger les fixtures de dev (pour tester le kohinos avec des données/comptes factices):<br/><em>php bin/console hautelook:fixtures:load --purge-with-truncate --env=test</em>', 200); } $user = $this->userManager->createUser(); $user->setEnabled(true); $user->addPossiblegroup($group); $user->addGroup($group); $form = $this->createForm(InstallFormType::class, ['user' => $user]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $siege = $form['siege']->getData(); $user = $form['user']->getData(); $groupe = $form['groupe']->getData(); $configs = $form['config']->getData(); $iban = $form['iban']->getData(); $website = $form['website']->getData(); $groupe->setSiege($siege); //Création du prestataire recevant les cotisations $presta = new Prestataire(); $presta->setMlc(true); $presta->setRaison('Monnaie locale'); $presta->setDescription('Association gérant la monnaie locale et recevant les cotisations'); $presta->setEnabled(true); $presta->setIban($iban); if (!empty($website)) { $presta->setWeb($website); } $presta->setSiret(' '); $groupePresta = $repogroup->findOneBy(['name' => 'Prestataire']); $user->addPossiblegroup($groupePresta); $presta->addUser($user); $presta->setGroupe($groupe); $this->em->persist($siege); if (null == $siege->getAccountWithCurrency(CurrencyEnum::CURRENCY_EMLC)) { $account = new AccountSiege(); $account ->setBalance($siege->getEcompteNantie()) ->setCurrency(CurrencyEnum::CURRENCY_EMLC) // compte de monnaie numérique nantie ; $siege->addAccount($account); $this->em->persist($account); } if (null == $siege->getAccountWithCurrency(CurrencyEnum::CURRENCY_MLC)) { $accountMLC = new AccountSiege(); $accountMLC ->setBalance($siege->getCompte()) ->setCurrency(CurrencyEnum::CURRENCY_MLC) // compte de monnaie papier au siege non nantie ; $siege->addAccount($accountMLC); $this->em->persist($accountMLC); } // if ($siege->getAccountWithCurrency(CurrencyEnum::CURRENCY_EURO) == null) { // $accountEuro = new AccountSiege(); // $accountEuro // ->setCurrency(CurrencyEnum::CURRENCY_EURO) // compte réel de nantissement // @TODO : offrir la possibilité de voir les opérations du compte euro du fond de garanti ? Ou plutôt de suivre les euros à récupérés aux comptoirs // ; // $siege->addAccount($accountEuro); // $this->em->persist($accountEuro); // } if (null == $siege->getAccountWithCurrency(CurrencyEnum::CURRENCY_MLC_NANTIE)) { $accountMlcNantie = new AccountSiege(); $accountMlcNantie ->setBalance($siege->getCompteNantie()) ->setCurrency(CurrencyEnum::CURRENCY_MLC_NANTIE) // compte de monnaie papier nantie ; $siege->addAccount($accountMlcNantie); $this->em->persist($accountMlcNantie); $this->em->persist($siege); } $this->em->persist($groupe); if (null == $groupe->getAccountWithCurrency(CurrencyEnum::CURRENCY_MLC)) { $account = new AccountGroupe(); $account ->setBalance($groupe->getCompte()) ->setCurrency(CurrencyEnum::CURRENCY_MLC) ; $groupe->addAccount($account); $this->em->persist($account); $this->em->persist($groupe); } $comptoirData = $form['comptoir']->getData(); $comptoirName = $comptoirData['name']; $comptoirCompte = $comptoirData['compte']; $comptoirGeoloc = $comptoirData['geoloc']; if (!empty($comptoir)) { $comptoir = new Comptoir(); $comptoir->setName($comptoirName); $comptoir->setEnabled(true); $comptoir->setGeoloc($comptoirGeoloc); $comptoir->setGroupe($groupe); $this->em->persist($comptoir); if (null == $comptoir->getAccountWithCurrency(CurrencyEnum::CURRENCY_MLC)) { $account = new AccountComptoir(); $account ->setBalance(empty($comptoirCompte) ? $comptoirCompte : 0) ->setCurrency(CurrencyEnum::CURRENCY_MLC) ; $comptoir->addAccount($account); $this->em->persist($account); $this->em->persist($comptoir); } } $this->userManager->updateUser($user); $this->em->persist($presta); if (null == $presta->getAccountWithCurrency(CurrencyEnum::CURRENCY_EMLC)) { $account = new AccountPrestataire(); $account ->setBalance($presta->getEcompte()) ->setCurrency(CurrencyEnum::CURRENCY_EMLC) ; $presta->addAccount($account); $this->em->persist($account); } if ($presta->isMlc() && null == $presta->getAccountWithCurrency(CurrencyEnum::CURRENCY_EURO)) { // Ajout du compte de fonctionnement euro pour le prestataire MLC $accountEuro = new AccountPrestataire(); $accountEuro ->setCurrency(CurrencyEnum::CURRENCY_EURO) ; $presta->addAccount($accountEuro); $this->em->persist($accountEuro); } $this->em->persist($presta); foreach ($configs as $config) { $this->em->persist($config); } $this->em->flush(); // Création de l'utilisateur avec ROLE_API pour le plugin Wordpress ou les applis tierces ! $userAPI = $this->userManager->createUser(); $userAPI->setEnabled(true); $userAPI->setUsername('userapi'); $userAPI->setPassword(md5(random_bytes(10))); $userAPI->setEmail('userapi@kohinos.fr'); $userAPI->addRole('ROLE_API'); $this->userManager->updateUser($userAPI); $this->em->flush(); $this->addFlash( 'success', "BRAVO ! Vous venez de configurer le Kohinos. Vous pouvez maintenant accéder à l'interface d'administration." ); $url = $this->generateUrl('fos_user_registration_confirmed'); $response = new RedirectResponse($url); // @TODO : send mail with this event catch ! $this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response)); return new RedirectResponse($this->generateUrl('sonata_admin_dashboard')); } return $this->render('@kohinos/installation.html.twig', [ 'form' => $form->createView(), ]); } /** * @Route("/geoloc", name="geolocAdresse") */ public function geoLocAction(Request $request) { $referer = $request->headers->get('referer'); if ($referer && !$request->isXmlHttpRequest()) { return $this->redirect($referer); } elseif (!$request->isXmlHttpRequest()) { return new Response('', Response::HTTP_BAD_REQUEST); } $status = 'success'; $return = null; if (!empty($request->get('cpostal')) && !empty($request->get('ville'))) { try { // GEOCODING ADDRESS : $httpClient = new \Http\Adapter\Guzzle6\Client(); $provider = Nominatim::withOpenStreetMapServer($httpClient, 'Mozilla/5.0'); $geocoder = new \Geocoder\StatefulGeocoder($provider, 'fr'); // Query geocoding from complete address $result = $geocoder->geocodeQuery(GeocodeQuery::create($request->get('adresse') . ' ' . $request->get('cpostal') . ' ' . $request->get('ville'))); if (count($result) > 0) { $coords = $result->first()->getCoordinates(); $return = ['lat' => $coords->getLatitude(), 'lon' => $coords->getLongitude()]; } else { $result = $geocoder->geocodeQuery(GeocodeQuery::create($request->get('cpostal') . ' ' . $request->get('ville'))); if (count($result) > 0) { $coords = $result->first()->getCoordinates(); $return = ['lat' => $coords->getLatitude(), 'lon' => $coords->getLongitude()]; } } } catch (\Exception $e) { $status = 'error'; } } else { $status = 'error'; } return new JsonResponse(['status' => $status, 'data' => $return]); } /** * Choix du groupe local géré. * * @Route("/login/groupe/choice/{usergrpid}/{grpid}", name="groupe_choice") * @ParamConverter("group", class="App:Usergroup", options={"mapping": {"usergrpid": "id"}}) * @ParamConverter("groupe", class="App:Groupe", options={"mapping": {"grpid": "id"}}) * @IsGranted("ROLE_USER") */ public function groupeChoiceAction(Usergroup $group, Groupe $groupe, Request $request) { $this->em->refresh($this->getUser()); if (!($this->getUser()->getPossiblegroups()->exists(function ($key, $value) { return in_array('ROLE_GESTION_GROUPE', $value->getRoles()) || in_array('ROLE_CONTACT', $value->getRoles()) || in_array('ROLE_TRESORIER', $value->getRoles()); }) and $this->getUser()->getGroupesgeres()->contains($groupe))) { $this->addFlash( 'error', 'Accès impossible !' ); return $this->redirectToRoute('index'); } $this->removeOldSessionParams(); // On enregistre le groupe local choisit en session $this->session->set('_groupegere', $groupe); $this->reloadUserTokenFromGroup($group, $request); return $this->redirectToRoute('sonata_admin_dashboard'); } /** * Choix du comptoir géré. * * @Route("/login/comptoir/choice/{usergrpid}/{cptid}", name="comptoir_choice") * @ParamConverter("group", class="App:Usergroup", options={"mapping": {"usergrpid": "id"}}) * @ParamConverter("comptoir", class="App:Comptoir", options={"mapping": {"cptid": "id"}}) * @IsGranted("ROLE_USER") */ public function comptoirChoiceAction(Usergroup $group, Comptoir $comptoir, Request $request) { $this->em->refresh($this->getUser()); if (!($this->getUser()->getPossiblegroups()->exists(function ($key, $value) { return in_array('ROLE_COMPTOIR', $value->getRoles()); }) and $this->getUser()->getComptoirsgeres()->contains($comptoir))) { $this->addFlash( 'error', 'Accès impossible !' ); return $this->redirectToRoute('index'); } $this->removeOldSessionParams(); // On enregistre le comptoir choisit en session $this->session->set('_comptoirgere', $comptoir); $this->reloadUserTokenFromGroup($group, $request); return $this->redirectToRoute('sonata_admin_dashboard'); } /** * Choix du presta géré. * * @Route("/login/presta/choice/{usergrpid}/{prestaid}", name="presta_choice") * @ParamConverter("group", class="App:Usergroup", options={"mapping": {"usergrpid": "id"}}) * @ParamConverter("prestataire", class="App:Prestataire", options={"mapping": {"prestaid": "id"}}) * @IsGranted("ROLE_USER") */ public function prestaChoiceAction(Usergroup $group, Prestataire $prestataire, Request $request) { $this->em->refresh($this->getUser()); if (!(($this->getUser()->getPossiblegroups()->exists(function ($key, $value) { return in_array('ROLE_PRESTATAIRE', $value->getRoles()); }) and $this->getUser()->getPrestataires()->contains($prestataire)) || (($this->getUser()->getPossiblegroups()->exists(function ($key, $value) { return in_array('ROLE_CAISSIER', $value->getRoles()); }) and $this->getUser()->getCaissiers()->contains($prestataire)))) ) { $this->addFlash( 'error', 'Accès impossible !' ); return $this->redirectToRoute('index'); } $this->removeOldSessionParams(); // On enregistre le presta choisit en session $this->session->set('_prestagere', $prestataire); $this->reloadUserTokenFromGroup($group, $request); return $this->redirectToRoute('index'); } /** * @Route("/login/group/choice/{id}", name="usergroup_choice") * @IsGranted("ROLE_USER") */ public function groupChoiceAction(Usergroup $group, Request $request) { if (!$this->getUser()->getPossiblegroups()->contains($group)) { $this->addFlash( 'error', 'Accès impossible !' ); return $this->redirectToRoute('index'); } $this->removeOldSessionParams(); $this->reloadUserTokenFromGroup($group, $request); if (in_array('ROLE_SUPER_ADMIN', $this->getUser()->getRoles(), true)) { // c'est un administrateur return new RedirectResponse($this->router->generate('sonata_admin_dashboard')); } return new RedirectResponse($this->router->generate('index')); } private function removeOldSessionParams() { $this->session->remove('_choixGroup'); $this->session->remove('_groupId'); $this->session->remove('_groupegere'); $this->session->remove('_comptoirgere'); $this->session->remove('_prestagere'); } private function reloadUserTokenFromGroup($group, $request) { $groups = [$group]; if ($this->getUser()->getGroups() !== $groups) { $this->getUser()->setGroups($groups); $this->em->persist($this->getUser()); $this->em->flush(); } $token = new PostAuthenticationGuardToken( $this->getUser(), 'main', $this->getUser()->getRoles() ); $this->tokenStorage->setToken($token); $this->guard->authenticateUserAndHandleSuccess( $this->getUser(), $request, $this->authenticator, 'main' ); $this->session->set('_security_main', serialize($token)); } }