add rate limiting and 2fa hardening
This commit is contained in:
@@ -486,6 +486,7 @@ async function loadProfile() {
|
||||
|
||||
// ---- ACCOUNT SETTINGS ----
|
||||
let latestRecoveryCodes = [];
|
||||
let pendingTwoFactorSetupToken = "";
|
||||
|
||||
function showAccountSettingsMessage(message, type = 'success') {
|
||||
const box = document.getElementById('account-settings-message');
|
||||
@@ -518,6 +519,18 @@ function setTwoFactorPanels(enabled) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateRecoveryCodeWarning(remaining, warning) {
|
||||
const warningBox = document.getElementById('recovery-codes-warning');
|
||||
if (!warningBox) return;
|
||||
|
||||
if (warning) {
|
||||
warningBox.textContent = `You only have ${remaining} recovery code${remaining === 1 ? '' : 's'} left. Generate and download new codes soon.`;
|
||||
warningBox.style.display = 'block';
|
||||
} else {
|
||||
warningBox.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function renderRecoveryCodes(codes) {
|
||||
latestRecoveryCodes = codes || [];
|
||||
const panel = document.getElementById('recovery-codes-panel');
|
||||
@@ -545,6 +558,7 @@ async function loadAccountSettings() {
|
||||
if (usernameInput) usernameInput.value = data.username || '';
|
||||
if (avatarPreview && data.username) avatarPreview.innerText = data.username[0].toLocaleUpperCase();
|
||||
if (remaining) remaining.innerText = data.recovery_codes_remaining || 0;
|
||||
updateRecoveryCodeWarning(data.recovery_codes_remaining || 0, !!data.recovery_codes_warning);
|
||||
|
||||
setTwoFactorPanels(!!data.two_factor_enabled);
|
||||
renderRecoveryCodes([]);
|
||||
@@ -614,6 +628,8 @@ async function startTwoFactorSetup() {
|
||||
const secret = document.getElementById('two-factor-secret');
|
||||
const otpauth = document.getElementById('two-factor-otpauth');
|
||||
|
||||
pendingTwoFactorSetupToken = data.setup_token || '';
|
||||
|
||||
if (panel) panel.style.display = 'block';
|
||||
if (qr) {
|
||||
qr.src = data.qr_code;
|
||||
@@ -636,16 +652,24 @@ async function enableTwoFactor(event) {
|
||||
|
||||
try {
|
||||
const data = await apiRequest('/api/2fa/enable', 'POST', {
|
||||
code: document.getElementById('two-factor-enable-code').value.trim()
|
||||
code: document.getElementById('two-factor-enable-code').value.trim(),
|
||||
setup_token: pendingTwoFactorSetupToken
|
||||
});
|
||||
|
||||
document.getElementById('two-factor-enable-form').reset();
|
||||
document.getElementById('two-factor-setup-panel').style.display = 'none';
|
||||
pendingTwoFactorSetupToken = '';
|
||||
setTwoFactorPanels(true);
|
||||
renderRecoveryCodes(data.recovery_codes || []);
|
||||
|
||||
const remaining = document.getElementById('recovery-codes-remaining');
|
||||
if (remaining) remaining.innerText = (data.recovery_codes || []).length;
|
||||
if (remaining) remaining.innerText = data.recovery_codes_remaining || (data.recovery_codes || []).length;
|
||||
updateRecoveryCodeWarning(data.recovery_codes_remaining || (data.recovery_codes || []).length, !!data.recovery_codes_warning);
|
||||
|
||||
if (data.access_token && data.refresh_token) {
|
||||
localStorage.setItem('access_token', data.access_token);
|
||||
localStorage.setItem('refresh_token', data.refresh_token);
|
||||
}
|
||||
|
||||
showAccountSettingsMessage('2FA enabled. Download your recovery codes now.');
|
||||
loadProfile();
|
||||
@@ -670,6 +694,7 @@ async function disableTwoFactor(event) {
|
||||
localStorage.removeItem('refresh_token');
|
||||
setTwoFactorPanels(false);
|
||||
renderRecoveryCodes([]);
|
||||
updateRecoveryCodeWarning(0, false);
|
||||
showAccountSettingsMessage('2FA disabled. Redirecting to login because sessions were revoked.');
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login';
|
||||
@@ -695,6 +720,7 @@ async function regenerateRecoveryCodes(event) {
|
||||
|
||||
const remaining = document.getElementById('recovery-codes-remaining');
|
||||
if (remaining) remaining.innerText = (data.recovery_codes || []).length;
|
||||
updateRecoveryCodeWarning((data.recovery_codes || []).length, false);
|
||||
|
||||
showAccountSettingsMessage('New recovery codes generated. Download them now.');
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user