fix: redirect loop on stale cookie, login broken for 64-char keys, stale docs

- /dashboard now validates key before redirecting to /home — bad/old keys
  clear the cookie and show login instead of looping
- Login form: remove old 4-group auto-formatter, fix maxlength 19→64,
  fix min length validation 19→10, update placeholder
- New key display: break-all so 64-char hex wraps properly
- docs.html: update example key format and description
This commit is contained in:
M1 2026-03-17 06:22:16 +04:00
parent 6bdd76b4f0
commit b8ac4e7b1f
3 changed files with 16 additions and 17 deletions

View File

@ -103,9 +103,9 @@
<p>All API requests require an account key passed as a Bearer token:</p> <p>All API requests require an account key passed as a Bearer token:</p>
<div class="cb"> <div class="cb">
<div class="cb-header"><span class="cb-lang">http</span></div> <div class="cb-header"><span class="cb-lang">http</span></div>
<pre>Authorization: Bearer XXXX-XXXX-XXXX-XXXX</pre> <pre>Authorization: Bearer &lt;your-64-char-hex-key&gt;</pre>
</div> </div>
<p>Create an account at <a href="/dashboard">/dashboard</a> or via the API. Keys are 16-character hex strings formatted as four groups.</p> <p>Create an account at <a href="/dashboard">/dashboard</a> or via the API. Keys are 64-character hex strings (256-bit). Shown once at registration &#8212; store them securely.</p>
</div> </div>
<!-- Account --> <!-- Account -->
@ -121,7 +121,7 @@
</div> </div>
<div class="cb"> <div class="cb">
<div class="cb-header"><span class="cb-lang">json — response</span></div> <div class="cb-header"><span class="cb-lang">json — response</span></div>
<pre>{ <span class="k">"key"</span>: <span class="s">"B8AE-9621-A963-F652"</span>, <span class="k">"email_registered"</span>: <span class="n">true</span> }</pre> <pre>{ <span class="k">"key"</span>: <span class="s">"5bf5311b56d09254c8a1f0e3..."</span>, <span class="k">"email_registered"</span>: <span class="n">true</span> }</pre>
</div> </div>
<h3>Update Email</h3> <h3>Update Email</h3>

View File

@ -21,9 +21,9 @@
<form id="login-form" action="/account/login" method="POST"> <form id="login-form" action="/account/login" method="POST">
<input type="hidden" name="_form" value="1"> <input type="hidden" name="_form" value="1">
<label class="block text-xs text-gray-500 uppercase tracking-wider mb-2">Account Key</label> <label class="block text-xs text-gray-500 uppercase tracking-wider mb-2">Account Key</label>
<input id="key-input" name="key" type="text" placeholder="XXXX-XXXX-XXXX-XXXX" autocomplete="off" spellcheck="false" <input id="key-input" name="key" type="text" placeholder="Paste your account key" autocomplete="off" spellcheck="false"
class="w-full bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 text-gray-100 placeholder-gray-600 focus:outline-none focus:border-blue-500 tracking-widest text-center text-lg font-mono" class="w-full bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 text-gray-100 placeholder-gray-600 focus:outline-none focus:border-blue-500 text-sm font-mono"
maxlength="19"> maxlength="64">
<button type="submit" <button type="submit"
class="w-full mt-3 bg-blue-600 hover:bg-blue-500 text-white font-medium py-3 rounded-lg transition-colors"> class="w-full mt-3 bg-blue-600 hover:bg-blue-500 text-white font-medium py-3 rounded-lg transition-colors">
Sign In Sign In
@ -53,7 +53,7 @@
<label class="block text-xs text-gray-500 uppercase tracking-wider mb-2">Your Account Key</label> <label class="block text-xs text-gray-500 uppercase tracking-wider mb-2">Your Account Key</label>
<div class="flex gap-2 mb-5"> <div class="flex gap-2 mb-5">
<div id="new-key-display" <div id="new-key-display"
class="flex-1 bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 text-blue-400 tracking-widest text-center text-lg font-bold font-mono select-all"></div> class="flex-1 bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 text-blue-400 text-sm font-mono select-all break-all"></div>
<button id="copy-key-btn" <button id="copy-key-btn"
class="px-4 bg-gray-800 hover:bg-gray-700 border border-gray-700 rounded-lg text-gray-400 hover:text-white transition-colors text-sm"> class="px-4 bg-gray-800 hover:bg-gray-700 border border-gray-700 rounded-lg text-gray-400 hover:text-white transition-colors text-sm">
Copy Copy
@ -84,20 +84,13 @@
const API = ''; const API = '';
let newKey = null; let newKey = null;
// Auto-format key input
const keyInput = document.getElementById('key-input'); const keyInput = document.getElementById('key-input');
if (keyInput) {
keyInput.addEventListener('input', e => {
let v = e.target.value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase().slice(0, 16);
e.target.value = (v.match(/.{1,4}/g) || []).join('-');
});
}
// JS-enhanced login (overrides form POST for better UX) // JS-enhanced login (overrides form POST for better UX)
document.getElementById('login-form').addEventListener('submit', async (e) => { document.getElementById('login-form').addEventListener('submit', async (e) => {
e.preventDefault(); e.preventDefault();
const key = keyInput.value.trim(); const key = keyInput.value.trim();
if (key.length < 19) return showError('Enter a valid account key'); if (key.length < 10) return showError('Enter a valid account key');
try { try {
const res = await fetch('/account/login', { const res = await fetch('/account/login', {
method: 'POST', method: 'POST',

View File

@ -80,8 +80,14 @@ export const dashboard = new Elysia()
.get("/dashboard/query-builder.js", () => Bun.file(`${dashDir}/query-builder.js`)) .get("/dashboard/query-builder.js", () => Bun.file(`${dashDir}/query-builder.js`))
// Login page // Login page
.get("/dashboard", ({ cookie }) => { .get("/dashboard", async ({ cookie }) => {
if (cookie?.pingql_key?.value) return redirect("/dashboard/home"); const key = cookie?.pingql_key?.value;
if (key) {
const resolved = await resolveKey(key);
if (resolved) return redirect("/dashboard/home");
// Invalid/stale key — clear it and show login
cookie.pingql_key?.remove();
}
return Bun.file(`${dashDir}/index.html`); return Bun.file(`${dashDir}/index.html`);
}) })