Refatoring : Working state

This commit is contained in:
julien
2026-03-16 14:21:31 +01:00
parent d0761ff010
commit d832d598fe
10 changed files with 449 additions and 358 deletions

View File

@@ -3,155 +3,10 @@ declare(strict_types=1);
namespace App\User;
use App\Shared\Http\FlashServiceInterface;
use App\Shared\Http\SessionManagerInterface;
use App\Shared\Pagination\PaginationPresenter;
use App\User\Exception\DuplicateEmailException;
use App\User\Exception\DuplicateUsernameException;
use App\User\Exception\InvalidRoleException;
use App\User\Exception\RoleAssignmentNotAllowedException;
use App\User\Exception\WeakPasswordException;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Views\Twig;
final class UserController
/**
* Pont de compatibilité : le contrôleur HTTP principal vit désormais dans
* App\User\Http\UserController.
*/
final class UserController extends Http\UserController
{
private const PER_PAGE = 15;
public function __construct(
private readonly Twig $view,
private readonly UserServiceInterface $userService,
private readonly FlashServiceInterface $flash,
private readonly SessionManagerInterface $sessionManager,
) {
}
public function index(Request $req, Response $res): Response
{
$page = PaginationPresenter::resolvePage($req->getQueryParams());
$paginated = $this->userService->findPaginated($page, self::PER_PAGE);
return $this->view->render($res, 'admin/users/index.twig', [
'users' => $paginated->getItems(),
'pagination' => PaginationPresenter::fromRequest($req, $paginated),
'currentUserId' => $this->sessionManager->getUserId(),
'assignableRoles' => User::assignableRoles(),
'error' => $this->flash->get('user_error'),
'success' => $this->flash->get('user_success'),
]);
}
public function showCreate(Request $req, Response $res): Response
{
return $this->view->render($res, 'admin/users/form.twig', [
'assignableRoles' => User::assignableRoles(),
'error' => $this->flash->get('user_error'),
]);
}
public function create(Request $req, Response $res): Response
{
$data = (array) $req->getParsedBody();
$username = trim((string) ($data['username'] ?? ''));
$email = trim((string) ($data['email'] ?? ''));
$password = trim((string) ($data['password'] ?? ''));
$confirm = trim((string) ($data['password_confirm'] ?? ''));
$rawRole = trim((string) ($data['role'] ?? ''));
$role = in_array($rawRole, User::assignableRoles(), true) ? $rawRole : User::ROLE_USER;
if ($password !== $confirm) {
$this->flash->set('user_error', 'Les mots de passe ne correspondent pas');
return $res->withHeader('Location', '/admin/users/create')->withStatus(302);
}
try {
$this->userService->createUser($username, $email, $password, $role);
$this->flash->set('user_success', "L'utilisateur « {$username} » a été créé avec succès");
return $res->withHeader('Location', '/admin/users')->withStatus(302);
} catch (DuplicateUsernameException) {
$this->flash->set('user_error', "Ce nom d'utilisateur est déjà pris");
} catch (DuplicateEmailException) {
$this->flash->set('user_error', 'Cette adresse e-mail est déjà utilisée');
} catch (WeakPasswordException) {
$this->flash->set('user_error', 'Le mot de passe doit contenir au moins 8 caractères');
} catch (InvalidRoleException|RoleAssignmentNotAllowedException $e) {
$this->flash->set('user_error', $e->getMessage());
} catch (\Throwable) {
$this->flash->set('user_error', "Une erreur inattendue s'est produite");
}
return $res->withHeader('Location', '/admin/users/create')->withStatus(302);
}
/**
* @param array<string, mixed> $args
*/
public function updateRole(Request $req, Response $res, array $args): Response
{
$id = (int) $args['id'];
$user = $this->userService->findById($id);
if ($user === null) {
$this->flash->set('user_error', 'Utilisateur introuvable');
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
if ($id === $this->sessionManager->getUserId()) {
$this->flash->set('user_error', 'Vous ne pouvez pas modifier votre propre rôle');
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
if ($user->isAdmin()) {
$this->flash->set('user_error', 'Le rôle d\'un administrateur ne peut pas être modifié depuis l\'interface');
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
$body = (array) $req->getParsedBody();
$rawRole = trim((string) ($body['role'] ?? ''));
$role = in_array($rawRole, User::assignableRoles(), true) ? $rawRole : null;
if ($role === null) {
$this->flash->set('user_error', 'Rôle invalide');
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
try {
$this->userService->updateRole($id, $role);
$this->flash->set('user_success', "Le rôle de « {$user->getUsername()} » a été mis à jour");
} catch (InvalidRoleException|RoleAssignmentNotAllowedException $e) {
$this->flash->set('user_error', $e->getMessage());
}
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
/**
* @param array<string, mixed> $args
*/
public function delete(Request $req, Response $res, array $args): Response
{
$id = (int) $args['id'];
$user = $this->userService->findById($id);
if ($user === null) {
$this->flash->set('user_error', 'Utilisateur introuvable');
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
if ($user->isAdmin()) {
$this->flash->set('user_error', 'Le compte administrateur ne peut pas être supprimé');
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
if ($id === $this->sessionManager->getUserId()) {
$this->flash->set('user_error', 'Vous ne pouvez pas supprimer votre propre compte');
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
$this->userService->delete($id);
$this->flash->set('user_success', "L'utilisateur « {$user->getUsername()} » a été supprimé avec succès");
return $res->withHeader('Location', '/admin/users')->withStatus(302);
}
}