Adds modal messages, fixes ratelimiter

main
Yasen Pramatarov 2025-01-04 13:41:02 +02:00
parent 9c129fcf76
commit eae2a8a47c
3 changed files with 127 additions and 64 deletions

View File

@ -53,11 +53,11 @@ class RateLimiter {
// Default IPs to whitelist (local interface and private networks IPs) // Default IPs to whitelist (local interface and private networks IPs)
$defaultIps = [ $defaultIps = [
['127.0.0.1', false, 'localhost IPv4'], ['127.0.0.1', 0, 'localhost IPv4'],
['::1', false, 'localhost IPv6'], ['::1', 0, 'localhost IPv6'],
['10.0.0.0/8', true, 'Private network (Class A)'], ['10.0.0.0/8', 1, 'Private network (Class A)'],
['172.16.0.0/12', true, 'Private network (Class B)'], ['172.16.0.0/12', 1, 'Private network (Class B)'],
['192.168.0.0/16', true, 'Private network (Class C)'] ['192.168.0.0/16', 1, 'Private network (Class C)']
]; ];
// Insert default whitelisted IPs if they don't exist // Insert default whitelisted IPs if they don't exist
@ -70,11 +70,11 @@ class RateLimiter {
// Insert known malicious networks // Insert known malicious networks
$defaultBlacklist = [ $defaultBlacklist = [
['0.0.0.0/8', true, 'Reserved address space - RFC 1122'], ['0.0.0.0/8', 1, 'Reserved address space - RFC 1122'],
['100.64.0.0/10', true, 'Carrier-grade NAT space - RFC 6598'], ['100.64.0.0/10', 1, 'Carrier-grade NAT space - RFC 6598'],
['192.0.2.0/24', true, 'TEST-NET-1 Documentation space - RFC 5737'], ['192.0.2.0/24', 1, 'TEST-NET-1 Documentation space - RFC 5737'],
['198.51.100.0/24', true, 'TEST-NET-2 Documentation space - RFC 5737'], ['198.51.100.0/24', 1, 'TEST-NET-2 Documentation space - RFC 5737'],
['203.0.113.0/24', true, 'TEST-NET-3 Documentation space - RFC 5737'] ['203.0.113.0/24', 1, 'TEST-NET-3 Documentation space - RFC 5737']
]; ];
$stmt = $this->db->prepare("INSERT OR IGNORE INTO {$this->blacklistTable} $stmt = $this->db->prepare("INSERT OR IGNORE INTO {$this->blacklistTable}
@ -155,13 +155,9 @@ class RateLimiter {
return false; return false;
} }
$stmt = $this->db->prepare("INSERT INTO {$this->whitelistTable} $stmt = $this->db->prepare("INSERT OR REPLACE INTO {$this->whitelistTable}
(ip_address, is_network, description, created_by) (ip_address, is_network, description, created_by)
VALUES (?, ?, ?, ?) VALUES (?, ?, ?, ?)");
ON DUPLICATE KEY UPDATE
is_network = VALUES(is_network),
description = VALUES(description),
created_by = VALUES(created_by)");
$result = $stmt->execute([$ip, $isNetwork, $description, $createdBy]); $result = $stmt->execute([$ip, $isNetwork, $description, $createdBy]);
@ -187,7 +183,7 @@ class RateLimiter {
} }
// Remove from whitelist // Remove from whitelist
public function removeFromWhitelist($ip, $userId = null, $removedBy = 'system') { public function removeFromWhitelist($ip, $removedBy = 'system', $userId = null) {
try { try {
// Get IP details before removal for logging // Get IP details before removal for logging
$stmt = $this->db->prepare("SELECT * FROM {$this->whitelistTable} WHERE ip_address = ?"); $stmt = $this->db->prepare("SELECT * FROM {$this->whitelistTable} WHERE ip_address = ?");
@ -233,14 +229,9 @@ class RateLimiter {
$expiryTime = $expiryHours ? date('Y-m-d H:i:s', strtotime("+{$expiryHours} hours")) : null; $expiryTime = $expiryHours ? date('Y-m-d H:i:s', strtotime("+{$expiryHours} hours")) : null;
$stmt = $this->db->prepare("INSERT INTO {$this->blacklistTable} $stmt = $this->db->prepare("INSERT OR REPLACE INTO {$this->blacklistTable}
(ip_address, is_network, reason, expiry_time, created_by) (ip_address, is_network, reason, expiry_time, created_by)
VALUES (?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?)");
ON DUPLICATE KEY UPDATE
is_network = VALUES(is_network),
reason = VALUES(reason),
expiry_time = VALUES(expiry_time),
created_by = VALUES(created_by)");
$result = $stmt->execute([$ip, $isNetwork, $reason, $expiryTime, $createdBy]); $result = $stmt->execute([$ip, $isNetwork, $reason, $expiryTime, $createdBy]);
@ -265,7 +256,7 @@ class RateLimiter {
} }
} }
public function removeFromBlacklist($ip, $userId = null, $removedBy = 'system') { public function removeFromBlacklist($ip, $removedBy = 'system', $userId = null) {
try { try {
// Get IP details before removal for logging // Get IP details before removal for logging
$stmt = $this->db->prepare("SELECT * FROM {$this->blacklistTable} WHERE ip_address = ?"); $stmt = $this->db->prepare("SELECT * FROM {$this->blacklistTable} WHERE ip_address = ?");

View File

@ -9,55 +9,97 @@ if (!($userObject->hasRight($user_id, 'superuser') ||
exit; exit;
} }
$action = $_GET['action'] ?? 'view'; // Initialize variables for feedback messages
$section = $_GET['section'] ?? 'whitelist'; $error_message = '';
$success_message = '';
// Handle form submissions // Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
switch ($_POST['action']) { $action = $_POST['action'];
$section = isset($_POST['section']) ? $_POST['section'] : (isset($_GET['section']) ? $_GET['section'] : 'whitelist');
try {
switch ($action) {
case 'add_whitelist': case 'add_whitelist':
if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit whitelist')) {
$ip = $_POST['ip_address']; throw new Exception('You do not have permission to modify the whitelist.');
$description = $_POST['description'];
$is_network = isset($_POST['is_network']) ? 1 : 0;
$rateLimiter->addToWhitelist($ip, $is_network, $description, $currentUser);
} }
if (empty($_POST['ip_address'])) {
throw new Exception('IP address is required.');
}
$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.');
}
$success_message = 'IP address successfully added to whitelist.';
break; break;
case 'remove_whitelist': case 'remove_whitelist':
if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit whitelist')) {
$ip = $_POST['ip_address']; throw new Exception('You do not have permission to modify the whitelist.');
$rateLimiter->removeFromWhitelist($ip, $user_id, $currentUser);
} }
if (empty($_POST['ip_address'])) {
throw new Exception('IP address is required.');
}
if (!$rateLimiter->removeFromWhitelist($_POST['ip_address'], $currentUser, $user_id)) {
throw new Exception('Failed to remove IP from whitelist.');
}
$success_message = 'IP address successfully removed from whitelist.';
break; break;
case 'add_blacklist': case 'add_blacklist':
if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit blacklist')) { if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit blacklist')) {
$ip = $_POST['ip_address']; throw new Exception('You do not have permission to modify the blacklist.');
$reason = $_POST['reason'];
$is_network = isset($_POST['is_network']) ? 1 : 0;
$expiry_hours = empty($_POST['expiry_hours']) ? null : intval($_POST['expiry_hours']);
$rateLimiter->addToBlacklist($ip, $is_network, $reason, $currentUser, null, $expiry_hours);
} }
if (empty($_POST['ip_address'])) {
throw new Exception('IP address is required.');
}
$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.');
}
$success_message = 'IP address successfully added to blacklist.';
break; break;
case 'remove_blacklist': case 'remove_blacklist':
if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit blacklist')) { if (!$userObject->hasRight($user_id, 'superuser') && !$userObject->hasRight($user_id, 'edit blacklist')) {
$ip = $_POST['ip_address']; throw new Exception('You do not have permission to modify the blacklist.');
$rateLimiter->removeFromBlacklist($ip, $user_id, $currentUser);
} }
if (empty($_POST['ip_address'])) {
throw new Exception('IP address is required.');
}
if (!$rateLimiter->removeFromBlacklist($_POST['ip_address'], $currentUser, $user_id)) {
throw new Exception('Failed to remove IP from blacklist.');
}
$success_message = 'IP address successfully removed from blacklist.';
break; break;
} }
} catch (Exception $e) {
$error_message = $e->getMessage();
}
// Redirect to prevent form resubmission if (empty($error_message)) {
header("Location: {$app_root}?page=security&section={$section}"); // Only redirect if there was no error
header("Location: {$app_root}?page=security&section={$section}" .
($success_message ? '&success=' . urlencode($success_message) : ''));
exit; exit;
}
} }
// Get the lists // Get success message from URL if redirected after successful action
if (isset($_GET['success'])) {
$success_message = $_GET['success'];
}
// Get current lists
$whitelisted = $rateLimiter->getWhitelistedIps(); $whitelisted = $rateLimiter->getWhitelistedIps();
$blacklisted = $rateLimiter->getBlacklistedIps(); $blacklisted = $rateLimiter->getBlacklistedIps();
// Include the template // Get current section
$section = isset($_GET['section']) ? $_GET['section'] : 'whitelist';
// Include template
include '../app/templates/security.php'; include '../app/templates/security.php';
?> ?>

View File

@ -3,6 +3,18 @@
<div class="row mb-4"> <div class="row mb-4">
<div class="col"> <div class="col">
<h2>Security Settings</h2> <h2>Security Settings</h2>
<?php if (!empty($error_message)): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?= htmlspecialchars($error_message) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if (!empty($success_message)): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?= htmlspecialchars($success_message) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<?php if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { ?> <?php if ($userObject->hasRight($user_id, 'superuser') || $userObject->hasRight($user_id, 'edit whitelist')) { ?>
<li class="nav-item"> <li class="nav-item">
@ -221,3 +233,21 @@
<?php } ?> <?php } ?>
</div> </div>
<!-- /Security Settings --> <!-- /Security Settings -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize Bootstrap alerts
var alerts = document.querySelectorAll('.alert');
alerts.forEach(function(alert) {
var closeButton = alert.querySelector('.btn-close');
if (closeButton) {
closeButton.addEventListener('click', function() {
alert.classList.remove('show');
setTimeout(function() {
alert.remove();
}, 150);
});
}
});
});
</script>