some progress in login forms
This commit is contained in:
parent
3a43694864
commit
e7569b0fe9
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
|
|
92
hesabixCore/src/Security/BackAuthAuthenticator.php
Normal file
92
hesabixCore/src/Security/BackAuthAuthenticator.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace App\Security;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserTokenRepository;
|
||||
use Doctrine\ORM\NonUniqueResultException;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
|
||||
|
||||
class BackAuthAuthenticator extends AbstractAuthenticator
|
||||
{
|
||||
/**
|
||||
* @var UserTokenRepository
|
||||
*/
|
||||
private UserTokenRepository $userTokenRepository;
|
||||
|
||||
public function __construct(UserTokenRepository $userRepository)
|
||||
{
|
||||
$this->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
|
||||
// */
|
||||
// }
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
|
||||
}
|
|
@ -48,8 +48,8 @@
|
|||
|
||||
<!-- Right Section -->
|
||||
<div>
|
||||
<a href="https://app.hesabix.ir/user/login" class="btn btn-sm btn-primary me-1">ورود</a>
|
||||
<a href="https://app.hesabix.ir/user/register" class="btn btn-sm btn-success">عضویت</a>
|
||||
<a href="{{ twigFunctions.systemSettings().appSite }}/user/login" class="btn btn-sm btn-primary me-1">ورود</a>
|
||||
<a href="{{ twigFunctions.systemSettings().appSite }}/user/register" class="btn btn-sm btn-success">عضویت</a>
|
||||
</div>
|
||||
|
||||
<!-- END Right Section -->
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<div class="alert alert-info">
|
||||
برای ارسال دیدگاه به حساب خود وارد شوید.
|
||||
<br>
|
||||
<a href="/login">ورود</a> | <a href="https://app.hesabix.ir/register">عضویت</a>
|
||||
<a href="/login">ورود</a> | <a href="{{ twigFunctions.systemSettings().appSite }}/register">عضویت</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="rounded bg-light px-2 pt-2 pb-1">
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<!-- Footer -->
|
||||
<ul class="list-inline flex-gow-1 p-5 fs-sm fw-medium mb-0">
|
||||
<li class="list-inline-item">
|
||||
<a class="text-muted" href="https://app.hesabix.ir/"> ورود به حسابیکس </a>
|
||||
<a class="text-muted" href="{{ twigFunctions.systemSettings().appSite }}/"> ورود به حسابیکس </a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- END Footer -->
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<h3 class="mx-5">
|
||||
متاسفانه پرداخت ناموفق بود!
|
||||
</h3>
|
||||
<a class="btn btn-lg btn-success mt-4" href="https://app.hesabix.ir/profile/dashboard">
|
||||
<a class="btn btn-lg btn-success mt-4" href="{{ twigFunctions.systemSettings().appSite }}/profile/dashboard">
|
||||
<i class="bi bi-buy"></i>
|
||||
بازگشت به پروفایل کاربری
|
||||
</a>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<h3 class="mx-5">
|
||||
با تشکر از پرداخت شما. سفارش شما اعمال شد.
|
||||
</h3>
|
||||
<a class="btn btn-lg btn-success mt-4" href="https://app.hesabix.ir/profile/dashboard">
|
||||
<a class="btn btn-lg btn-success mt-4" href="{{ twigFunctions.systemSettings().appSite }}/profile/dashboard">
|
||||
<i class="bi bi-buy"></i>
|
||||
بازگشت به پروفایل کاربری
|
||||
</a>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
نیاز نیست که هیچگونه نرم افزاری را نصب کنید. کافیست در سایت ثبت نام کرده و بلافاصله کسب و کار خود را مدیریت کنید.
|
||||
</p>
|
||||
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center">
|
||||
<a href="https://app.hesabix.ir/user/login" class="btn btn-primary btn-lg px-4 gap-3">
|
||||
<a href="{{ twigFunctions.systemSettings().appSite }}/user/login" class="btn btn-primary btn-lg px-4 gap-3">
|
||||
<i class="fa fa-door-open"></i>
|
||||
ورود | عضویت رایگان
|
||||
</a>
|
||||
|
|
Loading…
Reference in a new issue