- styles/forge-custom.scss : .content-wide (déjà utilisée par game_dashboard.html/index.html) passe de 1080px à 1600px, pleine largeur pour les écrans de gestion (§5) — la largeur du bloc <main> par défaut (760px, hérité par les pages d'auth/profil qui ne posent pas cette classe) reste inchangée, ces pages veulent justement rester étroites et centrées. - Pages d'authentification (login/register/2FA×2/mot de passe oublié/ réinitialisation) : le style="max-width:NNNpx" répété sur chacune est remplacé par les classes partagées .authScreen/.authCard(-wide), titre H1 en dégradé signature .forge-gradient-title — seul endroit du site, avec le logo, autorisé à l'utiliser (§3/§5). Grille de fond fine sur body.authBody, elle aussi réservée aux zones hero et absente des écrans de travail. - Logique JS inchangée (jauge de mot de passe dans register.html/ reset_password.html) — uniquement des classes/structure autour. 197 tests toujours verts, JS des pages modifiées revérifié (node --check). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
81 lines
3.0 KiB
HTML
81 lines
3.0 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Nouveau mot de passe — Forge Engine{% endblock %}
|
|
{% block body_class %}authBody{% endblock %}
|
|
{% block content %}
|
|
<section class="section authScreen">
|
|
<div class="container authCard authCard-wide">
|
|
<h1 class="title authTitle forge-gradient-title">Choisir un nouveau mot de passe</h1>
|
|
|
|
{% if invalid %}
|
|
<div class="notification is-danger">Ce lien de réinitialisation est invalide ou a expiré.</div>
|
|
<p class="hint mt-3"><a href="{{ url_for('forgot_password') }}">Redemander un lien</a></p>
|
|
{% else %}
|
|
{% if error %}
|
|
<div class="notification is-danger">{{ error }}</div>
|
|
{% endif %}
|
|
|
|
<form method="post" autocomplete="off">
|
|
<div class="field">
|
|
<label class="label">Nouveau mot de passe</label>
|
|
<div class="control"><input class="input" type="password" id="password" name="password" required autocomplete="new-password"></div>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<div class="passwordStrengthBar"><div class="passwordStrengthFill" id="pwFill"></div></div>
|
|
<ul class="passwordChecklist" id="pwChecklist">
|
|
<li data-check="longueur">Au moins 8 caractères</li>
|
|
<li data-check="majuscule">Une majuscule</li>
|
|
<li data-check="minuscule">Une minuscule</li>
|
|
<li data-check="chiffre">Un chiffre</li>
|
|
<li data-check="special">Un caractère spécial (ex. ! ? # -)</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label class="label">Confirmer le mot de passe</label>
|
|
<div class="control"><input class="input" type="password" name="password_confirm" required autocomplete="new-password"></div>
|
|
</div>
|
|
|
|
<div class="field mt-4">
|
|
<button type="submit" class="button primary is-fullwidth">Réinitialiser mon mot de passe</button>
|
|
</div>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
</section>
|
|
|
|
{% if not invalid %}
|
|
<script>
|
|
var MIN_SCORE_REQUIRED = {{ min_score_required }};
|
|
var PW_CHECKS = {
|
|
longueur: function (p) { return p.length >= 8; },
|
|
majuscule: function (p) { return /[A-Z]/.test(p); },
|
|
minuscule: function (p) { return /[a-z]/.test(p); },
|
|
chiffre: function (p) { return /\d/.test(p); },
|
|
special: function (p) { return /[^A-Za-z0-9]/.test(p); },
|
|
};
|
|
(function () {
|
|
var input = document.getElementById('password');
|
|
var fill = document.getElementById('pwFill');
|
|
var items = document.querySelectorAll('#pwChecklist li');
|
|
if (!input) return;
|
|
function update() {
|
|
var value = input.value || '';
|
|
var score = 0;
|
|
items.forEach(function (li) {
|
|
var ok = PW_CHECKS[li.dataset.check](value);
|
|
li.classList.toggle('ok', ok);
|
|
if (ok) score++;
|
|
});
|
|
var pct = (score / items.length) * 100;
|
|
fill.style.width = pct + '%';
|
|
fill.className = 'passwordStrengthFill' +
|
|
(score >= items.length ? ' strong' : score >= MIN_SCORE_REQUIRED ? ' good' : score >= 2 ? ' medium' : ' weak');
|
|
}
|
|
input.addEventListener('input', update);
|
|
update();
|
|
})();
|
|
</script>
|
|
{% endif %}
|
|
{% endblock %}
|