feat: registration and password reset

This commit is contained in:
Björn Fromme
2024-12-03 16:08:06 +01:00
parent 8b796a8543
commit 3e59031ba9
10 changed files with 285 additions and 22 deletions
+45 -20
View File
@@ -13,6 +13,7 @@ use App\BusProNet\Model\File;
use App\BusProNet\Model\Notification;
use App\BusProNet\Model\PersonalData;
use App\Form\Model\BookingData;
use App\Form\Model\RegistrationData;
use Psr\Log\LoggerInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
@@ -33,10 +34,11 @@ class ApiClient
public function __construct(
private readonly HttpClientInterface $httpClient,
private readonly SerializerInterface $serializer,
private readonly ResponseParser $responseParser,
private readonly LoggerInterface $logger,
array $options
) {
private readonly ResponseParser $responseParser,
private readonly LoggerInterface $logger,
array $options
)
{
$this->config = $this->resolveOptions($options);
}
@@ -57,6 +59,45 @@ class ApiClient
return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data);
}
/**
* @throws ApiClientException
*/
public function register(RegistrationData $registrationData): Notification
{
$data = [
'user' => $this->config['bpn_username'],
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA),
'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA],
'art' => 'Adresse_Neu',
'adressdaten' => [
'geschlecht' => $registrationData->gender,
'vorname' => $registrationData->firstName,
'name' => $registrationData->name,
'kommunikation' => [
'email' => $registrationData->email,
],
],
];
return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data);
}
/**
* @throws ApiClientException
*/
public function resetPassword(string $email): Notification
{
$data = [
'user' => $this->config['bpn_username'],
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA),
'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA],
'art' => 'Passwort_Anfrage',
'email' => $email,
];
return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data);
}
/**
* @throws ApiClientException
*/
@@ -180,22 +221,6 @@ class ApiClient
return $this->sendRequest(static::TYPE_AVAILABILITY, $data);
}
/**
* @throws ApiClientException
*/
public function resetPassword(string $email): Notification
{
$data = [
'user' => $this->config['bpn_username'],
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_CUSTOMER_DATA),
'satz' => ['@typ' => static::TYPE_CUSTOMER_DATA],
'art' => 'Passwort_Anfrage',
'email' => $email,
];
return $this->sendRequest(static::TYPE_CUSTOMER_DATA, $data);
}
/**
* @throws ApiClientException
*/
+50
View File
@@ -0,0 +1,50 @@
<?php
namespace App\Controller;
use App\BusProNet\ApiClient;
use App\BusProNet\Exception\ApiClientException;
use App\Form\Model\RegistrationData;
use App\Form\RegistrationType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class RegistrationController extends AbstractController
{
public function __construct(private readonly ApiClient $apiClient)
{
}
#[Route('/registration', name: 'app_registration')]
#[IsGranted('PUBLIC_ACCESS')]
public function index(Request $request): Response
{
$registrationData = new RegistrationData();
$form = $this->createForm(RegistrationType::class, $registrationData,[
'action' => $this->generateUrl('app_registration'),
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$response = $this->apiClient->register($registrationData);
if ($response->isSuccessful()) {
$this->addFlash('success', 'Du erhältst in Kürze eine E-Mail mit einem Link zum (Zurück)setzen deines Passworts.');
} else {
$this->addFlash('error', 'Möglicherweise bist du bereits registriert. Bitte setze dein Passwort zurück.');
}
} catch (ApiClientException $e) {
$this->addFlash('error', $e->getMessage());
}
return $this->redirectToRoute('app_login');
}
return $this->render('registration/index.html.twig', [
'form' => $form->createView(),
]);
}
}
@@ -0,0 +1,61 @@
<?php
namespace App\Controller;
use App\BusProNet\ApiClient;
use App\BusProNet\Exception\ApiClientException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
class ResetPasswordController extends AbstractController
{
public function __construct(private readonly ApiClient $apiClient)
{
}
#[Route('/reset-password', name: 'app_reset_password')]
#[IsGranted('PUBLIC_ACCESS')]
public function index(Request $request): Response
{
$form = $this
->createFormBuilder(null, [
'action' => $this->generateUrl('app_reset_password'),
])
->add('email', EmailType::class, [
'label' => 'E-Mail',
'constraints' => [
new NotBlank([
'message' => 'Bitte angeben',
]),
new Email([
'mode' => 'strict',
'message' => 'Bitte eine gültige E-Mail Adresse angeben',
])
],
])
->getForm()
;
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$this->apiClient->resetPassword($form->get('email')->getData());
$this->addFlash('success', 'Du erhältst in Kürze eine E-Mail mit einem Link zum (Zurück)setzen deines Passworts.');
} catch (ApiClientException $e) {
$this->addFlash('error', $e->getMessage());
}
return $this->redirectToRoute('app_login');
}
return $this->render('reset_password/index.html.twig', [
'form' => $form->createView(),
]);
}
}
+1
View File
@@ -37,6 +37,7 @@ class ParticipantData
public ?\DateTimeImmutable $dateOfBirth = null;
#[Assert\NotBlank(message: 'Bitte angeben')]
#[Assert\Email(message: 'Bitte eine gültige E-Mail Adresse angeben', mode: 'strict')]
public ?string $email = null;
#[Assert\NotBlank(message: 'Bitte angeben')]
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Form\Model;
use Symfony\Component\Validator\Constraints as Assert;
class RegistrationData
{
#[Assert\NotBlank(message: 'Bitte angeben')]
public ?string $firstName = null;
#[Assert\NotBlank(message: 'Bitte angeben')]
public ?string $name = null;
#[Assert\NotBlank(message: 'Bitte angeben')]
#[Assert\Choice(choices: ['M', 'W', 'd'])]
public ?string $gender = null;
#[Assert\NotBlank(message: 'Bitte angeben')]
#[Assert\Email(message: 'Bitte eine gültige E-Mail Adresse angeben', mode: 'strict')]
public ?string $email = null;
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace App\Form;
use App\Form\Model\RegistrationData;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('gender', ChoiceType::class, [
'label' => 'Gender',
'choices' => [
'männlich' => 'M',
'weiblich' => 'W',
'divers' => 'D',
],
])
->add('firstName', TextType::class, [
'label' => 'Name',
])
->add('name', TextType::class, [
'label' => 'Nachname',
])
->add('email', EmailType::class, [
'label' => 'E-Mail',
'property_path' => 'email',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => RegistrationData::class,
]);
}
}