PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.37
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.37
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / widgets / Login_Register_Form / Security_Dashboard.php

Security_Dashboard.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.37, at includes/widgets/Login_Register_Form/Security_Dashboard.php

733 lines 30.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace King_Addons\Widgets\Login_Register_Form;
4
5 if (!defined('ABSPATH')) {
6 exit; // Exit if accessed directly.
7 }
8
9 // Include Security Manager
10 require_once KING_ADDONS_PATH . 'includes/widgets/Login_Register_Form/Security_Manager.php';
11
12 /**
13 * Security Dashboard for Login Register Form widget
14 * Provides administrative interface for monitoring security events
15 */
16 class Security_Dashboard
17 {
18 /**
19 * Initialize the security dashboard
20 */
21 public static function init()
22 {
23 // Add admin menu
24 add_action('admin_menu', [__CLASS__, 'add_admin_menu'], 20);
25
26 // Add security logs capability check
27 add_action('admin_init', [__CLASS__, 'check_capabilities']);
28
29 // Add AJAX handlers for dashboard
30 add_action('wp_ajax_king_addons_clear_security_logs', [__CLASS__, 'clear_security_logs']);
31 add_action('wp_ajax_king_addons_unblock_ip', [__CLASS__, 'unblock_ip']);
32 add_action('wp_ajax_king_addons_export_security_report', [__CLASS__, 'export_security_report']);
33 }
34
35 /**
36 * Add admin menu for security dashboard
37 */
38 public static function add_admin_menu()
39 {
40 add_submenu_page(
41 'king-addons',
42 esc_html__('Login Security', 'king-addons'),
43 esc_html__('Login Security', 'king-addons'),
44 'manage_options',
45 'king-addons-login-security',
46 [__CLASS__, 'render_dashboard']
47 );
48 }
49
50 /**
51 * Check if user has capabilities to view security dashboard
52 */
53 public static function check_capabilities()
54 {
55 if (isset($_GET['page']) && $_GET['page'] === 'king-addons-login-security') {
56 if (!current_user_can('manage_options')) {
57 wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'king-addons'));
58 }
59 }
60 }
61
62 /**
63 * Render the security dashboard
64 */
65 public static function render_dashboard()
66 {
67 // Get security statistics
68 $stats = self::get_security_statistics();
69 $blocked_ips = self::get_blocked_ips();
70 $recent_attempts = self::get_recent_failed_attempts();
71
72 ?>
73 <div class="wrap">
74 <h1><?php echo esc_html__('King Addons - Login Security Dashboard', 'king-addons'); ?></h1>
75
76 <!-- Widget Information -->
77 <div class="king-addons-widget-info">
78 <div class="widget-info-header">
79 <h2><?php echo esc_html__('Login Register Form Widget Security', 'king-addons'); ?></h2>
80 <p class="description">
81 <?php echo esc_html__('This security dashboard monitors and protects the Login Register Form widget from various threats including brute-force attacks, spam registrations, malicious file uploads, and unauthorized access attempts.', 'king-addons'); ?>
82 </p>
83 </div>
84
85 <div class="security-features-grid">
86 <div class="security-feature">
87 <span class="dashicons dashicons-shield-alt"></span>
88 <h4><?php echo esc_html__('Rate Limiting', 'king-addons'); ?></h4>
89 <p><?php echo esc_html__('Automatically blocks IPs after failed login attempts', 'king-addons'); ?></p>
90 </div>
91
92 <div class="security-feature">
93 <span class="dashicons dashicons-upload"></span>
94 <h4><?php echo esc_html__('File Upload Security', 'king-addons'); ?></h4>
95 <p><?php echo esc_html__('Validates file types, sizes, and scans for malicious content', 'king-addons'); ?></p>
96 </div>
97
98 <div class="security-feature">
99 <span class="dashicons dashicons-admin-users"></span>
100 <h4><?php echo esc_html__('Anti-Enumeration', 'king-addons'); ?></h4>
101 <p><?php echo esc_html__('Prevents user enumeration through unified error messages', 'king-addons'); ?></p>
102 </div>
103
104 <div class="security-feature">
105 <span class="dashicons dashicons-share"></span>
106 <h4><?php echo esc_html__('Social Login Protection', 'king-addons'); ?></h4>
107 <p><?php echo esc_html__('Enhanced validation for Google and Facebook login data', 'king-addons'); ?></p>
108 </div>
109 </div>
110 </div>
111
112 <!-- Security Overview -->
113 <div class="king-addons-security-overview">
114 <h2><?php echo esc_html__('Security Statistics', 'king-addons'); ?></h2>
115 <p class="description">
116 <?php echo esc_html__('Real-time security metrics for the Login Register Form widget across your entire website.', 'king-addons'); ?>
117 </p>
118 <div class="king-addons-stats-grid">
119 <div class="king-addons-stat-card">
120 <h3><?php echo esc_html__('Failed Login Attempts (24h)', 'king-addons'); ?></h3>
121 <div class="stat-number"><?php echo esc_html($stats['failed_logins_24h']); ?></div>
122 </div>
123
124 <div class="king-addons-stat-card">
125 <h3><?php echo esc_html__('Blocked IPs', 'king-addons'); ?></h3>
126 <div class="stat-number"><?php echo esc_html($stats['blocked_ips']); ?></div>
127 </div>
128
129 <div class="king-addons-stat-card">
130 <h3><?php echo esc_html__('Suspicious Registrations', 'king-addons'); ?></h3>
131 <div class="stat-number"><?php echo esc_html($stats['suspicious_registrations']); ?></div>
132 </div>
133
134 <div class="king-addons-stat-card">
135 <h3><?php echo esc_html__('File Upload Blocks', 'king-addons'); ?></h3>
136 <div class="stat-number"><?php echo esc_html($stats['file_upload_blocks']); ?></div>
137 </div>
138 </div>
139 </div>
140
141 <!-- Currently Blocked IPs -->
142 <?php if (!empty($blocked_ips)): ?>
143 <div class="king-addons-blocked-ips">
144 <h2><?php echo esc_html__('Currently Blocked IPs', 'king-addons'); ?></h2>
145 <table class="wp-list-table widefat fixed striped">
146 <thead>
147 <tr>
148 <th><?php echo esc_html__('IP Address', 'king-addons'); ?></th>
149 <th><?php echo esc_html__('Attempts', 'king-addons'); ?></th>
150 <th><?php echo esc_html__('Last Attempt', 'king-addons'); ?></th>
151 <th><?php echo esc_html__('Expires', 'king-addons'); ?></th>
152 <th><?php echo esc_html__('Actions', 'king-addons'); ?></th>
153 </tr>
154 </thead>
155 <tbody>
156 <?php foreach ($blocked_ips as $ip_data): ?>
157 <tr>
158 <td><?php echo esc_html($ip_data['ip']); ?></td>
159 <td><?php echo esc_html($ip_data['attempts']); ?></td>
160 <td><?php echo esc_html(human_time_diff($ip_data['last_attempt'], time()) . ' ago'); ?></td>
161 <td><?php echo esc_html(human_time_diff(time(), $ip_data['expires']) . ' remaining'); ?></td>
162 <td>
163 <button class="button unblock-ip" data-ip="<?php echo esc_attr($ip_data['ip']); ?>">
164 <?php echo esc_html__('Unblock', 'king-addons'); ?>
165 </button>
166 </td>
167 </tr>
168 <?php endforeach; ?>
169 </tbody>
170 </table>
171 </div>
172 <?php endif; ?>
173
174 <!-- Recent Failed Attempts -->
175 <?php if (!empty($recent_attempts)): ?>
176 <div class="king-addons-recent-attempts">
177 <h2><?php echo esc_html__('Recent Failed Attempts', 'king-addons'); ?></h2>
178 <table class="wp-list-table widefat fixed striped">
179 <thead>
180 <tr>
181 <th><?php echo esc_html__('Time', 'king-addons'); ?></th>
182 <th><?php echo esc_html__('IP Address', 'king-addons'); ?></th>
183 <th><?php echo esc_html__('Type', 'king-addons'); ?></th>
184 <th><?php echo esc_html__('Details', 'king-addons'); ?></th>
185 </tr>
186 </thead>
187 <tbody>
188 <?php foreach ($recent_attempts as $attempt): ?>
189 <tr>
190 <td><?php echo esc_html(date('Y-m-d H:i:s', $attempt['time'])); ?></td>
191 <td><?php echo esc_html($attempt['ip']); ?></td>
192 <td><?php echo esc_html(ucfirst($attempt['type'])); ?></td>
193 <td><?php echo esc_html($attempt['details']); ?></td>
194 </tr>
195 <?php endforeach; ?>
196 </tbody>
197 </table>
198 </div>
199 <?php endif; ?>
200
201 <!-- Security Settings -->
202 <div class="king-addons-security-settings">
203 <h2><?php echo esc_html__('Security Settings for Login Register Form Widget', 'king-addons'); ?></h2>
204 <p class="description">
205 <?php echo esc_html__('Configure security parameters that apply to all Login Register Form widgets on your website. These settings help protect against brute-force attacks, spam registrations, and other security threats.', 'king-addons'); ?>
206 </p>
207 <form method="post" action="options.php">
208 <?php settings_fields('king_addons_security_settings'); ?>
209 <table class="form-table">
210 <tr>
211 <th scope="row">
212 <label for="king_addons_max_login_attempts">
213 <?php echo esc_html__('Max Login Attempts', 'king-addons'); ?>
214 </label>
215 </th>
216 <td>
217 <input type="number" id="king_addons_max_login_attempts" name="king_addons_max_login_attempts"
218 value="<?php echo esc_attr(get_option('king_addons_max_login_attempts', 5)); ?>" min="1" max="20" />
219 <p class="description">
220 <?php echo esc_html__('Number of failed login attempts before an IP address is temporarily blocked from accessing Login Register Form widgets. Recommended: 3-5 attempts.', 'king-addons'); ?>
221 <br><strong><?php echo esc_html__('Applies to:', 'king-addons'); ?></strong> <?php echo esc_html__('Login forms, Registration forms, Password reset forms', 'king-addons'); ?>
222 </p>
223 </td>
224 </tr>
225 <tr>
226 <th scope="row">
227 <label for="king_addons_lockout_duration">
228 <?php echo esc_html__('Lockout Duration (minutes)', 'king-addons'); ?>
229 </label>
230 </th>
231 <td>
232 <input type="number" id="king_addons_lockout_duration" name="king_addons_lockout_duration"
233 value="<?php echo esc_attr(get_option('king_addons_lockout_duration', 15)); ?>" min="1" max="1440" />
234 <p class="description">
235 <?php echo esc_html__('Duration in minutes to block an IP address after exceeding failed attempts. During this time, the IP cannot access any Login Register Form widgets. Recommended: 15-30 minutes.', 'king-addons'); ?>
236 <br><strong><?php echo esc_html__('Security Impact:', 'king-addons'); ?></strong> <?php echo esc_html__('Prevents brute-force attacks and automated bot attempts', 'king-addons'); ?>
237 </p>
238 </td>
239 </tr>
240 <tr>
241 <th scope="row">
242 <label for="king_addons_enable_security_logging">
243 <?php echo esc_html__('Enable Security Logging', 'king-addons'); ?>
244 </label>
245 </th>
246 <td>
247 <input type="checkbox" id="king_addons_enable_security_logging" name="king_addons_enable_security_logging" value="1"
248 <?php checked(get_option('king_addons_enable_security_logging', 1)); ?> />
249 <p class="description">
250 <?php echo esc_html__('Log all security events related to Login Register Form widgets including failed attempts, suspicious registrations, blocked file uploads, and social login activities. Logs help track and analyze security threats.', 'king-addons'); ?>
251 <br><strong><?php echo esc_html__('Recommended:', 'king-addons'); ?></strong> <?php echo esc_html__('Keep enabled for security monitoring and compliance', 'king-addons'); ?>
252 </p>
253 </td>
254 </tr>
255 </table>
256 <?php submit_button(); ?>
257 </form>
258 </div>
259
260 <!-- Actions -->
261 <div class="king-addons-security-actions">
262 <h2><?php echo esc_html__('Security Management Actions', 'king-addons'); ?></h2>
263 <p class="description">
264 <?php echo esc_html__('Manage security data and generate reports for Login Register Form widget security events.', 'king-addons'); ?>
265 </p>
266
267 <div class="security-actions-grid">
268 <div class="action-card">
269 <h4><?php echo esc_html__('Clear Security Logs', 'king-addons'); ?></h4>
270 <p><?php echo esc_html__('Remove all stored security logs and reset blocked IP addresses. This action cannot be undone.', 'king-addons'); ?></p>
271 <button class="button button-secondary" id="clear-security-logs">
272 <span class="dashicons dashicons-trash"></span>
273 <?php echo esc_html__('Clear All Logs', 'king-addons'); ?>
274 </button>
275 </div>
276
277 <div class="action-card">
278 <h4><?php echo esc_html__('Export Security Report', 'king-addons'); ?></h4>
279 <p><?php echo esc_html__('Generate and download a comprehensive security report including all statistics and blocked IPs.', 'king-addons'); ?></p>
280 <button class="button button-secondary" id="export-security-report">
281 <span class="dashicons dashicons-download"></span>
282 <?php echo esc_html__('Export Report', 'king-addons'); ?>
283 </button>
284 </div>
285 </div>
286 </div>
287 </div>
288
289 <style>
290 /* Widget Info Section */
291 .king-addons-widget-info {
292 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
293 color: white;
294 border-radius: 8px;
295 padding: 30px;
296 margin: 20px 0;
297 box-shadow: 0 4px 6px rgba(0,0,0,0.1);
298 }
299 .widget-info-header h2 {
300 color: white;
301 margin: 0 0 10px 0;
302 }
303 .widget-info-header .description {
304 color: rgba(255,255,255,0.9);
305 font-size: 16px;
306 margin-bottom: 25px;
307 }
308 .security-features-grid {
309 display: grid;
310 grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
311 gap: 20px;
312 }
313 .security-feature {
314 background: rgba(255,255,255,0.1);
315 backdrop-filter: blur(10px);
316 border-radius: 8px;
317 padding: 20px;
318 text-align: center;
319 border: 1px solid rgba(255,255,255,0.2);
320 }
321 .security-feature .dashicons {
322 font-size: 32px;
323 width: 32px;
324 height: 32px;
325 margin-bottom: 10px;
326 opacity: 0.9;
327 }
328 .security-feature h4 {
329 color: white;
330 margin: 10px 0;
331 font-size: 16px;
332 }
333 .security-feature p {
334 color: rgba(255,255,255,0.8);
335 font-size: 14px;
336 margin: 0;
337 }
338
339 /* Stats Grid */
340 .king-addons-stats-grid {
341 display: grid;
342 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
343 gap: 20px;
344 margin: 20px 0;
345 }
346 .king-addons-stat-card {
347 background: #fff;
348 border: 1px solid #ccd0d4;
349 border-radius: 8px;
350 padding: 25px;
351 text-align: center;
352 box-shadow: 0 2px 4px rgba(0,0,0,0.05);
353 transition: transform 0.2s ease;
354 }
355 .king-addons-stat-card:hover {
356 transform: translateY(-2px);
357 box-shadow: 0 4px 8px rgba(0,0,0,0.1);
358 }
359 .king-addons-stat-card h3 {
360 margin: 0 0 15px 0;
361 font-size: 14px;
362 color: #555;
363 text-transform: uppercase;
364 letter-spacing: 0.5px;
365 }
366 .stat-number {
367 font-size: 36px;
368 font-weight: bold;
369 color: #2271b1;
370 line-height: 1;
371 }
372
373 /* Main Sections */
374 .king-addons-security-overview,
375 .king-addons-blocked-ips,
376 .king-addons-recent-attempts,
377 .king-addons-security-settings,
378 .king-addons-security-actions {
379 background: #fff;
380 border: 1px solid #ccd0d4;
381 border-radius: 8px;
382 padding: 25px;
383 margin: 20px 0;
384 box-shadow: 0 2px 4px rgba(0,0,0,0.05);
385 }
386
387 /* Security Actions */
388 .security-actions-grid {
389 display: grid;
390 grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
391 gap: 20px;
392 margin-top: 20px;
393 }
394 .action-card {
395 background: #f8f9fa;
396 border: 1px solid #e9ecef;
397 border-radius: 8px;
398 padding: 20px;
399 text-align: center;
400 }
401 .action-card h4 {
402 margin: 0 0 10px 0;
403 color: #333;
404 }
405 .action-card p {
406 color: #666;
407 font-size: 14px;
408 margin-bottom: 15px;
409 }
410 .action-card button {
411 display: inline-flex;
412 align-items: center;
413 justify-content: center;
414 gap: 8px;
415 min-height: 32px;
416 }
417 .action-card button .dashicons {
418 font-size: 16px;
419 width: 16px;
420 height: 16px;
421 line-height: 16px;
422 vertical-align: middle;
423 }
424
425 /* Form improvements */
426 .form-table th {
427 width: 250px;
428 padding: 20px 10px 20px 0;
429 }
430 .form-table td {
431 padding: 20px 10px;
432 }
433 .form-table input[type="number"] {
434 width: 100px;
435 }
436 .form-table .description {
437 margin-top: 8px;
438 line-height: 1.5;
439 }
440 .form-table .description strong {
441 color: #2271b1;
442 }
443
444 /* Table improvements */
445 .wp-list-table th, .wp-list-table td {
446 padding: 12px;
447 }
448 .unblock-ip {
449 font-size: 12px;
450 padding: 4px 8px;
451 }
452
453 /* Loading animation */
454 @keyframes rotation {
455 from {
456 transform: rotate(0deg);
457 }
458 to {
459 transform: rotate(359deg);
460 }
461 }
462 </style>
463
464 <script>
465 jQuery(document).ready(function($) {
466 // Unblock IP functionality
467 $('.unblock-ip').on('click', function() {
468 const ip = $(this).data('ip');
469 if (confirm('Are you sure you want to unblock this IP?')) {
470 $.post(ajaxurl, {
471 action: 'king_addons_unblock_ip',
472 ip: ip,
473 nonce: '<?php echo wp_create_nonce('king_addons_security_nonce'); ?>'
474 }, function(response) {
475 if (response.success) {
476 location.reload();
477 } else {
478 alert('Failed to unblock IP: ' + response.data.message);
479 }
480 });
481 }
482 });
483
484 // Clear security logs
485 $('#clear-security-logs').on('click', function() {
486 if (confirm('Are you sure you want to clear all security logs?')) {
487 $.post(ajaxurl, {
488 action: 'king_addons_clear_security_logs',
489 nonce: '<?php echo wp_create_nonce('king_addons_security_nonce'); ?>'
490 }, function(response) {
491 if (response.success) {
492 location.reload();
493 } else {
494 alert('Failed to clear logs: ' + response.data.message);
495 }
496 });
497 }
498 });
499
500 // Export security report
501 $('#export-security-report').on('click', function() {
502 const $button = $(this);
503 const originalText = $button.html();
504
505 // Show loading state
506 $button.prop('disabled', true).html('<span class="dashicons dashicons-update-alt" style="animation: rotation 1s infinite linear;"></span> Generating...');
507
508 $.post(ajaxurl, {
509 action: 'king_addons_export_security_report',
510 nonce: '<?php echo wp_create_nonce('king_addons_security_nonce'); ?>'
511 }, function(response) {
512 if (response.success) {
513 // Create download link and trigger download
514 const link = document.createElement('a');
515 link.href = response.data.download_url;
516 link.download = response.data.filename;
517 link.style.display = 'none';
518 document.body.appendChild(link);
519 link.click();
520 document.body.removeChild(link);
521
522 alert('Security report downloaded successfully!');
523 } else {
524 alert('Failed to generate report: ' + response.data.message);
525 }
526 }).fail(function() {
527 alert('Network error occurred while generating report.');
528 }).always(function() {
529 // Restore button state
530 $button.prop('disabled', false).html(originalText);
531 });
532 });
533 });
534 </script>
535 <?php
536 }
537
538 /**
539 * Get security statistics
540 */
541 private static function get_security_statistics()
542 {
543 global $wpdb;
544
545 $stats = [
546 'failed_logins_24h' => 0,
547 'blocked_ips' => 0,
548 'suspicious_registrations' => 0,
549 'file_upload_blocks' => 0
550 ];
551
552 // Count blocked IPs
553 $transients = $wpdb->get_results(
554 "SELECT option_name FROM {$wpdb->options}
555 WHERE option_name LIKE '_transient_king_addons_%_attempts_%'
556 AND option_value >= 3"
557 );
558 $stats['blocked_ips'] = count($transients);
559
560 // Get failed attempts from error log (simplified - would need actual log parsing)
561 $log_file = ini_get('error_log');
562 if ($log_file && file_exists($log_file)) {
563 $log_content = file_get_contents($log_file);
564 $stats['failed_logins_24h'] = substr_count($log_content, 'King Addons Security: Failed login');
565 $stats['suspicious_registrations'] = substr_count($log_content, 'Suspicious registration pattern');
566 $stats['file_upload_blocks'] = substr_count($log_content, 'File upload blocked');
567 }
568
569 return $stats;
570 }
571
572 /**
573 * Get currently blocked IPs
574 */
575 private static function get_blocked_ips()
576 {
577 global $wpdb;
578
579 $blocked_ips = [];
580
581 $transients = $wpdb->get_results(
582 "SELECT option_name, option_value
583 FROM {$wpdb->options}
584 WHERE option_name LIKE '_transient_king_addons_%_attempts_%'"
585 );
586
587 foreach ($transients as $transient) {
588 $attempts = intval($transient->option_value);
589 if ($attempts >= Security_Manager::MAX_LOGIN_ATTEMPTS) {
590 // Extract IP from transient name
591 preg_match('/_transient_king_addons_\w+_attempts_(.+)/', $transient->option_name, $matches);
592 if (isset($matches[1])) {
593 $ip_hash = $matches[1];
594
595 // Get expiration time
596 $timeout_option = '_transient_timeout_' . str_replace('_transient_', '', $transient->option_name);
597 $expires = get_option($timeout_option, 0);
598
599 $blocked_ips[] = [
600 'ip' => 'IP Hash: ' . substr($ip_hash, 0, 8) . '...', // Don't expose full IPs
601 'attempts' => $attempts,
602 'last_attempt' => time() - 300, // Approximate
603 'expires' => $expires
604 ];
605 }
606 }
607 }
608
609 return $blocked_ips;
610 }
611
612 /**
613 * Get recent failed attempts from logs
614 */
615 private static function get_recent_failed_attempts()
616 {
617 $attempts = [];
618
619 // This would parse actual log files in a real implementation
620 // For now, return sample data structure
621
622 return $attempts;
623 }
624
625 /**
626 * AJAX handler to clear security logs
627 */
628 public static function clear_security_logs()
629 {
630 if (!wp_verify_nonce($_POST['nonce'], 'king_addons_security_nonce')) {
631 wp_send_json_error(['message' => 'Invalid nonce']);
632 }
633
634 if (!current_user_can('manage_options')) {
635 wp_send_json_error(['message' => 'Insufficient permissions']);
636 }
637
638 // Clear all rate limiting transients
639 global $wpdb;
640 $wpdb->query(
641 "DELETE FROM {$wpdb->options}
642 WHERE option_name LIKE '_transient_king_addons_%_attempts_%'
643 OR option_name LIKE '_transient_timeout_king_addons_%_attempts_%'"
644 );
645
646 wp_send_json_success(['message' => 'Security logs cleared successfully']);
647 }
648
649 /**
650 * AJAX handler to unblock IP
651 */
652 public static function unblock_ip()
653 {
654 if (!wp_verify_nonce($_POST['nonce'], 'king_addons_security_nonce')) {
655 wp_send_json_error(['message' => 'Invalid nonce']);
656 }
657
658 if (!current_user_can('manage_options')) {
659 wp_send_json_error(['message' => 'Insufficient permissions']);
660 }
661
662 $ip = sanitize_text_field($_POST['ip']);
663 if (empty($ip)) {
664 wp_send_json_error(['message' => 'Invalid IP address']);
665 }
666
667 // Clear attempts for this IP (simplified)
668 global $wpdb;
669 $ip_hash = md5($ip);
670 $wpdb->query($wpdb->prepare(
671 "DELETE FROM {$wpdb->options}
672 WHERE option_name LIKE %s
673 OR option_name LIKE %s",
674 '%_king_addons_%_attempts_' . $ip_hash,
675 '%_king_addons_%_attempts_' . $ip_hash . '%'
676 ));
677
678 wp_send_json_success(['message' => 'IP unblocked successfully']);
679 }
680
681 /**
682 * AJAX handler to export security report
683 */
684 public static function export_security_report()
685 {
686 if (!wp_verify_nonce($_POST['nonce'], 'king_addons_security_nonce')) {
687 wp_send_json_error(['message' => 'Invalid nonce']);
688 }
689
690 if (!current_user_can('manage_options')) {
691 wp_send_json_error(['message' => 'Insufficient permissions']);
692 }
693
694 // Generate security report
695 $stats = self::get_security_statistics();
696 $blocked_ips = self::get_blocked_ips();
697
698 $report = [
699 'generated_at' => current_time('Y-m-d H:i:s'),
700 'site_url' => get_site_url(),
701 'plugin_version' => defined('KING_ADDONS_VERSION') ? KING_ADDONS_VERSION : 'Unknown',
702 'statistics' => $stats,
703 'blocked_ips' => $blocked_ips,
704 'security_settings' => [
705 'max_login_attempts' => get_option('king_addons_max_login_attempts', 5),
706 'lockout_duration' => get_option('king_addons_lockout_duration', 15),
707 'security_logging_enabled' => get_option('king_addons_enable_security_logging', 1),
708 ]
709 ];
710
711 // Convert to JSON
712 $json_report = json_encode($report, JSON_PRETTY_PRINT);
713
714 // Create filename
715 $filename = 'king-addons-security-report-' . date('Y-m-d-H-i-s') . '.json';
716
717 // Return download URL
718 $upload_dir = wp_upload_dir();
719 $report_path = $upload_dir['path'] . '/' . $filename;
720
721 // Save file
722 if (file_put_contents($report_path, $json_report)) {
723 $download_url = $upload_dir['url'] . '/' . $filename;
724 wp_send_json_success([
725 'message' => 'Security report generated successfully',
726 'download_url' => $download_url,
727 'filename' => $filename
728 ]);
729 } else {
730 wp_send_json_error(['message' => 'Failed to generate report file']);
731 }
732 }
733 }