Restore to commit 74e578279624c6045ca440a3459ebfa1f8d54191
This commit is contained in:
88
chat/public/admin-login.js
Normal file
88
chat/public/admin-login.js
Normal file
@@ -0,0 +1,88 @@
|
||||
(() => {
|
||||
const form = document.getElementById('admin-login-form');
|
||||
const statusEl = document.getElementById('admin-login-status');
|
||||
const userEl = document.getElementById('admin-username');
|
||||
const passEl = document.getElementById('admin-password');
|
||||
|
||||
function setStatus(msg, isError = false) {
|
||||
if (!statusEl) return;
|
||||
statusEl.textContent = msg || '';
|
||||
statusEl.style.color = isError ? 'var(--danger)' : 'inherit';
|
||||
}
|
||||
|
||||
async function ensureSession() {
|
||||
try {
|
||||
// Include credentials explicitly so cookies are reliably sent/received across browsers
|
||||
const res = await fetch('/api/admin/me', { credentials: 'same-origin' });
|
||||
if (!res.ok) return;
|
||||
const data = await res.json();
|
||||
if (data && data.ok) {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const next = params.get('next');
|
||||
|
||||
// Only redirect if we have a next parameter and we're not already on that page
|
||||
if (next && typeof next === 'string' && next.startsWith('/') && window.location.pathname !== next) {
|
||||
window.location.href = next;
|
||||
} else if (!next) {
|
||||
// If no next parameter, go to admin dashboard
|
||||
window.location.href = '/admin';
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
setStatus('Signing in...');
|
||||
try {
|
||||
const payload = {
|
||||
username: userEl.value.trim(),
|
||||
password: passEl.value.trim(),
|
||||
};
|
||||
// Ensure credentials are included so Set-Cookie is accepted and future requests send cookies
|
||||
const res = await fetch('/api/admin/login', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok) throw new Error(data.error || 'Login failed');
|
||||
setStatus('Success, redirecting...');
|
||||
|
||||
// Respect optional `next` parameter (e.g. /admin/login?next=/test-checkout)
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const next = params.get('next');
|
||||
|
||||
// Poll /api/admin/me to ensure the session cookie is active before redirecting.
|
||||
// This avoids a race where the next page immediately checks /api/admin/me and gets 401.
|
||||
let sessionActive = false;
|
||||
for (let i = 0; i < 6; i++) {
|
||||
try {
|
||||
const meRes = await fetch('/api/admin/me', { credentials: 'same-origin' });
|
||||
if (meRes.ok) {
|
||||
sessionActive = true;
|
||||
break;
|
||||
}
|
||||
} catch (_) {
|
||||
// ignore
|
||||
}
|
||||
// small backoff
|
||||
await new Promise((r) => setTimeout(r, 150 * (i + 1)));
|
||||
}
|
||||
|
||||
// Redirect regardless (session will usually be active) but polling reduces redirect loops
|
||||
if (next && typeof next === 'string' && next.startsWith('/')) {
|
||||
window.location.href = next;
|
||||
} else {
|
||||
window.location.href = '/admin';
|
||||
}
|
||||
} catch (err) {
|
||||
setStatus(err.message, true);
|
||||
}
|
||||
});
|
||||
|
||||
ensureSession();
|
||||
})();
|
||||
Reference in New Issue
Block a user