From e7569b0fe98198e11a3fc81c381b042c77e5e20a Mon Sep 17 00:00:00 2001 From: Babak Alizadeh Date: Sat, 4 Nov 2023 04:39:35 -0400 Subject: [PATCH] some progress in login forms --- hesabixCore/config/packages/security.yaml | 7 +- .../src/Controller/Front/UserController.php | 51 +++++----- hesabixCore/src/Controller/UserController.php | 8 +- hesabixCore/src/Entity/Settings.php | 15 +++ hesabixCore/src/Entity/UserToken.php | 15 +++ .../src/Repository/UserTokenRepository.php | 15 ++- .../src/Security/BackAuthAuthenticator.php | 92 +++++++++++++++++++ hesabixCore/src/Service/twigFunctions.php | 4 + hesabixCore/templates/base.html.twig | 4 +- hesabixCore/templates/blog/post.html.twig | 2 +- .../TwigBundle/Exception/error404.html.twig | 2 +- hesabixCore/templates/buy/fail.html.twig | 2 +- hesabixCore/templates/buy/success.html.twig | 2 +- hesabixCore/templates/general/home.html.twig | 2 +- 14 files changed, 187 insertions(+), 34 deletions(-) create mode 100644 hesabixCore/src/Security/BackAuthAuthenticator.php diff --git a/hesabixCore/config/packages/security.yaml b/hesabixCore/config/packages/security.yaml index 2538918..a77281c 100644 --- a/hesabixCore/config/packages/security.yaml +++ b/hesabixCore/config/packages/security.yaml @@ -14,6 +14,7 @@ security: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false main: + stateless: true lazy: true provider: app_user_provider json_login: @@ -31,7 +32,6 @@ security: # switch_user: true logout: path: front_user_logout - # where to redirect after logout target: general_home form_login: @@ -39,6 +39,11 @@ security: login_path: front_user_login check_path: front_user_login enable_csrf: true + custom_authenticator: App\Security\BackAuthAuthenticator + remember_me: + secret: '%kernel.secret%' # required + lifetime: 116121600 # 4 years in seconds + always_remember_me: true # Easy way to control access for large sections of your site # Note: Only the *first* access control that matches will be used diff --git a/hesabixCore/src/Controller/Front/UserController.php b/hesabixCore/src/Controller/Front/UserController.php index eb9ec6d..89350a6 100644 --- a/hesabixCore/src/Controller/Front/UserController.php +++ b/hesabixCore/src/Controller/Front/UserController.php @@ -5,7 +5,9 @@ use App\Controller\CustomUserMessageAuthenticationException; use App\Entity\Business; use App\Entity\Permission; use App\Form\UserRegisterType; +use App\Security\BackAuthAuthenticator; use App\Service\Provider; +use App\Service\twigFunctions; use Symfony\Component\Routing\Annotation\Route; use App\Entity\UserToken; use Exception; @@ -23,6 +25,7 @@ use Symfony\Component\Form\FormError; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Mime\Address; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; +use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface; use Symfony\Contracts\Translation\TranslatorInterface; use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface; use Symfony\Component\EventDispatcher\EventDispatcher, @@ -75,10 +78,10 @@ class UserController extends AbstractController } #[Route('/register', name: 'front_user_register')] - public function front_user_register(Request $request,TranslatorInterface $translator, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager): Response + public function front_user_register(twigFunctions $functions,Request $request,TranslatorInterface $translator, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager): Response { //redirect to hesabix app register page - return $this->redirect('https://app.hesabix.ir/user/register'); + return $this->redirect($functions->systemSettings()->getAppSite() . '/user/register'); $user = new User(); $form = $this->createForm(UserRegisterType::class, $user); $form->handleRequest($request); @@ -148,27 +151,33 @@ class UserController extends AbstractController return $this->redirectToRoute('app_register'); } - #[Route('/login/by/token', name: 'app_login_by_token')] - public function app_login_by_token(Request $request): Response + #[Route('/login/by/token{route}', name: 'app_login_by_token' , requirements: ['route' => '.+'])] + public function app_login_by_token(string $route,AuthenticationUtils $authenticationUtils,twigFunctions $functions,Request $request, UserPasswordHasherInterface $userPasswordHasher, UserAuthenticatorInterface $userAuthenticator, BackAuthAuthenticator $authenticator, EntityManagerInterface $entityManager): Response { - - // log the user in on the current firewall - $security->login($user); + $token = $entityManager->getRepository(UserToken::class)->findOneBy(['tokenID'=>$request->get('tokenID')]); + if(!$token){ + $token = $entityManager->getRepository(UserToken::class)->findOneBy(['token'=>$request->get('tokenID')]); + if(!$token) + throw $this->createNotFoundException('توکن معتبر نیست'); + } - // if the firewall has more than one authenticator, you must pass it explicitly - // by using the name of built-in authenticators... - $security->login($user, 'form_login'); - // ...or the service id of custom authenticators - $security->login($user, ExampleAuthenticator::class); + $userAuthenticator->authenticateUser( + $token->getUser(), + $authenticator, + $request + ); + return $this->redirect($functions->systemSettings()->getAppSite() . $route); + } - // you can also log in on a different firewall - $security->login($user, 'form_login', 'other_firewall'); - - // use the redirection logic applied to regular login - $redirectResponse = $security->login($user); - return $redirectResponse; - - // or use a custom redirection logic (e.g. redirect users to their account page) - // return new RedirectResponse('...'); + /** + * @throws Exception + */ + #[Route('/logout/by/token{route}', name: 'app_logout_by_token' , requirements: ['route' => '.+'])] + public function app_logout_by_token(string $route,twigFunctions $functions,Request $request,Security $security, EntityManagerInterface $entityManager): Response + { + try { + $security->logout(false); + } catch (Exception $e){} + return $this->redirect($functions->systemSettings()->getAppSite() . $route); } } diff --git a/hesabixCore/src/Controller/UserController.php b/hesabixCore/src/Controller/UserController.php index 955920c..f093035 100644 --- a/hesabixCore/src/Controller/UserController.php +++ b/hesabixCore/src/Controller/UserController.php @@ -56,16 +56,16 @@ class UserController extends AbstractController 'message' => 'missing credentials', ], Response::HTTP_UNAUTHORIZED); } - - $tokenString = $this->RandomString(254); // somehow create an API token for $user $token = new UserToken(); $token->setUser($user); - $token->setToken($tokenString); + $token->setToken($this->RandomString(254)); + $token->setTokenID($this->RandomString(254)); $entityManager->persist($token); $entityManager->flush(); return $this->json([ 'user' => $user->getUserIdentifier(), - 'token' => $tokenString, + 'token' => $token->getToken(), + 'tokenID'=> $token->getTokenID() ]); } diff --git a/hesabixCore/src/Entity/Settings.php b/hesabixCore/src/Entity/Settings.php index 574206b..56a9ef2 100644 --- a/hesabixCore/src/Entity/Settings.php +++ b/hesabixCore/src/Entity/Settings.php @@ -25,6 +25,9 @@ class Settings #[ORM\Column(length: 255, nullable: true)] private ?string $zarinpalMerchant = null; + #[ORM\Column(length: 255, nullable: true)] + private ?string $appSite = null; + public function getId(): ?int { return $this->id; @@ -77,4 +80,16 @@ class Settings return $this; } + + public function getAppSite(): ?string + { + return $this->appSite; + } + + public function setAppSite(?string $appSite): static + { + $this->appSite = $appSite; + + return $this; + } } diff --git a/hesabixCore/src/Entity/UserToken.php b/hesabixCore/src/Entity/UserToken.php index 33b321c..eb3d8d3 100644 --- a/hesabixCore/src/Entity/UserToken.php +++ b/hesabixCore/src/Entity/UserToken.php @@ -20,6 +20,9 @@ class UserToken #[ORM\JoinColumn(nullable: false)] private ?User $user = null; + #[ORM\Column(length: 255, nullable: true)] + private ?string $tokenID = null; + public function getId(): ?int { return $this->id; @@ -48,4 +51,16 @@ class UserToken return $this; } + + public function getTokenID(): ?string + { + return $this->tokenID; + } + + public function setTokenID(?string $tokenID): static + { + $this->tokenID = $tokenID; + + return $this; + } } diff --git a/hesabixCore/src/Repository/UserTokenRepository.php b/hesabixCore/src/Repository/UserTokenRepository.php index 80d8f2c..2d53ea8 100644 --- a/hesabixCore/src/Repository/UserTokenRepository.php +++ b/hesabixCore/src/Repository/UserTokenRepository.php @@ -4,6 +4,7 @@ namespace App\Repository; use App\Entity\UserToken; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; +use Doctrine\ORM\NonUniqueResultException; use Doctrine\Persistence\ManagerRegistry; /** @@ -40,7 +41,7 @@ class UserTokenRepository extends ServiceEntityRepository } /** - * @throws \Doctrine\ORM\NonUniqueResultException + * @throws NonUniqueResultException */ public function findByApiToken($value): UserToken | null { @@ -54,6 +55,18 @@ class UserTokenRepository extends ServiceEntityRepository ; } + /** + * @throws NonUniqueResultException + */ + public function findByApiTokenID($value): UserToken | null + { + return $this->createQueryBuilder('u') + ->andWhere('u.tokenID = :val') + ->setParameter('val', $value) + ->orderBy('u.id', 'ASC') + ->getQuery() + ->getOneOrNullResult(); + } // public function findOneBySomeField($value): ?UserToken // { // return $this->createQueryBuilder('u') diff --git a/hesabixCore/src/Security/BackAuthAuthenticator.php b/hesabixCore/src/Security/BackAuthAuthenticator.php new file mode 100644 index 0000000..524daca --- /dev/null +++ b/hesabixCore/src/Security/BackAuthAuthenticator.php @@ -0,0 +1,92 @@ +userTokenRepository = $userRepository; + } + public function supports(Request $request): ?bool + { + // TODO: Implement supports() method. + } + + /** + * @throws NonUniqueResultException + */ + public function authenticate(Request $request): Passport + { + $apiToken = $request->get('tokenID'); + + if (null == $apiToken) { + // The token header was empty, authentication fails with HTTP Status + // Code 401 "Unauthorized" + throw new CustomUserMessageAuthenticationException('No API token provided'); + } + $tk = $this->userTokenRepository->findByApiTokenID($apiToken); + if (! $tk) { + throw new UserNotFoundException(); + } + + // TODO: Implement authenticate() method. + return new Passport( + new UserBadge($apiToken, function() use ($apiToken) { + $tk = $this->userTokenRepository->findByApiTokenID($apiToken); + if (! $tk) { + throw new UserNotFoundException(); + } + return $tk->getUser(); + }), + new PasswordCredentials($tk->getUser()->getPassword()), + [ + new RememberMeBadge(), + ] + ); + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response + { + // TODO: Implement onAuthenticationSuccess() method. + return new Response('1'); + } + + public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response + { + // TODO: Implement onAuthenticationFailure() method. + return new Response('0'); + } + +// public function start(Request $request, AuthenticationException $authException = null): Response +// { +// /* +// * If you would like this class to control what happens when an anonymous user accesses a +// * protected page (e.g. redirect to /login), uncomment this method and make this class +// * implement Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface. +// * +// * For more details, see https://symfony.com/doc/current/security/experimental_authenticators.html#configuring-the-authentication-entry-point +// */ +// } +} diff --git a/hesabixCore/src/Service/twigFunctions.php b/hesabixCore/src/Service/twigFunctions.php index d4de559..d3bcca1 100644 --- a/hesabixCore/src/Service/twigFunctions.php +++ b/hesabixCore/src/Service/twigFunctions.php @@ -5,6 +5,7 @@ namespace App\Service; use App\Entity\ChangeReport; +use App\Entity\Settings; use Doctrine\ORM\EntityManagerInterface; class twigFunctions @@ -84,5 +85,8 @@ class twigFunctions return '0.0.1'; } + public function systemSettings(){ + return $this->em->getRepository(Settings::class)->findAll()[0]; + } } \ No newline at end of file diff --git a/hesabixCore/templates/base.html.twig b/hesabixCore/templates/base.html.twig index 4441d87..2ca0d7f 100644 --- a/hesabixCore/templates/base.html.twig +++ b/hesabixCore/templates/base.html.twig @@ -48,8 +48,8 @@
- ورود - عضویت + ورود + عضویت
diff --git a/hesabixCore/templates/blog/post.html.twig b/hesabixCore/templates/blog/post.html.twig index 51a50f0..62464ca 100644 --- a/hesabixCore/templates/blog/post.html.twig +++ b/hesabixCore/templates/blog/post.html.twig @@ -52,7 +52,7 @@
برای ارسال دیدگاه به حساب خود وارد شوید.
- ورود | عضویت + ورود | عضویت
{% else %}
diff --git a/hesabixCore/templates/bundles/TwigBundle/Exception/error404.html.twig b/hesabixCore/templates/bundles/TwigBundle/Exception/error404.html.twig index bc5c211..6cd64c2 100644 --- a/hesabixCore/templates/bundles/TwigBundle/Exception/error404.html.twig +++ b/hesabixCore/templates/bundles/TwigBundle/Exception/error404.html.twig @@ -35,7 +35,7 @@ diff --git a/hesabixCore/templates/buy/fail.html.twig b/hesabixCore/templates/buy/fail.html.twig index cc16386..cf32913 100644 --- a/hesabixCore/templates/buy/fail.html.twig +++ b/hesabixCore/templates/buy/fail.html.twig @@ -10,7 +10,7 @@

متاسفانه پرداخت ناموفق بود!

- + بازگشت به پروفایل کاربری diff --git a/hesabixCore/templates/buy/success.html.twig b/hesabixCore/templates/buy/success.html.twig index 78847f3..75e8730 100644 --- a/hesabixCore/templates/buy/success.html.twig +++ b/hesabixCore/templates/buy/success.html.twig @@ -10,7 +10,7 @@

با تشکر از پرداخت شما. سفارش شما اعمال شد.

- + بازگشت به پروفایل کاربری diff --git a/hesabixCore/templates/general/home.html.twig b/hesabixCore/templates/general/home.html.twig index 753fba8..eab083d 100644 --- a/hesabixCore/templates/general/home.html.twig +++ b/hesabixCore/templates/general/home.html.twig @@ -12,7 +12,7 @@ نیاز نیست که هیچگونه نرم افزاری را نصب کنید. کافیست در سایت ثبت نام کرده و بلافاصله کسب و کار خود را مدیریت کنید.