Changeset 3480349
- Timestamp:
- 03/11/2026 04:10:04 PM (3 weeks ago)
- Location:
- atomic-edge-security/trunk
- Files:
-
- 6 edited
-
admin/js/adaptive-defense.js (modified) (5 diffs)
-
admin/js/admin.js (modified) (1 diff)
-
includes/class-atomicedge-ajax.php (modified) (7 diffs)
-
includes/class-atomicedge-api.php (modified) (3 diffs)
-
includes/class-atomicedge-dev-mode.php (modified) (1 diff)
-
includes/class-atomicedge.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
atomic-edge-security/trunk/admin/js/adaptive-defense.js
r3476055 r3480349 547 547 html += '<td>'; 548 548 if (!isPermanent) { 549 html += '<button type="button" class="button button-small atomicedge-ad-extend-block-btn" data-ip="' + self.escapeHtml(ip) + '" title="Extend +1 day">';549 html += '<button type="button" class="button button-small atomicedge-ad-extend-block-btn" data-ip="' + self.escapeHtml(ip) + '" title="Extend block">'; 550 550 html += '<span class="dashicons dashicons-clock" style="margin-top:3px;"></span></button> '; 551 html += '<button type="button" class="button button-small atomicedge-ad-make-permanent-btn" data-ip="' + self.escapeHtml(ip) + '" title="Make permanent">'; 552 html += '<span class="dashicons dashicons-lock" style="margin-top:3px;"></span></button> '; 551 if (atomicedge_admin.can_permanent_block) { 552 html += '<button type="button" class="button button-small atomicedge-ad-make-permanent-btn" data-ip="' + self.escapeHtml(ip) + '" title="Make permanent">'; 553 html += '<span class="dashicons dashicons-lock" style="margin-top:3px;"></span></button> '; 554 } else { 555 html += '<button type="button" class="button button-small" disabled title="Permanent blocks are a Pro feature. Upgrade your plan to enable this." style="opacity:0.5;cursor:not-allowed;">'; 556 html += '<span class="dashicons dashicons-lock" style="margin-top:3px;"></span></button> '; 557 } 553 558 } 554 559 html += '<button type="button" class="button button-small atomicedge-ad-unblock-btn" data-ip="' + self.escapeHtml(ip) + '" title="Unblock">'; … … 595 600 596 601 /** 597 * Extend a timed block by 1 day.602 * Extend a timed block using the site's configured duration. 598 603 * 599 604 * @param {string} ip IP address … … 608 613 action: 'atomicedge_extend_block', 609 614 nonce: atomicedge_admin.nonce, 610 ip: ip, 611 days: 1 615 ip: ip 612 616 }, 613 617 success: function(response) { 614 618 if (response.success) { 615 self.showNotice('Block for ' + ip + ' extended by 1 day.', 'success'); 619 var msg = response.data && response.data.message 620 ? response.data.message 621 : 'Block for ' + ip + ' has been extended.'; 622 self.showNotice(msg, 'success'); 616 623 self.loadBlockedIps(); 617 624 } else { … … 632 639 makePermanent: function(ip) { 633 640 var self = this; 641 642 // Client-side plan gate (defense in depth — server also enforces). 643 if (!atomicedge_admin.can_permanent_block) { 644 self.showNotice('Permanent blocks are a Pro feature. Please upgrade your plan to enable this.', 'warning'); 645 return; 646 } 634 647 635 648 if (!confirm('Make the block for ' + ip + ' permanent?')) { … … 650 663 self.loadBlockedIps(); 651 664 } else { 652 self.showNotice(response.data ? response.data.message : 'Failed to make block permanent', 'error'); 665 var msg = response.data ? response.data.message : 'Failed to make block permanent'; 666 var type = 'error'; 667 // Detect plan-limit error from API (defense-in-depth). 668 if (response.data && response.data.error_code === 'plan_limit') { 669 msg = 'Permanent blocks are a Pro feature. Please upgrade your plan to enable this.'; 670 type = 'warning'; 671 } 672 self.showNotice(msg, type); 653 673 } 654 674 }, -
atomic-edge-security/trunk/admin/js/admin.js
r3476684 r3480349 595 595 this.ajax('atomicedge_block_ip', { 596 596 ip: ip, 597 duration_hours: 24,598 597 reason: 'Blocked from WAF logs' 599 598 }, function() { -
atomic-edge-security/trunk/includes/class-atomicedge-ajax.php
r3476684 r3480349 1013 1013 */ 1014 1014 public function ajax_block_ip() { 1015 $post = $this->get_verified_post_fields( array( 'ip', ' duration_hours', 'permanent', 'reason' ) );1015 $post = $this->get_verified_post_fields( array( 'ip', 'permanent', 'reason' ) ); 1016 1016 1017 1017 if ( empty( $post['ip'] ) ) { … … 1019 1019 } 1020 1020 1021 $ip = $post['ip']; 1022 $duration_hours = isset( $post['duration_hours'] ) ? absint( $post['duration_hours'] ) : 24; 1023 $permanent = isset( $post['permanent'] ) && 'true' === $post['permanent']; 1024 $reason = isset( $post['reason'] ) ? sanitize_text_field( $post['reason'] ) : ''; 1021 $ip = $post['ip']; 1022 $permanent = isset( $post['permanent'] ) && 'true' === $post['permanent']; 1023 $reason = isset( $post['reason'] ) ? sanitize_text_field( $post['reason'] ) : ''; 1025 1024 1026 1025 // Dev mode: return simulated success (only when not connected to real API). … … 1036 1035 } 1037 1036 1038 $response = $this->api->block_ip( $ip, $ duration_hours, $permanent, $reason );1037 $response = $this->api->block_ip( $ip, $permanent, $reason ); 1039 1038 1040 1039 if ( $response['success'] ) { … … 1092 1091 /** 1093 1092 * Extend the block duration for a blocked IP. 1093 * Duration is server-authoritative (uses the site's configured auto_block_ttl_hours). 1094 1094 * 1095 1095 * @return void 1096 1096 */ 1097 1097 public function ajax_extend_block() { 1098 $post = $this->get_verified_post_fields( array( 'ip' , 'days') );1098 $post = $this->get_verified_post_fields( array( 'ip' ) ); 1099 1099 1100 1100 if ( empty( $post['ip'] ) ) { … … 1102 1102 } 1103 1103 1104 $ip = $post['ip']; 1105 $days = isset( $post['days'] ) ? max( 1, absint( $post['days'] ) ) : 1; 1104 $ip = $post['ip']; 1106 1105 1107 1106 // Dev mode: return simulated success (only when not connected to real API). … … 1109 1108 wp_send_json_success( array( 1110 1109 'message' => sprintf( 1111 /* translators: 1: IP address, 2: number of days */ 1112 __( '[Dev Mode] Block for %1$s extended by %2$d day(s).', 'atomic-edge-security' ), 1113 esc_html( $ip ), 1114 $days 1110 /* translators: %s: IP address */ 1111 __( '[Dev Mode] Block for %s has been extended.', 'atomic-edge-security' ), 1112 esc_html( $ip ) 1115 1113 ), 1116 'data' => AtomicEdge_Dev_Mode::simulate_extend_block( $ip , $days),1117 ) ); 1118 } 1119 1120 $response = $this->api->extend_block( $ip , $days);1114 'data' => AtomicEdge_Dev_Mode::simulate_extend_block( $ip ), 1115 ) ); 1116 } 1117 1118 $response = $this->api->extend_block( $ip ); 1121 1119 1122 1120 if ( $response['success'] ) { 1123 1121 wp_send_json_success( array( 1124 1122 'message' => sprintf( 1125 /* translators: 1: IP address, 2: number of days */ 1126 __( 'Block for %1$s extended by %2$d day(s).', 'atomic-edge-security' ), 1127 esc_html( $ip ), 1128 $days 1123 /* translators: %s: IP address */ 1124 __( 'Block for %s has been extended.', 'atomic-edge-security' ), 1125 esc_html( $ip ) 1129 1126 ), 1130 1127 'data' => $response['data'] ?? array(), … … 1173 1170 ) ); 1174 1171 } else { 1175 wp_send_json_error( array( 'message' => $response['error'] ?? __( 'Failed to make block permanent.', 'atomic-edge-security' ) ) ); 1172 $error_data = array( 'message' => $response['error'] ?? __( 'Failed to make block permanent.', 'atomic-edge-security' ) ); 1173 if ( ! empty( $response['error_code'] ) ) { 1174 $error_data['error_code'] = sanitize_text_field( $response['error_code'] ); 1175 } 1176 wp_send_json_error( $error_data ); 1176 1177 } 1177 1178 } -
atomic-edge-security/trunk/includes/class-atomicedge-api.php
r3476684 r3480349 622 622 /** 623 623 * Block an IP address via Adaptive Defense. 624 * 625 * @param string $ip IP address to block. 626 * @param int $duration_hours Duration in hours (default 24). 627 * @param bool $permanent Whether the block is permanent. 624 * Duration is server-authoritative (uses the site's configured auto_block_ttl_hours). 625 * 626 * @param string $ip IP address to block. 627 * @param bool $permanent Whether the block is permanent. 628 * @param string $reason Optional reason for blocking. 628 629 * @return array Result. 629 630 */ 630 public function block_ip( $ip, $ duration_hours = 24, $permanent = false, $reason = '' ) {631 public function block_ip( $ip, $permanent = false, $reason = '' ) { 631 632 $data = array( 632 'ip' => $ip, 633 'duration_hours' => $duration_hours, 634 'permanent' => $permanent, 633 'ip' => $ip, 634 'permanent' => $permanent, 635 635 ); 636 636 … … 670 670 /** 671 671 * Extend the block duration for a blocked IP address. 672 * 673 * @param string $ip IP address.674 * @param int $days Number of days to extend (default 1).672 * Duration is server-authoritative (uses the site's configured auto_block_ttl_hours). 673 * 674 * @param string $ip IP address. 675 675 * @return array Result. 676 676 */ 677 public function extend_block( $ip , $days = 1) {677 public function extend_block( $ip ) { 678 678 $response = $this->request( 'POST', '/adaptive-defense/extend-block', array( 679 'ip' => $ip, 680 'days' => $days, 679 'ip' => $ip, 681 680 ) ); 682 681 … … 819 818 // Handle HTTP errors. 820 819 if ( $code >= 400 ) { 821 $error_message = isset( $data['error'] ) ? $data['error'] : __( 'An error occurred.', 'atomic-edge-security' ); 820 $error_code = isset( $data['error'] ) ? $data['error'] : null; 821 $error_message = $error_code ?? __( 'An error occurred.', 'atomic-edge-security' ); 822 822 if ( isset( $data['message'] ) ) { 823 823 $error_message = $data['message']; 824 824 } 825 825 AtomicEdge::log( "API Error ({$code})", $error_message ); 826 returnarray(826 $result = array( 827 827 'success' => false, 828 828 'error' => $error_message, 829 829 'code' => $code, 830 830 ); 831 // Preserve the original error identifier (e.g. 'plan_limit') when 832 // the human-readable message is available separately. 833 if ( null !== $error_code && isset( $data['message'] ) && $error_code !== $data['message'] ) { 834 $result['error_code'] = $error_code; 835 } 836 return $result; 831 837 } 832 838 -
atomic-edge-security/trunk/includes/class-atomicedge-dev-mode.php
r3476055 r3480349 844 844 /** 845 845 * Simulate a successful extend block response. 846 * 847 * @param string $ip IP address.848 * @param int $days Number of days to extend.849 * @return array 850 */ 851 public static function simulate_extend_block( $ip , $days = 1) {846 * Duration is server-authoritative; simulates a 24h extension for dev mode. 847 * 848 * @param string $ip IP address. 849 * @return array 850 */ 851 public static function simulate_extend_block( $ip ) { 852 852 return array( 853 853 'message' => sprintf( 854 /* translators: 1: IP address, 2: number of days */ 855 __( '[Dev Mode] Block for %1$s extended by %2$d day(s).', 'atomic-edge-security' ), 856 $ip, 857 $days 854 /* translators: %s: IP address */ 855 __( '[Dev Mode] Block for %s has been extended.', 'atomic-edge-security' ), 856 $ip 858 857 ), 859 858 'ip' => $ip, 860 859 'is_blocked' => true, 861 860 'blocked_at' => gmdate( 'c', time() - 3600 ), 862 'block_expires_at' => gmdate( 'c', time() + ( $days * 86400 )),861 'block_expires_at' => gmdate( 'c', time() + 86400 ), 863 862 ); 864 863 } -
atomic-edge-security/trunk/includes/class-atomicedge.php
r3473194 r3480349 217 217 218 218 // Localize script with data for adaptive-defense.js. 219 $site_data = get_option( 'atomicedge_site_data', array() ); 220 $can_permanent_block = true; // Default: allow (server-side is the ultimate gate). 221 if ( is_array( $site_data ) ) { 222 if ( isset( $site_data['features']['adaptive_defense_permanent_blocks'] ) ) { 223 $can_permanent_block = (bool) $site_data['features']['adaptive_defense_permanent_blocks']; 224 } elseif ( isset( $site_data['plan_tier'] ) ) { 225 $can_permanent_block = ( 'free' !== $site_data['plan_tier'] ); 226 } 227 } 228 219 229 wp_localize_script( 220 230 'atomicedge-adaptive-defense', 221 231 'atomicedge_admin', 222 232 array( 223 'ajax_url' => admin_url( 'admin-ajax.php' ), 224 'nonce' => wp_create_nonce( 'atomicedge_ajax' ), 225 'access_control_url' => admin_url( 'admin.php?page=atomicedge-access-control&tab=blacklist' ), 233 'ajax_url' => admin_url( 'admin-ajax.php' ), 234 'nonce' => wp_create_nonce( 'atomicedge_ajax' ), 235 'access_control_url' => admin_url( 'admin.php?page=atomicedge-access-control&tab=blacklist' ), 236 'can_permanent_block' => $can_permanent_block, 226 237 ) 227 238 );
Note: See TracChangeset
for help on using the changeset viewer.