Reprise dans le répertoire de production du travail mené dans le worktree ux-service-enfance : - tableau de bord Service Enfance (dashboard.php) et navigation regroupée ; - guide d'utilisation (faq.php) accessible depuis toute la navigation ; - éditeur de semaine type mis en avant sur l'écran de saisie ; - droit à l'enveloppe de formation par agent, en remplacement de la case « formation déjà prévue dans la répartition annuelle » ; - correctif de « [object Object] » sur les cartes de quota du PTA ; - motif de travail par défaut à la saisie, heures travaillées complètes dans les PDF. Le docker-compose.yml de production est conservé : celui du worktree décrit une pile de test (conteneurs et volume suffixés « test », ports 9080/9081), qui aurait fait redémarrer l'application sur un volume MariaDB vide. Les migrations database/migration_v7_9*.sql sont obligatoires ; le service db-migrate les applique au déploiement. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
2.4 KiB
PHP
68 lines
2.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controllers;
|
|
|
|
use App\Core\Access;
|
|
use App\Core\Controller;
|
|
use App\Core\Csrf;
|
|
use App\Core\Security;
|
|
use App\Models\AgentModel;
|
|
use App\Models\StructureModel;
|
|
use PDO;
|
|
|
|
final class RoleController extends Controller
|
|
{
|
|
public function __construct(private PDO $pdo)
|
|
{
|
|
}
|
|
|
|
public function index(): void
|
|
{
|
|
$access = new Access($this->pdo);
|
|
|
|
// Le changement de rôle modifie l'état de la session : il est protégé
|
|
// par le jeton CSRF au même titre que les écritures de l'API.
|
|
if (($_GET['action'] ?? '') === 'reset') {
|
|
$provided = (string) ($_GET['csrf_token'] ?? '');
|
|
if ($provided !== '' && hash_equals(Csrf::ensureToken(), $provided)) {
|
|
$access->clear();
|
|
}
|
|
header('Location: role.php', true, 302);
|
|
exit;
|
|
}
|
|
|
|
$error = '';
|
|
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
|
|
$expected = Csrf::ensureToken();
|
|
$provided = (string) ($_POST['csrf_token'] ?? '');
|
|
if ($provided === '' || !hash_equals($expected, $provided)) {
|
|
$error = 'La session a expiré. Rechargez la page et recommencez.';
|
|
} else {
|
|
try {
|
|
$role = strtoupper(trim((string) ($_POST['role'] ?? '')));
|
|
$agentId = filter_var($_POST['agent_id'] ?? null, FILTER_VALIDATE_INT) ?: null;
|
|
$structureId = filter_var($_POST['structure_id'] ?? null, FILTER_VALIDATE_INT) ?: null;
|
|
$access->select($role, $agentId ? (int) $agentId : null, $structureId ? (int) $structureId : null);
|
|
header('Location: ' . $access->homeUrl(), true, 302);
|
|
exit;
|
|
} catch (\DomainException $e) {
|
|
$error = $e->getMessage();
|
|
}
|
|
}
|
|
}
|
|
|
|
Security::sendHtmlHeaders();
|
|
$this->render('pages/role', [
|
|
'pageTitle' => 'Choisir votre accès',
|
|
'cspNonce' => Security::nonce(),
|
|
'csrfToken' => Csrf::ensureToken(),
|
|
'agents' => (new AgentModel($this->pdo))->allActive(),
|
|
'structures' => (new StructureModel($this->pdo))->allActive(),
|
|
'error' => $error,
|
|
'currentProfile' => $access->isConfigured() ? $access->profile() : null,
|
|
]);
|
|
}
|
|
}
|