v2026.5.16 — Passage au schéma de versionning ANNÉE.MAJEURE.PATCH + faux input date custom (Mardi 24.04.2026)

This commit is contained in:
Quentin Rouiller
2026-04-23 13:03:58 +02:00
parent 763e63d9c6
commit ea5a42c5e1
5 changed files with 291 additions and 26 deletions
+103 -12
View File
@@ -157,19 +157,44 @@ async function fetchXhr2(origin, phpsessid, actionId) {
async function fetchFicheHtml(origin, phpsessid, formLink) {
const url = `${origin}/index.php?${formLink}&PHPSESSID=${encodeURIComponent(phpsessid)}`;
console.log("[bg] fetchFicheHtml →", url.substring(0, 120));
const r = await evFetch(url, origin);
if (!r.ok) {
const err = new Error("HTTP " + r.status);
err.kind = classifyHttpStatus(r.status);
err.status = r.status;
throw err;
// v2026.5.16 : juste après une reconnexion SSO, EasyVista retourne parfois
// une page intermédiaire tronquée (~8 Ko au lieu de ~250 Ko), le temps que
// les cookies SSO/Kerberos se propagent. On fait jusqu'à 3 tentatives avec
// 1.5s entre chaque si on détecte une taille suspecte.
const MAX_RETRIES = 3;
const RETRY_DELAY_MS = 1500;
const MIN_VALID_SIZE = 20000; // < 20 Ko = probablement page intermédiaire
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
const r = await evFetch(url, origin);
if (!r.ok) {
const err = new Error("HTTP " + r.status);
err.kind = classifyHttpStatus(r.status);
err.status = r.status;
throw err;
}
const html = await r.text();
console.log(`[bg] fiche status = ${r.status} | taille = ${html.length}${attempt > 1 ? ` (tentative ${attempt}/${MAX_RETRIES})` : ""}`);
// Si réponse clairement une redirection courte → login expiré, inutile de retry
if (html.length < 500) {
console.warn("[bg] ⚠ fiche très courte, contenu =", JSON.stringify(html));
return html;
}
// Si taille suspecte (< 20 Ko), probable page intermédiaire SSO : retry
if (html.length < MIN_VALID_SIZE && attempt < MAX_RETRIES) {
console.warn(`[bg] ⚠ fiche anormalement petite (${html.length} octets), retry dans ${RETRY_DELAY_MS} ms...`);
await new Promise(res => setTimeout(res, RETRY_DELAY_MS));
continue;
}
// Sinon : on retourne ce qu'on a
return html;
}
const html = await r.text();
console.log("[bg] fiche status =", r.status, "| taille =", html.length);
if (html.length < 500) {
console.warn("[bg] ⚠ fiche très courte, contenu =", JSON.stringify(html));
}
return html;
// Ne devrait pas arriver (la boucle fait return avant)
throw new Error("fetchFicheHtml: max retries reached");
}
// v4.1.7 : API timeline EasyVista. Renvoie le JSON des actions d'une fiche,
@@ -375,6 +400,67 @@ function originForContext(context) {
: "https://itsma.vd.ch";
}
/**
* v2026.5.16 : surveille un onglet ouvert pour détecter si le Windows SSO
* a échoué et rediriger vers la bonne page.
*
* Quand la session portail Canton est expirée, EasyVista redirige vers
* https://portail.etat-de-vaud.ch/iamlogin/?spEntityID=...
* (page de login manuel moche). On préfère rediriger vers
* https://portail.etat-de-vaud.ch/iam/accueil/
* qui déclenche le Windows Kerberos SSO automatique.
*
* @param {number} tabId - ID de l'onglet à surveiller
*/
function watchReconnectTabForIamLogin(tabId) {
let redirected = false;
const timeoutMs = 60000; // surveille max 60s
const listener = (updatedTabId, changeInfo, tab) => {
if (updatedTabId !== tabId) return;
if (redirected) return;
const url = changeInfo.url || (tab && tab.url) || "";
if (!url) return;
// Détecter la page de login manuel
// Patterns : portail.etat-de-vaud.ch/iamlogin/ ou www.portail.vd.ch/iamlogin/
if (/\/iamlogin\//i.test(url) && /portail\./i.test(url)) {
redirected = true;
// Choisir le domaine de redirection :
// - si on voit portail.etat-de-vaud.ch → rester sur interne
// - si on voit www.portail.vd.ch → rester sur externe
let targetUrl;
if (/portail\.etat-de-vaud\.ch/i.test(url)) {
targetUrl = "https://portail.etat-de-vaud.ch/iam/accueil/";
} else {
targetUrl = "https://www.portail.vd.ch/iam/accueil/";
}
console.log(`[bg] watchReconnectTab : iamlogin détecté, redirection vers ${targetUrl}`);
chrome.tabs.update(tabId, { url: targetUrl }).catch(e => {
console.warn("[bg] watchReconnectTab : update failed", e);
});
}
};
chrome.tabs.onUpdated.addListener(listener);
// Stop la surveillance après 60s pour ne pas accumuler des listeners morts
setTimeout(() => {
try {
chrome.tabs.onUpdated.removeListener(listener);
} catch (e) {}
}, timeoutMs);
// Si l'onglet est fermé, stop aussi
const closeListener = (closedTabId) => {
if (closedTabId === tabId) {
try { chrome.tabs.onUpdated.removeListener(listener); } catch (e) {}
try { chrome.tabs.onRemoved.removeListener(closeListener); } catch (e) {}
}
};
chrome.tabs.onRemoved.addListener(closeListener);
}
// ============================================================================
// v4.2 : récupération de l'utilisateur connecté
// ============================================================================
@@ -1098,6 +1184,11 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
url: `${origin}/`, // racine → EV redirige vers SSO si besoin
active: true
});
// v2026.5.16 : surveiller cet onglet — si on tombe sur la page de
// login manuel portail.etat-de-vaud.ch/iamlogin/, rediriger vers
// portail.etat-de-vaud.ch/iam/accueil/ qui déclenche le Windows
// SSO Kerberos automatiquement.
watchReconnectTabForIamLogin(tab.id);
sendResponse({ ok: true, tabId: tab.id, origin });
} catch (err) {
sendResponse({ ok: false, error: err.message || String(err) });