99 lines
3.6 KiB
PHP
99 lines
3.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Netig\Netslim\Identity\UI\Http;
|
|
|
|
use Netig\Netslim\Identity\Application\AuthServiceInterface;
|
|
use Netig\Netslim\Identity\Domain\Exception\WeakPasswordException;
|
|
use Netig\Netslim\Identity\UI\Http\Request\ChangePasswordRequest;
|
|
use Netig\Netslim\Kernel\Http\Application\Flash\FlashServiceInterface;
|
|
use Netig\Netslim\Kernel\Http\Application\Session\SessionManagerInterface;
|
|
use Psr\Http\Message\ResponseInterface as Response;
|
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
|
use Psr\Log\LoggerInterface;
|
|
use Slim\Views\Twig;
|
|
|
|
/**
|
|
* Gère les actions liées au compte courant, notamment le changement de mot de passe.
|
|
*/
|
|
class AccountController
|
|
{
|
|
public function __construct(
|
|
private readonly Twig $view,
|
|
private readonly AuthServiceInterface $authService,
|
|
private readonly FlashServiceInterface $flash,
|
|
private readonly SessionManagerInterface $sessionManager,
|
|
private readonly ?LoggerInterface $logger = null,
|
|
) {}
|
|
|
|
public function showChangePassword(Request $req, Response $res): Response
|
|
{
|
|
$referer = $req->getHeaderLine('Referer');
|
|
$path = parse_url($referer, PHP_URL_PATH);
|
|
$path = is_string($path) ? $path : '';
|
|
$backUrl = (str_starts_with($path, '/') && $path !== '/account/password')
|
|
? $path
|
|
: AdminHomePath::resolve();
|
|
|
|
return $this->view->render($res, '@Identity/account/password-change.twig', [
|
|
'error' => $this->flash->get('password_error'),
|
|
'success' => $this->flash->get('password_success'),
|
|
'back_url' => $backUrl,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Valide puis applique le changement de mot de passe pour l'utilisateur connecté.
|
|
*/
|
|
public function changePassword(Request $req, Response $res): Response
|
|
{
|
|
$changePasswordRequest = ChangePasswordRequest::fromRequest($req);
|
|
$userId = $this->sessionManager->getUserId() ?? 0;
|
|
|
|
try {
|
|
$changePasswordRequest->ensureConfirmed();
|
|
$this->authService->changePassword(
|
|
$userId,
|
|
$changePasswordRequest->currentPassword,
|
|
$changePasswordRequest->newPassword,
|
|
);
|
|
$this->flash->set('password_success', 'Mot de passe modifié avec succès');
|
|
} catch (WeakPasswordException $e) {
|
|
$this->flash->set('password_error', $e->getMessage());
|
|
} catch (\InvalidArgumentException $e) {
|
|
$message = $e->getMessage();
|
|
if ($message === 'Mot de passe actuel incorrect') {
|
|
$message = 'Le mot de passe actuel est incorrect';
|
|
}
|
|
$this->flash->set('password_error', $message);
|
|
} catch (\Throwable $e) {
|
|
$incidentId = $this->logUnexpectedError($req, $e, [
|
|
'user_id' => $userId,
|
|
]);
|
|
$this->flash->set('password_error', "Une erreur inattendue s\'est produite (réf. {$incidentId})");
|
|
}
|
|
|
|
return $res->withHeader('Location', '/account/password')->withStatus(302);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $context
|
|
*/
|
|
private function logUnexpectedError(Request $req, \Throwable $e, array $context = []): string
|
|
{
|
|
$incidentId = bin2hex(random_bytes(8));
|
|
|
|
$this->logger?->error('Account password change failed', $context + [
|
|
'incident_id' => $incidentId,
|
|
'route' => (string) $req->getUri()->getPath(),
|
|
'method' => $req->getMethod(),
|
|
'exception_class' => $e::class,
|
|
'exception_message' => $e->getMessage(),
|
|
'exception' => $e,
|
|
]);
|
|
|
|
return $incidentId;
|
|
}
|
|
}
|