Files
ludikevent_crm/src/Controller/HomeController.php

182 lines
7.9 KiB
PHP
Raw Normal View History

<?php
namespace App\Controller;
use App\Entity\Account;
use App\Entity\AccountResetPasswordRequest;
use App\Form\RequestPasswordConfirmType;
use App\Form\RequestPasswordRequestType;
use App\Service\ResetPassword\Event\ResetPasswordConfirmEvent;
use App\Service\ResetPassword\Event\ResetPasswordEvent;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class HomeController extends AbstractController
{
#[Route(path: '/', name: 'app_home', options: ['sitemap' => false], methods: ['GET'])]
public function index(AuthenticationUtils $authenticationUtils): Response
{
return $this->render('home.twig',[
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),
]);
}
#[Route(path: '/logout', name: 'app_logout', options: ['sitemap' => false], methods: ['GET','POST'])]
public function logout(): Response
{
}
#[Route(path: '/mot-de-passe-oublie', name: 'app_forgot_password', options: ['sitemap' => false], methods: ['GET','POST'])]
public function forgotPassword(Request $request,EventDispatcherInterface $eventDispatcher): Response
{
$requestPasswordRequest = new ResetPasswordEvent();
$form = $this->createForm(RequestPasswordRequestType::class,$requestPasswordRequest);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$eventDispatcher->dispatch($requestPasswordRequest);
return $this->redirectToRoute('app_forgot_password_sent');
}
return $this->render('security/forgot_password.twig', [
'form' => $form->createView(),
]);
}
#[Route(path: '/mot-de-passe-oublie/sent', name: 'app_forgot_password_sent', options: ['sitemap' => false], methods: ['GET','POST'])]
public function forgotPasswordSent(Request $request,EventDispatcherInterface $eventDispatcher): Response
{
return $this->render('security/forgot_password_success.twig', [
]);
}
#[Route(path: '/mot-de-passe-oublie/{id}/{token}', name: 'app_forgot_password_confirm', options: ['sitemap' => false], methods: ['GET','POST'])]
public function forgotPasswordConfirm(UserPasswordHasherInterface $userPasswordHasher,EventDispatcherInterface $eventDispatcher,Request $request,EntityManagerInterface $entityManager,string $id,string $token): Response
{
$errorMessage = "Requête non valide.";
if (!is_numeric($id)) {
$this->addFlash("error", $errorMessage);
return $this->redirectToRoute('app_forgot_password');
}
$account = $entityManager->getRepository(Account::class)->find((int)$id);
if (!$account instanceof Account) {
$this->addFlash("error", $errorMessage);
return $this->redirectToRoute('app_forgot_password');
}
$requestToken = $entityManager->getRepository(AccountResetPasswordRequest::class)->findOneBy([
'Account' => $account, // Assurez-vous que 'Account' est le nom correct de la propriété/colonne dans votre entité AccountResetPasswordRequest.
'token' => $token
]);
if (!$requestToken instanceof AccountResetPasswordRequest) {
$this->addFlash("error", $errorMessage);
return $this->redirectToRoute('app_forgot_password');
}
$now = new \DateTimeImmutable();
if ($requestToken->getExpiresAt() < $now) {
$this->addFlash("error", "Le lien de réinitialisation de mot de passe a expiré.");
return $this->redirectToRoute('app_forgot_password');
}
$event = new ResetPasswordConfirmEvent();
$form = $this->createForm(RequestPasswordConfirmType::class,$event);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$account->setPassword($userPasswordHasher->hashPassword($account,$event->getPassword()));
$entityManager->persist($account);
$entityManager->flush();
$this->addFlash("success", "Votre mot de passe a été mis à jour avec succès.");
return $this->redirectToRoute('app_home');
}
return $this->render('security/forgot-password-confirm.twig', [
'form' => $form->createView(),
'noIndex' => true,
'id' => $id,
'token' => $token,
'account' => $account,
]);
}
const SENTRY_HOST = '';
const SENTRY_PROJECT_IDS = [''];
#[Route('/uptime',name: 'app_uptime',options: ['sitemap' => false], methods: ['GET'])]
public function app_uptime(Request $request,HttpClientInterface $httpClient): Response
{
return $this->json([]);
}
#[Route('/tunnel',name: 'app_tunnel',options: ['sitemap' => false], methods: ['POST'])]
public function tunnel(Request $request,HttpClientInterface $httpClient): Response
{
$envelope = $request->getContent();
if (empty($envelope)) {
return $this->json([]);
}
try {
// 2. Extract the header piece (first line)
$pieces = explode("\n", $envelope, 2);
$piece = $pieces[0];
// 3. Parse the header (which is JSON)
$header = json_decode($piece, true);
if (!isset($header['dsn'])) {
throw new \Exception("Missing DSN in envelope header.");
}
// 4. Extract and validate DSN and Project ID
$dsnUrl = parse_url($header['dsn']);
$dsnHostname = $dsnUrl['host'] ?? null;
$dsnPath = $dsnUrl['path'] ?? '/';
// Remove leading/trailing slashes from the path to get the project_id
$projectId = trim($dsnPath, '/');
if ($dsnHostname !== self::SENTRY_HOST) {
throw new \Exception("Invalid sentry hostname: {$dsnHostname}");
}
if (empty($projectId) || !in_array($projectId, self::SENTRY_PROJECT_IDS)) {
throw new \Exception("Invalid sentry project id: {$projectId}");
}
// 5. Construct the upstream Sentry URL
$upstreamSentryUrl = "https://" . self::SENTRY_HOST . "/api/" . $projectId . "/envelope/";
// 6. Forward the request using an HTTP client (e.g., Guzzle)
$response = $httpClient->request("POST",$upstreamSentryUrl, [
'body' => $envelope,
'headers' => [
// Sentry expects this content type
'Content-Type' => 'application/x-sentry-envelope',
// Forward the content encoding if present, though often not needed
// 'Content-Encoding' => $request->headers->get('Content-Encoding'),
],
]);
// 7. Return the status from the upstream Sentry response
return new JsonResponse([], $response->getStatusCode());
} catch (\Exception $e) {
// Log the error for server-side debugging
error_log("Error tunneling to Sentry: " . $e->getMessage());
// Return a success status (200/202) or a non-specific 500 to the client.
// Returning a non-error status (like 200) is often preferred for tunnels
// to avoid triggering ad-blockers on failures.
return new JsonResponse([
'error' => 'An error occurred during tunneling.'
], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
}
}
}