7.4 KiB
PTA V7.27 — Le Service Enfance distribue les jetons des agents et des responsables
Le problème traité
Depuis la V7.11, tout compte d’accès passait par la DSI : création, jeton perdu, départ d’un remplaçant. Or c’est le Service Enfance qui sait qu’un agent est arrivé, qu’un responsable a laissé son jeton chez lui ou qu’un contrat s’arrête. Le détour par la DSI ajoutait un délai — parfois plusieurs jours — sans ajouter le moindre contrôle : la DSI ne pouvait rien vérifier de ce qu’on lui demandait, elle exécutait.
Ce qui change
L’onglet Administration du Service Enfance gagne une section « Jetons d’accès des agents et des responsables », sous les horaires de couverture. On y fait, pour ces deux rôles, ce que la page DSI permet :
- créer un compte pour un agent ou un lieu qui n’en a pas encore ;
- régénérer un jeton perdu ou compromis — l’ancien cesse aussitôt de fonctionner ;
- désactiver puis réactiver un compte (départ temporaire) ;
- supprimer un compte définitivement ;
- générer en lot les jetons de toutes les identités actives qui n’en ont pas.
Comme sur la page DSI, un jeton produit n’est lisible qu’une fois, dans le panneau « Jetons à transmettre » : la base n’en garde qu’une empreinte SHA-256. Perdu, il ne se retrouve pas — il se régénère.
Ce qui ne change pas : la frontière de privilège
La délégation s’arrête à deux rôles : AGENT et RESPONSABLE_STRUCTURE. Les comptes SERVICE_ENFANCE et DSI n’apparaissent pas dans cette section, ne sont pas créables, et toute action qui en désigne un est refusée en 403. Ce n’est pas une commodité d’affichage :
- un compte Service Enfance créé par le Service Enfance serait une auto-promotion — le rôle se distribuerait lui-même, sans contrôle extérieur ;
- un compte DSI créé par le Service Enfance lui ouvrirait le journal d’activité, c’est-à-dire la trace de ses propres actions.
Le second facteur de la V7.12 reste hors de portée : ces deux rôles n’ont pas de mot de passe, et le Service Enfance n’a aucun moyen d’en effacer un. La réinitialisation de mot de passe reste une action DSI, sur la page DSI.
La borne est posée des deux côtés :
| Où | Quoi |
|---|---|
AccessAccountController::ROLES_DELEGUES |
La liste blanche PHP, contrôlée avant toute écriture et à la relecture de tout compte désigné |
CompteModel::lister(['roles' => …]) |
La liste SQL est bornée ; le filtre d’interface ne peut que restreindre à l’intérieur de cette borne |
migration_v7_9h_jetons_service_enfance.sql |
La permission can_manage_field_access, accordée au seul Service Enfance |
Une frontière de privilège ne doit pas dépendre d’un seul des deux côtés : une ligne mal saisie en base ne doit pas pouvoir ouvrir la création de comptes privilégiés, et inversement.
Traçabilité
Toutes les actions sont journalisées en catégorie ADMINISTRATION, avec le rôle de l’acteur et un
contexte canal = DELEGATION_SERVICE_ENFANCE qui les distingue des mêmes actions faites par la DSI.
Les refus le sont aussi, en ACCES_REFUSE : ROLE_HORS_PERIMETRE (création tentée sur un rôle
privilégié) et COMPTE_HORS_PERIMETRE (action tentée sur un compte privilégié). La DSI garde donc la
lecture complète de ce que le Service Enfance fait des accès.
Fichiers
| Fichier | Rôle |
|---|---|
database/migration_v7_9h_jetons_service_enfance.sql |
Permission can_manage_field_access. Aucune page nouvelle : « Administration » est déjà ouverte au Service Enfance |
app/Controllers/AccessAccountController.php |
Les cinq endpoints, la liste blanche et les refus |
api/acces_comptes.php, acces_compte_creer.php, acces_compte_jeton.php, acces_compte_statut.php, acces_comptes_manquants.php |
Points d’entrée minces |
app/Models/CompteModel.php |
Filtre roles sur lister() |
app/Views/partials/administration.php |
La section et le panneau des jetons |
assets/js/access-tokens.js |
Module accessTokens |
V7.28 — Couper l’accès depuis la fiche des agents
La page Agents gagne, à côté de « Modifier », un bouton qui coupe ou rétablit l’accès de l’agent : « Couper l’accès » / « Rétablir l’accès ». C’est le geste courant — un départ, un arrêt long, un retour — là où la section « Jetons d’accès » de l’onglet Administration porte la distribution des jetons elle-même.
Ce bouton ne touche pas au jeton : désactiver puis réactiver rend le même jeton valable, et l’agent n’a rien à recevoir. Il ne touche pas non plus à la fiche de l’agent, qui reste planifiable — c’est l’accès à l’application qui est coupé, pas la personne au planning. Un agent qui n’a pas encore de compte affiche un bouton inerte « Sans compte d’accès », qui renvoie vers Administration : seul cet écran sait afficher un jeton fraîchement produit.
Aucun droit nouveau : le module agentAccess réutilise api/acces_comptes.php et
api/acces_compte_statut.php, donc les mêmes gardes, la même liste blanche de rôles et la même
journalisation. L’état des comptes n’est pas rendu par PHP mais chargé par le module — le HTML
servi ne porte aucune information sur les comptes, comme sur l’écran DSI.
V7.29 — Un accès coupé retire l’agent des listes d’affectation
Couper l’accès d’un agent le retire désormais des listes où l’on affecte :
| Écran | Effet |
|---|---|
Saisie (api/agents.php → AgentModel::listForLocation()) |
L’agent n’est plus proposé dans le sélecteur |
Équipes (PageController::teams() → allSelectable()) |
L’agent n’est plus proposé à la composition |
Trois bornes, toutes portées par le même NOT EXISTS de AgentModel::SANS_COMPTE_COUPE :
- un agent SANS compte reste proposé. Il n’a pas encore reçu son jeton, ce qui est l’état normal avant distribution : le filtrer viderait les listes d’une installation neuve ;
- le filtre porte sur
compte_acces.actif, pas suragent.actif: fermer une fiche d’agent et couper un accès restent deux décisions distinctes ; - les écrans de consultation (planning par agent, vue annuelle, PTA détaillé) et le référentiel Agents continuent de montrer l’agent. Sans quoi on ne pourrait plus ni relire son année passée, ni lui rétablir son accès — le bouton vit précisément sur cette page.
Ce qui n’est pas défait : les créneaux déjà saisis et les équipes déjà composées restent en place. Couper un accès n’efface rien du passé. En revanche, un lien profond qui désigne un agent coupé (file de validation, tableau de bord) ne peut plus le sélectionner : l’écran de saisie le dit alors explicitement, plutôt que de rester vide — rétablir l’accès rend la saisie de nouveau possible.
Correctif embarqué
CompteModel::lister() répétait le paramètre nommé :q quatre fois dans sa clause de recherche. PDO
tourne ici sans émulation de requêtes préparées (ATTR_EMULATE_PREPARES = 0) : MariaDB refuse
alors un même paramètre employé plusieurs fois. Toute recherche par nom, matricule ou début de
jeton échouait en 500 sur la page DSI, depuis la V7.11. Les marqueurs sont désormais numérotés
(:q_0 … :q_3). Le même champ de recherche existant dans la nouvelle section, le défaut aurait été
reconduit tel quel.