| @@ -8,8 +8,9 @@ | ||
| 8 | 8 | namespace WP_Defender\Controller; |
| 9 | 9 | |
| 10 | 10 | use Calotes\Component\Request; |
| 11 | 11 | use Calotes\Component\Response; |
| 12 | +use WP_Defender\Component\Network_Cron_Manager; | |
| 12 | 13 | use WP_Defender\Component\Config\Config_Hub_Helper; |
| 13 | 14 | use WP_Defender\Event; |
| 14 | 15 | use WP_Defender\Traits\Setting; |
| 15 | 16 | use WP_Defender\Traits\Defender_Dashboard_Client; |
| @@ -70,8 +71,10 @@ | ||
| 70 | 71 | $this->model = $model; |
| 71 | 72 | $this->service = $service; |
| 72 | 73 | $this->wpmudev = $wpmudev; |
| 73 | 74 | |
| 75 | + add_action( 'admin_init', array( $this, 'maybe_hcm_connection_attempt' ), 20 ); | |
| 76 | + add_action( 'wpdef_hub_connector_synced', array( $this, 'maybe_hcm_connection_attempt' ) ); | |
| 74 | 77 | add_action( 'wpmudev_hub_connector_first_sync_completed', array( $this, 'maybe_hcm_connection_attempt' ) ); |
| 75 | 78 | |
| 76 | 79 | /** |
| 77 | 80 | * Download and store Blocklist from the API. |
| @@ -76,19 +79,28 @@ | ||
| 76 | 79 | /** |
| 77 | 80 | * Download and store Blocklist from the API. |
| 78 | 81 | */ |
| 79 | 82 | if ( $this->service->is_active_via_plugin() ) { |
| 80 | - if ( ! wp_next_scheduled( 'wpdef_antibot_global_firewall_fetch_blocklist' ) ) { | |
| 81 | - wp_schedule_event( time() + 15, Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_SCHEDULE, 'wpdef_antibot_global_firewall_fetch_blocklist' ); | |
| 82 | - } | |
| 83 | + /** | |
| 84 | + * Network Cron Manager | |
| 85 | + * | |
| 86 | + * @var Network_Cron_Manager $network_cron_manager | |
| 87 | + */ | |
| 88 | + $network_cron_manager = wd_di()->get( Network_Cron_Manager::class ); | |
| 89 | + $network_cron_manager->register_callback( | |
| 90 | + 'wpdef_antibot_global_firewall_fetch_blocklist', | |
| 91 | + array( $this, 'handle_download_and_store_blocklist' ), | |
| 92 | + 12 * HOUR_IN_SECONDS, | |
| 93 | + time() + 15 | |
| 94 | + ); | |
| 83 | 95 | } elseif ( wp_next_scheduled( 'wpdef_antibot_global_firewall_fetch_blocklist' ) ) { |
| 84 | 96 | wp_clear_scheduled_hook( 'wpdef_antibot_global_firewall_fetch_blocklist' ); |
| 85 | 97 | } |
| 86 | - add_action( 'wpdef_antibot_global_firewall_fetch_blocklist', array( $this, 'handle_download_and_store_blocklist' ) ); | |
| 87 | 98 | |
| 88 | 99 | if ( $this->wpmudev->is_wpmu_hosting() ) { |
| 89 | 100 | add_action( 'init', array( $this, 'sync_state' ) ); |
| 90 | 101 | } |
| 102 | + add_action( 'init', array( $this, 'handle_expired_membership' ) ); | |
| 91 | 103 | } |
| 92 | 104 | |
| 93 | 105 | /** |
| 94 | 106 | * Handle request to save settings. |
| @@ -100,28 +112,29 @@ | ||
| 100 | 112 | */ |
| 101 | 113 | public function save_settings( Request $request ) { |
| 102 | 114 | $data = $request->get_data( |
| 103 | 115 | array( |
| 104 | - 'enabled' => array( 'type' => 'bool' ), | |
| 105 | - 'managed_by' => array( 'type' => 'string' ), | |
| 116 | + 'enabled' => array( 'type' => 'bool' ), | |
| 117 | + 'managed_by' => array( 'type' => 'string' ), | |
| 106 | 118 | // Temporary property. |
| 107 | - 'module_title' => array( | |
| 119 | + 'module_title' => array( | |
| 108 | 120 | 'type' => 'string', |
| 109 | 121 | 'sanitize' => 'sanitize_text_field', |
| 110 | 122 | ), |
| 111 | - 'module_location' => array( | |
| 123 | + 'module_location' => array( | |
| 112 | 124 | 'type' => 'string', |
| 113 | 125 | 'sanitize' => 'sanitize_text_field', |
| 114 | 126 | ), |
| 127 | + 'redirect_to_feature_page' => array( 'type' => 'bool' ), | |
| 115 | 128 | // End. |
| 116 | 129 | ) |
| 117 | 130 | ); |
| 118 | - $old_enabled = (bool) $this->model->enabled; | |
| 131 | + $old_enabled = $this->model->enabled; | |
| 119 | 132 | |
| 120 | 133 | $location = 'Feature Page'; |
| 121 | 134 | // Split module's titles and locations. |
| 122 | 135 | if ( isset( $data['module_title'] ) && 'antibot' === $data['module_title'] ) { |
| 123 | - if ( empty( $data['module_location'] ) ) { | |
| 136 | + if ( ! isset( $data['module_location'] ) || '' === $data['module_location'] ) { | |
| 124 | 137 | $location = 'Dashboard'; |
| 125 | 138 | } else { |
| 126 | 139 | $location = $data['module_location']; |
| 127 | 140 | unset( $data['module_location'] ); |
| @@ -153,13 +166,8 @@ | ||
| 153 | 166 | } |
| 154 | 167 | } |
| 155 | 168 | |
| 156 | 169 | Config_Hub_Helper::set_clear_active_flag(); |
| 157 | - | |
| 158 | - // Hide the Antibot notice on the Dashboard page. | |
| 159 | - if ( ! empty( $data['enabled'] ) ) { | |
| 160 | - delete_site_option( Antibot_Global_Firewall_Component::NOTICE_SLUG ); | |
| 161 | - } | |
| 162 | 170 | // Maybe track. |
| 163 | 171 | if ( ! defender_is_wp_cli() && $old_enabled !== $data['enabled'] ) { |
| 164 | 172 | wd_di()->get( Antibot_Analytics::class )->track_antibot( $old_enabled, $location ); |
| 165 | 173 | } |
| @@ -167,13 +175,20 @@ | ||
| 167 | 175 | $update_message = $this->get_update_message( $data, $old_enabled, Antibot_Global_Firewall_Setting::get_module_name() ); |
| 168 | 176 | $referrer = wp_get_referer(); |
| 169 | 177 | if ( $referrer && strpos( $referrer, 'page=wp-defender' ) !== false ) { |
| 170 | 178 | $update_message = sprintf( |
| 171 | - /* translators: 1: Bold open tag, 2: Bold close tag */ | |
| 179 | + /* translators: 1: Module name. */ | |
| 172 | 180 | __( '%s is now enabled.', 'defender-security' ), |
| 173 | 181 | '<strong>' . Antibot_Global_Firewall_Setting::get_module_name() . '</strong>' |
| 174 | 182 | ); |
| 175 | 183 | } |
| 184 | + | |
| 185 | + $data_frontend = $this->data_frontend(); | |
| 186 | + | |
| 187 | + if ( isset( $data['redirect_to_feature_page'] ) && $data['redirect_to_feature_page'] ) { | |
| 188 | + $data_frontend['redirect'] = network_admin_url( 'admin.php?page=wdf-ip-lockout' ); | |
| 189 | + } | |
| 190 | + | |
| 176 | 191 | return new Response( |
| 177 | 192 | true, |
| 178 | 193 | array_merge( |
| 179 | 194 | array( |
| @@ -179,9 +194,9 @@ | ||
| 179 | 194 | array( |
| 180 | 195 | 'message' => $update_message, |
| 181 | 196 | 'auto_close' => true, |
| 182 | 197 | ), |
| 183 | - $this->data_frontend() | |
| 198 | + $data_frontend | |
| 184 | 199 | ) |
| 185 | 200 | ); |
| 186 | 201 | } |
| 187 | 202 | |
| @@ -191,27 +206,15 @@ | ||
| 191 | 206 | ); |
| 192 | 207 | } |
| 193 | 208 | |
| 194 | 209 | /** |
| 195 | - * Hide the Antibot notice. | |
| 196 | - * | |
| 197 | - * @return Response | |
| 198 | - * @defender_route | |
| 199 | - */ | |
| 200 | - public function hide_antibot_notice(): Response { | |
| 201 | - delete_site_option( Antibot_Global_Firewall_Component::NOTICE_SLUG ); | |
| 202 | - | |
| 203 | - return new Response( true, array() ); | |
| 204 | - } | |
| 205 | - | |
| 206 | - /** | |
| 207 | 210 | * Queue assets and require data. |
| 208 | 211 | * |
| 209 | 212 | * @return void |
| 210 | 213 | */ |
| 211 | 214 | public function enqueue_assets() { |
| 212 | - if ( $this->is_page_active() ) { | |
| 213 | - wp_localize_script( 'def-iplockout', 'antibot', $this->data_frontend() ); | |
| 215 | + if ( ! $this->is_page_active() ) { | |
| 216 | + return; | |
| 214 | 217 | } |
| 215 | 218 | } |
| 216 | 219 | |
| 217 | 220 | /** |
| @@ -219,22 +222,8 @@ | ||
| 219 | 222 | * |
| 220 | 223 | * @return array |
| 221 | 224 | */ |
| 222 | 225 | public function data_frontend(): array { |
| 223 | - /** | |
| 224 | - * Show the onboarding reminder notice if: | |
| 225 | - * 1. If the reminder time is set and the time difference is greater than a week. | |
| 226 | - * 2. No click on the Cross icon before. | |
| 227 | - */ | |
| 228 | - $is_reminder = false; | |
| 229 | - $last_reminder = get_site_option( Onboard::REMINDER_KEY, 0 ); | |
| 230 | - if ( ! empty( $last_reminder ) ) { | |
| 231 | - $time_diff = time() - $last_reminder; | |
| 232 | - if ( $time_diff > WEEK_IN_SECONDS ) { | |
| 233 | - $is_reminder = true; | |
| 234 | - } | |
| 235 | - } | |
| 236 | - | |
| 237 | 226 | $model_export = $this->model->export(); |
| 238 | 227 | $model_export['managed_by'] = $this->service->get_managed_by(); |
| 239 | 228 | $module_name = Antibot_Global_Firewall_Setting::get_module_name(); |
| 240 | 229 | |
| @@ -243,15 +232,19 @@ | ||
| 243 | 232 | 'model' => $model_export, |
| 244 | 233 | 'misc' => array( |
| 245 | 234 | 'module_slug' => Antibot_Global_Firewall_Setting::get_module_slug(), |
| 246 | 235 | 'module_name' => $module_name, |
| 247 | - 'show_notice' => $is_reminder | |
| 248 | - && (bool) get_site_option( Antibot_Global_Firewall_Component::NOTICE_SLUG, false ), | |
| 236 | + 'show_notice' => false, | |
| 249 | 237 | 'sync_schedule' => __( 'Twice Daily', 'defender-security' ), |
| 250 | 238 | 'ips_count' => $this->service->get_blocklisted_ip_count(), |
| 239 | + 'blocklist_stats_full' => $this->service->get_cached_blocklist_stats_data(), | |
| 251 | 240 | 'frontend_is_enabled' => $this->service->frontend_is_enabled(), |
| 252 | 241 | 'frontend_mode' => $this->service->frontend_mode(), |
| 253 | 242 | 'is_active' => $this->service->is_active(), |
| 243 | + 'show_stats_button' => ! $this->wpmudev->is_whitelabel_enabled(), | |
| 244 | + 'show_checker' => ! $this->wpmudev->is_wpmu_hosting() | |
| 245 | + || $this->wpmudev->is_wpmu_dev_admin() | |
| 246 | + || ! ( $this->service->is_active_via_hosting() && $this->wpmudev->is_whitelabel_enabled() ), | |
| 254 | 247 | 'active_tooltip_text' => __( 'List of exploit attempts detected and blocked across all connected sites by AntiBot Firewall.', 'defender-security' ), |
| 255 | 248 | 'inactive_tooltip_text' => sprintf( |
| 256 | 249 | /* translators: %s: Module name. */ |
| 257 | 250 | __( '%s is Inactive.', 'defender-security' ), |
| @@ -256,8 +249,11 @@ | ||
| 256 | 249 | /* translators: %s: Module name. */ |
| 257 | 250 | __( '%s is Inactive.', 'defender-security' ), |
| 258 | 251 | $module_name |
| 259 | 252 | ), |
| 253 | + 'current_user' => esc_html( wp_get_current_user()->display_name ?? __( 'User', 'defender-security' ) ), | |
| 254 | + 'is_expired_membership' => $this->is_expired_membership_type(), | |
| 255 | + 'show_antibot_options' => $this->service->get_states_of_antibot_options_for_different_hosting_types(), | |
| 260 | 256 | ), |
| 261 | 257 | ), |
| 262 | 258 | $this->dump_routes_and_nonces() |
| 263 | 259 | ); |
| @@ -269,15 +265,15 @@ | ||
| 269 | 265 | * @return void |
| 270 | 266 | */ |
| 271 | 267 | public function handle_download_and_store_blocklist(): void { |
| 272 | 268 | if ( is_multisite() ) { |
| 273 | - $next_run = get_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION, 0 ); | |
| 274 | - if ( ! empty( $next_run ) && $next_run > time() ) { | |
| 269 | + $next_run = (int) get_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION, 0 ); | |
| 270 | + if ( $next_run > 0 && $next_run > time() ) { | |
| 275 | 271 | return; |
| 276 | 272 | } |
| 277 | 273 | |
| 278 | - $interval = wd_di()->get( Scheduler::class )->get_cron_schedule_interval( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_SCHEDULE ); | |
| 279 | - $next_run = time() + ( ! empty( $interval ) ? $interval : 12 * HOUR_IN_SECONDS ); | |
| 274 | + $interval = (int) wd_di()->get( Scheduler::class )->get_cron_schedule_interval( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_SCHEDULE ); | |
| 275 | + $next_run = time() + ( $interval > 0 ? $interval : 12 * HOUR_IN_SECONDS ); | |
| 280 | 276 | update_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION, $next_run ); |
| 281 | 277 | } |
| 282 | 278 | |
| 283 | 279 | if ( true === $this->service->is_active_via_plugin() ) { |
| @@ -302,9 +298,9 @@ | ||
| 302 | 298 | public function maybe_hcm_connection_attempt() { |
| 303 | 299 | $data = get_site_transient( Hub_Connector::TRANSIENT_KEY ); |
| 304 | 300 | $module_slug = $data['module_slug'] ?? ''; |
| 305 | 301 | |
| 306 | - if ( Antibot_Global_Firewall_Setting::get_module_slug() === $module_slug && self::get_status() ) { | |
| 302 | + if ( Antibot_Global_Firewall_Setting::get_module_slug() === $module_slug && self::get_hcm_status() ) { | |
| 307 | 303 | delete_site_transient( Hub_Connector::TRANSIENT_KEY ); |
| 308 | 304 | |
| 309 | 305 | if ( 'plugin' === $this->service->get_managed_by() ) { |
| 310 | 306 | $this->service->managed_by_plugin_action(); |
| @@ -315,10 +311,14 @@ | ||
| 315 | 311 | } |
| 316 | 312 | |
| 317 | 313 | /** |
| 318 | 314 | * Export the data of this module, we will use this for export to HUB, create a preset etc. |
| 315 | + * | |
| 316 | + * @return array | |
| 319 | 317 | */ |
| 320 | - public function to_array() {} | |
| 318 | + public function to_array(): array { | |
| 319 | + return array(); | |
| 320 | + } | |
| 321 | 321 | |
| 322 | 322 | /** |
| 323 | 323 | * Import the data from the HUB, or from the preset. |
| 324 | 324 | * |
| @@ -346,12 +346,16 @@ | ||
| 346 | 346 | */ |
| 347 | 347 | public function remove_data() { |
| 348 | 348 | $this->service->delete_blocklist(); |
| 349 | 349 | |
| 350 | + delete_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION ); | |
| 351 | + // Don't display Antibot global notice. We can delete slugs about this notice in the future. | |
| 350 | 352 | delete_site_option( Antibot_Global_Firewall_Component::NOTICE_SLUG ); |
| 351 | - delete_site_option( Antibot_Global_Firewall_Component::DOWNLOAD_SYNC_NEXT_RUN_OPTION ); | |
| 353 | + delete_site_option( Antibot_Global_Firewall_Component::GLOBAL_NOTICE_TIME_OPTION ); | |
| 354 | + // Blocklist stats data. | |
| 352 | 355 | delete_site_transient( Antibot_Global_Firewall_Component::BLOCKLIST_STATS_KEY . '_' . Antibot_Global_Firewall_Setting::MODE_BASIC ); |
| 353 | 356 | delete_site_transient( Antibot_Global_Firewall_Component::BLOCKLIST_STATS_KEY . '_' . Antibot_Global_Firewall_Setting::MODE_STRICT ); |
| 357 | + delete_site_transient( Antibot_Global_Firewall_Component::BLOCKLIST_STATS_FULL_KEY ); | |
| 354 | 358 | delete_site_transient( Antibot_Global_Firewall_Component::IS_SWITCHING_TO_PLUGIN_IN_PROGRESS ); |
| 355 | 359 | } |
| 356 | 360 | |
| 357 | 361 | /** |
| @@ -363,19 +367,8 @@ | ||
| 363 | 367 | return array(); |
| 364 | 368 | } |
| 365 | 369 | |
| 366 | 370 | /** |
| 367 | - * Disconnect site from HUB. | |
| 368 | - * | |
| 369 | - * @defender_route | |
| 370 | - * @return Response | |
| 371 | - */ | |
| 372 | - public function disconnect_site(): Response { | |
| 373 | - $this->logout(); | |
| 374 | - return new Response( true, array( 'message' => __( 'Your site has been disconnected successfully!', 'defender-security' ) ) ); | |
| 375 | - } | |
| 376 | - | |
| 377 | - /** | |
| 378 | 371 | * Handle request to switch managed by. |
| 379 | 372 | * |
| 380 | 373 | * @defender_route |
| 381 | 374 | * @return Response |
| @@ -426,9 +419,9 @@ | ||
| 426 | 419 | 'sanitize' => 'sanitize_text_field', |
| 427 | 420 | ), |
| 428 | 421 | 'email' => array( |
| 429 | 422 | 'type' => 'string', |
| 430 | - 'sanitize' => 'sanitize_text_field', | |
| 423 | + 'sanitize' => 'sanitize_email', | |
| 431 | 424 | ), |
| 432 | 425 | 'service' => array( |
| 433 | 426 | 'type' => 'string', |
| 434 | 427 | 'sanitize' => 'sanitize_text_field', |
| @@ -438,18 +431,40 @@ | ||
| 438 | 431 | 'sanitize' => 'sanitize_text_field', |
| 439 | 432 | ), |
| 440 | 433 | ) |
| 441 | 434 | ); |
| 435 | + | |
| 436 | + $reporter_email = isset( $data['email'] ) ? trim( $data['email'] ) : ''; | |
| 437 | + if ( '' === $reporter_email || ! is_email( $reporter_email ) ) { | |
| 438 | + return new Response( | |
| 439 | + false, | |
| 440 | + array( | |
| 441 | + 'message' => esc_html__( 'A valid email address is required.', 'defender-security' ), | |
| 442 | + ) | |
| 443 | + ); | |
| 444 | + } | |
| 445 | + | |
| 442 | 446 | // Logging. |
| 443 | 447 | $message = sprintf( |
| 444 | 448 | 'IP: %s, email: %s, service: %s, reason: %s', |
| 445 | 449 | $data['ip'], |
| 446 | - $data['email'], | |
| 450 | + $reporter_email, | |
| 447 | 451 | $data['service'], |
| 448 | 452 | $data['reason'] |
| 449 | 453 | ); |
| 450 | 454 | $this->service->log_ip_message( $message ); |
| 451 | 455 | |
| 456 | + // Track the request. Forced so it operates independently of tracking consent. | |
| 457 | + $this->forced_track( | |
| 458 | + 'def_request_trusted_ip', | |
| 459 | + array( | |
| 460 | + 'IP Address' => $data['ip'], | |
| 461 | + 'User Email' => $reporter_email, | |
| 462 | + 'Service' => $data['service'], | |
| 463 | + 'Reason' => $data['reason'], | |
| 464 | + ) | |
| 465 | + ); | |
| 466 | + | |
| 452 | 467 | return new Response( true, array() ); |
| 453 | 468 | } |
| 454 | 469 | |
| 455 | 470 | /** |
| @@ -483,8 +498,17 @@ | ||
| 483 | 498 | |
| 484 | 499 | $bl_service = wd_di()->get( Blacklist_Lockout::class ); |
| 485 | 500 | $gi_service = wd_di()->get( Global_IP::class ); |
| 486 | 501 | |
| 502 | + $ip = $data['ip']; | |
| 503 | + | |
| 504 | + $is_ip_allowed = $bl_service->is_ip_whitelisted( $ip ) | |
| 505 | + || $bl_service->is_country_whitelist( $ip ) | |
| 506 | + || ( $gi_service->is_global_ip_enabled() && $gi_service->is_ip_allowed( $ip ) ); | |
| 507 | + | |
| 508 | + // Fetch the latest Custom IP blocklist from the Hub so we don't rely on stale cached data. | |
| 509 | + $gi_service->fetch_global_ip_list(); | |
| 510 | + | |
| 487 | 511 | return new Response( |
| 488 | 512 | true, |
| 489 | 513 | array( |
| 490 | 514 | 'success' => true, |
| @@ -489,11 +513,11 @@ | ||
| 489 | 513 | array( |
| 490 | 514 | 'success' => true, |
| 491 | 515 | 'show_notice' => false, |
| 492 | 516 | 'message' => __( 'The IP address is searched successfully.', 'defender-security' ), |
| 493 | - 'local' => $bl_service->is_blacklist( $data['ip'] ), | |
| 494 | - 'central' => $gi_service->is_global_ip_enabled() && $gi_service->is_ip_blocked( $data['ip'] ), | |
| 495 | - 'antibot' => $this->service->is_ip_blocked( $data['ip'] ), | |
| 517 | + 'local' => ! $is_ip_allowed && $bl_service->is_blacklist( $data['ip'] ), | |
| 518 | + 'central' => ! $is_ip_allowed && $gi_service->is_global_ip_enabled() && $gi_service->is_ip_blocked( $data['ip'] ), | |
| 519 | + 'antibot' => ! $is_ip_allowed && $this->service->is_ip_blocked( $ip ), | |
| 496 | 520 | ) |
| 497 | 521 | ); |
| 498 | 522 | } |
| 499 | 523 | |
| @@ -522,17 +546,19 @@ | ||
| 522 | 546 | 'message' => esc_html__( 'Invalid IP address.', 'defender-security' ), |
| 523 | 547 | ) |
| 524 | 548 | ); |
| 525 | 549 | } |
| 526 | - $collection = 'allowlist'; | |
| 550 | + $collection = 'allowlist'; | |
| 551 | + $model = wd_di()->get( \WP_Defender\Model\Setting\Blacklist_Lockout::class ); | |
| 552 | + $already_in_list = $model->is_ip_in_list( $ip, $collection ); | |
| 553 | + | |
| 527 | 554 | // Add to Local allowlist. |
| 528 | - $model = wd_di()->get( \WP_Defender\Model\Setting\Blacklist_Lockout::class ); | |
| 529 | - if ( ! $model->is_ip_in_list( $ip, $collection ) ) { | |
| 555 | + if ( ! $already_in_list ) { | |
| 530 | 556 | $model->add_to_list( $ip, $collection ); |
| 531 | 557 | } |
| 532 | 558 | // Add to Custom IP allowlist. |
| 533 | 559 | $global_ip_service = wd_di()->get( Global_IP::class ); |
| 534 | - if ( $global_ip_service->can_central_ip_autosync() ) { | |
| 560 | + if ( ! $already_in_list && $global_ip_service->can_central_ip_autosync() ) { | |
| 535 | 561 | $data = array( |
| 536 | 562 | 'allow_list' => array( $ip ), |
| 537 | 563 | ); |
| 538 | 564 | |
| @@ -546,22 +572,40 @@ | ||
| 546 | 572 | ); |
| 547 | 573 | } |
| 548 | 574 | } |
| 549 | 575 | |
| 576 | + $manage_link_open = '<a href="' . network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist#tab-ip-allowlist' ) . '">'; | |
| 577 | + $manage_link_close = '</a>'; | |
| 578 | + | |
| 579 | + if ( $already_in_list ) { | |
| 580 | + $message = sprintf( | |
| 581 | + /* translators: 1: IP address. 2: Opening anchor tag. 3: Closing anchor tag. */ | |
| 582 | + esc_html__( | |
| 583 | + 'IP %1$s is already in your Site\'s allowlist. You can manage it in %2$sIP Lockouts%3$s.', | |
| 584 | + 'defender-security' | |
| 585 | + ), | |
| 586 | + $ip, | |
| 587 | + $manage_link_open, | |
| 588 | + $manage_link_close | |
| 589 | + ); | |
| 590 | + } else { | |
| 591 | + $message = sprintf( | |
| 592 | + /* translators: 1: IP address. 2: Opening anchor tag. 3: Closing anchor tag. */ | |
| 593 | + esc_html__( | |
| 594 | + 'IP %1$s has been added to your Site\'s allowlist. You can manage it in %2$sIP Lockouts%3$s.', | |
| 595 | + 'defender-security' | |
| 596 | + ), | |
| 597 | + $ip, | |
| 598 | + $manage_link_open, | |
| 599 | + $manage_link_close | |
| 600 | + ); | |
| 601 | + } | |
| 602 | + | |
| 550 | 603 | return new Response( |
| 551 | 604 | true, |
| 552 | 605 | array( |
| 553 | - 'message' => sprintf( | |
| 554 | - /* translators: 1: IP address. 2: Opening anchor tag. 3: Closing anchor tag. */ | |
| 555 | - esc_html__( | |
| 556 | - 'IP %1$s has been added to your Site\'s allowlist. You can manage it in %2$sIP Lockouts%3$s.', | |
| 557 | - 'defender-security' | |
| 558 | - ), | |
| 559 | - $ip, | |
| 560 | - '<a href="' . network_admin_url( 'admin.php?page=wdf-ip-lockout&view=blocklist#tab-ip-allowlist' ) . '">', | |
| 561 | - '</a>' | |
| 562 | - ), | |
| 563 | - 'interval' => 5, | |
| 606 | + 'message' => $message, | |
| 607 | + 'already_in_list' => $already_in_list, | |
| 564 | 608 | ) |
| 565 | 609 | ); |
| 566 | 610 | } |
| 567 | 611 | |
| @@ -634,7 +678,61 @@ | ||
| 634 | 678 | 'data' => array( |
| 635 | 679 | 'message' => __( 'Failed to switch. Please try again.', 'defender-security' ), |
| 636 | 680 | 'auto_close' => true, |
| 637 | 681 | ), |
| 682 | + ); | |
| 683 | + } | |
| 684 | + | |
| 685 | + /** | |
| 686 | + * Handle expired membership by automatically disabling the AntiBot Global Firewall module. | |
| 687 | + * Logs the action when the feature is disabled due to expired membership. | |
| 688 | + * | |
| 689 | + * @return void | |
| 690 | + */ | |
| 691 | + public function handle_expired_membership(): void { | |
| 692 | + if ( $this->model->enabled && $this->is_expired_membership_type() ) { | |
| 693 | + $this->service->managed_by_plugin_action( false ); | |
| 694 | + $this->log( 'AntiBot Global Firewall automatically disabled due to expired membership.', Antibot_Global_Firewall_Component::LOG_FILE_NAME ); | |
| 695 | + } | |
| 696 | + } | |
| 697 | + | |
| 698 | + /** | |
| 699 | + * Handle request to send feedback. | |
| 700 | + * | |
| 701 | + * @param Request $request The request object. | |
| 702 | + * | |
| 703 | + * @defender_route | |
| 704 | + * @return Response | |
| 705 | + */ | |
| 706 | + public function send_feedback( Request $request ) { | |
| 707 | + $data = $request->get_data( | |
| 708 | + array( | |
| 709 | + 'feedback' => array( 'type' => 'string' ), | |
| 710 | + ) | |
| 711 | + ); | |
| 712 | + if ( '' !== $data['feedback'] ) { | |
| 713 | + // Send feedback. | |
| 714 | + $this->track_feature( | |
| 715 | + 'Antibot Survey', | |
| 716 | + array( | |
| 717 | + 'Notice Action' => 'Share feedback', | |
| 718 | + 'Feedback' => $data['feedback'], | |
| 719 | + ) | |
| 720 | + ); | |
| 721 | + } | |
| 722 | + | |
| 723 | + $message = sprintf( | |
| 724 | + /* translators: 1: Open tag, 2: Close tag */ | |
| 725 | + __( '%1$sThanks for your feedback!%2$s It helps us make Defender even better.', 'defender-security' ), | |
| 726 | + '<strong>', | |
| 727 | + '</strong>' | |
| 728 | + ); | |
| 729 | + | |
| 730 | + return new Response( | |
| 731 | + true, | |
| 732 | + array( | |
| 733 | + 'message' => $message, | |
| 734 | + 'auto_close' => true, | |
| 735 | + ) | |
| 638 | 736 | ); |
| 639 | 737 | } |
| 640 | 738 | } |