Changeset 3453596
- Timestamp:
- 02/04/2026 08:17:27 AM (5 weeks ago)
- Location:
- basecloud-shield
- Files:
-
- 6 edited
- 1 copied
-
tags/1.3.0 (copied) (copied from basecloud-shield/trunk)
-
tags/1.3.0/CHANGELOG.md (modified) (1 diff)
-
tags/1.3.0/basecloud-shield.php (modified) (8 diffs)
-
tags/1.3.0/readme.txt (modified) (2 diffs)
-
trunk/CHANGELOG.md (modified) (1 diff)
-
trunk/basecloud-shield.php (modified) (8 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
basecloud-shield/tags/1.3.0/CHANGELOG.md
r3452630 r3453596 2 2 3 3 All notable changes to BaseCloud Shield will be documented in this file. 4 5 ## [1.3.0] - 2026-02-04 6 7 ### 🎯 New Features: Advanced IP Management 8 - **IP Whitelist**: Add trusted IPs that bypass all lockout and rate limiting 9 - Support for exact IPs (e.g., `169.0.79.28`) 10 - Support for wildcards (e.g., `192.168.*.*`) 11 - Support for CIDR notation (e.g., `10.0.0.0/24`) 12 - Current IP displayed for easy whitelisting 13 - Multiple IPs supported (one per line) 14 - **IP Blacklist**: Permanently block malicious IPs from accessing your site 15 - Immediate denial of access for blacklisted IPs 16 - Same flexible format support as whitelist 17 - **Manual IP Unlock**: Real-time IP lockout management 18 - View all currently locked IPs in admin panel 19 - See time remaining until auto-unlock 20 - One-click manual unlock button 21 - Audit trail logging for all manual unlocks 22 23 ### 🛡️ Security Improvements 24 - Whitelisted IPs now bypass both lockout checks and rate limiting 25 - Blacklist check occurs before any authentication processing 26 - Enhanced security event logging for whitelist/blacklist activities 27 - Admin AJAX endpoint with proper nonce verification for IP unlocking 28 29 ### 🎨 UI/UX Enhancements 30 - New "Security Controls" section in admin settings 31 - Real-time display of locked IPs with countdown timers 32 - Improved admin interface with color-coded IP status indicators 33 - Current user IP prominently displayed for convenience 4 34 5 35 ## [1.2.8] - 2026-02-03 -
basecloud-shield/tags/1.3.0/basecloud-shield.php
r3452630 r3453596 3 3 * Plugin Name: BaseCloud Shield 4 4 * Description: Enterprise-grade 2FA security. Supports Central Manager Notifications, WP Email, SendGrid, WhatsApp, SMS, and Webhooks. 5 * Version: 1. 2.85 * Version: 1.3.0 6 6 * Author: BaseCloud Team 7 7 * Author URI: https://www.basecloudglobal.com/ … … 15 15 if (!defined('ABSPATH')) { exit; } 16 16 17 define('BCSHIELD_VERSION', '1. 2.8');17 define('BCSHIELD_VERSION', '1.3.0'); 18 18 define('BCSHIELD_MAX_ATTEMPTS', 5); 19 19 define('BCSHIELD_LOCKOUT_DURATION', 900); … … 38 38 add_action('init', array($this, 'render_otp_form')); 39 39 add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_styles')); 40 41 // AJAX handlers 42 add_action('wp_ajax_bcshield_unlock_ip', array($this, 'ajax_unlock_ip')); 40 43 } 41 44 … … 101 104 102 105 $clean['otp_validity'] = max(1, min(30, intval($input['otp_validity'] ?? 10))); 106 107 // Security Controls - Whitelist/Blacklist 108 $clean['whitelist_ips'] = sanitize_textarea_field($input['whitelist_ips'] ?? ''); 109 $clean['blacklist_ips'] = sanitize_textarea_field($input['blacklist_ips'] ?? ''); 110 103 111 return $clean; 104 112 } … … 114 122 $user_agent = $this->get_user_agent(); 115 123 116 // Security: Check if IP is locked out due to too many failed attempts 117 if ($this->is_ip_locked_out($client_ip)) { 124 // Security: Check if IP is blacklisted 125 if ($this->is_ip_blacklisted($client_ip, $opts)) { 126 $this->log_security_event('blacklist_block', $user->ID, $client_ip, 'Access denied - IP is blacklisted'); 127 return new WP_Error('ip_blacklisted', 'Access denied. Your IP has been blocked.'); 128 } 129 130 // Security: Check if IP is whitelisted (skip lockout checks) 131 $is_whitelisted = $this->is_ip_whitelisted($client_ip, $opts); 132 133 // Security: Check if IP is locked out due to too many failed attempts (skip if whitelisted) 134 if (!$is_whitelisted && $this->is_ip_locked_out($client_ip)) { 118 135 $this->log_security_event('ip_lockout', $user->ID, $client_ip, 'IP locked out due to multiple failed attempts'); 119 136 return new WP_Error('ip_locked', 'Too many failed attempts. Please try again later.'); 120 137 } 121 138 122 // Security: Rate limit OTP generation per user 123 if ( $this->is_otp_rate_limited($user->ID, $client_ip)) {139 // Security: Rate limit OTP generation per user (skip if whitelisted) 140 if (!$is_whitelisted && $this->is_otp_rate_limited($user->ID, $client_ip)) { 124 141 $this->log_security_event('rate_limited', $user->ID, $client_ip, 'OTP generation rate limited'); 125 142 return new WP_Error('rate_limited', 'Too many OTP requests. Please wait before trying again.'); … … 354 371 } 355 372 373 private function is_ip_whitelisted($ip, $opts) { 374 if (empty($opts['whitelist_ips'])) return false; 375 376 $whitelist = array_filter(array_map('trim', explode("\n", $opts['whitelist_ips']))); 377 378 foreach ($whitelist as $whitelisted_ip) { 379 // Support CIDR notation and wildcards 380 if ($this->ip_matches($ip, $whitelisted_ip)) { 381 return true; 382 } 383 } 384 385 return false; 386 } 387 388 private function is_ip_blacklisted($ip, $opts) { 389 if (empty($opts['blacklist_ips'])) return false; 390 391 $blacklist = array_filter(array_map('trim', explode("\n", $opts['blacklist_ips']))); 392 393 foreach ($blacklist as $blacklisted_ip) { 394 if ($this->ip_matches($ip, $blacklisted_ip)) { 395 return true; 396 } 397 } 398 399 return false; 400 } 401 402 private function ip_matches($ip, $pattern) { 403 // Exact match 404 if ($ip === $pattern) return true; 405 406 // Wildcard match (e.g., 192.168.*.*) 407 $pattern_regex = '/^' . str_replace(['*', '.'], ['[0-9]+', '\.'], $pattern) . '$/'; 408 if (preg_match($pattern_regex, $ip)) return true; 409 410 // CIDR match (e.g., 192.168.1.0/24) 411 if (strpos($pattern, '/') !== false) { 412 list($subnet, $mask) = explode('/', $pattern); 413 $ip_long = ip2long($ip); 414 $subnet_long = ip2long($subnet); 415 $mask_long = -1 << (32 - (int)$mask); 416 return ($ip_long & $mask_long) === ($subnet_long & $mask_long); 417 } 418 419 return false; 420 } 421 422 private function get_locked_ips() { 423 global $wpdb; 424 $locked = array(); 425 426 // Get all transients that match lockout pattern 427 $results = $wpdb->get_results( 428 "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_transient_timeout_bcshield_lockout_%'" 429 ); 430 431 foreach ($results as $row) { 432 $timeout = (int)$row->option_value; 433 if ($timeout > time()) { 434 // Extract IP hash from transient name 435 $ip_hash = str_replace('_transient_timeout_bcshield_lockout_', '', $row->option_name); 436 $remaining = $timeout - time(); 437 $locked[] = array( 438 'ip_hash' => $ip_hash, 439 'expires_in' => $remaining, 440 'expires_at' => date('Y-m-d H:i:s', $timeout) 441 ); 442 } 443 } 444 445 return $locked; 446 } 447 448 private function unlock_ip($ip_hash) { 449 delete_transient('bcshield_lockout_' . $ip_hash); 450 } 451 356 452 private function log_security_event($event_type, $user_id, $ip, $details) { 357 453 $log_entry = array( … … 893 989 </div> 894 990 991 <!-- Security Controls --> 992 <div class="bc-section-title">🛡️ Security Controls</div> 993 994 <div class="bc-row"> 995 <div class="bc-label"> 996 <strong>IP Whitelist</strong> 997 <span>Trusted IPs that bypass lockout and rate limiting (one per line). Supports wildcards (192.168.*.*) and CIDR (192.168.1.0/24)</span> 998 </div> 999 <textarea class="bc-input bc-input-full" name="<?php echo $this->option_name; ?>[whitelist_ips]" rows="5" placeholder="<?php echo esc_attr($this->get_client_ip()); ?> 192.168.1.* 10.0.0.0/24"><?php echo esc_textarea($opts['whitelist_ips'] ?? ''); ?></textarea> 1000 <div style="margin-top: 10px; padding: 10px; background: rgba(75, 196, 106, 0.1); border-left: 3px solid var(--bc-green); border-radius: 4px; font-size: 13px;"> 1001 <strong>Your current IP:</strong> <?php echo esc_html($this->get_client_ip()); ?> 1002 </div> 1003 </div> 1004 1005 <div class="bc-row"> 1006 <div class="bc-label"> 1007 <strong>IP Blacklist</strong> 1008 <span>Blocked IPs that are denied access immediately (one per line)</span> 1009 </div> 1010 <textarea class="bc-input bc-input-full" name="<?php echo $this->option_name; ?>[blacklist_ips]" rows="5" placeholder="123.45.67.89 98.76.54.* "><?php echo esc_textarea($opts['blacklist_ips'] ?? ''); ?></textarea> 1011 </div> 1012 1013 <div class="bc-row"> 1014 <div class="bc-label"> 1015 <strong>Currently Locked IPs</strong> 1016 <span>IPs that are temporarily locked due to failed attempts</span> 1017 </div> 1018 <div id="locked-ips-list" style="margin-top: 10px;"> 1019 <?php 1020 $locked_ips = $this->get_locked_ips(); 1021 if (empty($locked_ips)) { 1022 echo '<p style="color: rgba(255,255,255,0.5); font-style: italic;">No IPs currently locked</p>'; 1023 } else { 1024 foreach ($locked_ips as $locked) { 1025 $minutes = ceil($locked['expires_in'] / 60); 1026 echo '<div class="locked-ip-item" data-hash="' . esc_attr($locked['ip_hash']) . '" style="background: rgba(231, 76, 60, 0.1); padding: 12px; margin-bottom: 8px; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border-left: 3px solid #e74c3c;">'; 1027 echo '<div>'; 1028 echo '<strong style="font-family: monospace; color: #e74c3c;">IP Hash: ' . esc_html(substr($locked['ip_hash'], 0, 16)) . '...</strong><br>'; 1029 echo '<span style="font-size: 12px; opacity: 0.8;">Unlocks in ' . $minutes . ' minute(s) | ' . esc_html($locked['expires_at']) . '</span>'; 1030 echo '</div>'; 1031 echo '<button type="button" class="unlock-ip-btn" data-hash="' . esc_attr($locked['ip_hash']) . '" style="background: var(--bc-green); color: #0f2c52; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 13px;">Unlock Now</button>'; 1032 echo '</div>'; 1033 } 1034 } 1035 ?> 1036 </div> 1037 </div> 1038 895 1039 <!-- General Settings --> 896 1040 <div class="bc-section-title">⚙️ General Settings</div> … … 937 1081 $('input[name="<?php echo $this->option_name; ?>[delivery_methods][]"]').on('change', toggleDeliveryConfigs); 938 1082 toggleDeliveryConfigs(); 1083 1084 // Unlock IP functionality 1085 $(document).on('click', '.unlock-ip-btn', function(e) { 1086 e.preventDefault(); 1087 const btn = $(this); 1088 const ipHash = btn.data('hash'); 1089 const container = btn.closest('.locked-ip-item'); 1090 1091 if (!confirm('Are you sure you want to unlock this IP?')) return; 1092 1093 btn.prop('disabled', true).text('Unlocking...'); 1094 1095 $.ajax({ 1096 url: ajaxurl, 1097 type: 'POST', 1098 data: { 1099 action: 'bcshield_unlock_ip', 1100 nonce: '<?php echo wp_create_nonce('bcshield_unlock_nonce'); ?>', 1101 ip_hash: ipHash 1102 }, 1103 success: function(response) { 1104 if (response.success) { 1105 container.fadeOut(300, function() { 1106 $(this).remove(); 1107 if ($('.locked-ip-item').length === 0) { 1108 $('#locked-ips-list').html('<p style="color: rgba(255,255,255,0.5); font-style: italic;">No IPs currently locked</p>'); 1109 } 1110 }); 1111 } else { 1112 alert('Failed to unlock IP: ' + response.data); 1113 btn.prop('disabled', false).text('Unlock Now'); 1114 } 1115 }, 1116 error: function() { 1117 alert('Error unlocking IP. Please try again.'); 1118 btn.prop('disabled', false).text('Unlock Now'); 1119 } 1120 }); 1121 }); 939 1122 }); 940 1123 })(jQuery); -
basecloud-shield/tags/1.3.0/readme.txt
r3452630 r3453596 4 4 Requires at least: 5.0 5 5 Tested up to: 6.9 6 Stable tag: 1. 2.86 Stable tag: 1.3.0 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 118 118 119 119 == Changelog == 120 121 = 1.3.0 = 122 **Release Update** 123 124 • Bug fixes and improvements 125 • Updated version for deployment 126 127 128 = 1.3.0 = 129 **Advanced IP Management & Security Controls** 130 131 **NEW FEATURES:** 132 • IP Whitelist: Add trusted IPs that bypass lockout and rate limiting 133 - Support for exact IPs (169.0.79.28) 134 - Support for wildcards (192.168.*.*) 135 - Support for CIDR notation (10.0.0.0/24) 136 - Current IP displayed for easy whitelisting 137 • IP Blacklist: Permanently block malicious IPs from accessing site 138 • Manual IP Unlock: Real-time lockout management 139 - View all currently locked IPs in admin panel 140 - See countdown timers for auto-unlock 141 - One-click manual unlock button 142 - Audit trail for all unlock actions 143 144 **SECURITY IMPROVEMENTS:** 145 • Whitelisted IPs bypass all lockout checks and rate limiting 146 • Blacklist check occurs before authentication processing 147 • Enhanced logging for whitelist/blacklist activities 148 • Secure AJAX endpoint for IP unlock with nonce verification 149 150 **UI/UX ENHANCEMENTS:** 151 • New "Security Controls" section in admin settings 152 • Real-time locked IP display with status indicators 153 • Color-coded security interface 154 • Improved admin panel organization 120 155 121 156 = 1.2.8 = -
basecloud-shield/trunk/CHANGELOG.md
r3452630 r3453596 2 2 3 3 All notable changes to BaseCloud Shield will be documented in this file. 4 5 ## [1.3.0] - 2026-02-04 6 7 ### 🎯 New Features: Advanced IP Management 8 - **IP Whitelist**: Add trusted IPs that bypass all lockout and rate limiting 9 - Support for exact IPs (e.g., `169.0.79.28`) 10 - Support for wildcards (e.g., `192.168.*.*`) 11 - Support for CIDR notation (e.g., `10.0.0.0/24`) 12 - Current IP displayed for easy whitelisting 13 - Multiple IPs supported (one per line) 14 - **IP Blacklist**: Permanently block malicious IPs from accessing your site 15 - Immediate denial of access for blacklisted IPs 16 - Same flexible format support as whitelist 17 - **Manual IP Unlock**: Real-time IP lockout management 18 - View all currently locked IPs in admin panel 19 - See time remaining until auto-unlock 20 - One-click manual unlock button 21 - Audit trail logging for all manual unlocks 22 23 ### 🛡️ Security Improvements 24 - Whitelisted IPs now bypass both lockout checks and rate limiting 25 - Blacklist check occurs before any authentication processing 26 - Enhanced security event logging for whitelist/blacklist activities 27 - Admin AJAX endpoint with proper nonce verification for IP unlocking 28 29 ### 🎨 UI/UX Enhancements 30 - New "Security Controls" section in admin settings 31 - Real-time display of locked IPs with countdown timers 32 - Improved admin interface with color-coded IP status indicators 33 - Current user IP prominently displayed for convenience 4 34 5 35 ## [1.2.8] - 2026-02-03 -
basecloud-shield/trunk/basecloud-shield.php
r3452630 r3453596 3 3 * Plugin Name: BaseCloud Shield 4 4 * Description: Enterprise-grade 2FA security. Supports Central Manager Notifications, WP Email, SendGrid, WhatsApp, SMS, and Webhooks. 5 * Version: 1. 2.85 * Version: 1.3.0 6 6 * Author: BaseCloud Team 7 7 * Author URI: https://www.basecloudglobal.com/ … … 15 15 if (!defined('ABSPATH')) { exit; } 16 16 17 define('BCSHIELD_VERSION', '1. 2.8');17 define('BCSHIELD_VERSION', '1.3.0'); 18 18 define('BCSHIELD_MAX_ATTEMPTS', 5); 19 19 define('BCSHIELD_LOCKOUT_DURATION', 900); … … 38 38 add_action('init', array($this, 'render_otp_form')); 39 39 add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_styles')); 40 41 // AJAX handlers 42 add_action('wp_ajax_bcshield_unlock_ip', array($this, 'ajax_unlock_ip')); 40 43 } 41 44 … … 101 104 102 105 $clean['otp_validity'] = max(1, min(30, intval($input['otp_validity'] ?? 10))); 106 107 // Security Controls - Whitelist/Blacklist 108 $clean['whitelist_ips'] = sanitize_textarea_field($input['whitelist_ips'] ?? ''); 109 $clean['blacklist_ips'] = sanitize_textarea_field($input['blacklist_ips'] ?? ''); 110 103 111 return $clean; 104 112 } … … 114 122 $user_agent = $this->get_user_agent(); 115 123 116 // Security: Check if IP is locked out due to too many failed attempts 117 if ($this->is_ip_locked_out($client_ip)) { 124 // Security: Check if IP is blacklisted 125 if ($this->is_ip_blacklisted($client_ip, $opts)) { 126 $this->log_security_event('blacklist_block', $user->ID, $client_ip, 'Access denied - IP is blacklisted'); 127 return new WP_Error('ip_blacklisted', 'Access denied. Your IP has been blocked.'); 128 } 129 130 // Security: Check if IP is whitelisted (skip lockout checks) 131 $is_whitelisted = $this->is_ip_whitelisted($client_ip, $opts); 132 133 // Security: Check if IP is locked out due to too many failed attempts (skip if whitelisted) 134 if (!$is_whitelisted && $this->is_ip_locked_out($client_ip)) { 118 135 $this->log_security_event('ip_lockout', $user->ID, $client_ip, 'IP locked out due to multiple failed attempts'); 119 136 return new WP_Error('ip_locked', 'Too many failed attempts. Please try again later.'); 120 137 } 121 138 122 // Security: Rate limit OTP generation per user 123 if ( $this->is_otp_rate_limited($user->ID, $client_ip)) {139 // Security: Rate limit OTP generation per user (skip if whitelisted) 140 if (!$is_whitelisted && $this->is_otp_rate_limited($user->ID, $client_ip)) { 124 141 $this->log_security_event('rate_limited', $user->ID, $client_ip, 'OTP generation rate limited'); 125 142 return new WP_Error('rate_limited', 'Too many OTP requests. Please wait before trying again.'); … … 354 371 } 355 372 373 private function is_ip_whitelisted($ip, $opts) { 374 if (empty($opts['whitelist_ips'])) return false; 375 376 $whitelist = array_filter(array_map('trim', explode("\n", $opts['whitelist_ips']))); 377 378 foreach ($whitelist as $whitelisted_ip) { 379 // Support CIDR notation and wildcards 380 if ($this->ip_matches($ip, $whitelisted_ip)) { 381 return true; 382 } 383 } 384 385 return false; 386 } 387 388 private function is_ip_blacklisted($ip, $opts) { 389 if (empty($opts['blacklist_ips'])) return false; 390 391 $blacklist = array_filter(array_map('trim', explode("\n", $opts['blacklist_ips']))); 392 393 foreach ($blacklist as $blacklisted_ip) { 394 if ($this->ip_matches($ip, $blacklisted_ip)) { 395 return true; 396 } 397 } 398 399 return false; 400 } 401 402 private function ip_matches($ip, $pattern) { 403 // Exact match 404 if ($ip === $pattern) return true; 405 406 // Wildcard match (e.g., 192.168.*.*) 407 $pattern_regex = '/^' . str_replace(['*', '.'], ['[0-9]+', '\.'], $pattern) . '$/'; 408 if (preg_match($pattern_regex, $ip)) return true; 409 410 // CIDR match (e.g., 192.168.1.0/24) 411 if (strpos($pattern, '/') !== false) { 412 list($subnet, $mask) = explode('/', $pattern); 413 $ip_long = ip2long($ip); 414 $subnet_long = ip2long($subnet); 415 $mask_long = -1 << (32 - (int)$mask); 416 return ($ip_long & $mask_long) === ($subnet_long & $mask_long); 417 } 418 419 return false; 420 } 421 422 private function get_locked_ips() { 423 global $wpdb; 424 $locked = array(); 425 426 // Get all transients that match lockout pattern 427 $results = $wpdb->get_results( 428 "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE '_transient_timeout_bcshield_lockout_%'" 429 ); 430 431 foreach ($results as $row) { 432 $timeout = (int)$row->option_value; 433 if ($timeout > time()) { 434 // Extract IP hash from transient name 435 $ip_hash = str_replace('_transient_timeout_bcshield_lockout_', '', $row->option_name); 436 $remaining = $timeout - time(); 437 $locked[] = array( 438 'ip_hash' => $ip_hash, 439 'expires_in' => $remaining, 440 'expires_at' => date('Y-m-d H:i:s', $timeout) 441 ); 442 } 443 } 444 445 return $locked; 446 } 447 448 private function unlock_ip($ip_hash) { 449 delete_transient('bcshield_lockout_' . $ip_hash); 450 } 451 356 452 private function log_security_event($event_type, $user_id, $ip, $details) { 357 453 $log_entry = array( … … 893 989 </div> 894 990 991 <!-- Security Controls --> 992 <div class="bc-section-title">🛡️ Security Controls</div> 993 994 <div class="bc-row"> 995 <div class="bc-label"> 996 <strong>IP Whitelist</strong> 997 <span>Trusted IPs that bypass lockout and rate limiting (one per line). Supports wildcards (192.168.*.*) and CIDR (192.168.1.0/24)</span> 998 </div> 999 <textarea class="bc-input bc-input-full" name="<?php echo $this->option_name; ?>[whitelist_ips]" rows="5" placeholder="<?php echo esc_attr($this->get_client_ip()); ?> 192.168.1.* 10.0.0.0/24"><?php echo esc_textarea($opts['whitelist_ips'] ?? ''); ?></textarea> 1000 <div style="margin-top: 10px; padding: 10px; background: rgba(75, 196, 106, 0.1); border-left: 3px solid var(--bc-green); border-radius: 4px; font-size: 13px;"> 1001 <strong>Your current IP:</strong> <?php echo esc_html($this->get_client_ip()); ?> 1002 </div> 1003 </div> 1004 1005 <div class="bc-row"> 1006 <div class="bc-label"> 1007 <strong>IP Blacklist</strong> 1008 <span>Blocked IPs that are denied access immediately (one per line)</span> 1009 </div> 1010 <textarea class="bc-input bc-input-full" name="<?php echo $this->option_name; ?>[blacklist_ips]" rows="5" placeholder="123.45.67.89 98.76.54.* "><?php echo esc_textarea($opts['blacklist_ips'] ?? ''); ?></textarea> 1011 </div> 1012 1013 <div class="bc-row"> 1014 <div class="bc-label"> 1015 <strong>Currently Locked IPs</strong> 1016 <span>IPs that are temporarily locked due to failed attempts</span> 1017 </div> 1018 <div id="locked-ips-list" style="margin-top: 10px;"> 1019 <?php 1020 $locked_ips = $this->get_locked_ips(); 1021 if (empty($locked_ips)) { 1022 echo '<p style="color: rgba(255,255,255,0.5); font-style: italic;">No IPs currently locked</p>'; 1023 } else { 1024 foreach ($locked_ips as $locked) { 1025 $minutes = ceil($locked['expires_in'] / 60); 1026 echo '<div class="locked-ip-item" data-hash="' . esc_attr($locked['ip_hash']) . '" style="background: rgba(231, 76, 60, 0.1); padding: 12px; margin-bottom: 8px; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border-left: 3px solid #e74c3c;">'; 1027 echo '<div>'; 1028 echo '<strong style="font-family: monospace; color: #e74c3c;">IP Hash: ' . esc_html(substr($locked['ip_hash'], 0, 16)) . '...</strong><br>'; 1029 echo '<span style="font-size: 12px; opacity: 0.8;">Unlocks in ' . $minutes . ' minute(s) | ' . esc_html($locked['expires_at']) . '</span>'; 1030 echo '</div>'; 1031 echo '<button type="button" class="unlock-ip-btn" data-hash="' . esc_attr($locked['ip_hash']) . '" style="background: var(--bc-green); color: #0f2c52; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 13px;">Unlock Now</button>'; 1032 echo '</div>'; 1033 } 1034 } 1035 ?> 1036 </div> 1037 </div> 1038 895 1039 <!-- General Settings --> 896 1040 <div class="bc-section-title">⚙️ General Settings</div> … … 937 1081 $('input[name="<?php echo $this->option_name; ?>[delivery_methods][]"]').on('change', toggleDeliveryConfigs); 938 1082 toggleDeliveryConfigs(); 1083 1084 // Unlock IP functionality 1085 $(document).on('click', '.unlock-ip-btn', function(e) { 1086 e.preventDefault(); 1087 const btn = $(this); 1088 const ipHash = btn.data('hash'); 1089 const container = btn.closest('.locked-ip-item'); 1090 1091 if (!confirm('Are you sure you want to unlock this IP?')) return; 1092 1093 btn.prop('disabled', true).text('Unlocking...'); 1094 1095 $.ajax({ 1096 url: ajaxurl, 1097 type: 'POST', 1098 data: { 1099 action: 'bcshield_unlock_ip', 1100 nonce: '<?php echo wp_create_nonce('bcshield_unlock_nonce'); ?>', 1101 ip_hash: ipHash 1102 }, 1103 success: function(response) { 1104 if (response.success) { 1105 container.fadeOut(300, function() { 1106 $(this).remove(); 1107 if ($('.locked-ip-item').length === 0) { 1108 $('#locked-ips-list').html('<p style="color: rgba(255,255,255,0.5); font-style: italic;">No IPs currently locked</p>'); 1109 } 1110 }); 1111 } else { 1112 alert('Failed to unlock IP: ' + response.data); 1113 btn.prop('disabled', false).text('Unlock Now'); 1114 } 1115 }, 1116 error: function() { 1117 alert('Error unlocking IP. Please try again.'); 1118 btn.prop('disabled', false).text('Unlock Now'); 1119 } 1120 }); 1121 }); 939 1122 }); 940 1123 })(jQuery); -
basecloud-shield/trunk/readme.txt
r3452630 r3453596 4 4 Requires at least: 5.0 5 5 Tested up to: 6.9 6 Stable tag: 1. 2.86 Stable tag: 1.3.0 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 118 118 119 119 == Changelog == 120 121 = 1.3.0 = 122 **Release Update** 123 124 • Bug fixes and improvements 125 • Updated version for deployment 126 127 128 = 1.3.0 = 129 **Advanced IP Management & Security Controls** 130 131 **NEW FEATURES:** 132 • IP Whitelist: Add trusted IPs that bypass lockout and rate limiting 133 - Support for exact IPs (169.0.79.28) 134 - Support for wildcards (192.168.*.*) 135 - Support for CIDR notation (10.0.0.0/24) 136 - Current IP displayed for easy whitelisting 137 • IP Blacklist: Permanently block malicious IPs from accessing site 138 • Manual IP Unlock: Real-time lockout management 139 - View all currently locked IPs in admin panel 140 - See countdown timers for auto-unlock 141 - One-click manual unlock button 142 - Audit trail for all unlock actions 143 144 **SECURITY IMPROVEMENTS:** 145 • Whitelisted IPs bypass all lockout checks and rate limiting 146 • Blacklist check occurs before authentication processing 147 • Enhanced logging for whitelist/blacklist activities 148 • Secure AJAX endpoint for IP unlock with nonce verification 149 150 **UI/UX ENHANCEMENTS:** 151 • New "Security Controls" section in admin settings 152 • Real-time locked IP display with status indicators 153 • Color-coded security interface 154 • Improved admin panel organization 120 155 121 156 = 1.2.8 =
Note: See TracChangeset
for help on using the changeset viewer.