diff --git a/app/classes/messages.php b/app/classes/messages.php index a336820..5f1c44e 100644 --- a/app/classes/messages.php +++ b/app/classes/messages.php @@ -7,106 +7,136 @@ class Messages { const TYPE_INFO = 'info'; const TYPE_WARNING = 'warning'; - // Message categories - const SECURITY = [ - 'WHITELIST_ADD_SUCCESS' => [ - 'message' => 'IP address successfully added to whitelist.', - 'type' => self::TYPE_SUCCESS, - 'dismissible' => true - ], - 'WHITELIST_ADD_ERROR' => [ - 'message' => 'Failed to add IP to whitelist. Please check the IP format.', - 'type' => self::TYPE_ERROR, - 'dismissible' => true - ], - 'WHITELIST_REMOVE_SUCCESS' => [ - 'message' => 'IP address successfully removed from whitelist.', - 'type' => self::TYPE_SUCCESS, - 'dismissible' => true - ], - 'WHITELIST_REMOVE_ERROR' => [ - 'message' => 'Failed to remove IP from whitelist.', - 'type' => self::TYPE_ERROR, - 'dismissible' => true - ], - 'BLACKLIST_ADD_SUCCESS' => [ - 'message' => 'IP address successfully added to blacklist.', - 'type' => self::TYPE_SUCCESS, - 'dismissible' => true - ], - 'BLACKLIST_ADD_ERROR' => [ - 'message' => 'Failed to add IP to blacklist. Please check the IP format.', - 'type' => self::TYPE_ERROR, - 'dismissible' => true - ], - 'BLACKLIST_REMOVE_SUCCESS' => [ - 'message' => 'IP address successfully removed from blacklist.', - 'type' => self::TYPE_SUCCESS, - 'dismissible' => true - ], - 'BLACKLIST_REMOVE_ERROR' => [ - 'message' => 'Failed to remove IP from blacklist.', - 'type' => self::TYPE_ERROR, - 'dismissible' => true - ], - 'IP_REQUIRED' => [ - 'message' => 'IP address is required.', - 'type' => self::TYPE_ERROR, - 'dismissible' => true - ], - 'PERMISSION_DENIED' => [ - 'message' => 'You do not have permission to perform this action.', - 'type' => self::TYPE_ERROR, - 'dismissible' => false - ], - 'RATE_LIMIT_INFO' => [ - 'message' => 'Rate limiting is active. This helps protect against brute force attacks.', + // Default message configurations + const NOTICE = [ + 'DEFAULT' => [ 'type' => self::TYPE_INFO, + 'dismissible' => true + ] + ]; + + const ERROR = [ + 'DEFAULT' => [ + 'type' => self::TYPE_ERROR, 'dismissible' => false ] ]; const LOGIN = [ - 'LOGIN_FAILED' => [ - 'message' => 'Invalid username or password.', - 'type' => self::TYPE_ERROR, + 'LOGIN_SUCCESS' => [ + 'type' => self::TYPE_SUCCESS, 'dismissible' => true ], - 'LOGIN_BLOCKED' => [ - 'message' => 'Too many failed attempts. Please try again later.', + 'LOGIN_FAILED' => [ 'type' => self::TYPE_ERROR, 'dismissible' => false ], + 'LOGOUT_SUCCESS' => [ + 'type' => self::TYPE_SUCCESS, + 'dismissible' => true + ], 'IP_BLACKLISTED' => [ - 'message' => 'Access denied. Your IP address is blacklisted.', + 'type' => self::TYPE_ERROR, + 'dismissible' => false + ], + 'IP_NOT_WHITELISTED' => [ + 'type' => self::TYPE_ERROR, + 'dismissible' => false + ], + 'TOO_MANY_ATTEMPTS' => [ 'type' => self::TYPE_ERROR, 'dismissible' => false ] ]; + const SECURITY = [ + 'WHITELIST_ADD_SUCCESS' => [ + 'type' => self::TYPE_SUCCESS, + 'dismissible' => true + ], + 'WHITELIST_ADD_ERROR' => [ + 'type' => self::TYPE_ERROR, + 'dismissible' => true + ], + 'WHITELIST_REMOVE_SUCCESS' => [ + 'type' => self::TYPE_SUCCESS, + 'dismissible' => true + ], + 'WHITELIST_REMOVE_ERROR' => [ + 'type' => self::TYPE_ERROR, + 'dismissible' => true + ], + 'BLACKLIST_ADD_SUCCESS' => [ + 'type' => self::TYPE_SUCCESS, + 'dismissible' => true + ], + 'BLACKLIST_ADD_ERROR' => [ + 'type' => self::TYPE_ERROR, + 'dismissible' => true + ], + 'BLACKLIST_REMOVE_SUCCESS' => [ + 'type' => self::TYPE_SUCCESS, + 'dismissible' => true + ], + 'BLACKLIST_REMOVE_ERROR' => [ + 'type' => self::TYPE_ERROR, + 'dismissible' => true + ], + 'RATE_LIMIT_INFO' => [ + 'type' => self::TYPE_INFO, + 'dismissible' => false + ], + 'PERMISSION_DENIED' => [ + 'type' => self::TYPE_ERROR, + 'dismissible' => false + ], + 'IP_REQUIRED' => [ + 'type' => self::TYPE_ERROR, + 'dismissible' => false + ] + ]; + + private static $strings = null; + + /** + * Get message strings + */ + private static function getStrings() { + if (self::$strings === null) { + self::$strings = require __DIR__ . '/../includes/messages-strings.php'; + } + return self::$strings; + } + /** * Get message configuration by key */ public static function get($category, $key) { - $messages = constant("self::$category"); - return $messages[$key] ?? null; + $config = constant("self::$category")[$key] ?? null; + if (!$config) return null; + + $strings = self::getStrings(); + $message = $strings[$category][$key] ?? ''; + + return array_merge($config, ['message' => $message]); } /** * Render message HTML */ - public static function render($category, $key, $customMessage = null) { + public static function render($category, $key, $customMessage = null, $dismissible = null) { $config = self::get($category, $key); if (!$config) return ''; $message = $customMessage ?? $config['message']; - $dismissible = $config['dismissible'] ? ' alert-dismissible fade show' : ''; - $dismissButton = $config['dismissible'] ? '' : ''; + $isDismissible = $dismissible ?? $config['dismissible']; + $dismissClass = $isDismissible ? ' alert-dismissible fade show' : ''; + $dismissButton = $isDismissible ? '' : ''; return sprintf( '', $config['type'], - $dismissible, + $dismissClass, htmlspecialchars($message), $dismissButton ); @@ -115,14 +145,15 @@ class Messages { /** * Store message in session for display after redirect */ - public static function flash($category, $key, $customMessage = null) { + public static function flash($category, $key, $customMessage = null, $dismissible = null) { if (!isset($_SESSION['flash_messages'])) { $_SESSION['flash_messages'] = []; } $_SESSION['flash_messages'][] = [ 'category' => $category, 'key' => $key, - 'custom_message' => $customMessage + 'custom_message' => $customMessage, + 'dismissible' => $dismissible ]; } diff --git a/app/classes/ratelimiter.php b/app/classes/ratelimiter.php index 42dfa1d..a3e3b85 100644 --- a/app/classes/ratelimiter.php +++ b/app/classes/ratelimiter.php @@ -3,8 +3,8 @@ class RateLimiter { public $db; private $log; - public $maxAttempts = 5; // Maximum login attempts - public $decayMinutes = 15; // Time window in minutes + public $maxAttempts = 5; // Maximum login attempts + public $decayMinutes = 15; // Time window in minutes public $autoBlacklistThreshold = 10; // Attempts before auto-blacklist public $autoBlacklistDuration = 24; // Hours to blacklist for public $ratelimitTable = 'login_attempts'; @@ -22,7 +22,7 @@ class RateLimiter { // Login attempts table $sql = "CREATE TABLE IF NOT EXISTS {$this->ratelimitTable} ( id INTEGER PRIMARY KEY AUTOINCREMENT, - ip_address TEXT NOT NULL, + ip_address TEXT NOT NULL UNIQUE, username TEXT NOT NULL, attempted_at TEXT DEFAULT (DATETIME('now')) )"; @@ -45,7 +45,7 @@ class RateLimiter { ip_address TEXT NOT NULL UNIQUE, is_network BOOLEAN DEFAULT 0 CHECK(is_network IN (0,1)), reason TEXT, - expiry_time TEXT NULL, + expiry_time TEXT NULL, created_at TEXT DEFAULT (DATETIME('now')), created_by TEXT )"; @@ -53,11 +53,11 @@ class RateLimiter { // Default IPs to whitelist (local interface and private networks IPs) $defaultIps = [ - ['127.0.0.1', 0, 'localhost IPv4'], - ['::1', 0, 'localhost IPv6'], - ['10.0.0.0/8', 1, 'Private network (Class A)'], - ['172.16.0.0/12', 1, 'Private network (Class B)'], - ['192.168.0.0/16', 1, 'Private network (Class C)'] + ['127.0.0.1', false, 'localhost IPv4'], + ['::1', false, 'localhost IPv6'], + ['10.0.0.0/8', true, 'Private network (Class A)'], + ['172.16.0.0/12', true, 'Private network (Class B)'], + ['192.168.0.0/16', true, 'Private network (Class C)'] ]; // Insert default whitelisted IPs if they don't exist @@ -70,11 +70,11 @@ class RateLimiter { // Insert known malicious networks $defaultBlacklist = [ - ['0.0.0.0/8', 1, 'Reserved address space - RFC 1122'], - ['100.64.0.0/10', 1, 'Carrier-grade NAT space - RFC 6598'], - ['192.0.2.0/24', 1, 'TEST-NET-1 Documentation space - RFC 5737'], - ['198.51.100.0/24', 1, 'TEST-NET-2 Documentation space - RFC 5737'], - ['203.0.113.0/24', 1, 'TEST-NET-3 Documentation space - RFC 5737'] + ['0.0.0.0/8', true, 'Reserved address space - RFC 1122'], + ['100.64.0.0/10', true, 'Carrier-grade NAT space - RFC 6598'], + ['192.0.2.0/24', true, 'TEST-NET-1 Documentation space - RFC 5737'], + ['198.51.100.0/24', true, 'TEST-NET-2 Documentation space - RFC 5737'], + ['203.0.113.0/24', true, 'TEST-NET-3 Documentation space - RFC 5737'] ]; $stmt = $this->db->prepare("INSERT OR IGNORE INTO {$this->blacklistTable} @@ -87,27 +87,21 @@ class RateLimiter { } - private function isIpWhitelisted($ip) { - // Check exact IP match and CIDR ranges - $stmt = $this->db->prepare("SELECT ip_address, is_network FROM {$this->whitelistTable}"); - $stmt->execute(); - - while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - if ($row['is_network']) { - if ($this->ipInRange($ip, $row['ip_address'])) { - return true; - } - } else { - if ($ip === $row['ip_address']) { - return true; - } - } - } - - return false; + /** + * Get number of recent login attempts for an IP + */ + public function getRecentAttempts($ip) { + $stmt = $this->db->prepare("SELECT COUNT(*) as attempts FROM {$this->ratelimitTable} + WHERE ip_address = ? AND attempted_at > datetime('now', '-' || :minutes || ' minutes')"); + $stmt->execute([$ip, $this->decayMinutes]); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + return intval($result['attempts']); } - private function isIpBlacklisted($ip) { + /** + * Check if an IP is blacklisted + */ + public function isIpBlacklisted($ip) { // First check if IP is explicitly blacklisted or in a blacklisted range $stmt = $this->db->prepare("SELECT ip_address, is_network, expiry_time FROM {$this->blacklistTable}"); $stmt->execute(); @@ -132,6 +126,29 @@ class RateLimiter { return false; } + /** + * Check if an IP is whitelisted + */ + public function isIpWhitelisted($ip) { + // Check exact IP match and CIDR ranges + $stmt = $this->db->prepare("SELECT ip_address, is_network FROM {$this->whitelistTable}"); + $stmt->execute(); + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + if ($row['is_network']) { + if ($this->ipInRange($ip, $row['ip_address'])) { + return true; + } + } else { + if ($ip === $row['ip_address']) { + return true; + } + } + } + + return false; + } + private function ipInRange($ip, $cidr) { list($subnet, $bits) = explode('/', $cidr); @@ -151,6 +168,7 @@ class RateLimiter { $message = "Cannot whitelist {$ip} - IP is currently blacklisted"; if ($userId) { $this->log->insertLog($userId, "IP Whitelist: {$message}", 'system'); + Messages::flash('ERROR', 'DEFAULT', $message); } return false; } @@ -177,6 +195,7 @@ class RateLimiter { } catch (Exception $e) { if ($userId) { $this->log->insertLog($userId, "IP Whitelist: Failed to add {$ip}: " . $e->getMessage(), 'system'); + Messages::flash('ERROR', 'DEFAULT', "IP Whitelist: Failed to add {$ip}: " . $e->getMessage()); } return false; } @@ -211,6 +230,7 @@ class RateLimiter { } catch (Exception $e) { if ($userId) { $this->log->insertLog($userId, "IP Whitelist: Failed to remove {$ip}: " . $e->getMessage(), 'system'); + Messages::flash('ERROR', 'DEFAULT', "IP Whitelist: Failed to remove {$ip}: " . $e->getMessage()); } return false; } @@ -223,6 +243,7 @@ class RateLimiter { $message = "Cannot blacklist {$ip} - IP is currently whitelisted"; if ($userId) { $this->log->insertLog($userId, "IP Blacklist: {$message}", 'system'); + Messages::flash('ERROR', 'DEFAULT', $message); } return false; } @@ -251,6 +272,7 @@ class RateLimiter { } catch (Exception $e) { if ($userId) { $this->log->insertLog($userId, "IP Blacklist: Failed to add {$ip}: " . $e->getMessage(), 'system'); + Messages::flash('ERROR', 'DEFAULT', "IP Blacklist: Failed to add {$ip}: " . $e->getMessage()); } return false; } @@ -283,6 +305,7 @@ class RateLimiter { } catch (Exception $e) { if ($userId) { $this->log->insertLog($userId, "IP Blacklist: Failed to remove {$ip}: " . $e->getMessage(), 'system'); + Messages::flash('ERROR', 'DEFAULT', "IP Blacklist: Failed to remove {$ip}: " . $e->getMessage()); } return false; } @@ -317,6 +340,7 @@ class RateLimiter { return true; } catch (Exception $e) { $this->log->insertLog(0, "Failed to cleanup expired entries: " . $e->getMessage(), 'system'); + Messages::flash('ERROR', 'DEFAULT', "Failed to cleanup expired entries: " . $e->getMessage()); return false; } } @@ -390,9 +414,9 @@ class RateLimiter { $stmt = $this->db->prepare($sql); $stmt->execute([ - ':ip' => $ipAddress, - ':username' => $username, - ':minutes' => $this->decayMinutes + ':ip' => $ipAddress, + ':username' => $username, + ':minutes' => $this->decayMinutes ]); $result = $stmt->fetch(PDO::FETCH_ASSOC); @@ -405,7 +429,7 @@ class RateLimiter { $stmt = $this->db->prepare($sql); $stmt->execute([ - ':minutes' => $this->decayMinutes + ':minutes' => $this->decayMinutes ]); } @@ -418,9 +442,9 @@ class RateLimiter { $stmt = $this->db->prepare($sql); $stmt->execute([ - ':ip' => $ipAddress, - ':username' => $username, - ':minutes' => $this->decayMinutes + ':ip' => $ipAddress, + ':username' => $username, + ':minutes' => $this->decayMinutes ]); $result = $stmt->fetch(PDO::FETCH_ASSOC); diff --git a/app/includes/messages-show.php b/app/includes/messages-show.php new file mode 100644 index 0000000..9cc4ddf --- /dev/null +++ b/app/includes/messages-show.php @@ -0,0 +1,9 @@ + diff --git a/app/includes/messages-strings.php b/app/includes/messages-strings.php new file mode 100644 index 0000000..6c72862 --- /dev/null +++ b/app/includes/messages-strings.php @@ -0,0 +1,36 @@ + [ + 'LOGIN_SUCCESS' => 'Login successful.', + 'LOGIN_FAILED' => 'Login failed. Please check your credentials.', + 'LOGOUT_SUCCESS' => 'Logout successful. You can log in again.', + 'IP_BLACKLISTED' => 'Access denied. Your IP address is blacklisted.', + 'IP_NOT_WHITELISTED' => 'Access denied. Your IP address is not whitelisted.', + 'TOO_MANY_ATTEMPTS' => 'Too many login attempts. Please try again later.', + ], + 'SECURITY' => [ + 'WHITELIST_ADD_SUCCESS' => 'IP address successfully added to whitelist.', + 'WHITELIST_ADD_ERROR' => 'Failed to add IP to whitelist. Please check the IP format.', + 'WHITELIST_REMOVE_SUCCESS' => 'IP address successfully removed from whitelist.', + 'WHITELIST_REMOVE_ERROR' => 'Failed to remove IP from whitelist.', + 'BLACKLIST_ADD_SUCCESS' => 'IP address successfully added to blacklist.', + 'BLACKLIST_ADD_ERROR' => 'Failed to add IP to blacklist. Please check the IP format.', + 'BLACKLIST_REMOVE_SUCCESS' => 'IP address successfully removed from blacklist.', + 'BLACKLIST_REMOVE_ERROR' => 'Failed to remove IP from blacklist.', + 'RATE_LIMIT_INFO' => 'Rate limiting is active. This helps protect against brute force attacks.', + 'PERMISSION_DENIED' => 'Permission denied. You do not have the required rights.', + 'IP_REQUIRED' => 'IP address is required.', + ], + 'REGISTER' => [ + 'SUCCESS' => 'Registration successful. You can log in now.', + 'FAILED' => 'Registration failed: %s', + 'DISABLED' => 'Registration is disabled.', + ], + 'SYSTEM' => [ + 'DB_ERROR' => 'Error connecting to the database: %s', + 'DB_CONNECT_ERROR' => 'Error connecting to DB: %s', + 'DB_UNKNOWN_TYPE' => 'Error: unknown database type "%s"', + ], +]; diff --git a/app/includes/messages.php b/app/includes/messages.php index 58b95d5..d9fdc3f 100644 --- a/app/includes/messages.php +++ b/app/includes/messages.php @@ -1,17 +1,15 @@ $flash['category'], + 'key' => $flash['key'], + 'custom_message' => $flash['custom_message'] + ]; + }, $flash_messages)); } + +?> diff --git a/app/includes/sanitize.php b/app/includes/sanitize.php index 6cff317..ad15a5e 100644 --- a/app/includes/sanitize.php +++ b/app/includes/sanitize.php @@ -21,6 +21,15 @@ if (isset($_REQUEST['until_time'])) { $until_time = htmlspecialchars($_REQUEST['until_time']); } +// sanitize session vars +if (isset($_SESSION)) { + foreach ($_SESSION as $key => $value) { + if (is_string($value)) { + $_SESSION[$key] = htmlspecialchars($value); + } + } +} + // hosts if (isset($_POST['address'])) { $address = htmlspecialchars($_POST['address']); diff --git a/app/pages/dashboard.php b/app/pages/dashboard.php index 73651a1..f0d7f15 100644 --- a/app/pages/dashboard.php +++ b/app/pages/dashboard.php @@ -9,6 +9,10 @@ * 3. The most recent 10 conferences. */ +// Get any new messages +include '../app/includes/messages.php'; +include '../app/includes/messages-show.php'; + require '../app/classes/conference.php'; require '../app/classes/participant.php'; diff --git a/app/pages/login.php b/app/pages/login.php index c9a0523..0eb3ae1 100644 --- a/app/pages/login.php +++ b/app/pages/login.php @@ -21,11 +21,28 @@ try { // connect to database $dbWeb = connectDB($config); + // Initialize RateLimiter + require_once '../app/classes/ratelimiter.php'; + $rateLimiter = new RateLimiter($dbWeb); + if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) { try { $username = $_POST['username']; $password = $_POST['password']; + // Check if IP is blacklisted + if ($rateLimiter->isIpBlacklisted($user_IP)) { + throw new Exception(Messages::get('LOGIN', 'IP_BLACKLISTED')['message']); + } + + // Check rate limiting (but skip if IP is whitelisted) + if (!$rateLimiter->isIpWhitelisted($user_IP)) { + $attempts = $rateLimiter->getRecentAttempts($user_IP); + if ($attempts >= $rateLimiter->maxAttempts) { + throw new Exception(Messages::get('LOGIN', 'LOGIN_BLOCKED')['message']); + } + } + // login successful if ( $userObject->login($username, $password) ) { // if remember_me is checked, max out the session @@ -52,32 +69,40 @@ try { 'samesite' => 'Strict' ]); - // redirect to index - $_SESSION['notice'] = "Login successful"; + // Log successful login $user_id = $userObject->getUserId($username)[0]['id']; $logObject->insertLog($user_id, "Login: User \"$username\" logged in. IP: $user_IP", 'user'); + + // Set success message and redirect + Messages::flash('LOGIN', 'LOGIN_SUCCESS'); header('Location: ' . htmlspecialchars($app_root)); exit(); + } else { + throw new Exception(Messages::get('LOGIN', 'LOGIN_FAILED')['message']); } } catch (Exception $e) { // Log the failed attempt - $error = $e->getMessage(); + Messages::flash('ERROR', 'DEFAULT', $e->getMessage()); if (isset($username)) { $user_id = $userObject->getUserId($username)[0]['id'] ?? 0; - $logObject->insertLog($user_id, "Login: Failed login attempt for user \"$username\". IP: $user_IP. Reason: {$error}", 'user'); + $logObject->insertLog($user_id, "Login: Failed login attempt for user \"$username\". IP: $user_IP. Reason: {$e->getMessage()}", 'user'); } - include '../app/templates/block-message.php'; } } } catch (Exception $e) { - $error = getError('There was an unexpected error. Please try again.', $e->getMessage()); + Messages::flash('ERROR', 'DEFAULT', 'There was an unexpected error. Please try again.'); } +// Show configured login message if any if (!empty($config['login_message'])) { - $notice = $config['login_message']; - include '../app/templates/block-message.php'; + echo Messages::render('NOTICE', 'DEFAULT', $config['login_message'], false); } +// Get any new messages +include '../app/includes/messages.php'; +include '../app/includes/messages-show.php'; + +// Load the template include '../app/templates/form-login.php'; ?> diff --git a/app/pages/register.php b/app/pages/register.php index 420c65b..f3aa431 100644 --- a/app/pages/register.php +++ b/app/pages/register.php @@ -8,12 +8,9 @@ * and redirects to the login page on success or displays an error message on failure. */ -// check if the registration is allowed +// registration is allowed, go on if ($config['registration_enabled'] === true) { - // clear any previous error messages - unset($error); - try { // connect to database @@ -28,27 +25,30 @@ if ($config['registration_enabled'] === true) { // redirect to login if ($result === true) { - $_SESSION['notice'] = "Registration successful.
You can log in now."; + Messages::flash('NOTICE', 'DEFAULT', "Registration successful.
You can log in now."); header('Location: ' . htmlspecialchars($app_root)); exit(); // registration fail, redirect to login } else { - $_SESSION['error'] = "Registration failed. $result"; + Messages::flash('ERROR', 'DEFAULT', "Registration failed. $result"); header('Location: ' . htmlspecialchars($app_root)); exit(); } } } catch (Exception $e) { - $error = $e->getMessage(); + Messages::flash('ERROR', 'DEFAULT', $e->getMessage()); } - include '../app/templates/block-message.php'; + // Get any new messages + include '../app/includes/messages.php'; + include '../app/includes/messages-show.php'; + + // Load the template include '../app/templates/form-register.php'; // registration disabled } else { - $notice = 'Registration is disabled'; - include '../app/templates/block-message.php'; + echo Messages::render('NOTICE', 'DEFAULT', 'Registration is disabled', false); } ?> diff --git a/app/pages/security.php b/app/pages/security.php index 6146b80..78ae7c8 100644 --- a/app/pages/security.php +++ b/app/pages/security.php @@ -9,15 +9,18 @@ if (!($userObject->hasRight($user_id, 'superuser') || exit; } -// Include Messages class -require_once '../app/classes/messages.php'; - -// Initialize variables for feedback messages -$messages = []; +if (!isset($currentUser)) { + include '../app/templates/error-unauthorized.php'; + exit; +} // Get current section $section = isset($_POST['section']) ? $_POST['section'] : (isset($_GET['section']) ? $_GET['section'] : 'whitelist'); +// Initialize RateLimiter +require_once '../app/classes/ratelimiter.php'; +$rateLimiter = new RateLimiter($dbWeb); + // Handle form submissions if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { $action = $_POST['action']; @@ -81,6 +84,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { } } catch (Exception $e) { $messages[] = ['category' => 'SECURITY', 'key' => 'CUSTOM_ERROR', 'custom_message' => $e->getMessage()]; + Messages::flash('SECURITY', 'CUSTOM_ERROR', 'custom_message'); } if (empty($messages)) { @@ -90,16 +94,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { } } -// Get flash messages from previous request -$flash_messages = Messages::getFlash(); -$messages = array_merge($messages, array_map(function($flash) { - return [ - 'category' => $flash['category'], - 'key' => $flash['key'], - 'custom_message' => $flash['custom_message'] - ]; -}, $flash_messages)); - // Always show rate limit info message for rate limiting section if ($section === 'ratelimit') { $messages[] = ['category' => 'SECURITY', 'key' => 'RATE_LIMIT_INFO']; @@ -109,7 +103,11 @@ if ($section === 'ratelimit') { $whitelisted = $rateLimiter->getWhitelistedIps(); $blacklisted = $rateLimiter->getBlacklistedIps(); -// Include template +// Get any new messages +include '../app/includes/messages.php'; +include '../app/includes/messages-show.php'; + +// Load the template include '../app/templates/security.php'; ?> diff --git a/app/templates/block-message.php b/app/templates/block-message.php deleted file mode 100644 index 79490a0..0000000 --- a/app/templates/block-message.php +++ /dev/null @@ -1,18 +0,0 @@ - diff --git a/app/templates/page-footer.php b/app/templates/page-footer.php index 079813d..802962d 100644 --- a/app/templates/page-footer.php +++ b/app/templates/page-footer.php @@ -18,6 +18,28 @@ $(document).ready(function(){ $('[data-toggle="tooltip"]').tooltip(); }); + + + + + diff --git a/app/templates/page-header.php b/app/templates/page-header.php index ba771a3..da5ea15 100644 --- a/app/templates/page-header.php +++ b/app/templates/page-header.php @@ -37,3 +37,13 @@ +
+
+
+ + + + + +
+
diff --git a/app/templates/security.php b/app/templates/security.php index faba804..861426b 100644 --- a/app/templates/security.php +++ b/app/templates/security.php @@ -3,9 +3,6 @@

Security Settings

- - -