PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / controller / class-global-ip.php

class-global-ip.php in Defender Security – Malware Scanner, Login Security & Firewall 6.3.0, at src/controller/class-global-ip.php

370 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * It handles functionalities such as saving settings, fetching and syncing global IP lists from the HUB.
4 *
5 * @package WP_Defender\Controller
6 */
7
8 namespace WP_Defender\Controller;
9
10 use WP_Defender\Controller;
11 use Calotes\Component\Request;
12 use Calotes\Component\Response;
13 use WP_Defender\Traits\Setting;
14 use WP_Defender\Traits\Formats;
15 use WP_Defender\Behavior\WPMUDEV;
16 use WP_Defender\Component\Network_Cron_Manager;
17 use WP_Defender\Model\Setting\Global_Ip_Lockout;
18 use WP_Defender\Component\Config\Config_Hub_Helper;
19 use WP_Defender\Component\IP\Antibot_Global_Firewall;
20 use WP_Defender\Component\IP\Global_IP as Global_IP_Component;
21
22 /**
23 * Handles global IP lockout settings.
24 */
25 class Global_Ip extends Controller {
26
27 use Setting;
28 use Formats;
29
30 /**
31 * Module slug for identifying Custom IP sync auto-enable after Hub connection.
32 *
33 * @const string
34 */
35 public const MODULE_SLUG = 'custom-ip-sync';
36
37 /**
38 * The slug identifier for this controller.
39 *
40 * @var string
41 */
42 protected $slug = 'wdf-ip-lockout';
43
44 /**
45 * The model for handling the data.
46 *
47 * @var Global_Ip_Lockout
48 */
49 protected $model;
50
51 /**
52 * Service for handling logic.
53 *
54 * @var Global_IP_Component
55 */
56 protected $service;
57
58 /**
59 * The WPMUDEV instance used for interacting with WPMUDEV services.
60 *
61 * @var WPMUDEV
62 */
63 private $wpmudev;
64
65 /**
66 * Initializes the model and service, registers routes, and sets up scheduled events if the model is active.
67 */
68 public function __construct() {
69 $this->register_routes();
70 add_action( 'defender_enqueue_assets', array( $this, 'enqueue_assets' ) );
71 $this->model = wd_di()->get( Global_Ip_Lockout::class );
72 $this->service = wd_di()->get( Global_IP_Component::class );
73 $this->wpmudev = wd_di()->get( WPMUDEV::class );
74
75 /**
76 * Network Cron Manager
77 *
78 * @var Network_Cron_Manager $network_cron_manager
79 */
80 $network_cron_manager = wd_di()->get( Network_Cron_Manager::class );
81 $network_cron_manager->register_callback(
82 'wpdef_fetch_global_ip_list',
83 array( $this, 'fetch_global_ip_list' ),
84 HOUR_IN_SECONDS
85 );
86
87 add_action( 'init', array( $this->service, 'handle_expired_membership' ) );
88 if ( $this->wpmudev->is_wpmu_hosting() ) {
89 // sync_state must run before can_blocklist_autosync is evaluated, so both hooks use priority 10.
90 add_action( 'init', array( $this, 'sync_state' ) );
91 }
92 // Register after sync_state so the model reflects the current Hosting state.
93 add_action( 'init', array( $this, 'maybe_register_blocklist_autosync_hook' ) );
94 // admin_init priority 20 runs after Hub_Connector sets the transient (priority 10);
95 // the other two hooks cover async-sync cases.
96 add_action( 'admin_init', array( $this, 'maybe_hcm_connection_attempt' ), 20 );
97 add_action( 'wpdef_hub_connector_synced', array( $this, 'maybe_hcm_connection_attempt' ) );
98 add_action( 'wpmudev_hub_connector_first_sync_completed', array( $this, 'maybe_hcm_connection_attempt' ) );
99 }
100
101 /**
102 * Auto-enable Custom IP list sync after Hub connection if user triggered from Custom Rules page.
103 *
104 * @return void
105 */
106 public function maybe_hcm_connection_attempt(): void {
107 $data = get_site_transient( Hub_Connector::TRANSIENT_KEY );
108 $module_slug = $data['module_slug'] ?? '';
109
110 if ( self::MODULE_SLUG !== $module_slug || ! self::get_hcm_status() ) {
111 return;
112 }
113
114 delete_site_transient( Hub_Connector::TRANSIENT_KEY );
115 }
116
117 /**
118 * Save settings.
119 *
120 * @param Request $request The request object containing new settings data.
121 *
122 * @return Response
123 * @defender_route
124 */
125 public function save_settings( Request $request ) {
126 $data = $request->get_data(
127 array(
128 'enabled' => array( 'type' => 'bool' ),
129 'allow_self_unlock' => array( 'type' => 'bool' ),
130 'blocklist_autosync' => array( 'type' => 'bool' ),
131 // Temporary property.
132 'module_title' => array(
133 'type' => 'string',
134 'sanitize' => 'sanitize_text_field',
135 ),
136 // End.
137 )
138 );
139
140 $message_type = 'central_ip';
141 // Split messages.
142 if ( isset( $data['module_title'] ) && 'antibot' === $data['module_title'] ) {
143 $message_type = 'antibot';
144 unset( $data['module_title'] );
145 }
146
147 $old_enabled = $this->model->enabled;
148 $old_self_unlock = $this->model->allow_self_unlock;
149
150 $this->model->import( $data );
151 if ( $this->model->validate() ) {
152 $this->model->save();
153 Config_Hub_Helper::set_clear_active_flag();
154 if ( 'central_ip' === $message_type ) {
155 if ( isset( $data['enabled'] ) && $old_enabled !== $this->model->enabled ) {
156 $this->service->toggle_on_hosting( $this->model->enabled );
157 }
158 $message = $this->get_update_message( $data, $old_enabled, Global_Ip_Lockout::get_module_name() );
159 } else {
160 $message = '';
161 if ( $data['allow_self_unlock'] ?? false ) {
162 $message = esc_html__( 'Temporary self unlock CAPTCHA challenge is enabled successfully.', 'defender-security' );
163 } elseif ( true === $old_self_unlock && ! ( $data['allow_self_unlock'] ?? false ) ) {
164 $message = esc_html__( 'Temporary self unlock CAPTCHA challenge is disabled successfully.', 'defender-security' );
165 }
166 }
167
168 return new Response(
169 true,
170 array_merge(
171 array(
172 'message' => $message,
173 'auto_close' => true,
174 ),
175 $this->data_frontend()
176 )
177 );
178 }
179
180 return new Response(
181 false,
182 array( 'message' => $this->model->get_formatted_errors() )
183 );
184 }
185
186 /**
187 * Enqueues scripts and styles for this page.
188 * Only enqueues assets if the page is active.
189 */
190 public function enqueue_assets() {
191 if ( ! $this->is_page_active() ) {
192 return;
193 }
194 }
195
196 /**
197 * Provides data for the frontend.
198 *
199 * @return array An array of data for the frontend.
200 */
201 public function data_frontend(): array {
202 return array_merge(
203 array(
204 'model' => $this->model->export(),
205 'misc' => array(
206 'show_global_ips_disable' => $this->wpmudev->is_disabled_hub_option(),
207 'is_wpmu_dev_admin' => $this->wpmudev->is_wpmu_dev_admin(),
208 'module_name' => Global_Ip_Lockout::get_module_name(),
209 'text_to_connect' => sprintf(
210 /* translators: %s: Module name. */
211 esc_html__( 'Connect to a WPMU DEV account to activate %s.', 'defender-security' ),
212 Global_Ip_Lockout::get_module_name()
213 ),
214 'is_show_dashboard_notice' => $this->service->is_show_dashboard_notice(),
215 'is_expired_membership' => $this->service->is_expired_membership_type(),
216 ),
217 'hub' => array(
218 'global_ip_list' => $this->service->get_formated_global_ip_list(),
219 'global_ip_setting_url' => defender_is_unlimited_hosting()
220 ? wd_di()->get( Antibot_Global_Firewall::class )->get_uh_site_tools_link()
221 : $this->wpmudev->get_api_base_url() . 'hub2/security-center/custom-ip-list',
222 ),
223 ),
224 $this->dump_routes_and_nonces()
225 );
226 }
227
228 /**
229 * Fetch Global IP list from HUB.
230 *
231 * @return void
232 * @since 3.4.0
233 */
234 public function fetch_global_ip_list(): void {
235 if ( true === $this->model->enabled ) {
236 $this->service->fetch_global_ip_list();
237 }
238 }
239
240 /**
241 * Refresh Global IP list.
242 *
243 * @return Response
244 * @defender_route
245 * @since 3.4.0
246 */
247 public function refresh_global_ip_list(): Response {
248 $data = $this->service->fetch_global_ip_list();
249
250 if ( ! is_wp_error( $data ) ) {
251 return new Response(
252 true,
253 array(
254 'message' => esc_html__(
255 'The Custom IP List has been updated successfully.',
256 'defender-security'
257 ),
258 'global_ip_list' => $this->service->get_formated_global_ip_list(),
259 )
260 );
261 } else {
262 return new Response(
263 false,
264 array(
265 'message' => esc_html__(
266 'An error occurred while synchronizing the Custom IP List.',
267 'defender-security'
268 ),
269 )
270 );
271 }
272 }
273
274 /**
275 * Add an IP to blacklist.
276 *
277 * @param string $ip The IP to blacklist.
278 *
279 * @return void
280 */
281 public function blacklist_an_ip( string $ip ): void {
282 $data = array(
283 'block_list' => array( $ip ),
284 );
285 $this->service->add_to_global_ip_list( $data );
286 }
287
288 /**
289 * Converts the current object state to an array.
290 *
291 * @return array The array representation of the object.
292 */
293 public function to_array(): array {
294 return array();
295 }
296
297 /**
298 * Imports data into the model.
299 *
300 * @param array $data Data to be imported into the model.
301 */
302 public function import_data( array $data ) {
303 $model = $this->model;
304 if ( isset( $data['global_ip_list'] ) ) {
305 $model->enabled = (bool) $data['global_ip_list'];
306 if ( isset( $data['global_ip_list_blocklist_autosync'] ) ) {
307 $model->blocklist_autosync = (bool) $data['global_ip_list_blocklist_autosync'];
308 }
309 } else {
310 $model->enabled = false;
311 $model->blocklist_autosync = false;
312 }
313 $model->save();
314 }
315
316 /**
317 * Removes settings for all submodules.
318 */
319 public function remove_settings() {
320 }
321
322 /**
323 * Delete all the data & the cache.
324 */
325 public function remove_data() {
326 delete_site_transient( Global_IP_Component::LIST_KEY );
327 delete_site_option( Global_IP_Component::LIST_LAST_SYNCED_KEY );
328 $this->service->delete_dashboard_notice_reminder();
329 }
330
331 /**
332 * Exports strings.
333 *
334 * @return array An array of strings.
335 */
336 public function export_strings() {
337 return array();
338 }
339
340 /**
341 * Register the blocklist autosync hook after sync_state has updated the model.
342 *
343 * @return void
344 */
345 public function maybe_register_blocklist_autosync_hook(): void {
346 if ( $this->service->can_blocklist_autosync() ) {
347 // No need to run Rate mechanism for IP lockouts because we do it in Blacklist class.
348 add_action( 'wd_blacklist_this_ip', array( $this, 'blacklist_an_ip' ) );
349 }
350 }
351
352 /**
353 * Sync custom ip list status with Hosting.
354 *
355 * @return void
356 */
357 public function sync_state(): void {
358 $hosting_enabled = defender_get_hosting_feature_state( 'globaliplist' );
359 if ( '' === $hosting_enabled ) {
360 return;
361 }
362 $hosting_enabled = (bool) $hosting_enabled;
363 if ( $hosting_enabled !== $this->model->enabled ) {
364 $this->model->enabled = $hosting_enabled;
365 $this->model->blocklist_autosync = $hosting_enabled;
366 $this->model->save();
367 }
368 }
369 }
370