Changeset 3482336
- Timestamp:
- 03/14/2026 01:30:45 AM (3 weeks ago)
- Location:
- atomic-edge-security/trunk
- Files:
-
- 4 edited
-
admin/js/admin.js (modified) (8 diffs)
-
atomicedge.php (modified) (2 diffs)
-
includes/class-atomicedge-ajax.php (modified) (4 diffs)
-
readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
atomic-edge-security/trunk/admin/js/admin.js
r3480349 r3482336 395 395 var actionCell; 396 396 if (log.is_blocked) { 397 actionCell = '<span class="atomicedge-bl ocked-badge" title="This IP is blocked" style="color:#b32d2e;font-weight:600;">' +398 '<span class="dashicons dashicons-lock" style="font-size:14px;width:14px;height:14px;margin-top:3px;"></span> Bl ocked</span>';397 actionCell = '<span class="atomicedge-blacklisted-badge" title="This IP is blacklisted" style="color:#b32d2e;font-weight:600;">' + 398 '<span class="dashicons dashicons-lock" style="font-size:14px;width:14px;height:14px;margin-top:3px;"></span> Blacklisted</span>'; 399 399 } else { 400 actionCell = '<button type="button" class="button button-small atomicedge-bl ock-ip" data-ip="' + self.escapeHtml(log.client_ip || '') + '">Block IP</button>';400 actionCell = '<button type="button" class="button button-small atomicedge-blacklist-ip" data-ip="' + self.escapeHtml(log.client_ip || '') + '">Blacklist</button>'; 401 401 } 402 402 var row = '<tr>' + … … 411 411 }); 412 412 413 // Bind bl ock IP buttons — blocks go to Adaptive Defense (not IP blacklist).414 $tbody.find('.atomicedge-bl ock-ip').on('click', function() {413 // Bind blacklist buttons — adds IP to the Access Control IP blacklist. 414 $tbody.find('.atomicedge-blacklist-ip').on('click', function() { 415 415 var $btn = $(this); 416 416 var ip = $btn.data('ip'); 417 417 if (confirm(atomicedgeAdmin.strings.confirm)) { 418 self.bl ockIpFromWafLogs(ip, $btn);418 self.blacklistIpFromWafLogs(ip, $btn); 419 419 } 420 420 }); … … 579 579 * Block an IP from the WAF logs page via Adaptive Defense. 580 580 * 581 * This sends the block to the AD system (ActorProfile), NOT the582 * Access Control IP blacklist (SiteSettings). The existing583 * ajax_block_ip AJAX handler + api->block_ip() method are reused.581 * This adds the IP to the Access Control IP blacklist 582 * (SiteSettings.ip_blacklist) via the existing ajax_add_ip_blacklist 583 * AJAX handler + api->add_ip_blacklist() method. 584 584 * 585 585 * @param {string} ip IP address. 586 586 * @param {jQuery} $button The button element to update on success. 587 587 */ 588 bl ockIpFromWafLogs: function(ip, $button) {588 blacklistIpFromWafLogs: function(ip, $button) { 589 589 var self = this; 590 590 … … 593 593 } 594 594 595 this.ajax('atomicedge_block_ip', { 595 var description = 'Added from WordPress on ' + this.formatTimestamp(); 596 597 this.ajax('atomicedge_add_ip_blacklist', { 596 598 ip: ip, 597 reason: 'Blocked from WAF logs'599 description: description 598 600 }, function() { 599 // Reload WAF logs so the is_blocked badge appears.601 // Reload WAF logs so the blacklisted badge appears. 600 602 if ($('#atomicedge-waf-table').length) { 601 603 self.loadWafLogs(); … … 606 608 $button.prop('disabled', true) 607 609 .removeClass('button-small') 608 .addClass('atomicedge-bl ocked-btn')609 .html('<span class="dashicons dashicons-yes-alt" style="margin-top:3px;color:#00a32a;"></span> Bl ocked');610 } 611 612 self.showNotice(ip + ' has been blocked via Adaptive Defense.', 'success');610 .addClass('atomicedge-blacklisted-btn') 611 .html('<span class="dashicons dashicons-yes-alt" style="margin-top:3px;color:#00a32a;"></span> Blacklisted'); 612 } 613 614 self.showNotice(ip + ' has been added to the IP blacklist.', 'success'); 613 615 }, function(errData) { 614 616 if ($button) { 615 $button.prop('disabled', false).text('Bl ock IP');617 $button.prop('disabled', false).text('Blacklist'); 616 618 } 617 619 var message = (errData && errData.message) ? errData.message : atomicedgeAdmin.strings.error; … … 1357 1359 1358 1360 /** 1359 * AJAX helper 1360 */ 1361 ajax: function(action, data, success, error) { 1361 * AJAX helper. 1362 * 1363 * On nonce expiry the helper transparently refreshes the nonce and 1364 * retries the original request once. If the retry also fails the 1365 * error is surfaced to the caller normally. 1366 * 1367 * @param {string} action WordPress AJAX action name. 1368 * @param {Object} data POST data (action & nonce are added automatically). 1369 * @param {Function} success Callback on success (receives response.data). 1370 * @param {Function} error Callback on failure (receives response.data). 1371 * @param {boolean} _isRetry Internal flag — do not set manually. 1372 */ 1373 ajax: function(action, data, success, error, _isRetry) { 1362 1374 var self = this; 1363 1375 data = data || {}; … … 1370 1382 data: data, 1371 1383 success: function(response) { 1384 // Transparent nonce refresh: if the server flags a nonce 1385 // error and this is not already a retry, fetch a fresh 1386 // nonce and replay the request. 1387 if (!response.success && response.data && response.data.nonce_error && !_isRetry) { 1388 self.refreshNonceAndRetry(action, data, success, error); 1389 return; 1390 } 1391 1372 1392 if (response.success) { 1373 1393 if (typeof success === 'function') { … … 1394 1414 1395 1415 /** 1416 * Fetch a fresh nonce from the server and replay the failed request. 1417 * 1418 * The refresh endpoint is cookie-authenticated (no nonce required) 1419 * so it succeeds even when the original nonce has expired. 1420 * 1421 * @param {string} action Original AJAX action. 1422 * @param {Object} data Original POST data. 1423 * @param {Function} success Original success callback. 1424 * @param {Function} error Original error callback. 1425 */ 1426 refreshNonceAndRetry: function(action, data, success, error) { 1427 var self = this; 1428 1429 $.ajax({ 1430 url: atomicedgeAdmin.ajaxUrl, 1431 type: 'POST', 1432 data: { action: 'atomicedge_refresh_nonce' }, 1433 success: function(response) { 1434 if (response.success && response.data && response.data.nonce) { 1435 // Store the fresh nonce for all future requests. 1436 atomicedgeAdmin.nonce = response.data.nonce; 1437 // Replay the original request (flagged as retry). 1438 self.ajax(action, data, success, error, true); 1439 } else { 1440 self.showNotice( 1441 'Your session has expired. Please refresh the page and try again.', 1442 'error' 1443 ); 1444 } 1445 }, 1446 error: function() { 1447 self.showNotice( 1448 'Your session has expired. Please refresh the page and try again.', 1449 'error' 1450 ); 1451 } 1452 }); 1453 }, 1454 1455 /** 1396 1456 * Validate IP address or CIDR 1397 1457 */ -
atomic-edge-security/trunk/atomicedge.php
r3476684 r3482336 4 4 * Plugin URI: https://atomicedge.io/wordpress 5 5 * Description: Connect your WordPress site to Atomic Edge WAF/CDN for advanced security protection, analytics, and access control management. 6 * Version: 2.5. 06 * Version: 2.5.1 7 7 * Requires at least: 5.8 8 8 * Requires PHP: 7.4 … … 26 26 27 27 // Plugin constants. 28 define( 'ATOMICEDGE_VERSION', '2.5. 0' );28 define( 'ATOMICEDGE_VERSION', '2.5.1' ); 29 29 define( 'ATOMICEDGE_PLUGIN_FILE', __FILE__ ); 30 30 define( 'ATOMICEDGE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); -
atomic-edge-security/trunk/includes/class-atomicedge-ajax.php
r3480349 r3482336 103 103 add_action( 'wp_ajax_atomicedge_delete_actor', array( $this, 'ajax_delete_actor' ) ); 104 104 add_action( 'wp_ajax_atomicedge_dismiss_detection', array( $this, 'ajax_dismiss_detection' ) ); 105 106 // Nonce refresh (lightweight, no nonce required — cookie-authenticated). 107 add_action( 'wp_ajax_atomicedge_refresh_nonce', array( $this, 'ajax_refresh_nonce' ) ); 105 108 } 106 109 … … 119 122 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; 120 123 if ( ! $nonce || ! wp_verify_nonce( $nonce, 'atomicedge_ajax' ) ) { 121 wp_send_json_error( array( 'message' => __( 'Security check failed.', 'atomic-edge-security' ) ) ); 124 wp_send_json_error( array( 125 'message' => __( 'Security check failed.', 'atomic-edge-security' ), 126 'nonce_error' => true, 127 ) ); 122 128 } 123 129 … … 297 303 if ( ! $this->api->is_valid_ip( $ip ) ) { 298 304 wp_send_json_error( array( 'message' => __( 'Invalid IP address or CIDR range.', 'atomic-edge-security' ) ) ); 305 } 306 307 // Dev mode: return simulated success (only when not connected to real API). 308 if ( $this->should_use_dev_mode() ) { 309 wp_send_json_success( array( 310 'message' => sprintf( 311 /* translators: %s: IP address */ 312 __( '[Dev Mode] IP %s has been added to the blacklist.', 'atomic-edge-security' ), 313 esc_html( $ip ) 314 ), 315 ) ); 299 316 } 300 317 … … 1462 1479 1463 1480 /** 1481 * Return a fresh nonce so the client can retry after expiry. 1482 * 1483 * This endpoint intentionally skips nonce verification — the wp_ajax_ 1484 * hook already proves the user is logged in (cookie-authenticated), and 1485 * the only value returned is a new nonce which is harmless to expose. 1486 * A capability check ensures only admins can obtain a nonce. 1487 * 1488 * @return void 1489 */ 1490 public function ajax_refresh_nonce() { 1491 if ( ! current_user_can( 'manage_options' ) ) { 1492 wp_send_json_error( array( 'message' => __( 'Unauthorized.', 'atomic-edge-security' ) ) ); 1493 } 1494 1495 wp_send_json_success( array( 'nonce' => wp_create_nonce( 'atomicedge_ajax' ) ) ); 1496 } 1497 1498 /** 1464 1499 * Get the user ID for 2FA operations. 1465 1500 * -
atomic-edge-security/trunk/readme.txt
r3476684 r3482336 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 2.5. 07 Stable tag: 2.5.1 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 112 112 113 113 == Changelog == 114 115 = 2.5.1 = 116 * CHANGE: WAF Logs "Block IP" button renamed to "Blacklist" — now adds IPs to edge-level IP Blacklist instead of Adaptive Defense 117 * NEW: Dev mode support for WAF logs blacklist button 118 * NEW: AJAX nonce auto-refresh — expired nonces are transparently refreshed without page reload 114 119 115 120 = 2.5.0 =
Note: See TracChangeset
for help on using the changeset viewer.