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)/
|
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||||
security: false
|
security: false
|
||||||
main:
|
main:
|
||||||
|
stateless: true
|
||||||
lazy: true
|
lazy: true
|
||||||
provider: app_user_provider
|
provider: app_user_provider
|
||||||
json_login:
|
json_login:
|
||||||
|
@ -31,7 +32,6 @@ security:
|
||||||
# switch_user: true
|
# switch_user: true
|
||||||
logout:
|
logout:
|
||||||
path: front_user_logout
|
path: front_user_logout
|
||||||
|
|
||||||
# where to redirect after logout
|
# where to redirect after logout
|
||||||
target: general_home
|
target: general_home
|
||||||
form_login:
|
form_login:
|
||||||
|
@ -39,6 +39,11 @@ security:
|
||||||
login_path: front_user_login
|
login_path: front_user_login
|
||||||
check_path: front_user_login
|
check_path: front_user_login
|
||||||
enable_csrf: true
|
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
|
# Easy way to control access for large sections of your site
|
||||||
# Note: Only the *first* access control that matches will be used
|
# 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\Business;
|
||||||
use App\Entity\Permission;
|
use App\Entity\Permission;
|
||||||
use App\Form\UserRegisterType;
|
use App\Form\UserRegisterType;
|
||||||
|
use App\Security\BackAuthAuthenticator;
|
||||||
use App\Service\Provider;
|
use App\Service\Provider;
|
||||||
|
use App\Service\twigFunctions;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
use App\Entity\UserToken;
|
use App\Entity\UserToken;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
@ -23,6 +25,7 @@ use Symfony\Component\Form\FormError;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\Mime\Address;
|
use Symfony\Component\Mime\Address;
|
||||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||||
|
use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
|
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher,
|
use Symfony\Component\EventDispatcher\EventDispatcher,
|
||||||
|
@ -75,10 +78,10 @@ class UserController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/register', name: 'front_user_register')]
|
#[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
|
//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();
|
$user = new User();
|
||||||
$form = $this->createForm(UserRegisterType::class, $user);
|
$form = $this->createForm(UserRegisterType::class, $user);
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
@ -148,27 +151,33 @@ class UserController extends AbstractController
|
||||||
return $this->redirectToRoute('app_register');
|
return $this->redirectToRoute('app_register');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/login/by/token', name: 'app_login_by_token')]
|
#[Route('/login/by/token{route}', name: 'app_login_by_token' , requirements: ['route' => '.+'])]
|
||||||
public function app_login_by_token(Request $request): Response
|
public function app_login_by_token(string $route,AuthenticationUtils $authenticationUtils,twigFunctions $functions,Request $request, UserPasswordHasherInterface $userPasswordHasher, UserAuthenticatorInterface $userAuthenticator, BackAuthAuthenticator $authenticator, EntityManagerInterface $entityManager): Response
|
||||||
{
|
{
|
||||||
|
$token = $entityManager->getRepository(UserToken::class)->findOneBy(['tokenID'=>$request->get('tokenID')]);
|
||||||
// log the user in on the current firewall
|
if(!$token){
|
||||||
$security->login($user);
|
$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
|
$userAuthenticator->authenticateUser(
|
||||||
// by using the name of built-in authenticators...
|
$token->getUser(),
|
||||||
$security->login($user, 'form_login');
|
$authenticator,
|
||||||
// ...or the service id of custom authenticators
|
$request
|
||||||
$security->login($user, ExampleAuthenticator::class);
|
);
|
||||||
|
return $this->redirect($functions->systemSettings()->getAppSite() . $route);
|
||||||
|
}
|
||||||
|
|
||||||
// you can also log in on a different firewall
|
/**
|
||||||
$security->login($user, 'form_login', 'other_firewall');
|
* @throws Exception
|
||||||
|
*/
|
||||||
// use the redirection logic applied to regular login
|
#[Route('/logout/by/token{route}', name: 'app_logout_by_token' , requirements: ['route' => '.+'])]
|
||||||
$redirectResponse = $security->login($user);
|
public function app_logout_by_token(string $route,twigFunctions $functions,Request $request,Security $security, EntityManagerInterface $entityManager): Response
|
||||||
return $redirectResponse;
|
{
|
||||||
|
try {
|
||||||
// or use a custom redirection logic (e.g. redirect users to their account page)
|
$security->logout(false);
|
||||||
// return new RedirectResponse('...');
|
} catch (Exception $e){}
|
||||||
|
return $this->redirect($functions->systemSettings()->getAppSite() . $route);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,16 +56,16 @@ class UserController extends AbstractController
|
||||||
'message' => 'missing credentials',
|
'message' => 'missing credentials',
|
||||||
], Response::HTTP_UNAUTHORIZED);
|
], Response::HTTP_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$tokenString = $this->RandomString(254); // somehow create an API token for $user
|
|
||||||
$token = new UserToken();
|
$token = new UserToken();
|
||||||
$token->setUser($user);
|
$token->setUser($user);
|
||||||
$token->setToken($tokenString);
|
$token->setToken($this->RandomString(254));
|
||||||
|
$token->setTokenID($this->RandomString(254));
|
||||||
$entityManager->persist($token);
|
$entityManager->persist($token);
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
return $this->json([
|
return $this->json([
|
||||||
'user' => $user->getUserIdentifier(),
|
'user' => $user->getUserIdentifier(),
|
||||||
'token' => $tokenString,
|
'token' => $token->getToken(),
|
||||||
|
'tokenID'=> $token->getTokenID()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,9 @@ class Settings
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
private ?string $zarinpalMerchant = null;
|
private ?string $zarinpalMerchant = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
private ?string $appSite = null;
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
|
@ -77,4 +80,16 @@ class Settings
|
||||||
|
|
||||||
return $this;
|
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)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
private ?User $user = null;
|
private ?User $user = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
private ?string $tokenID = null;
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
|
@ -48,4 +51,16 @@ class UserToken
|
||||||
|
|
||||||
return $this;
|
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 App\Entity\UserToken;
|
||||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\ORM\NonUniqueResultException;
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +41,7 @@ class UserTokenRepository extends ServiceEntityRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
* @throws NonUniqueResultException
|
||||||
*/
|
*/
|
||||||
public function findByApiToken($value): UserToken | null
|
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
|
// public function findOneBySomeField($value): ?UserToken
|
||||||
// {
|
// {
|
||||||
// return $this->createQueryBuilder('u')
|
// 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\ChangeReport;
|
||||||
|
use App\Entity\Settings;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
class twigFunctions
|
class twigFunctions
|
||||||
|
@ -84,5 +85,8 @@ class twigFunctions
|
||||||
return '0.0.1';
|
return '0.0.1';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function systemSettings(){
|
||||||
|
return $this->em->getRepository(Settings::class)->findAll()[0];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -48,8 +48,8 @@
|
||||||
|
|
||||||
<!-- Right Section -->
|
<!-- Right Section -->
|
||||||
<div>
|
<div>
|
||||||
<a href="https://app.hesabix.ir/user/login" class="btn btn-sm btn-primary me-1">ورود</a>
|
<a href="{{ twigFunctions.systemSettings().appSite }}/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/register" class="btn btn-sm btn-success">عضویت</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- END Right Section -->
|
<!-- END Right Section -->
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
برای ارسال دیدگاه به حساب خود وارد شوید.
|
برای ارسال دیدگاه به حساب خود وارد شوید.
|
||||||
<br>
|
<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>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="rounded bg-light px-2 pt-2 pb-1">
|
<div class="rounded bg-light px-2 pt-2 pb-1">
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<ul class="list-inline flex-gow-1 p-5 fs-sm fw-medium mb-0">
|
<ul class="list-inline flex-gow-1 p-5 fs-sm fw-medium mb-0">
|
||||||
<li class="list-inline-item">
|
<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>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- END Footer -->
|
<!-- END Footer -->
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<h3 class="mx-5">
|
<h3 class="mx-5">
|
||||||
متاسفانه پرداخت ناموفق بود!
|
متاسفانه پرداخت ناموفق بود!
|
||||||
</h3>
|
</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>
|
<i class="bi bi-buy"></i>
|
||||||
بازگشت به پروفایل کاربری
|
بازگشت به پروفایل کاربری
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<h3 class="mx-5">
|
<h3 class="mx-5">
|
||||||
با تشکر از پرداخت شما. سفارش شما اعمال شد.
|
با تشکر از پرداخت شما. سفارش شما اعمال شد.
|
||||||
</h3>
|
</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>
|
<i class="bi bi-buy"></i>
|
||||||
بازگشت به پروفایل کاربری
|
بازگشت به پروفایل کاربری
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
نیاز نیست که هیچگونه نرم افزاری را نصب کنید. کافیست در سایت ثبت نام کرده و بلافاصله کسب و کار خود را مدیریت کنید.
|
نیاز نیست که هیچگونه نرم افزاری را نصب کنید. کافیست در سایت ثبت نام کرده و بلافاصله کسب و کار خود را مدیریت کنید.
|
||||||
</p>
|
</p>
|
||||||
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center">
|
<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>
|
<i class="fa fa-door-open"></i>
|
||||||
ورود | عضویت رایگان
|
ورود | عضویت رایگان
|
||||||
</a>
|
</a>
|
||||||
|
|
Loading…
Reference in a new issue