- Implemented.
Rebuilt embed-example.html with inline, full-screen, and popup examples. Fixed host-page/frame scrolling and contained reply navigation. New logins now transactionally replace prior sessions; displaced clients return to login. Added per-user session/IP locking with automatic SQLite migration. Added modular Spam Control dashboard for locks, honeypot, and CAPTCHA settings. Moved CAPTCHA controls out of Plans & Platform.
This commit is contained in:
+2
-9
@@ -64,15 +64,7 @@ function loginUser(): never {
|
||||
jsonResponse(['error' => 'Invalid username or password'], 401);
|
||||
}
|
||||
|
||||
if (getConfigVal('chat.session_lock_ip', true) || getConfigVal('chat.session_lock_cookie', true)) {
|
||||
$cutoff = time() - ((int)getConfigVal('security.session_timeout_hours', 24) * 3600);
|
||||
$existingStmt = $db->prepare("SELECT id,ip FROM sessions WHERE user_id=? AND last_active>?");
|
||||
$existingStmt->execute([$user['id'], $cutoff]);
|
||||
$existing = $existingStmt->fetch();
|
||||
if ($existing && getConfigVal('chat.session_lock_ip', true) && $existing['ip'] !== clientIP()) {
|
||||
jsonResponse(['error' => 'Already logged in from another location'], 403);
|
||||
}
|
||||
}
|
||||
assertUserSessionLoginAllowed($db, (int)$user['id']);
|
||||
|
||||
if (!empty($user['two_factor_enabled']) && featureValue($user, 'email_2fa', false)) {
|
||||
if (empty($user['email_verified_at']) || empty($user['email'])) {
|
||||
@@ -109,6 +101,7 @@ function verifyTwoFactor(): never {
|
||||
if ($row) $db->prepare("UPDATE login_challenges SET attempts=attempts+1 WHERE id=?")->execute([$challenge]);
|
||||
jsonResponse(['error' => 'Invalid or expired login code'], 401);
|
||||
}
|
||||
assertUserSessionLoginAllowed($db, (int)$row['user_id']);
|
||||
$db->prepare("DELETE FROM login_challenges WHERE id=?")->execute([$challenge]);
|
||||
createUserSession($db, (int)$row['user_id']);
|
||||
trackEvent('login_2fa', '/api/auth.php', (int)$row['user_id']);
|
||||
|
||||
Reference in New Issue
Block a user