3m-portal/auth.js
Vadym Samoilenko 53a85c788d Add full auth system: SQLite sessions, email invites, admin console
- Real email/password login backed by SQLite (better-sqlite3)
- HttpOnly cookie sessions with 8h sliding TTL
- Admin role: invite users via Mailgun magic-link, manage roles/status
- Per-user One2Edit username mapping for job filtering
- Self-service forgot-password / reset-password via email
- Admin console (admin.html) with user table, invite modal, row actions
- New pages: change-password, forgot-password, reset-password, accept-invite
- Gated /api proxy: requires valid session, anti-hijack sessionId check
- Bootstrap initial admins from INITIAL_ADMINS env var on first boot
- Remove Oliver login button, SSO buttons, and legacy api.js/login.js
- deploy.sh: add build-essential (for native module), npm install, data dir

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 11:26:40 +01:00

47 lines
1.7 KiB
JavaScript

async function handleLogin() {
const email = document.getElementById('email').value.trim();
const password = document.getElementById('password').value;
const errorMessage = document.getElementById('errorMessage');
const loginButton = document.getElementById('loginButton');
const buttonText = document.getElementById('loginButtonText');
const spinner = document.getElementById('loginSpinner');
errorMessage.style.display = 'none';
if (!email || !password) {
errorMessage.textContent = 'Please enter your email and password.';
errorMessage.style.display = 'block';
return;
}
loginButton.disabled = true;
buttonText.textContent = 'Signing in...';
spinner.style.display = 'inline-block';
try {
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
const data = await res.json();
if (!res.ok) {
throw new Error(data.error || 'Login failed');
}
if (data.mustChangePassword) {
window.location.href = 'change-password.html';
} else {
window.location.href = 'dashboard.html';
}
} catch (error) {
errorMessage.textContent = error.message || 'An error occurred. Please try again.';
errorMessage.style.display = 'block';
loginButton.disabled = false;
buttonText.textContent = 'Sign In';
spinner.style.display = 'none';
}
}
document.getElementById('loginButton').addEventListener('click', handleLogin);