Version initiale — carte des établissements scolaires
Carte Leaflet (annuaire Éducation nationale) + API PHP/MySQL : fiche établissement (effectifs, IPS, population INSEE, DPE ADEME), GED documents/photos, commentaires par groupe, gestion utilisateurs et politique de mots de passe. Imports opendata (effectifs, IPS, population, DPE, IRIS). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mon mot de passe</title>
|
||||
<link rel="stylesheet" href="style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="auth-wrap">
|
||||
<div class="auth-card">
|
||||
<h1>Mon mot de passe</h1>
|
||||
<div id="forced-banner" class="forced-banner" hidden>
|
||||
🔒 Pour des raisons de sécurité, vous devez choisir un nouveau mot de passe avant de continuer.
|
||||
</div>
|
||||
<p id="who" class="hint"></p>
|
||||
|
||||
<div id="not-auth" hidden>
|
||||
<p class="propose-msg err">Vous n'êtes pas connecté.</p>
|
||||
<p class="auth-foot"><a href="admin.html">Se connecter</a></p>
|
||||
</div>
|
||||
|
||||
<form id="change-form" autocomplete="off" hidden>
|
||||
<div class="field">
|
||||
<label for="cur">Mot de passe actuel</label>
|
||||
<input id="cur" type="password" required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="pw">Nouveau mot de passe</label>
|
||||
<input id="pw" type="password" required>
|
||||
<div id="pw-meter" class="pw-meter"></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="pw2">Confirmer</label>
|
||||
<input id="pw2" type="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary">Changer le mot de passe</button>
|
||||
<p id="msg" class="propose-msg"></p>
|
||||
</form>
|
||||
|
||||
<p id="nav-foot" class="auth-foot" hidden><a href="admin.html">← Espace administration</a> · <a href="index.html">Carte</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="pwpolicy.js"></script>
|
||||
<script>
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const forced = new URLSearchParams(location.search).get('forced') === '1';
|
||||
PWPolicy.attach($('pw'), $('pw-meter'));
|
||||
|
||||
(async function boot() {
|
||||
let user = null;
|
||||
try { user = (await (await fetch('api/auth.php?action=me')).json()).user; } catch {}
|
||||
if (!user) { $('not-auth').hidden = false; return; }
|
||||
$('who').textContent = `Connecté : ${user.username}`;
|
||||
$('change-form').hidden = false;
|
||||
if (forced || user.must_change) {
|
||||
$('forced-banner').hidden = false;
|
||||
} else {
|
||||
$('nav-foot').hidden = false;
|
||||
}
|
||||
})();
|
||||
|
||||
$('change-form').addEventListener('submit', async (ev) => {
|
||||
ev.preventDefault();
|
||||
const cur = $('cur').value, pw = $('pw').value, pw2 = $('pw2').value;
|
||||
const r = PWPolicy.check(pw);
|
||||
if (!r.ok) { showErr('Mot de passe trop faible : ' + r.unmet.join(' ; ') + '.'); return; }
|
||||
if (pw !== pw2) { showErr('Les deux mots de passe ne correspondent pas.'); return; }
|
||||
try {
|
||||
const res = await fetch('api/auth.php?action=change_password', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ current: cur, new: pw }),
|
||||
});
|
||||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok) { showErr(data.error || ('HTTP ' + res.status)); return; }
|
||||
$('change-form').reset();
|
||||
$('msg').className = 'propose-msg ok';
|
||||
$('msg').innerHTML = '✅ Mot de passe changé. <a href="admin.html">Continuer</a>.';
|
||||
$('forced-banner').hidden = true;
|
||||
} catch (err) { showErr('Erreur : ' + err.message); }
|
||||
});
|
||||
|
||||
function showErr(t) { $('msg').className = 'propose-msg err'; $('msg').textContent = t; }
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user