src/Helper/Security/SecurityHelper.php line 87

Open in your IDE?
  1. <?php
  2. namespace App\Helper\Security;
  3. use App\Helper\SuluHelper;
  4. use App\Normalizer\Security\CustomerNormalizer;
  5. use App\Security\Customer\Customer;
  6. use Croisiland\CommonBundle\Provider\ErpUrlProvider;
  7. use Croisiland\CommonBundle\Provider\SuluUrlProvider;
  8. use Exception;
  9. use Sulu\Component\DocumentManager\DocumentManagerInterface;
  10. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  11. use Symfony\Component\HttpFoundation\Cookie;
  12. use Symfony\Component\HttpFoundation\RequestStack;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\Serializer\Exception\ExceptionInterface;
  15. use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
  16. use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
  17. use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
  18. use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
  19. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  20. use Symfony\Contracts\HttpClient\HttpClientInterface;
  21. class SecurityHelper
  22. {
  23. private const string CUSTOMER_SESSION_TOKEN_KEY = 'customer_session_token';
  24. protected HttpClientInterface $httpClient;
  25. protected ParameterBagInterface $parameterBag;
  26. protected RequestStack $requestStack;
  27. protected DocumentManagerInterface $documentManager;
  28. protected SuluHelper $suluHelper;
  29. protected ErpUrlProvider $erpUrlProvider;
  30. protected SuluUrlProvider $suluUrlProvider;
  31. public function __construct(HttpClientInterface $httpClient,
  32. ParameterBagInterface $parameterBag,
  33. RequestStack $requestStack,
  34. DocumentManagerInterface $documentManager,
  35. SuluHelper $suluHelper,
  36. ErpUrlProvider $erpUrlProvider,
  37. SuluUrlProvider $suluUrlProvider)
  38. {
  39. $this->httpClient = $httpClient;
  40. $this->parameterBag = $parameterBag;
  41. $this->requestStack = $requestStack;
  42. $this->documentManager = $documentManager;
  43. $this->suluHelper = $suluHelper;
  44. $this->erpUrlProvider = $erpUrlProvider;
  45. $this->suluUrlProvider = $suluUrlProvider;
  46. }
  47. /**
  48. * @param string $email
  49. * @param string $password
  50. * @param bool $rememberMe
  51. * @return Customer
  52. * @throws ClientExceptionInterface
  53. * @throws DecodingExceptionInterface
  54. * @throws RedirectionExceptionInterface
  55. * @throws ServerExceptionInterface
  56. * @throws TransportExceptionInterface
  57. */
  58. public function authenticateCustomer(string $email, string $password, bool $rememberMe = true): Customer
  59. {
  60. $response = $this->customerApiLoginFromCredentials($email, $password, $rememberMe);
  61. return (new Customer())
  62. ->setEmail($email)
  63. ->setFirstName($response['first_name'])
  64. ->setLastName($response['last_name'])
  65. ->setToken($response['token']);
  66. }
  67. /**
  68. * @return Customer|null
  69. * @throws ClientExceptionInterface
  70. * @throws DecodingExceptionInterface
  71. * @throws RedirectionExceptionInterface
  72. * @throws ServerExceptionInterface
  73. * @throws TransportExceptionInterface
  74. */
  75. public function getLoggedCustomer(): ?Customer
  76. {
  77. $token = $this->requestStack->getCurrentRequest()->cookies->get(self::CUSTOMER_SESSION_TOKEN_KEY);
  78. if (null === $token) {
  79. $token = $this->requestStack->getSession()->get(self::CUSTOMER_SESSION_TOKEN_KEY);
  80. }
  81. if (null === $token) {
  82. return null;
  83. }
  84. try {
  85. $credentials = $this->customerApiLoginFromToken($token);
  86. return (new Customer())
  87. ->setEmail($credentials['email'])
  88. ->setFirstName($credentials['first_name'])
  89. ->setLastName($credentials['last_name'])
  90. ->setToken($token);
  91. }
  92. catch (Exception $e) {
  93. return null;
  94. }
  95. }
  96. /**
  97. * @param Response $response
  98. * @param string $token
  99. * @param bool $rememberMe
  100. * @return void
  101. */
  102. public function setCustomerToken(Response $response, string $token, bool $rememberMe = true): void
  103. {
  104. if ($rememberMe) {
  105. $response->headers->setCookie(
  106. Cookie::create(self::CUSTOMER_SESSION_TOKEN_KEY, $token, time() + 2592000)
  107. );
  108. }
  109. else {
  110. $this->requestStack->getSession()->set(self::CUSTOMER_SESSION_TOKEN_KEY, $token);
  111. }
  112. }
  113. /**
  114. * @param Response $response
  115. * @return void
  116. */
  117. public function removeCustomerToken(Response $response): void
  118. {
  119. $response->headers->setCookie(
  120. Cookie::create(self::CUSTOMER_SESSION_TOKEN_KEY, '', time() - 1)
  121. );
  122. $this->requestStack->getSession()->remove(self::CUSTOMER_SESSION_TOKEN_KEY);
  123. }
  124. /**
  125. * @param Customer $customer
  126. * @return array<string>
  127. * @throws ClientExceptionInterface
  128. * @throws DecodingExceptionInterface
  129. * @throws RedirectionExceptionInterface
  130. * @throws ServerExceptionInterface
  131. * @throws TransportExceptionInterface
  132. * @throws Exception
  133. */
  134. public function subscribe(Customer $customer): array
  135. {
  136. try {
  137. $customerNormalizer = new CustomerNormalizer();
  138. $url = $this->erpUrlProvider->generateUrl('subscription', [], true);
  139. $response = $this->httpClient->request('POST', $url, [
  140. 'body' => array_merge($customerNormalizer->normalize($customer), [
  141. 'accountVerificationLink' => $this->suluUrlProvider->generateUrl('customer_waiting_subscription'),
  142. ])
  143. ]);
  144. $content = $response->toArray(false);
  145. }
  146. catch (Exception|ExceptionInterface $e) {
  147. throw new Exception("Impossible de procéder à l'inscription, veuillez réessayer plus tard");
  148. }
  149. if (Response::HTTP_OK !== $response->getStatusCode())
  150. {
  151. throw new Exception($content['message']);
  152. }
  153. return $content;
  154. }
  155. /**
  156. * @param string $token
  157. * @return array<string>
  158. * @throws ClientExceptionInterface
  159. * @throws DecodingExceptionInterface
  160. * @throws RedirectionExceptionInterface
  161. * @throws ServerExceptionInterface
  162. * @throws TransportExceptionInterface
  163. * @throws Exception
  164. */
  165. public function getCustomerFromToken(string $token): array
  166. {
  167. try {
  168. $url = $this->erpUrlProvider->generateUrl('get_customer_from_token', [], true);
  169. $response = $this->httpClient->request('POST', $url, [
  170. 'body' => [
  171. 'token' => $token
  172. ]
  173. ]);
  174. $content = $response->toArray(false);
  175. }
  176. catch (Exception $e) {
  177. throw new Exception("Impossible de vérifier ce token");
  178. }
  179. if (Response::HTTP_OK !== $response->getStatusCode())
  180. {
  181. throw new Exception($content['message']);
  182. }
  183. return $content;
  184. }
  185. /**
  186. * @param string $email
  187. * @return array<string>
  188. * @throws ClientExceptionInterface
  189. * @throws DecodingExceptionInterface
  190. * @throws RedirectionExceptionInterface
  191. * @throws ServerExceptionInterface
  192. * @throws TransportExceptionInterface
  193. */
  194. public function resetPasswordRequest(string $email): array
  195. {
  196. try {
  197. $url = $this->erpUrlProvider->generateUrl('reset_password_request', [], true);
  198. $response = $this->httpClient->request('POST', $url, [
  199. 'body' => [
  200. 'email' => $email,
  201. 'resetPasswordLink' => $this->suluUrlProvider->generateUrl('customer_reset_password'),
  202. ]
  203. ]);
  204. $content = $response->toArray(false);
  205. }
  206. catch (Exception $e) {
  207. throw new Exception("Une erreur s’est produite, veuillez réessayer ultérieurement.");
  208. }
  209. if (Response::HTTP_OK !== $response->getStatusCode())
  210. {
  211. throw new Exception($content['message']);
  212. }
  213. return $content;
  214. }
  215. /**
  216. * @param string $token
  217. * @return bool
  218. * @throws ClientExceptionInterface
  219. * @throws DecodingExceptionInterface
  220. * @throws RedirectionExceptionInterface
  221. * @throws ServerExceptionInterface
  222. * @throws TransportExceptionInterface
  223. */
  224. public function checkResetPasswordToken(string $token): bool
  225. {
  226. try {
  227. $url = $this->erpUrlProvider->generateUrl('check_reset_password_token', [], true);
  228. $response = $this->httpClient->request('POST', $url, [
  229. 'body' => [
  230. 'token' => $token
  231. ]
  232. ]);
  233. $content = $response->toArray(false);
  234. }
  235. catch (Exception $e) {
  236. throw new Exception("Impossible de réinitialiser le mot de passe de ce compte");
  237. }
  238. if (Response::HTTP_OK !== $response->getStatusCode())
  239. {
  240. throw new Exception($content['message']);
  241. }
  242. return (bool)$content['checked'];
  243. }
  244. /**
  245. * @param string $token
  246. * @param string $password
  247. * @return array<string>
  248. * @throws ClientExceptionInterface
  249. * @throws DecodingExceptionInterface
  250. * @throws RedirectionExceptionInterface
  251. * @throws ServerExceptionInterface
  252. * @throws TransportExceptionInterface
  253. */
  254. public function updatePassword(string $token, string $password): array
  255. {
  256. try {
  257. $url = $this->erpUrlProvider->generateUrl('update_password', [], true);
  258. $response = $this->httpClient->request('POST', $url, [
  259. 'body' => [
  260. 'token' => $token,
  261. 'password' => $password
  262. ]
  263. ]);
  264. $content = $response->toArray(false);
  265. }
  266. catch (Exception $e) {
  267. throw new Exception("Impossible de modifier le mot de passe de ce compte");
  268. }
  269. if (Response::HTTP_OK !== $response->getStatusCode())
  270. {
  271. throw new Exception($content['message']);
  272. }
  273. return $content;
  274. }
  275. /**
  276. * @param string $token
  277. * @return array
  278. * @throws ClientExceptionInterface
  279. * @throws DecodingExceptionInterface
  280. * @throws RedirectionExceptionInterface
  281. * @throws ServerExceptionInterface
  282. * @throws TransportExceptionInterface
  283. */
  284. public function accountVerification(string $token): array
  285. {
  286. try {
  287. $url = $this->erpUrlProvider->generateUrl('account_verification', [], true);
  288. $response = $this->httpClient->request('POST', $url, [
  289. 'body' => [
  290. 'token' => $token
  291. ]
  292. ]);
  293. $content = $response->toArray(false);
  294. }
  295. catch (Exception $e) {
  296. throw new Exception("Impossible vérifier votre compte, veuillez réessayer plus tard");
  297. }
  298. if (Response::HTTP_OK !== $response->getStatusCode())
  299. {
  300. throw new Exception($content['message']);
  301. }
  302. return $content;
  303. }
  304. /**
  305. * @param string $email
  306. * @return array
  307. * @throws ClientExceptionInterface
  308. * @throws DecodingExceptionInterface
  309. * @throws RedirectionExceptionInterface
  310. * @throws ServerExceptionInterface
  311. * @throws TransportExceptionInterface
  312. */
  313. public function accountVerificationLinkRequest(string $email): array
  314. {
  315. try {
  316. $url = $this->erpUrlProvider->generateUrl('account_verification_link_request', [], true);
  317. $response = $this->httpClient->request('POST', $url, [
  318. 'body' => [
  319. 'email' => $email,
  320. 'accountVerificationLink' => $this->suluUrlProvider->generateUrl('customer_waiting_subscription'),
  321. ]
  322. ]);
  323. $content = $response->toArray(false);
  324. }
  325. catch (Exception $e) {
  326. throw new Exception("Impossible d'éffectuer votre demande, veuillez réessayer plus tard");
  327. }
  328. if (Response::HTTP_OK !== $response->getStatusCode())
  329. {
  330. throw new Exception($content['message']);
  331. }
  332. return $content;
  333. }
  334. /**
  335. * @return string
  336. */
  337. public function getIndexUrl(): string
  338. {
  339. return $this->erpUrlProvider->generateUrl('customer_portal_login', [
  340. 'redirectUrl' => urlencode($this->erpUrlProvider->generateUrl('customer_portal_home'))
  341. ]);
  342. }
  343. /**
  344. * @param int $quoteId
  345. * @return string
  346. */
  347. public function getQuoteDetailsUrl(int $quoteId): string
  348. {
  349. return $this->erpUrlProvider->generateUrl('customer_portal_login', [
  350. 'redirectUrl' => urlencode($this->erpUrlProvider->generateUrl('customer_portal_commercial_proposal', ['quote' => $quoteId]))
  351. ]);
  352. }
  353. /**
  354. * @return string
  355. */
  356. public function getAccountVerificationUrl(): string
  357. {
  358. return $this->erpUrlProvider->generateUrl('account_verification', [], true);
  359. }
  360. /**
  361. * @param string $email
  362. * @param string $password
  363. * @param bool $rememberMe
  364. * @return string[]
  365. * @throws ClientExceptionInterface
  366. * @throws DecodingExceptionInterface
  367. * @throws RedirectionExceptionInterface
  368. * @throws ServerExceptionInterface
  369. * @throws TransportExceptionInterface
  370. */
  371. private function customerApiLoginFromCredentials(string $email, string $password, bool $rememberMe = false): array
  372. {
  373. return $this->customerApiLogin([
  374. 'username' => $email,
  375. 'password' => $password,
  376. 'rememberMe' => $rememberMe,
  377. ]);
  378. }
  379. /**
  380. * @param string $token
  381. * @return string[]
  382. * @throws ClientExceptionInterface
  383. * @throws DecodingExceptionInterface
  384. * @throws RedirectionExceptionInterface
  385. * @throws ServerExceptionInterface
  386. * @throws TransportExceptionInterface
  387. */
  388. private function customerApiLoginFromToken(string $token): array
  389. {
  390. return $this->customerApiLogin([
  391. 'authentication_token' => $token
  392. ]);
  393. }
  394. /**
  395. * @param array<string> $body
  396. * @return array<string>
  397. * @throws ClientExceptionInterface
  398. * @throws DecodingExceptionInterface
  399. * @throws RedirectionExceptionInterface
  400. * @throws ServerExceptionInterface
  401. * @throws TransportExceptionInterface
  402. * @throws Exception
  403. */
  404. private function customerApiLogin(array $body): array
  405. {
  406. try {
  407. $url = $this->erpUrlProvider->generateUrl('api_login', [], true);
  408. $response = $this->httpClient->request('POST', $url, [
  409. 'body' => $body
  410. ]);
  411. $content = $response->toArray(false);
  412. }
  413. catch (Exception $e) {
  414. throw new Exception("Impossible de se connecter à votre compte client, veuillez réessayer plus tard.");
  415. }
  416. if (Response::HTTP_OK !== $response->getStatusCode())
  417. {
  418. throw new Exception($content['message']);
  419. }
  420. return $content;
  421. }
  422. }