[USER][UI][AUTHENTICATION] Add registration form
This commit is contained in:
parent
17dc298dfa
commit
c973517397
|
@ -3,7 +3,24 @@
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Core\Controller;
|
use App\Core\Controller;
|
||||||
|
use App\Core\DB\DB;
|
||||||
|
use App\Core\Form;
|
||||||
|
use function App\Core\I18n\_m;
|
||||||
|
use App\Entity\LocalUser;
|
||||||
|
use App\Entity\Profile;
|
||||||
|
use App\Security\Authenticator;
|
||||||
|
use App\Security\EmailVerifier;
|
||||||
|
use app\Util\Common;
|
||||||
|
use App\Util\Nickname;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
|
||||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
||||||
|
use Symfony\Component\Validator\Constraints\Length;
|
||||||
|
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||||
|
|
||||||
class Security extends Controller
|
class Security extends Controller
|
||||||
{
|
{
|
||||||
|
@ -25,4 +42,80 @@ class Security extends Controller
|
||||||
{
|
{
|
||||||
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
|
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function register(Request $request,
|
||||||
|
EmailVerifier $email_verifier,
|
||||||
|
GuardAuthenticatorHandler $guard_handler,
|
||||||
|
Authenticator $authenticator)
|
||||||
|
{
|
||||||
|
$form = Form::create([
|
||||||
|
['nickname', TextType::class, [
|
||||||
|
'label' => _m('Nickname'),
|
||||||
|
'constraints' => [new Length([
|
||||||
|
'min' => 1,
|
||||||
|
'minMessage' => _m('Your password should be at least {{ limit }} characters long'),
|
||||||
|
'max' => 64,
|
||||||
|
'maxMessage' => _m('Your password should be at most {{ limit }} characters long'), ]),
|
||||||
|
],
|
||||||
|
]],
|
||||||
|
['email', EmailType::class, ['label' => _m('Email')]],
|
||||||
|
['password', PasswordType::class, [
|
||||||
|
'label' => _m('Password'),
|
||||||
|
'mapped' => false,
|
||||||
|
'constraints' => [
|
||||||
|
new NotBlank(['message' => _m('Please enter a password')]),
|
||||||
|
new Length(['min' => 6, 'minMessage' => _m('Your password should be at least {{ limit }} characters'), 'max' => 60]),
|
||||||
|
],
|
||||||
|
]],
|
||||||
|
['register', SubmitType::class, ['label' => _m('Register')]],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$form->handleRequest($request);
|
||||||
|
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
|
$data = $form->getData();
|
||||||
|
$data['password'] = $form->get('password')->getData();
|
||||||
|
|
||||||
|
$valid_nickname = Nickname::isValid($data['nickname'], Nickname::CHECK_USED);
|
||||||
|
if (!$valid_nickname) {
|
||||||
|
throw new \Exception(_m('Invalid nickname'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$profile = new Profile($data['nickname']);
|
||||||
|
$user = new LocalUser($data['nickname'], $data['email'], $data['password']);
|
||||||
|
|
||||||
|
DB::persist($user);
|
||||||
|
DB::persist($profile);
|
||||||
|
DB::flush();
|
||||||
|
|
||||||
|
// generate a signed url and email it to the user
|
||||||
|
if (Common::config('site', 'use_email')) {
|
||||||
|
$email_verifier->sendEmailConfirmation(
|
||||||
|
'verify_email',
|
||||||
|
$user,
|
||||||
|
(new TemplatedEmail())
|
||||||
|
->from(new Address(Common::config('site', 'email'), Common::config('site', 'nickname')))
|
||||||
|
->to($user->getOutgoingEmail())
|
||||||
|
->subject(_m('Please Confirm your Email'))
|
||||||
|
->htmlTemplate('security/confirmation_email.html.twig')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$user->setIsEmailVerified(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $guard_handler->authenticateUserAndHandleSuccess(
|
||||||
|
$user,
|
||||||
|
$request,
|
||||||
|
$authenticator,
|
||||||
|
'main' // firewall name in security.yaml
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'_template' => 'security/register.html.twig',
|
||||||
|
'registration_form' => $form->createView(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return ['_template' => 'security/register.html.twig', 'form' => $form->createView()];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ abstract class Main
|
||||||
{
|
{
|
||||||
$r->connect('login', '/login', [C\Security::class, 'login']);
|
$r->connect('login', '/login', [C\Security::class, 'login']);
|
||||||
$r->connect('logout', '/logout', [C\Security::class, 'logout']);
|
$r->connect('logout', '/logout', [C\Security::class, 'logout']);
|
||||||
|
$r->connect('register', '/register', [C\Security::class, 'register']);
|
||||||
|
|
||||||
$r->connect('main_all', '/main/all', C\NetworkPublic::class);
|
$r->connect('main_all', '/main/all', C\NetworkPublic::class);
|
||||||
|
|
||||||
|
|
51
src/Security/EmailVerifier.php
Normal file
51
src/Security/EmailVerifier.php
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Security;
|
||||||
|
|
||||||
|
use App\Core\DB\DB;
|
||||||
|
use App\Core\Mailer;
|
||||||
|
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
|
use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
|
||||||
|
use SymfonyCasts\Bundle\VerifyEmail\VerifyEmailHelperInterface;
|
||||||
|
|
||||||
|
class EmailVerifier
|
||||||
|
{
|
||||||
|
private $verify_email_helper;
|
||||||
|
|
||||||
|
public function __construct(VerifyEmailHelperInterface $helper)
|
||||||
|
{
|
||||||
|
$this->verifyEmailHelper = $helper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendEmailConfirmation(string $verify_email_route_name, UserInterface $user, TemplatedEmail $email): void
|
||||||
|
{
|
||||||
|
$signatureComponents = $this->verify_email_helper->generateSignature(
|
||||||
|
$verify_email_route_name,
|
||||||
|
$user->getId(),
|
||||||
|
$user->getOutgoingEmail()
|
||||||
|
);
|
||||||
|
|
||||||
|
$context = $email->getContext();
|
||||||
|
$context['signedUrl'] = $signatureComponents->getSignedUrl();
|
||||||
|
$context['expiresAt'] = $signatureComponents->getExpiresAt();
|
||||||
|
|
||||||
|
$email->context($context);
|
||||||
|
|
||||||
|
Mailer::send($email);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws VerifyEmailExceptionInterface
|
||||||
|
*/
|
||||||
|
public function handleEmailConfirmation(Request $request, UserInterface $user): void
|
||||||
|
{
|
||||||
|
$this->verify_email_helper->validateEmailConfirmation($request->getUri(), $user->getId(), $user->getOutgoingEmail());
|
||||||
|
|
||||||
|
$user->setIsEmailVerified(true);
|
||||||
|
|
||||||
|
DB::persist($user);
|
||||||
|
DB::flush();
|
||||||
|
}
|
||||||
|
}
|
11
templates/security/confirmation_email.html.twig
Normal file
11
templates/security/confirmation_email.html.twig
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<h1>Hi! Please confirm your email!</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Please confirm your email address by clicking the following link: <br><br>
|
||||||
|
<a href="{{ signedUrl|raw }}">Confirm my Email</a>.
|
||||||
|
This link will expire in {{ expiresAt|date('g') }} hour(s).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Cheers!
|
||||||
|
</p>
|
16
templates/security/register.html.twig
Normal file
16
templates/security/register.html.twig
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}Register{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{% for flashError in app.flashes('verify_email_error') %}
|
||||||
|
<div class="alert alert-danger" role="alert">{{ flashError }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<h1>Register</h1>
|
||||||
|
|
||||||
|
<div style="position: relative; top: 10em; left: 20em;">
|
||||||
|
{{ form(registration_form) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue
Block a user