Compare commits

...

4 Commits

3 changed files with 66 additions and 20 deletions

View File

@ -1,5 +1,9 @@
<?php <?php
// Already required in index.php, but we require it here,
// because this class could be used standalone
require_once __DIR__ . '/../helpers/logger_loader.php';
/** /**
* Class TwoFactorAuthentication * Class TwoFactorAuthentication
* *
@ -98,7 +102,10 @@ class TwoFactorAuthentication {
if ($code !== null) { if ($code !== null) {
// Verify the setup code // Verify the setup code
if (!$this->verify($userId, $code)) { if (!$this->verify($userId, $code)) {
error_log("Code verification failed"); app_log('warning', '2FA setup code verification failed', [
'scope' => 'security',
'user_id' => $userId,
]);
return false; return false;
} }
@ -117,7 +124,10 @@ class TwoFactorAuthentication {
if ($this->db->inTransaction()) { if ($this->db->inTransaction()) {
$this->db->rollBack(); $this->db->rollBack();
} }
error_log('2FA enable error: ' . $e->getMessage()); app_log('error', '2FA enable error: ' . $e->getMessage(), [
'scope' => 'security',
'user_id' => $userId,
]);
return false; return false;
} }
} }
@ -157,7 +167,10 @@ class TwoFactorAuthentication {
return false; return false;
} catch (Exception $e) { } catch (Exception $e) {
error_log('2FA verification error: ' . $e->getMessage()); app_log('error', '2FA verification error: ' . $e->getMessage(), [
'scope' => 'security',
'user_id' => $userId,
]);
return false; return false;
} }
} }
@ -351,7 +364,10 @@ class TwoFactorAuthentication {
return false; return false;
} catch (Exception $e) { } catch (Exception $e) {
error_log('Backup code verification error: ' . $e->getMessage()); app_log('error', 'Backup code verification error: ' . $e->getMessage(), [
'scope' => 'security',
'user_id' => $userId,
]);
return false; return false;
} }
} }
@ -378,7 +394,10 @@ class TwoFactorAuthentication {
return $stmt->execute([$userId]); return $stmt->execute([$userId]);
} catch (Exception $e) { } catch (Exception $e) {
error_log('2FA disable error: ' . $e->getMessage()); app_log('error', '2FA disable error: ' . $e->getMessage(), [
'scope' => 'security',
'user_id' => $userId,
]);
return false; return false;
} }
} }
@ -397,7 +416,10 @@ class TwoFactorAuthentication {
return $result && $result['enabled']; return $result && $result['enabled'];
} catch (Exception $e) { } catch (Exception $e) {
error_log('2FA status check error: ' . $e->getMessage()); app_log('error', '2FA status check error: ' . $e->getMessage(), [
'scope' => 'security',
'user_id' => $userId,
]);
return false; return false;
} }
} }
@ -413,7 +435,10 @@ class TwoFactorAuthentication {
return $stmt->fetch(PDO::FETCH_ASSOC); return $stmt->fetch(PDO::FETCH_ASSOC);
} catch (Exception $e) { } catch (Exception $e) {
error_log('Failed to get user 2FA settings: ' . $e->getMessage()); app_log('error', 'Failed to get user 2FA settings: ' . $e->getMessage(), [
'scope' => 'security',
'user_id' => $userId,
]);
return null; return null;
} }
} }

View File

@ -13,3 +13,25 @@ function getLoggerInstance($database) {
require_once __DIR__ . '/../core/NullLogger.php'; require_once __DIR__ . '/../core/NullLogger.php';
return new \App\Core\NullLogger(); return new \App\Core\NullLogger();
} }
if (!function_exists('app_log')) {
/**
* Lightweight logging helper that prefers the plugin logger but falls back to NullLogger.
*/
function app_log(string $level, string $message, array $context = []): void {
global $logObject;
if (isset($logObject) && is_object($logObject) && method_exists($logObject, 'log')) {
$logObject->log($level, $message, $context);
return;
}
static $fallbackLogger = null;
if ($fallbackLogger === null) {
require_once __DIR__ . '/../core/NullLogger.php';
$fallbackLogger = new \App\Core\NullLogger();
}
$fallbackLogger->log($level, $message, $context);
}
}

View File

@ -122,18 +122,10 @@ $pipeline->add(function() {
return true; return true;
}); });
// For public pages, we don't need to validate the session // Always detect authenticated session so templates shared
// The Router will handle authentication for protected pages // between public and private pages behave consistently.
$validSession = false; $validSession = Session::isValidSession(true);
$userId = null; $userId = $validSession ? Session::getUserId() : null;
// Only check session for non-public pages
if (!in_array($page, $public_pages)) {
$validSession = Session::isValidSession(true);
if ($validSession) {
$userId = Session::getUserId();
}
}
// Initialize feedback message system // Initialize feedback message system
require_once '../app/classes/feedback.php'; require_once '../app/classes/feedback.php';
@ -162,6 +154,9 @@ $allowed_urls = filter_allowed_urls($allowed_urls);
require_once __DIR__ . '/../app/core/Router.php'; require_once __DIR__ . '/../app/core/Router.php';
use App\Core\Router; use App\Core\Router;
$currentUser = Router::checkAuth($config, $app_root, $public_pages, $page); $currentUser = Router::checkAuth($config, $app_root, $public_pages, $page);
if ($currentUser === null && $validSession) {
$currentUser = Session::getUsername();
}
// Connect to DB via DatabaseConnector // Connect to DB via DatabaseConnector
require_once __DIR__ . '/../app/core/DatabaseConnector.php'; require_once __DIR__ . '/../app/core/DatabaseConnector.php';
@ -176,6 +171,8 @@ use App\Core\LogThrottler;
require_once __DIR__ . '/../app/core/NullLogger.php'; require_once __DIR__ . '/../app/core/NullLogger.php';
use App\Core\NullLogger; use App\Core\NullLogger;
$logObject = new NullLogger(); $logObject = new NullLogger();
require_once __DIR__ . '/../app/helpers/logger_loader.php';
// Get the user IP // Get the user IP
require_once __DIR__ . '/../app/helpers/ip_helper.php'; require_once __DIR__ . '/../app/helpers/ip_helper.php';
$user_IP = ''; $user_IP = '';
@ -220,7 +217,9 @@ try {
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
// Do not break the app; log only // Do not break the app; log only
error_log('Migration check failed: ' . $e->getMessage()); app_log('error', 'Migration check failed: ' . $e->getMessage(), [
'scope' => 'system',
]);
} }
// CSRF middleware and run pipeline // CSRF middleware and run pipeline