src/Controller/Website/Mybiz/Member/MemberApiController.php line 401

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Website\Mybiz\Member;
  3. use App\Constants\AppConstant;
  4. use App\Dto\Api\Member\MemberInformationsDto;
  5. use App\Dto\Api\Member\MemberLoginDto;
  6. use App\Dto\Api\User\UserJwtTokenDto;
  7. use App\Dto\Authorization\AuthorizationHeaderDto;
  8. use App\Dto\Member\MemberChangePasswordDto;
  9. use App\Dto\Member\MemberCreatorDto;
  10. use App\Dto\Member\MemberPersonalInformationDto;
  11. use App\Entity\Member;
  12. use App\Entity\Space;
  13. use App\Entity\User;
  14. use App\EventListener\Api\TokenInterceptor\MybizTokenAuthenticatorInterface;
  15. use App\Exception\Country\CountryNotFoundException;
  16. use App\Exception\Member\MemberNotFoundException;
  17. use App\Exception\User\UserAlreadyExistsExcecption;
  18. use App\Repository\MemberRepository;
  19. use App\Repository\SpaceRepository;
  20. use App\Repository\UserRepository;
  21. use App\Service\Api\ApiRequestContentParser;
  22. use App\Service\Api\Mobile\Login\MemberLoginResponseDtoProvider;
  23. use App\Service\Authorization\MybizRequestAuthorizationChecker;
  24. use App\Service\Authorization\MybizRequestJwtChecker;
  25. use App\Service\Log\LogAdder;
  26. use App\Service\Log\WebhookLogAdder;
  27. use App\Service\Member\API\MemberResponseProvider;
  28. use App\Service\Member\Jwt\UserJwtManager;
  29. use App\Service\Member\MemberInformation\MemberInformationProvider;
  30. use App\Service\Member\MemberPasswordUpdater;
  31. use App\Service\Member\MemberUpdater;
  32. use App\Service\Member\Subscription\MemberSignupCreator;
  33. use App\Service\Notification\NotificationContentProvider;
  34. use App\Service\Notification\NotificationSaver;
  35. use App\Traits\JsonRequestTrait;
  36. use Doctrine\ORM\EntityManagerInterface;
  37. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  38. use Symfony\Component\HttpFoundation\JsonResponse;
  39. use Symfony\Component\HttpFoundation\Request;
  40. use Symfony\Component\HttpFoundation\Response;
  41. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  42. use Symfony\Component\Routing\Annotation\Route;
  43. use Symfony\Contracts\Translation\TranslatorInterface;
  44. class MemberApiController extends AbstractController implements MybizTokenAuthenticatorInterface
  45. {
  46.     use JsonRequestTrait;
  47.     /**
  48.      * Création d'un membre
  49.      *
  50.      * Création d'un member depuis l'API.
  51.      *
  52.      * @Route("/v1/member/create", name="api_member_create", methods={"POST"})
  53.      */
  54.     public function createMember(
  55.         Request                          $request,
  56.         TranslatorInterface              $translator,
  57.         WebhookLogAdder                  $webhookLogAdder,
  58.         MybizRequestAuthorizationChecker $mybizRequestAuthorizationChecker,
  59.         ApiRequestContentParser          $apiRequestContentParser,
  60.         MemberSignupCreator              $memberSignupCreator,
  61.         LogAdder                         $logAdder,
  62.         NotificationContentProvider      $notificationContentProvider,
  63.         NotificationSaver                $notificationSaver,
  64.         SpaceRepository                  $spaceRepository
  65.     ): JsonResponse
  66.     {
  67.         try {
  68.             $preferredLanguage $request->headers->get("accept-language");
  69.             if (null === $preferredLanguage || false === in_array($preferredLanguageAppConstant::LOCALEStrue)) {
  70.                 $preferredLanguage AppConstant::DEFAULT_LOCALE;
  71.             }
  72.             /** @var MemberCreatorDto|null $memberCreatorDto */
  73.             $memberCreatorDto $apiRequestContentParser->parseRequestContentForMember(
  74.                 $this->getJsonFromContent($request),
  75.                 $preferredLanguage
  76.             );
  77.         } catch (\JsonException|MemberNotFoundException $e) {
  78.             return $mybizRequestAuthorizationChecker->getParseErrorMessage($e);
  79.         }
  80.         $webhookLogAdder->add(
  81.             Space::SPACE_LUUME,
  82.             null,
  83.             null,
  84.             "Inscription du membre {$memberCreatorDto->getEmail()} depuis le endpoint d'API",
  85.             $memberCreatorDto->toArray()
  86.         );
  87.         $firstSubscriptionSpace $spaceRepository->findOneBy(["name" => Space::SPACE_LUUME]);
  88.         if (null === $firstSubscriptionSpace) {
  89.             return $mybizRequestAuthorizationChecker->getDefaultErrorMessage(new \RuntimeException("firstSubscriptionSpace not found"));
  90.         }
  91.         try {
  92.             $member $memberSignupCreator->createMember(
  93.                 $request,
  94.                 $memberCreatorDto,
  95.                 $firstSubscriptionSpace
  96.             );
  97.             $memberSponsor $member->getSponsor();
  98.             $sponsorId null !== $memberSponsor $memberSponsor->getId() : null;
  99.             $sponsorName null !== $memberSponsor $memberSponsor->getFullname() : null;
  100.             if ($member->isOfferedSponsor()) {
  101.                 $notification $notificationContentProvider->provide(
  102.                     NotificationContentProvider::NOTIFICATION_OFFERED_SPONSOR,
  103.                     // On spécifie le membre et non le sponsor pour passer dans le mail des informations du membre
  104.                     // ensuite récupérer le sponsor en faisant $member->getSponsor().
  105.                     $member
  106.                 );
  107.                 // On envoie aussi un mail
  108.                 $notification->setHasToSentByMail(true);
  109.                 $notification->setIcon("lni lni-box-gift-1");
  110.                 $notificationSaver->save($notificationtrue);
  111.                 // Si on a offert le membre à un sponsor on ne renvoie pas l'information à Luume
  112.                 $sponsorId null;
  113.                 $sponsorName null;
  114.             }
  115.             /** @var User|null $user */
  116.             $user $member->getUser();
  117.             $logAdder->add(
  118.                 LogAdder::LOG_TYPE_MEMBER_CREATION,
  119.                 null,
  120.                 $member->getId(),
  121.                 $user->getId(),
  122.                 LogAdder::STATUS_OK,
  123.                 "Création du membre {$member->getId()} depuis {$request->headers->get("App-Provider")} - {$request->headers->get("App-Version")}",
  124.             );
  125.             return $this->json([
  126.                 "memberId" => $member->getId(),
  127.                 "sponsorId" => $sponsorId,
  128.                 "sponsorName" => $sponsorName
  129.             ], Response::HTTP_OK);
  130.         } catch (UserAlreadyExistsExcecption $e) {
  131.             return $this->json([
  132.                 "error" => $translator->trans("validator.user.email_already_exists", ["%email%" => $memberCreatorDto->getEmail()], "validator"$request->headers->get("App-Language"))
  133.             ], Response::HTTP_CONFLICT);
  134.         } catch (\Throwable $e) {
  135.             return $mybizRequestAuthorizationChecker->getDefaultErrorMessage($e);
  136.         }
  137.     }
  138.     /**
  139.      * Tentative de connexion d'un membre par login mot de passe
  140.      *
  141.      * tentative de connexion d'un membre depuis l'API
  142.      *
  143.      * @Route("/v1/member/login", name="api_member_login", methods={"POST"})
  144.      */
  145.     public function login(
  146.         Request                          $request,
  147.         EntityManagerInterface           $em,
  148.         TranslatorInterface              $translator,
  149.         ApiRequestContentParser          $apiRequestContentParser,
  150.         UserJwtManager                   $userJwtManager,
  151.         MemberLoginResponseDtoProvider   $memberLoginResponseDtoProvider,
  152.         MemberResponseProvider           $memberResponseProvider,
  153.         MybizRequestAuthorizationChecker $mybizRequestAuthorizationChecker,
  154.         UserPasswordHasherInterface      $passwordHasher,
  155.         UserRepository                   $userRepository
  156.     ): JsonResponse
  157.     {
  158.         try {
  159.             $authorizationHeaderDto AuthorizationHeaderDto::generateFromRequest($request);
  160.         } catch (\Throwable $e) {
  161.             return $mybizRequestAuthorizationChecker->getDefaultErrorMessage($e);
  162.         }
  163.         try {
  164.             /** @var MemberLoginDto|null $memberLoginDto */
  165.             $memberLoginDto $apiRequestContentParser->parseRequestContent($requestApiRequestContentParser::MEMBER_LOGIN_PARSER);
  166.         } catch (\Throwable $e) {
  167.             return $mybizRequestAuthorizationChecker->getParseErrorMessage($e);
  168.         }
  169.         /** @var User|null $user */
  170.         $user $userRepository->findOneBy([
  171.             "email" => $memberLoginDto->getEmail()
  172.         ]);
  173.         if (null === $user) {
  174.             return $this->json([
  175.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  176.             ], Response::HTTP_FORBIDDEN);
  177.         }
  178.         if (false === $passwordHasher->isPasswordValid($user$memberLoginDto->getPassword())) {
  179.             return $this->json([
  180.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  181.             ], Response::HTTP_FORBIDDEN);
  182.         }
  183.         $member $user->getMember();
  184.         if (null === $member) {
  185.             return $this->json([
  186.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  187.             ], Response::HTTP_FORBIDDEN);
  188.         }
  189.         if (true === $member->isDeleted()) {
  190.             return $this->json([
  191.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  192.             ], Response::HTTP_FORBIDDEN);
  193.         }
  194.         // création du token JWT
  195.         $userJwtManager->create($user);
  196.         $user->setLastLoginAt(new \DateTime());
  197.         $em->flush();
  198.         return $memberResponseProvider->getMemberLoginResponse($user$member$authorizationHeaderDto$memberLoginResponseDtoProvider$translator);
  199.     }
  200.     /**
  201.      * Tentative de connexion d'un membre par login JWT TOKEN
  202.      *
  203.      * tentative de connexion d'un membre depuis l'API
  204.      *
  205.      * @Route("/v1/member/jwt-auth", name="api_member_jwt_token", methods={"POST"})
  206.      */
  207.     public function jwtTokenAuthentication(
  208.         Request                          $request,
  209.         TranslatorInterface              $translator,
  210.         MybizRequestAuthorizationChecker $mybizRequestAuthorizationChecker,
  211.         ApiRequestContentParser          $apiRequestContentParser,
  212.         UserJwtManager                   $userJwtManager,
  213.         MemberLoginResponseDtoProvider   $memberLoginResponseDtoProvider,
  214.         MemberResponseProvider           $memberResponseProvider,
  215.         MemberRepository                 $memberRepository
  216.     ): JsonResponse
  217.     {
  218.         try {
  219.             $authorizationHeaderDto AuthorizationHeaderDto::generateFromRequest($request);
  220.         } catch (\Throwable $e) {
  221.             return $mybizRequestAuthorizationChecker->getDefaultErrorMessage($e);
  222.         }
  223.         try {
  224.             /** @var UserJwtTokenDto|null $userJwtTokenDto */
  225.             $userJwtTokenDto $apiRequestContentParser->parseRequestContent($requestApiRequestContentParser::MEMBER_JWT_AUTHENTICATION_PARSER);
  226.         } catch (\Throwable $e) {
  227.             return $mybizRequestAuthorizationChecker->getParseErrorMessage($e);
  228.         }
  229.         /** @var Member|null $member */
  230.         $user $userJwtManager->getUserByJwtToken($userJwtTokenDto->getJwtToken());
  231.         if (null === $user) {
  232.             return $this->json([
  233.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  234.             ], Response::HTTP_FORBIDDEN);
  235.         }
  236.         if (false === $userJwtManager->isValidate($user)) {
  237.             return $this->json([
  238.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  239.             ], Response::HTTP_FORBIDDEN);
  240.         }
  241.         $member $user->getMember();
  242.         if (null === $member || true === $member->isDeleted()) {
  243.             return $this->json([
  244.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  245.             ], Response::HTTP_FORBIDDEN);
  246.         }
  247.         return $memberResponseProvider->getMemberLoginResponse($user$member$authorizationHeaderDto$memberLoginResponseDtoProvider$translator);
  248.     }
  249.     /**
  250.      * Mise à jour d'un membre
  251.      *
  252.      * Mise à jour des informations d'un membre depuis l'API, pour modifier le mot de passe d'un membre, c'est le même endpoint qui est utilisé avec le mot de passe renseigné.
  253.      *
  254.      * @Route("/v1/member/update", name="api_member_update", methods={"POST"})
  255.      */
  256.     public function updateMember(
  257.         Request                          $request,
  258.         TranslatorInterface              $translator,
  259.         MybizRequestAuthorizationChecker $mybizRequestAuthorizationChecker,
  260.         WebhookLogAdder                  $webhookLogAdder,
  261.         ApiRequestContentParser          $apiRequestContentParser,
  262.         MemberUpdater                    $memberUpdater,
  263.         MemberPasswordUpdater            $memberPasswordUpdater,
  264.         MemberRepository                 $memberRepository
  265.     ): JsonResponse
  266.     {
  267.         $appLanguage $request->headers->get("App-Language");
  268.         try {
  269.             $requestContent $this->getJsonFromContent($request);
  270.             /** @var MemberPersonalInformationDto|null $memberPersonalInformationDto */
  271.             $memberPersonalInformationDto $apiRequestContentParser->parseRequestContent($requestApiRequestContentParser::MEMBER_UPDATER_PARSER);
  272.         } catch (\Throwable $e) {
  273.             return $mybizRequestAuthorizationChecker->getParseErrorMessage($e);
  274.         }
  275.         $member $memberRepository->findMemberByEmail($memberPersonalInformationDto->getEmail());
  276.         if (null === $member) {
  277.             return $this->json([
  278.                 "error" => $translator->trans("validator.user.email_invalid", ["%email%" => $memberPersonalInformationDto->getEmail()], "validator"$appLanguage)
  279.             ], Response::HTTP_CONFLICT);
  280.         }
  281.         $webhookLogAdder->add(
  282.             Space::SPACE_LUUME,
  283.             $member,
  284.             null,
  285.             "Mise à jour du membre {$memberPersonalInformationDto->getEmail()} depuis le endpoint d'API",
  286.             $memberPersonalInformationDto->toArray()
  287.         );
  288.         try {
  289.             $memberUpdater->updateMemberFromPersonalInformationDto($member$memberPersonalInformationDto);
  290.         } catch (CountryNotFoundException $e) {
  291.             return $this->json([
  292.                 "error" => $e->getMessage()
  293.             ], Response::HTTP_NOT_FOUND);
  294.         }
  295.         $requestPassword $requestContent["password"];
  296.         if (!empty($requestPassword)) {
  297.             try {
  298.                 $memberPasswordUpdater->updatePassword($member$requestPassword);
  299.             } catch (\Throwable $e) {
  300.                 return $mybizRequestAuthorizationChecker->getDefaultErrorMessage($e);
  301.             }
  302.         }
  303.         return $this->json([], Response::HTTP_OK);
  304.     }
  305.     /**
  306.      * Mise à jour du mot de passe d'un membre
  307.      *
  308.      * @Route("/v1/member/update-password", name="api_member_update_password", methods={"POST"})
  309.      */
  310.     public function updatePassword(
  311.         Request                     $request,
  312.         TranslatorInterface         $translator,
  313.         UserPasswordHasherInterface $userPasswordHasher,
  314.         ApiRequestContentParser     $apiRequestContentParser,
  315.         MemberPasswordUpdater       $memberPasswordUpdater,
  316.         MybizRequestJwtChecker      $mybizRequestJwtChecker
  317.     ): JsonResponse
  318.     {
  319.         try {
  320.             $member $mybizRequestJwtChecker->checkJwt($request);
  321.         } catch (\Throwable $e) {
  322.             return $mybizRequestJwtChecker->getUnknownJWTErrorMessage();
  323.         }
  324.         try {
  325.             /** @var MemberChangePasswordDto|null $memberChangePasswordDto */
  326.             $memberChangePasswordDto $apiRequestContentParser->parseRequestContent($requestApiRequestContentParser::MEMBER_UPDATE_PASSWORD_PARSER);
  327.         } catch (\Throwable $e) {
  328.             return $mybizRequestJwtChecker->getDefaultErrorMessage($e);
  329.         }
  330.         $user $member->getUser();
  331.         if (false === $userPasswordHasher->isPasswordValid($user$memberChangePasswordDto->old)) {
  332.             return $this->json([
  333.                 "error" => $translator->trans("validator.password.old_mismatch", [], "validator")
  334.             ], Response::HTTP_FORBIDDEN);
  335.         }
  336.         try {
  337.             $memberPasswordUpdater->updatePassword($member$memberChangePasswordDto->new);
  338.             return $this->json([], Response::HTTP_OK);
  339.         } catch (\Throwable $e) {
  340.             $this->addFlash("danger"$translator->trans("validator.server_error", [], "validator"));
  341.             return $this->json([
  342.                 "error" => $translator->trans("validator.password.update_error", [], "validator")
  343.             ], Response::HTTP_OK);
  344.         }
  345.     }
  346.     /**
  347.      * Récupération des informations d'un membre
  348.      *
  349.      * Permet de récupérer certaines informations sur un membre
  350.      *
  351.      * @Route("/v1/member/informations", name="api_member_informations", methods={"POST"})
  352.      */
  353.     public function getInformations(
  354.         Request                          $request,
  355.         TranslatorInterface              $translator,
  356.         ApiRequestContentParser          $apiRequestContentParser,
  357.         MybizRequestAuthorizationChecker $mybizRequestAuthorizationChecker,
  358.         MemberInformationProvider        $memberInformationProvider,
  359.         UserRepository                   $userRepository
  360.     ): JsonResponse
  361.     {
  362.         try {
  363.             $authorizationHeaderDto AuthorizationHeaderDto::generateFromRequest($request);
  364.         } catch (\Throwable $e) {
  365.             return $mybizRequestAuthorizationChecker->getDefaultErrorMessage($e);
  366.         }
  367.         try {
  368.             /** @var MemberInformationsDto|null $memberInformationsDto */
  369.             $memberInformationsDto $apiRequestContentParser->parseRequestContent($requestApiRequestContentParser::MEMBER_INFORMATIONS_PARSER);
  370.         } catch (\Throwable $e) {
  371.             return $mybizRequestAuthorizationChecker->getParseErrorMessage($e);
  372.         }
  373.         /** @var User|null $user */
  374.         $user $userRepository->findOneBy([
  375.             "email" => $memberInformationsDto->getEmail()
  376.         ]);
  377.         if (null === $user) {
  378.             return $this->json([
  379.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  380.             ], Response::HTTP_FORBIDDEN);
  381.         }
  382.         $member $user->getMember();
  383.         if (null === $member) {
  384.             return $this->json([
  385.                 "error" => $translator->trans("validator.user.id_invalid", [], "validator"$authorizationHeaderDto->getLanguage())
  386.             ], Response::HTTP_FORBIDDEN);
  387.         }
  388.         return $this->json(
  389.             $memberInformationProvider->getMemberInformationResponseDto($member)->toArray(),
  390.             Response::HTTP_OK
  391.         );
  392.     }
  393.     /**
  394.      * Création d'un membre
  395.      *
  396.      * Création d'un member depuis l'API.
  397.      *
  398.      * @Route("/v1/member/check/{email}", name="api_member_check_email", methods={"GET"})
  399.      */
  400.     public function checkUserEmail(
  401.         UserRepository $userRespository,
  402.         string         $email
  403.     ): JsonResponse
  404.     {
  405.         /** @var User|null $user */
  406.         $user $userRespository->findOneBy([
  407.             "email" => $email
  408.         ]);
  409.         if (null === $user) {
  410.             return $this->json([], Response::HTTP_NOT_FOUND);
  411.         }
  412.         return $this->json([], Response::HTTP_OK);
  413.     }
  414.     /**
  415.      * Route pour tester sir le JWT est encore valable ou non
  416.      *
  417.      * @Route("/v1/mobile/jwt/valid", name="api_mobile_jwt_valid", methods={"GET"})
  418.      */
  419.     public function jwtValid(
  420.         Request                          $request,
  421.         MybizRequestAuthorizationChecker $mybizRequestAuthorizationChecker,
  422.         MybizRequestJwtChecker           $mybizRequestJwtChecker,
  423.         MemberLoginResponseDtoProvider   $memberLoginResponseDtoProvider,
  424.         MemberResponseProvider           $memberResponseProvider,
  425.         TranslatorInterface              $translator,
  426.         UserRepository                   $userRepository
  427.     ): JsonResponse
  428.     {
  429.         try {
  430.             $authorizationHeaderDto AuthorizationHeaderDto::generateFromRequest($request);
  431.         } catch (\Throwable $e) {
  432.             return $mybizRequestAuthorizationChecker->getDefaultErrorMessage($e);
  433.         }
  434.         try {
  435.             $member $mybizRequestJwtChecker->checkJwt($request);
  436.         } catch (\Throwable $e) {
  437.             return $mybizRequestJwtChecker->getUnknownJWTErrorMessage();
  438.         }
  439.         /** @var User|null $user */
  440.         $user $userRepository->findOneBy([
  441.             "email" => $member->getEmail()
  442.         ]);
  443.         return $memberResponseProvider->getMemberLoginResponse($user$member$authorizationHeaderDto$memberLoginResponseDtoProvider$translator);
  444.     }
  445. }