PMB — détails techniques
Description et fonctionnalités de ce module : PMB.
Nature et rôle
Module ENT pmb-connector (rangé dans connectors/, comme moodle-connector) : passerelle vers
un catalogue CDI externe, qui alimente le médiacentre en notices bibliographiques via
fr.openent.mediacentre.source.PMB. Il n'héberge aucune notice : il en dépose une copie dans
l'index du médiacentre à chaque moissonnage (amass).
- Schéma SQL dédié
pmb(db-schema), tablepmb.etablissement. - Protocole vers PMB : webservice apijsonrpc (
ws/connector_out.php?source_id=…), authentification Basic. - Droit workflow
pmb.structure.exportpour les routes d'export d'annuaire.
Un serveur PMB par établissement
host/endpoint/source_id/credentials ne sont pas une configuration globale du module
dans ent-core.yaml, mais une donnée par établissement :
CREATE TABLE pmb.etablissement (
id bigserial PRIMARY KEY,
idneo VARCHAR(36),
uai VARCHAR(8),
nom VARCHAR(50) NOT NULL,
principal boolean NOT NULL DEFAULT FALSE,
id_principal bigint,
pmb_host VARCHAR,
pmb_endpoint VARCHAR,
pmb_source_id VARCHAR,
pmb_username VARCHAR,
pmb_password VARCHAR,
pmb_page_size INTEGER,
pmb_opac_url VARCHAR
);
PMBServer n'est pas une instance unique mais un registre par UAI (PMBServer.get(uai)),
réenregistré à chaque relevé à partir de ces colonnes. Un établissement pas encore configuré est
simplement ignoré (log + rapport), il ne fait pas échouer les autres.
id_principal sert à partager une connexion déjà configurée : cité scolaire (plusieurs UAI,
un même CDI physique) ou catalogue régional/départemental mutualisé. Dans les deux cas, l'UAI
secondaire laisse ses colonnes pmb_* vides et hérite de la connexion de la ligne visée par
id_principal — établissement réel, ou simple ligne « virtuelle » ne portant que des identifiants
de connexion partagés.
pmbSourceId est l'identifiant de la source de connecteur sortant apijsonrpc créée côté admin
PMB (Administration › Connecteurs › Sortants › ajouter une source), pas un préfixe ou un nom
de base : pmbEndpoint (ws/connector_out.php) n'accepte aucun paramètre database. Le
webservice doit en outre être autorisé pour un groupe d'utilisateurs externes (Administration ›
Utilisateurs externes) correspondant à pmbUsername/pmbPassword, comparés en clair côté PMB.
Routes et droits
| Route | Droit | Usage |
|---|---|---|
GET /pmb/schools | super-administrateur | lister TOUS les établissements connus du connecteur |
GET /pmb/schools/mine | super-administrateur ou administrateur local | établissement(s) de l'utilisateur courant — filtrage sur user.getStructures() |
POST /pmb/schools | super-administrateur | créer un établissement (idneo, uai, nom, principal, id_principal) — opération structurelle |
PUT /pmb/schools/:schoolId/connection | super-administrateur ou administrateur local de cet établissement | configurer sa connexion (pmbHost, pmbEndpoint, pmbSourceId, pmbUsername, pmbPassword, pmbPageSize) |
DELETE /pmb/schools/:schoolId | super-administrateur | supprimer un établissement |
POST /pmb/email/send | utilisateur autorisé sur la ressource | email de demande d'informations au prestataire PMB |
GET /pmb/gestionnaire/list?uai=&type=cdi|pret | workflow pmb.structure.export | gestionnaires du CDI / gestionnaires de prêt |
GET /pmb/user/structures/list?uai=&type=Student|Teacher|Personnel | super-administrateur | utilisateurs de l'établissement, pour les comptes emprunteurs |
GET /schools/mine et PUT /schools/:id/connection acceptent AdminFilter (super-admin OU
administrateur local), mais SchoolController vérifie en plus, pour un administrateur local,
que l'idneo de l'établissement visé figure dans user.getStructures() — sans ce contrôle
explicite, AdminFilter seul autoriserait un administrateur local à modifier la connexion de
N'IMPORTE QUEL établissement.
Les listes de gestionnaires sont bâties sur deux groupes de l'annuaire, nommés dans la
configuration du module (export.group_manager pour le CDI, export.group_manager_lend_manual
pour le prêt).
BFF du dashboard
Le BFF (pages/api/admin/pmb/…) relaie la session ENT (cookies oneSessionId/XSRF-TOKEN, cf.
_proxy.ts) vers les routes ci-dessus — pas de jeton statique comme pour WordPress, qui est un
service tiers sans notion de session ENT. L'autorisation réelle est entièrement tranchée côté
pmb-connector, pas dupliquée dans le BFF. L'email de demande d'informations part par le service
configuré dans « Configuration des emails », pas par des variables d'environnement statiques.
Écran et captures : Connexions PMB (CDI).
Un établissement n'est moissonné que si son nœud Structure porte 'PMB' dans sa propriété
exports (même mécanisme que les autres exports entcore) :
MATCH (s:Structure {UAI: '<uai>'})
SET s.exports = coalesce(s.exports, []) + 'PMB'
Sans ce flag, retrieveDeployedStructures() ne renvoie jamais l'établissement et l'amass tourne
à vide silencieusement (log Stopping PMB amass worker: empty structures), même si sa connexion
pmb_* est correctement remplie.
Configuration du module (ent-core.yaml)
| Clé | Rôle |
|---|---|
PMB.page_size | défaut global (notices par page lors de l'amass), surchargeable par établissement (pmb_page_size) |
db-schema: pmb | schéma PostgreSQL du connecteur |
export.group_manager / export.group_manager_lend_manual | noms des groupes de gestionnaires côté annuaire |
infraMail | expéditeur de l'email de demande d'informations |
Aucune autre clé (host/source_id/credentials) n'est attendue ici : elle proviendrait d'une
configuration globale, remplacée par la configuration par établissement.
Déroulé d'un relevé (amass)
- Un cron (
amass-cron, défaut0 1 * * * ? *) déclencheAmassTaskcôté médiacentre, qui appelle.amass()sur chaque source configurée. PMB.amass()envoie un message sur le bus (fr.openent.pmb.controllers.PmbController|amass).PmbController.amass()récupère les établissements où le module est déployé et dont l'exportPMBest activé, résout les regroupementsid_principal, construit la configuration de connexion de chacun, puis déploie unAmassWorker(verticle worker).AmassWorkerenregistre lePMBServerde chaque établissement (PMBServer.register), lance une recherche plein texte (pmbesSearch_simpleSearch) puis pagine les résultats (pmbesSearch_fetchSearchRecords).- Chaque notice est convertie depuis l'UNIMARC (
BibliographicRecord,UniMarcField) puis envoyée au médiacentre (fr.openent.mediacentre.source.PMB|records) pour indexation.
Liens OPAC posés sur les notices
BibliographicRecord.toJSON() porte deux liens, calculés sur l'OPAC et non sur pmb_host :
<host>/index.php est le back-office de PMB, réservé aux gestionnaires du CDI — un élève qui
suivait ce lien tombait sur l'authentification bibliothécaire.
| Champ | Construction |
|---|---|
link | <opac>/index.php?lvl=notice_display&id=<id> — consultation de la notice |
reservation_link | <opac>/do_resa.php?lvl=resa&id_notice=<id> — exactement le lien que l'OPAC pose lui-même (opac_css/classes/record_datas.class.php, get_resas_datas) |
L'OPAC est déduit de endpoint, qui porte le chemin d'installation de façon fiable
(/pmb/ws/connector_out.php → racine /pmb → OPAC <host>/pmb/opac_css), le dispatcher des
connecteurs sortants étant toujours à <racine PMB>/ws/connector_out.php. La colonne
pmb_opac_url (migration 04-add-pmb-opac-url.sql) couvre les installations qui exposent l'OPAC
ailleurs ; PMBServer trace l'URL retenue au moissonnage.
Le lien de réservation est posé sans condition : disponibilité d'un exemplaire, plafond de
réservations et paramètre opac.resa sont des états que seul PMB connaît et qui changent entre
deux moissonnages. C'est PMB qui refuse, avec son message. Côté médiacentre, le champ est porté
par source/PMB.java dans l'index et rendu par SearchCard.tsx (mediacentre.card.reserve).
Connexion unique (CAS)
PmbRegisteredService (entcore, cas/src/main/java/org/entcore/cas/services/) résout les UAI de
l'utilisateur puis interroge le bus
(fr.openent.pmb.controllers.PmbController|getPrincipalUAIs) pour les remplacer par les UAI
principaux. Un lecteur d'un établissement rattaché est donc présenté à PMB sous l'UAI du
catalogue partagé, celui qui porte réellement ses comptes emprunteurs. Le ticket CAS suffit
ensuite pour la consultation comme pour la réservation, y compris depuis le lien
do_resa.php.
Diagnostic
| Symptôme | Cause probable | Vérification |
|---|---|---|
Stopping PMB amass worker: empty structures | aucun établissement avec 'PMB' IN s.exports (Neo4j) | activer l'export PMB sur la structure |
Établissement ignoré, log Configuration PMB incomplète pour l'établissement … | colonnes pmb_* incomplètes en base | PUT /pmb/schools/:schoolId/connection |
No content to map due to end-of-input sur la réponse PMB | webservice PMB inaccessible, mauvais source_id/identifiants, ou réponse vide | rejouer l'appel en direct (curl -u <user>:<pwd> -X POST "<host><endpoint>?source_id=<id>" -d '{"method":"pmbesSearch_simpleSearch",...}') |
No result for structure <uai> (empty PMB catalog?) | recherche sans résultat ("result": null) — catalogue vide ou terme sans correspondance | attendu si le catalogue PMB de l'établissement ne contient aucune notice |
| Notices présentes mais sans bouton « Réserver au CDI » | notices issues d'un moissonnage antérieur à pmb_opac_url / au champ reservation_link | relancer un moissonnage |
| Lien de notice qui aboutit à une authentification bibliothécaire | OPAC mal déduit (installation atypique) | renseigner pmb_opac_url |
Logs INFO de ce module invisibles | logger racine en WARN sans override pour fr.openent (tools/logback-ent.xml) | ajouter un logger fr.openent en INFO |
Couverture de tests
Le moissonnage et le webservice PMB lui-même n'ont pas de test e2e (pas de vrai serveur PMB en
environnement de test) ; l'écran d'administration du dashboard, lui, est couvert par
apps/dashboard-e2e/src/modules/03_admin/13_connexion_pmb_cdi.spec.ts — 3 scénarios, non
destructifs (lecture/capture, aucune connexion n'est réellement enregistrée) :
- accès à la page (pas de 5xx) ;
- vue super-administrateur — tableau des établissements + ouverture du formulaire de connexion ;
- vue administrateur local — connexion de son établissement, ou message si pas encore ajouté.
Le même fichier détecte le rôle via l'UI rendue et s'exécute pour tous les profils Playwright
(superadmin, chef…), skippant proprement les scénarios non pertinents pour un profil donné.
Conformité
Évaluation au référentiel Open ENT NG (module pmb-connector).
| Maillon de la chaîne qualité | Référence |
|---|---|
| 🎯 Fonctionnalités attendues | fiche fonctionnelle |
| 🧪 Tests réalisés | écran d'administration : couverture e2e ; moissonnage PMB : aucun test e2e à ce jour |
| ✅ Tests de conformité | tableau de conformité |