hbox-docs/docs/cuenta.html

185 lines
7.2 KiB
HTML

<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mi cuenta — HBOX</title>
<script src="js/tema.js"></script>
<link rel="stylesheet" href="formularios/acta.css">
<style>
.campo{margin:12px 0}
.quien{background:var(--hg-plano);border:1px solid var(--linea);border-radius:10px;
padding:12px 14px;margin-bottom:14px;font-size:15px}
.quien b{font-size:17px}
.fuerza{height:6px;border-radius:3px;background:var(--linea);margin-top:6px;overflow:hidden}
.fuerza i{display:block;height:100%;width:0;transition:width .2s,background .2s}
.pista{font-size:12.5px;color:var(--tinta2);margin-top:5px}
.admin{border:1px solid var(--linea)}
button.enviar{width:100%;margin-top:6px}
.ver{font-size:13px;color:var(--naranja);cursor:pointer;user-select:none;margin-top:6px;display:inline-block}
</style>
</head>
<body>
<div class="wrap">
<header class="top">
<h1>Mi cuenta</h1>
<p>Aquí cambias tu contraseña de acceso al sitio.</p>
</header>
<div style="display:flex;justify-content:space-between;margin:2px 0 10px">
<a class="volver" href="./">← Documentación</a>
<a class="volver" href="salir.html">Cerrar sesión</a>
</div>
<div class="quien" id="quien">Consultando quién eres…</div>
<section class="paso">
<h2>Cambiar mi contraseña</h2>
<p class="sub">Elige algo que recuerdes sin apuntarlo. Mínimo 8 caracteres.</p>
<div class="campo">
<label for="actual">Contraseña actual</label>
<input type="password" id="actual" autocomplete="current-password">
</div>
<div class="campo">
<label for="nueva">Contraseña nueva</label>
<input type="password" id="nueva" autocomplete="new-password">
<div class="fuerza"><i id="barra"></i></div>
<div class="pista" id="pista">Mientras más larga, mejor; una frase con espacios sirve.</div>
</div>
<div class="campo">
<label for="confirma">Repite la contraseña nueva</label>
<input type="password" id="confirma" autocomplete="new-password">
<span class="ver" id="ver">Ver lo que escribí</span>
</div>
<button class="enviar" id="guardar">Guardar contraseña nueva</button>
<div class="msg" id="msg"></div>
</section>
<section class="paso admin" id="bloqueAdmin" style="display:none">
<h2>Restablecer la contraseña de alguien más</h2>
<p class="sub">Solo administración. Úsalo cuando un técnico olvidó la suya: no necesitas la anterior.</p>
<div class="campo">
<label for="quienReset">Usuario</label>
<select id="quienReset"></select>
</div>
<div class="campo">
<label for="nuevaR">Contraseña nueva para esa persona</label>
<input type="text" id="nuevaR" autocomplete="off" placeholder="se la pasas en persona o por mensaje directo">
</div>
<button class="enviar" id="resetear">Restablecer</button>
<div class="msg" id="msgR"></div>
</section>
<section class="paso">
<h2>Si olvidaste tu contraseña</h2>
<p class="sub" style="margin:0">
No hay recuperación por correo: pídele a Leo que te la restablezca desde esta misma página.
Si todavía no tienes acceso, pídeselo a Leo (Administración → <a href="tableros/equipo/">Usuarios y equipo</a>).
</p>
</section>
</div>
<script>
const $ = id => document.getElementById(id);
let yo = '';
function aviso(el, texto, bien) {
el.className = 'msg ' + (bien ? 'ok' : 'err');
el.innerHTML = texto;
el.scrollIntoView({ block: 'nearest' });
}
// --- quién soy + si soy admin ---
(async () => {
try {
const j = await (await fetch('/api/whoami')).json();
yo = j.user || '';
$('quien').innerHTML = yo
? 'Entraste como <b>' + yo + '</b>' + (j.admin ? ' · administrador' : '')
: 'No puedo identificarte. Vuelve a entrar al sitio y recarga esta página.';
if (j.admin) {
$('bloqueAdmin').style.display = '';
try {
const u = await (await fetch('/api/usuarios')).json();
(u.usuarios || []).forEach(n => {
const o = document.createElement('option'); o.value = n; o.textContent = n;
if (n === yo) o.textContent = n + ' (tú)';
$('quienReset').append(o);
});
} catch (e) {}
}
} catch (e) {
$('quien').textContent = 'No pude contactar al servidor.';
}
})();
// --- medidor simple: la longitud es lo que más cuenta ---
$('nueva').addEventListener('input', () => {
const v = $('nueva').value;
let p = Math.min(100, v.length * 8);
if (/[^a-zA-Z0-9]/.test(v)) p += 10;
if (/[0-9]/.test(v) && /[a-zA-Z]/.test(v)) p += 10;
p = Math.min(100, p);
const b = $('barra');
b.style.width = p + '%';
b.style.background = p < 40 ? 'var(--falla)' : p < 70 ? 'var(--aviso)' : 'var(--ok)';
$('pista').textContent = v.length < 8
? 'Te faltan ' + (8 - v.length) + ' caracteres.'
: p < 70 ? 'Aceptable. Si la alargas un poco queda mucho mejor.'
: 'Buena contraseña.';
});
$('ver').addEventListener('click', () => {
const t = $('nueva').type === 'password' ? 'text' : 'password';
$('nueva').type = t; $('confirma').type = t; $('actual').type = t;
$('ver').textContent = t === 'text' ? 'Ocultar' : 'Ver lo que escribí';
});
const AVISO_SESION =
'<br><br>Tu navegador todavía recuerda la contraseña anterior, así que puedes seguir '
+ 'navegando sin problema. <b>La nueva la vas a necesitar la próxima vez que entres.</b> '
+ 'Si quieres probarla ahora, usa <a href="salir.html">Cerrar sesión</a>.';
$('guardar').addEventListener('click', async () => {
const b = $('guardar');
b.disabled = true; b.textContent = 'Guardando…';
try {
const r = await fetch('/api/password', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ actual: $('actual').value, nueva: $('nueva').value, confirma: $('confirma').value })
});
const j = await r.json();
if (!r.ok || !j.ok) throw new Error(j.error || ('HTTP ' + r.status));
aviso($('msg'), '<b>Contraseña cambiada.</b>' + AVISO_SESION, true);
$('actual').value = $('nueva').value = $('confirma').value = '';
$('barra').style.width = '0';
} catch (e) {
aviso($('msg'), e.message, false);
}
b.disabled = false; b.textContent = 'Guardar contraseña nueva';
});
$('resetear').addEventListener('click', async () => {
const u = $('quienReset').value, nueva = $('nuevaR').value;
if (!u) return aviso($('msgR'), 'Elige a quién le vas a restablecer la contraseña.', false);
if (!confirm('¿Restablecer la contraseña de ' + u + '?')) return;
const b = $('resetear'); b.disabled = true; b.textContent = 'Restableciendo…';
try {
const r = await fetch('/api/password', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ usuario: u, nueva: nueva, confirma: nueva })
});
const j = await r.json();
if (!r.ok || !j.ok) throw new Error(j.error || ('HTTP ' + r.status));
aviso($('msgR'), 'Contraseña de <b>' + u + '</b> restablecida. Pásasela en persona o por '
+ 'mensaje directo, y dile que la cambie aquí mismo cuando entre.'
+ (u === yo ? AVISO_SESION : ''), true);
$('nuevaR').value = '';
} catch (e) {
aviso($('msgR'), e.message, false);
}
b.disabled = false; b.textContent = 'Restablecer';
});
</script>
</body>
</html>