diff --git a/app/classes/messages.php b/app/classes/messages.php
new file mode 100644
index 0000000..a336820
--- /dev/null
+++ b/app/classes/messages.php
@@ -0,0 +1,137 @@
+ [
+ '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.',
+ 'type' => self::TYPE_INFO,
+ 'dismissible' => false
+ ]
+ ];
+
+ const LOGIN = [
+ 'LOGIN_FAILED' => [
+ 'message' => 'Invalid username or password.',
+ 'type' => self::TYPE_ERROR,
+ 'dismissible' => true
+ ],
+ 'LOGIN_BLOCKED' => [
+ 'message' => 'Too many failed attempts. Please try again later.',
+ 'type' => self::TYPE_ERROR,
+ 'dismissible' => false
+ ],
+ 'IP_BLACKLISTED' => [
+ 'message' => 'Access denied. Your IP address is blacklisted.',
+ 'type' => self::TYPE_ERROR,
+ 'dismissible' => false
+ ]
+ ];
+
+ /**
+ * Get message configuration by key
+ */
+ public static function get($category, $key) {
+ $messages = constant("self::$category");
+ return $messages[$key] ?? null;
+ }
+
+ /**
+ * Render message HTML
+ */
+ public static function render($category, $key, $customMessage = null) {
+ $config = self::get($category, $key);
+ if (!$config) return '';
+
+ $message = $customMessage ?? $config['message'];
+ $dismissible = $config['dismissible'] ? ' alert-dismissible fade show' : '';
+ $dismissButton = $config['dismissible'] ? '' : '';
+
+ return sprintf(
+ '
%s%s
',
+ $config['type'],
+ $dismissible,
+ htmlspecialchars($message),
+ $dismissButton
+ );
+ }
+
+ /**
+ * Store message in session for display after redirect
+ */
+ public static function flash($category, $key, $customMessage = null) {
+ if (!isset($_SESSION['flash_messages'])) {
+ $_SESSION['flash_messages'] = [];
+ }
+ $_SESSION['flash_messages'][] = [
+ 'category' => $category,
+ 'key' => $key,
+ 'custom_message' => $customMessage
+ ];
+ }
+
+ /**
+ * Get and clear all flash messages
+ */
+ public static function getFlash() {
+ $messages = $_SESSION['flash_messages'] ?? [];
+ unset($_SESSION['flash_messages']);
+ return $messages;
+ }
+}
diff --git a/app/pages/security.php b/app/pages/security.php
index c9cf76f..6146b80 100644
--- a/app/pages/security.php
+++ b/app/pages/security.php
@@ -9,96 +9,106 @@ if (!($userObject->hasRight($user_id, 'superuser') ||
exit;
}
+// Include Messages class
+require_once '../app/classes/messages.php';
+
// Initialize variables for feedback messages
-$error_message = '';
-$success_message = '';
+$messages = [];
+
+// Get current section
+$section = isset($_POST['section']) ? $_POST['section'] : (isset($_GET['section']) ? $_GET['section'] : 'whitelist');
// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$action = $_POST['action'];
- $section = isset($_POST['section']) ? $_POST['section'] : (isset($_GET['section']) ? $_GET['section'] : 'whitelist');
try {
switch ($action) {
case 'add_whitelist':
if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit whitelist')) {
- throw new Exception('You do not have permission to modify the whitelist.');
+ throw new Exception(Messages::get('SECURITY', 'PERMISSION_DENIED')['message']);
}
if (empty($_POST['ip_address'])) {
- throw new Exception('IP address is required.');
+ throw new Exception(Messages::get('SECURITY', 'IP_REQUIRED')['message']);
}
$is_network = isset($_POST['is_network']) ? 1 : 0;
if (!$rateLimiter->addToWhitelist($_POST['ip_address'], $is_network, $_POST['description'] ?? '', $currentUser, $user_id)) {
- throw new Exception('Failed to add IP to whitelist. Please check the IP format.');
+ throw new Exception(Messages::get('SECURITY', 'WHITELIST_ADD_ERROR')['message']);
}
- $success_message = 'IP address successfully added to whitelist.';
+ Messages::flash('SECURITY', 'WHITELIST_ADD_SUCCESS');
break;
case 'remove_whitelist':
if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit whitelist')) {
- throw new Exception('You do not have permission to modify the whitelist.');
+ throw new Exception(Messages::get('SECURITY', 'PERMISSION_DENIED')['message']);
}
if (empty($_POST['ip_address'])) {
- throw new Exception('IP address is required.');
+ throw new Exception(Messages::get('SECURITY', 'IP_REQUIRED')['message']);
}
if (!$rateLimiter->removeFromWhitelist($_POST['ip_address'], $currentUser, $user_id)) {
- throw new Exception('Failed to remove IP from whitelist.');
+ throw new Exception(Messages::get('SECURITY', 'WHITELIST_REMOVE_ERROR')['message']);
}
- $success_message = 'IP address successfully removed from whitelist.';
+ Messages::flash('SECURITY', 'WHITELIST_REMOVE_SUCCESS');
break;
case 'add_blacklist':
if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit blacklist')) {
- throw new Exception('You do not have permission to modify the blacklist.');
+ throw new Exception(Messages::get('SECURITY', 'PERMISSION_DENIED')['message']);
}
if (empty($_POST['ip_address'])) {
- throw new Exception('IP address is required.');
+ throw new Exception(Messages::get('SECURITY', 'IP_REQUIRED')['message']);
}
$is_network = isset($_POST['is_network']) ? 1 : 0;
$expiry_hours = !empty($_POST['expiry_hours']) ? intval($_POST['expiry_hours']) : null;
if (!$rateLimiter->addToBlacklist($_POST['ip_address'], $is_network, $_POST['reason'] ?? '', $currentUser, $user_id, $expiry_hours)) {
- throw new Exception('Failed to add IP to blacklist. Please check the IP format.');
+ throw new Exception(Messages::get('SECURITY', 'BLACKLIST_ADD_ERROR')['message']);
}
- $success_message = 'IP address successfully added to blacklist.';
+ Messages::flash('SECURITY', 'BLACKLIST_ADD_SUCCESS');
break;
case 'remove_blacklist':
if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit blacklist')) {
- throw new Exception('You do not have permission to modify the blacklist.');
+ throw new Exception(Messages::get('SECURITY', 'PERMISSION_DENIED')['message']);
}
if (empty($_POST['ip_address'])) {
- throw new Exception('IP address is required.');
+ throw new Exception(Messages::get('SECURITY', 'IP_REQUIRED')['message']);
}
if (!$rateLimiter->removeFromBlacklist($_POST['ip_address'], $currentUser, $user_id)) {
- throw new Exception('Failed to remove IP from blacklist.');
+ throw new Exception(Messages::get('SECURITY', 'BLACKLIST_REMOVE_ERROR')['message']);
}
- $success_message = 'IP address successfully removed from blacklist.';
+ Messages::flash('SECURITY', 'BLACKLIST_REMOVE_SUCCESS');
break;
}
} catch (Exception $e) {
- $error_message = $e->getMessage();
+ $messages[] = ['category' => 'SECURITY', 'key' => 'CUSTOM_ERROR', 'custom_message' => $e->getMessage()];
}
- if (empty($error_message)) {
- // Only redirect if there was no error
- header("Location: {$app_root}?page=security§ion={$section}" .
- ($success_message ? '&success=' . urlencode($success_message) : ''));
+ if (empty($messages)) {
+ // Only redirect if there were no errors
+ header("Location: {$app_root}?page=security§ion={$section}");
exit;
}
}
-// Get success message from URL if redirected after successful action
-if (isset($_GET['success'])) {
- $success_message = $_GET['success'];
+// 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'];
}
// Get current lists
$whitelisted = $rateLimiter->getWhitelistedIps();
$blacklisted = $rateLimiter->getBlacklistedIps();
-// Get current section
-$section = isset($_GET['section']) ? $_GET['section'] : 'whitelist';
-
// Include template
include '../app/templates/security.php';
diff --git a/app/templates/security.php b/app/templates/security.php
index f6e461c..faba804 100644
--- a/app/templates/security.php
+++ b/app/templates/security.php
@@ -3,18 +3,9 @@
Security Settings
-
-
- = htmlspecialchars($error_message) ?>
-
-
-
-
-
- = htmlspecialchars($success_message) ?>
-
-
-
+
+ = Messages::render($msg['category'], $msg['key'], $msg['custom_message'] ?? null) ?>
+
hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { ?>
-