- Logged-in users can change their own password from a "Password" link in the top-right pill (dialog -> POST /api/auth/password, which requires the current password). - Login page gains a "Forgot password?" link explaining that resets are admin-assisted (admins reset from the console). No SMTP, so no email reset flow yet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
2.5 KiB
JavaScript
69 lines
2.5 KiB
JavaScript
/* Login page logic for the Work Package Suite.
|
|
Posts credentials to /api/auth/login. On success the server sets an HttpOnly
|
|
session cookie (not readable here — that's the point) and we redirect to the
|
|
page the user was trying to reach, or the home page. */
|
|
(function () {
|
|
'use strict';
|
|
|
|
var form = document.getElementById('login-form');
|
|
var errorBox = document.getElementById('error');
|
|
var submitBtn = document.getElementById('submit');
|
|
|
|
// Where to go after signing in: the ?next= param if it's a safe same-site
|
|
// path, otherwise the home page. (Reject absolute/scheme URLs to avoid an
|
|
// open-redirect.)
|
|
function nextTarget() {
|
|
try {
|
|
var next = new URLSearchParams(location.search).get('next') || '';
|
|
if (next && next.charAt(0) === '/' && next.charAt(1) !== '/') return next;
|
|
} catch (e) {}
|
|
return 'index.html';
|
|
}
|
|
|
|
function showError(msg) {
|
|
errorBox.textContent = msg;
|
|
errorBox.classList.add('show');
|
|
}
|
|
|
|
var forgot = document.getElementById('forgot-link');
|
|
if (forgot) {
|
|
forgot.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
var m = document.getElementById('forgot-msg');
|
|
if (m) m.style.display = 'block';
|
|
});
|
|
}
|
|
|
|
form.addEventListener('submit', function (e) {
|
|
e.preventDefault();
|
|
errorBox.classList.remove('show');
|
|
var username = document.getElementById('username').value.trim();
|
|
var password = document.getElementById('password').value;
|
|
if (!username || !password) { showError('Enter your username and password.'); return; }
|
|
|
|
submitBtn.disabled = true;
|
|
submitBtn.textContent = 'Signing in…';
|
|
|
|
fetch('/api/auth/login', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ username: username, password: password })
|
|
})
|
|
.then(function (r) {
|
|
if (r.ok) { location.replace(nextTarget()); return null; }
|
|
return r.json().catch(function () { return null; }).then(function (j) {
|
|
if (r.status === 401) showError('Invalid username or password.');
|
|
else if (r.status === 403) showError((j && j.detail) || 'Your account is disabled.');
|
|
else showError((j && j.detail) || ('Sign-in failed (HTTP ' + r.status + ').'));
|
|
submitBtn.disabled = false;
|
|
submitBtn.textContent = 'Sign in';
|
|
});
|
|
})
|
|
.catch(function () {
|
|
showError('Could not reach the server. Check your connection and try again.');
|
|
submitBtn.disabled = false;
|
|
submitBtn.textContent = 'Sign in';
|
|
});
|
|
});
|
|
})();
|