Fix session revocation bug that could log out current device
- Fix: DELETE all other sessions query used empty string fallback when req.sessionId was undefined, causing id != '' to match ALL rows (including current session). Now skips deletion if sessionId unknown. - Fix: Revoke All endpoint returns error if current session not identified - Fix: var confirm shadowing window.confirm in password change handler
This commit is contained in:
parent
4fa2b58d75
commit
adf1365fa2
3 changed files with 9 additions and 6 deletions
|
|
@ -594,13 +594,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var current = document.getElementById('pw-current');
|
var current = document.getElementById('pw-current');
|
||||||
var newPw = document.getElementById('pw-new');
|
var newPw = document.getElementById('pw-new');
|
||||||
var confirm = document.getElementById('pw-confirm');
|
var confirmPw = document.getElementById('pw-confirm');
|
||||||
var status = document.getElementById('pw-change-status');
|
var status = document.getElementById('pw-change-status');
|
||||||
if (!current || !newPw || !confirm) return;
|
if (!current || !newPw || !confirmPw) return;
|
||||||
|
|
||||||
if (!current.value || !newPw.value) { showToast('Fill in all fields', 'error'); return; }
|
if (!current.value || !newPw.value) { showToast('Fill in all fields', 'error'); return; }
|
||||||
if (newPw.value.length < 8) { showToast('New password must be 8+ characters', 'error'); return; }
|
if (newPw.value.length < 8) { showToast('New password must be 8+ characters', 'error'); return; }
|
||||||
if (newPw.value !== confirm.value) { showToast('Passwords do not match', 'error'); return; }
|
if (newPw.value !== confirmPw.value) { showToast('Passwords do not match', 'error'); return; }
|
||||||
|
|
||||||
if (status) { status.textContent = 'Changing...'; status.style.color = 'var(--g500)'; }
|
if (status) { status.textContent = 'Changing...'; status.style.color = 'var(--g500)'; }
|
||||||
|
|
||||||
|
|
@ -614,7 +614,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
showToast(data.message || 'Password changed', 'success');
|
showToast(data.message || 'Password changed', 'success');
|
||||||
if (data.passwordWarning) setTimeout(function() { showToast(data.passwordWarning, 'warning'); }, 1500);
|
if (data.passwordWarning) setTimeout(function() { showToast(data.passwordWarning, 'warning'); }, 1500);
|
||||||
current.value = ''; newPw.value = ''; confirm.value = '';
|
current.value = ''; newPw.value = ''; confirmPw.value = '';
|
||||||
if (status) { status.textContent = ''; }
|
if (status) { status.textContent = ''; }
|
||||||
if (typeof loadSessions === 'function') loadSessions();
|
if (typeof loadSessions === 'function') loadSessions();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -449,7 +449,9 @@ router.post('/change-password', authMiddleware, async (req, res) => {
|
||||||
await db.run('UPDATE users SET password = ? WHERE id = ?', [hash, req.user.id]);
|
await db.run('UPDATE users SET password = ? WHERE id = ?', [hash, req.user.id]);
|
||||||
|
|
||||||
// Destroy all OTHER sessions (keep current one)
|
// Destroy all OTHER sessions (keep current one)
|
||||||
try { await db.run('DELETE FROM user_sessions WHERE user_id = ? AND id != ?', [req.user.id, req.sessionId || '']); } catch (e) { /* best effort */ }
|
if (req.sessionId) {
|
||||||
|
try { await db.run('DELETE FROM user_sessions WHERE user_id = ? AND id != ?', [req.user.id, req.sessionId]); } catch (e) { /* best effort */ }
|
||||||
|
}
|
||||||
|
|
||||||
await db.run('INSERT INTO audit_log (user_id, action, ip_address) VALUES (?, ?, ?)', [req.user.id, 'password_changed', req.ip]);
|
await db.run('INSERT INTO audit_log (user_id, action, ip_address) VALUES (?, ?, ?)', [req.user.id, 'password_changed', req.ip]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,10 @@ router.delete('/:id', async function(req, res) {
|
||||||
// Revoke all other sessions
|
// Revoke all other sessions
|
||||||
router.delete('/', async function(req, res) {
|
router.delete('/', async function(req, res) {
|
||||||
try {
|
try {
|
||||||
|
if (!req.sessionId) return res.status(400).json({ error: 'Current session not identified. Log out and log back in.' });
|
||||||
var result = await db.run(
|
var result = await db.run(
|
||||||
'DELETE FROM user_sessions WHERE user_id = ? AND id != ?',
|
'DELETE FROM user_sessions WHERE user_id = ? AND id != ?',
|
||||||
[req.user.id, req.sessionId || '']
|
[req.user.id, req.sessionId]
|
||||||
);
|
);
|
||||||
res.json({ success: true, revoked: result.changes });
|
res.json({ success: true, revoked: result.changes });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue