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 $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; } }