<?php
declare(strict_types=1);
namespace App\Controller;
use App\Exception\ValidationErrorException;
use App\Response\MessageResponse;
use App\Service\CustomerServiceInterface;
use App\Service\Security\AuthServiceInterface;
use App\Service\User\UserServiceInterface;
use App\Validator\ViolationsTrait;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
final class SecurityController extends AbstractController
{
use ViolationsTrait;
public function __construct(
private AuthServiceInterface $authService,
private UserServiceInterface $userService,
private CustomerServiceInterface $customerService,
private ValidatorInterface $validator,
) {
}
#[Route('/', name: 'default_route')]
public function index(): Response
{
return new Response('No direct access.', 400);
}
#[Route(path: '/auth/forgotten_password/{email}', name: 'auth_forgotten_password', methods: ['GET'])]
public function forgottenPassword(string $email): Response
{
if (!empty(trim($email))) {
$user = $this->userService->getUserByEmail($email);
if (null === $user) {
$user = $this->customerService->findCustomerByEmail($email);
}
if (null !== $user) {
$this->authService->resetPassword($user);
}
}
return new MessageResponse('OK');
}
/**
* @throws ValidationErrorException
*/
#[Route(path: '/auth/reset_password/{resetToken}', name: 'auth_reset_password', methods: ['POST'])]
public function changePassword(string $resetToken, Request $request): MessageResponse
{
$user = $this->userService->findByResetToken($resetToken);
$request = json_decode($request->getContent(), true);
if (
null === $user->getResetTokenCreatedAt() ||
(new \DateTimeImmutable())->getTimestamp() - $user->getResetTokenCreatedAt()->getTimestamp() >= 172800
) {
throw new \DomainException('ERROR.USER.PASSWORD.TOKEN.EXPIRED', Response::HTTP_BAD_REQUEST);
}
if (!isset($request['newPassword'])) {
throw new \DomainException('ERROR.USER.PASSWORD.MISSING', Response::HTTP_BAD_REQUEST);
}
$user->setPassword($request['newPassword']);
$this->checkViolations($this->validator->validate($user));
$this->authService->changePassword($user);
return new MessageResponse('INFO.USER.PASSWORD.UPDATED');
}
#[Route(path: '/auth/invalidate_refresh_token', name: 'auth_invalidate_refresh_token', methods: ['GET'])]
#[IsGranted('ROLE_ADMIN')]
public function invalidateRefreshToken(): Response
{
if (!$this->getUser() instanceof UserInterface) {
throw new \DomainException('ERROR.USER.INVALID.ACCESS.RIGHTS', 403);
}
$this->authService->invalidate($this->getUser());
return new MessageResponse('INFO.USER.REFRESH.TOKEN.INVALIDATED');
}
}