PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.83
51.1.86 51.1.84 51.1.85 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 All 40 releases
← All changes | includes/widgets/Login_Register_Form/Security_Dashboard.php +435 -369 51.1.36 → 51.1.83 View file →
@@ -59,9 +59,9 @@
59 59 }
60 60 }
61 61
62 62 /**
63 - * Render the security dashboard
63 + * Render the security dashboard - V3 Premium style inspired Design
64 64 */
65 65 public static function render_dashboard()
66 66 {
67 67 // Get security statistics
@@ -67,407 +67,482 @@
67 67 // Get security statistics
68 68 $stats = self::get_security_statistics();
69 69 $blocked_ips = self::get_blocked_ips();
70 70 $recent_attempts = self::get_recent_failed_attempts();
71 +
72 + // Theme mode is per-user
73 + $theme_mode = get_user_meta(get_current_user_id(), 'king_addons_theme_mode', true);
74 + $allowed_theme_modes = ['dark', 'light', 'auto'];
75 + if (!in_array($theme_mode, $allowed_theme_modes, true)) {
76 + $theme_mode = 'auto';
77 + }
71 78
79 + // Enqueue shared V3 styles
80 + wp_enqueue_style(
81 + 'king-addons-admin-v3',
82 + KING_ADDONS_URL . 'includes/admin/layouts/shared/admin-v3-styles.css',
83 + [],
84 + KING_ADDONS_VERSION
85 + );
72 86 ?>
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>
87 + <script>
88 + (function() {
89 + document.body && document.body.classList.add('ka-admin-v3');
90 + const mode = '<?php echo esc_js($theme_mode); ?>';
91 + const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
92 + const isDark = mode === 'auto' ? !!(mql && mql.matches) : mode === 'dark';
93 + document.documentElement.classList.toggle('ka-v3-dark', isDark);
94 + document.body && document.body.classList.toggle('ka-v3-dark', isDark);
95 + })();
96 + </script>
140 97
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 98 <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);
99 + /* Security Dashboard V3 - Additional styles */
100 + .ka-security-v3 .ka-features-grid {
101 + display: grid;
102 + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
103 + gap: 16px;
104 + margin-bottom: 24px;
298 105 }
299 - .widget-info-header h2 {
300 - color: white;
301 - margin: 0 0 10px 0;
106 +
107 + .ka-security-v3 .ka-feature-card {
108 + background: #fff;
109 + border-radius: 16px;
110 + padding: 24px;
111 + text-align: center;
112 + border: 1px solid rgba(0, 0, 0, 0.04);
113 + transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
302 114 }
303 - .widget-info-header .description {
304 - color: rgba(255,255,255,0.9);
305 - font-size: 16px;
306 - margin-bottom: 25px;
115 +
116 + body.ka-v3-dark .ka-security-v3 .ka-feature-card {
117 + background: #1c1c1e;
118 + border-color: rgba(255, 255, 255, 0.06);
307 119 }
308 - .security-features-grid {
309 - display: grid;
310 - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
311 - gap: 20px;
120 +
121 + .ka-security-v3 .ka-feature-card:hover {
122 + transform: translateY(-4px);
123 + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.08);
312 124 }
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);
125 +
126 + body.ka-v3-dark .ka-security-v3 .ka-feature-card:hover {
127 + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
320 128 }
321 - .security-feature .dashicons {
129 +
130 + .ka-security-v3 .ka-feature-card .dashicons {
322 131 font-size: 32px;
323 132 width: 32px;
324 133 height: 32px;
325 - margin-bottom: 10px;
326 - opacity: 0.9;
134 + color: #ef4444;
135 + margin-bottom: 12px;
327 136 }
328 - .security-feature h4 {
329 - color: white;
330 - margin: 10px 0;
331 - font-size: 16px;
137 +
138 + .ka-security-v3 .ka-feature-card h4 {
139 + margin: 0 0 6px;
140 + font-size: 15px;
141 + font-weight: 600;
142 + color: #1d1d1f;
332 143 }
333 - .security-feature p {
334 - color: rgba(255,255,255,0.8);
335 - font-size: 14px;
144 +
145 + body.ka-v3-dark .ka-security-v3 .ka-feature-card h4,
146 + body.ka-v3-dark .ka-security-v3 .ka-stat-card h3 {
147 + color: #f5f5f7;
148 + }
149 +
150 + .ka-security-v3 .ka-feature-card p {
336 151 margin: 0;
152 + font-size: 13px;
153 + color: #86868b;
337 154 }
338 -
339 - /* Stats Grid */
340 - .king-addons-stats-grid {
155 +
156 + /* Stats override for security color */
157 + .ka-security-v3 .ka-stat-card .ka-stat-number {
158 + color: #ef4444;
159 + }
160 +
161 + /* Actions grid */
162 + .ka-security-v3 .ka-actions-grid {
341 163 display: grid;
342 - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
164 + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
343 165 gap: 20px;
344 - margin: 20px 0;
345 166 }
346 - .king-addons-stat-card {
347 - background: #fff;
348 - border: 1px solid #ccd0d4;
349 - border-radius: 8px;
350 - padding: 25px;
167 +
168 + .ka-security-v3 .ka-action-card {
169 + background: rgba(0, 0, 0, 0.02);
170 + border: 1px solid rgba(0, 0, 0, 0.04);
171 + border-radius: 16px;
172 + padding: 24px;
351 173 text-align: center;
352 - box-shadow: 0 2px 4px rgba(0,0,0,0.05);
353 - transition: transform 0.2s ease;
174 + transition: all 0.3s;
354 175 }
355 - .king-addons-stat-card:hover {
356 - transform: translateY(-2px);
357 - box-shadow: 0 4px 8px rgba(0,0,0,0.1);
176 +
177 + body.ka-v3-dark .ka-security-v3 .ka-action-card {
178 + background: rgba(255, 255, 255, 0.04);
179 + border-color: rgba(255, 255, 255, 0.06);
358 180 }
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;
181 +
182 + .ka-security-v3 .ka-action-card h4 {
183 + margin: 0 0 8px;
184 + font-size: 15px;
185 + font-weight: 600;
186 + color: #1d1d1f;
365 187 }
366 - .stat-number {
367 - font-size: 36px;
368 - font-weight: bold;
369 - color: #2271b1;
370 - line-height: 1;
188 +
189 + body.ka-v3-dark .ka-security-v3 .ka-action-card h4 {
190 + color: #f5f5f7;
371 191 }
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 {
192 +
193 + .ka-security-v3 .ka-action-card p {
194 + margin: 0 0 16px;
195 + font-size: 13px;
196 + color: #86868b;
197 + }
198 +
199 + .ka-security-v3 .ka-action-btn {
200 + display: inline-flex;
201 + align-items: center;
202 + gap: 8px;
379 203 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);
204 + border: 1px solid rgba(0, 0, 0, 0.1);
205 + padding: 10px 20px;
206 + border-radius: 980px;
207 + font-size: 14px;
208 + color: #1d1d1f;
209 + cursor: pointer;
210 + transition: all 0.2s;
385 211 }
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;
212 +
213 + body.ka-v3-dark .ka-security-v3 .ka-action-btn {
214 + background: #2c2c2e;
215 + border-color: rgba(255, 255, 255, 0.1);
216 + color: #f5f5f7;
393 217 }
394 - .action-card {
395 - background: #f8f9fa;
396 - border: 1px solid #e9ecef;
397 - border-radius: 8px;
398 - padding: 20px;
399 - text-align: center;
218 +
219 + .ka-security-v3 .ka-action-btn:hover {
220 + border-color: #ef4444;
221 + color: #ef4444;
400 222 }
401 - .action-card h4 {
402 - margin: 0 0 10px 0;
403 - color: #333;
223 +
224 + body.ka-v3-dark .ka-security-v3 .ka-action-btn:hover {
225 + border-color: #ef4444;
226 + color: #ef4444;
404 227 }
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 {
228 +
229 + .ka-security-v3 .ka-action-btn .dashicons {
418 230 font-size: 16px;
419 231 width: 16px;
420 232 height: 16px;
421 - line-height: 16px;
422 - vertical-align: middle;
423 233 }
424 -
425 - /* Form improvements */
426 - .form-table th {
427 - width: 250px;
428 - padding: 20px 10px 20px 0;
234 +
235 + /* Security specific input focus */
236 + .ka-security-v3 input:focus {
237 + border-color: #ef4444 !important;
238 + box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.1) !important;
429 239 }
430 - .form-table td {
431 - padding: 20px 10px;
240 +
241 + body.ka-v3-dark .ka-security-v3 input:focus {
242 + box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.2) !important;
432 243 }
433 - .form-table input[type="number"] {
434 - width: 100px;
244 +
245 + /* Security toggle color */
246 + .ka-security-v3 .ka-toggle input:checked + .ka-toggle-slider {
247 + background: #ef4444 !important;
435 248 }
436 - .form-table .description {
437 - margin-top: 8px;
438 - line-height: 1.5;
439 - }
440 - .form-table .description strong {
441 - color: #2271b1;
442 - }
249 + </style>
443 250
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 - }
251 + <div class="ka-admin-wrap ka-security-v3">
252 + <!-- Header -->
253 + <div class="ka-admin-header">
254 + <div class="ka-admin-header-left">
255 + <div class="ka-admin-header-icon red">
256 + <span class="dashicons dashicons-shield"></span>
257 + </div>
258 + <div>
259 + <h1 class="ka-admin-title"><?php esc_html_e('Login Security', 'king-addons'); ?></h1>
260 + <p class="ka-admin-subtitle"><?php esc_html_e('Monitor and protect Login Register Form widgets', 'king-addons'); ?></p>
261 + </div>
262 + </div>
263 + <div class="ka-admin-header-actions">
264 + <div class="ka-v3-segmented" id="ka-v3-theme-segment" role="radiogroup" aria-label="<?php echo esc_attr(esc_html__('Theme', 'king-addons')); ?>" data-active="<?php echo esc_attr($theme_mode); ?>">
265 + <span class="ka-v3-segmented-indicator" aria-hidden="true"></span>
266 + <button type="button" class="ka-v3-segmented-btn" data-theme="light" aria-pressed="<?php echo $theme_mode === 'light' ? 'true' : 'false'; ?>">
267 + <span class="ka-v3-segmented-icon" aria-hidden="true">☀︎</span>
268 + <?php esc_html_e('Light', 'king-addons'); ?>
269 + </button>
270 + <button type="button" class="ka-v3-segmented-btn" data-theme="dark" aria-pressed="<?php echo $theme_mode === 'dark' ? 'true' : 'false'; ?>">
271 + <span class="ka-v3-segmented-icon" aria-hidden="true">☾</span>
272 + <?php esc_html_e('Dark', 'king-addons'); ?>
273 + </button>
274 + <button type="button" class="ka-v3-segmented-btn" data-theme="auto" aria-pressed="<?php echo $theme_mode === 'auto' ? 'true' : 'false'; ?>">
275 + <span class="ka-v3-segmented-icon" aria-hidden="true">◐</span>
276 + <?php esc_html_e('Auto', 'king-addons'); ?>
277 + </button>
278 + </div>
279 + </div>
280 + </div>
452 281
453 - /* Loading animation */
454 - @keyframes rotation {
455 - from {
456 - transform: rotate(0deg);
282 + <!-- Features -->
283 + <div class="ka-features-grid">
284 + <div class="ka-feature-card">
285 + <span class="dashicons dashicons-shield-alt"></span>
286 + <h4><?php esc_html_e('Rate Limiting', 'king-addons'); ?></h4>
287 + <p><?php esc_html_e('Auto-blocks IPs after failed attempts', 'king-addons'); ?></p>
288 + </div>
289 + <div class="ka-feature-card">
290 + <span class="dashicons dashicons-upload"></span>
291 + <h4><?php esc_html_e('File Security', 'king-addons'); ?></h4>
292 + <p><?php esc_html_e('Validates uploads & scans content', 'king-addons'); ?></p>
293 + </div>
294 + <div class="ka-feature-card">
295 + <span class="dashicons dashicons-admin-users"></span>
296 + <h4><?php esc_html_e('Anti-Enumeration', 'king-addons'); ?></h4>
297 + <p><?php esc_html_e('Unified error messages', 'king-addons'); ?></p>
298 + </div>
299 + <div class="ka-feature-card">
300 + <span class="dashicons dashicons-share"></span>
301 + <h4><?php esc_html_e('Social Login', 'king-addons'); ?></h4>
302 + <p><?php esc_html_e('Enhanced OAuth validation', 'king-addons'); ?></p>
303 + </div>
304 + </div>
305 +
306 + <!-- Stats -->
307 + <div class="ka-stats-grid">
308 + <div class="ka-stat-card">
309 + <h3 class="ka-stat-title"><?php esc_html_e('Failed Logins (24h)', 'king-addons'); ?></h3>
310 + <div class="ka-stat-number"><?php echo esc_html($stats['failed_logins_24h']); ?></div>
311 + </div>
312 + <div class="ka-stat-card">
313 + <h3 class="ka-stat-title"><?php esc_html_e('Blocked IPs', 'king-addons'); ?></h3>
314 + <div class="ka-stat-number"><?php echo esc_html($stats['blocked_ips']); ?></div>
315 + </div>
316 + <div class="ka-stat-card">
317 + <h3 class="ka-stat-title"><?php esc_html_e('Suspicious Registrations', 'king-addons'); ?></h3>
318 + <div class="ka-stat-number"><?php echo esc_html($stats['suspicious_registrations']); ?></div>
319 + </div>
320 + <div class="ka-stat-card">
321 + <h3 class="ka-stat-title"><?php esc_html_e('Upload Blocks', 'king-addons'); ?></h3>
322 + <div class="ka-stat-number"><?php echo esc_html($stats['file_upload_blocks']); ?></div>
323 + </div>
324 + </div>
325 +
326 + <!-- Blocked IPs -->
327 + <?php if (!empty($blocked_ips)): ?>
328 + <div class="ka-card">
329 + <div class="ka-card-header">
330 + <span class="dashicons dashicons-dismiss" style="color: #ef4444;"></span>
331 + <h2><?php esc_html_e('Blocked IPs', 'king-addons'); ?></h2>
332 + </div>
333 + <div class="ka-card-body" style="padding:0">
334 + <table class="ka-table">
335 + <thead>
336 + <tr>
337 + <th><?php esc_html_e('IP Address', 'king-addons'); ?></th>
338 + <th><?php esc_html_e('Attempts', 'king-addons'); ?></th>
339 + <th><?php esc_html_e('Last Attempt', 'king-addons'); ?></th>
340 + <th><?php esc_html_e('Expires', 'king-addons'); ?></th>
341 + <th><?php esc_html_e('Actions', 'king-addons'); ?></th>
342 + </tr>
343 + </thead>
344 + <tbody>
345 + <?php foreach ($blocked_ips as $ip_data): ?>
346 + <tr>
347 + <td><?php echo esc_html($ip_data['ip']); ?></td>
348 + <td><?php echo esc_html($ip_data['attempts']); ?></td>
349 + <td><?php echo esc_html(human_time_diff($ip_data['last_attempt'], time()) . ' ago'); ?></td>
350 + <td><?php echo esc_html(human_time_diff(time(), $ip_data['expires']) . ' remaining'); ?></td>
351 + <td>
352 + <button class="ka-action-btn unblock-ip" data-ip="<?php echo esc_attr($ip_data['ip']); ?>">
353 + <?php esc_html_e('Unblock', 'king-addons'); ?>
354 + </button>
355 + </td>
356 + </tr>
357 + <?php endforeach; ?>
358 + </tbody>
359 + </table>
360 + </div>
361 + </div>
362 + <?php endif; ?>
363 +
364 + <!-- Settings -->
365 + <div class="ka-card">
366 + <div class="ka-card-header">
367 + <span class="dashicons dashicons-admin-settings" style="color: #ef4444;"></span>
368 + <h2><?php esc_html_e('Security Settings', 'king-addons'); ?></h2>
369 + </div>
370 + <div class="ka-card-body">
371 + <form method="post" action="options.php">
372 + <?php settings_fields('king_addons_security_settings'); ?>
373 + <div class="ka-row">
374 + <div class="ka-row-label"><?php esc_html_e('Max Login Attempts', 'king-addons'); ?></div>
375 + <div class="ka-row-field">
376 + <input type="number" name="king_addons_max_login_attempts"
377 + value="<?php echo esc_attr(get_option('king_addons_max_login_attempts', 5)); ?>" min="1" max="20" />
378 + <p class="ka-row-desc"><?php esc_html_e('Failed attempts before IP is blocked. Recommended: 3-5', 'king-addons'); ?></p>
379 + </div>
380 + </div>
381 + <div class="ka-row">
382 + <div class="ka-row-label"><?php esc_html_e('Lockout Duration', 'king-addons'); ?></div>
383 + <div class="ka-row-field">
384 + <input type="number" name="king_addons_lockout_duration"
385 + value="<?php echo esc_attr(get_option('king_addons_lockout_duration', 15)); ?>" min="1" max="1440" />
386 + <span style="color:#86868b;margin-left:6px"><?php esc_html_e('minutes', 'king-addons'); ?></span>
387 + <p class="ka-row-desc"><?php esc_html_e('Duration to block an IP after exceeding attempts. Recommended: 15-30', 'king-addons'); ?></p>
388 + </div>
389 + </div>
390 + <div class="ka-row">
391 + <div class="ka-row-label"><?php esc_html_e('Security Logging', 'king-addons'); ?></div>
392 + <div class="ka-row-field">
393 + <label class="ka-toggle">
394 + <input type="checkbox" name="king_addons_enable_security_logging" value="1"
395 + <?php checked(get_option('king_addons_enable_security_logging', 1)); ?> />
396 + <span class="ka-toggle-slider"></span>
397 + <span class="ka-toggle-label"><?php esc_html_e('Log security events', 'king-addons'); ?></span>
398 + </label>
399 + <p class="ka-row-desc"><?php esc_html_e('Record failed attempts, blocks, and suspicious activity', 'king-addons'); ?></p>
400 + </div>
401 + </div>
402 +
403 + <div style="margin-top: 20px; padding-top: 20px; border-top: 1px solid rgba(0,0,0,0.04);">
404 + <button type="submit" class="ka-btn ka-btn-primary"><?php esc_html_e('Save Settings', 'king-addons'); ?></button>
405 + </div>
406 + </form>
407 + </div>
408 + </div>
409 +
410 + <!-- Actions -->
411 + <div class="ka-card">
412 + <div class="ka-card-header">
413 + <span class="dashicons dashicons-admin-tools" style="color: #ef4444;"></span>
414 + <h2><?php esc_html_e('Management Actions', 'king-addons'); ?></h2>
415 + </div>
416 + <div class="ka-card-body">
417 + <div class="ka-actions-grid">
418 + <div class="ka-action-card">
419 + <h4><?php esc_html_e('Clear Security Logs', 'king-addons'); ?></h4>
420 + <p><?php esc_html_e('Remove all logs and reset blocked IPs', 'king-addons'); ?></p>
421 + <button class="ka-action-btn" id="clear-security-logs">
422 + <span class="dashicons dashicons-trash"></span>
423 + <?php esc_html_e('Clear Logs', 'king-addons'); ?>
424 + </button>
425 + </div>
426 + <div class="ka-action-card">
427 + <h4><?php esc_html_e('Export Report', 'king-addons'); ?></h4>
428 + <p><?php esc_html_e('Download security report as JSON', 'king-addons'); ?></p>
429 + <button class="ka-action-btn" id="export-security-report">
430 + <span class="dashicons dashicons-download"></span>
431 + <?php esc_html_e('Export', 'king-addons'); ?>
432 + </button>
433 + </div>
434 + </div>
435 + </div>
436 + </div>
437 + </div>
438 +
439 + <script>
440 + (function() {
441 + const segment = document.getElementById('ka-v3-theme-segment');
442 + if (!segment) {
443 + return;
457 444 }
458 - to {
459 - transform: rotate(359deg);
445 +
446 + const ajaxUrl = '<?php echo esc_url(admin_url('admin-ajax.php')); ?>';
447 + const nonce = '<?php echo esc_js(wp_create_nonce('king_addons_dashboard_ui')); ?>';
448 + const buttons = segment.querySelectorAll('.ka-v3-segmented-btn');
449 +
450 + const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
451 + let mode = (segment.getAttribute('data-active') || 'dark').toString();
452 + let mqlHandler = null;
453 +
454 + function setPressedState(activeMode) {
455 + segment.setAttribute('data-active', activeMode);
456 + buttons.forEach((btn) => {
457 + const theme = btn.getAttribute('data-theme');
458 + btn.setAttribute('aria-pressed', theme === activeMode ? 'true' : 'false');
459 + });
460 460 }
461 - }
462 - </style>
463 461
464 - <script>
462 + function saveUISetting(key, value) {
463 + try {
464 + const body = new URLSearchParams();
465 + body.set('action', 'king_addons_save_dashboard_ui');
466 + body.set('nonce', nonce);
467 + body.set('key', key);
468 + body.set('value', value);
469 +
470 + fetch(ajaxUrl, {
471 + method: 'POST',
472 + headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
473 + body: body.toString(),
474 + credentials: 'same-origin'
475 + });
476 + } catch (e) {}
477 + }
478 +
479 + function applyTheme(isDark) {
480 + document.body.classList.toggle('ka-v3-dark', isDark);
481 + document.documentElement.classList.toggle('ka-v3-dark', isDark);
482 + }
483 +
484 + function setThemeMode(nextMode, save) {
485 + mode = nextMode;
486 + setPressedState(nextMode);
487 +
488 + if (mqlHandler && mql) {
489 + if (mql.removeEventListener) {
490 + mql.removeEventListener('change', mqlHandler);
491 + } else if (mql.removeListener) {
492 + mql.removeListener(mqlHandler);
493 + }
494 + mqlHandler = null;
495 + }
496 +
497 + if (nextMode === 'auto') {
498 + applyTheme(!!(mql && mql.matches));
499 + mqlHandler = (e) => {
500 + if (mode !== 'auto') {
501 + return;
502 + }
503 + applyTheme(!!e.matches);
504 + };
505 + if (mql) {
506 + if (mql.addEventListener) {
507 + mql.addEventListener('change', mqlHandler);
508 + } else if (mql.addListener) {
509 + mql.addListener(mqlHandler);
510 + }
511 + }
512 + } else {
513 + applyTheme(nextMode === 'dark');
514 + }
515 +
516 + if (save) {
517 + saveUISetting('theme_mode', nextMode);
518 + }
519 + }
520 +
521 + // Optional global for any legacy handlers
522 + window.kaV3ToggleDark = function() {
523 + const isDark = document.body.classList.contains('ka-v3-dark');
524 + setThemeMode(isDark ? 'light' : 'dark', true);
525 + };
526 +
527 + segment.addEventListener('click', (e) => {
528 + const btn = e.target && e.target.closest ? e.target.closest('.ka-v3-segmented-btn') : null;
529 + if (!btn) {
530 + return;
531 + }
532 + e.preventDefault();
533 + const theme = (btn.getAttribute('data-theme') || 'dark').toString();
534 + setThemeMode(theme, true);
535 + });
536 +
537 + setThemeMode(mode, false);
538 + })();
539 +
465 540 jQuery(document).ready(function($) {
466 541 // Unblock IP functionality
467 542 $('.unblock-ip').on('click', function() {
468 543 const ip = $(this).data('ip');
469 - if (confirm('Are you sure you want to unblock this IP?')) {
544 + if (confirm('<?php echo esc_js(__('Are you sure you want to unblock this IP?', 'king-addons')); ?>')) {
470 545 $.post(ajaxurl, {
471 546 action: 'king_addons_unblock_ip',
472 547 ip: ip,
473 548 nonce: '<?php echo wp_create_nonce('king_addons_security_nonce'); ?>'
@@ -474,9 +549,9 @@
474 549 }, function(response) {
475 550 if (response.success) {
476 551 location.reload();
477 552 } else {
478 - alert('Failed to unblock IP: ' + response.data.message);
553 + alert('<?php echo esc_js(__('Failed to unblock IP', 'king-addons')); ?>');
479 554 }
480 555 });
481 556 }
482 557 });
@@ -482,9 +557,9 @@
482 557 });
483 558
484 559 // Clear security logs
485 560 $('#clear-security-logs').on('click', function() {
486 - if (confirm('Are you sure you want to clear all security logs?')) {
561 + if (confirm('<?php echo esc_js(__('Are you sure you want to clear all security logs?', 'king-addons')); ?>')) {
487 562 $.post(ajaxurl, {
488 563 action: 'king_addons_clear_security_logs',
489 564 nonce: '<?php echo wp_create_nonce('king_addons_security_nonce'); ?>'
490 565 }, function(response) {
@@ -490,9 +565,9 @@
490 565 }, function(response) {
491 566 if (response.success) {
492 567 location.reload();
493 568 } else {
494 - alert('Failed to clear logs: ' + response.data.message);
569 + alert('<?php echo esc_js(__('Failed to clear logs', 'king-addons')); ?>');
495 570 }
496 571 });
497 572 }
498 573 });
@@ -500,34 +575,25 @@
500 575 // Export security report
501 576 $('#export-security-report').on('click', function() {
502 577 const $button = $(this);
503 578 const originalText = $button.html();
579 + $button.prop('disabled', true).text('<?php echo esc_js(__('Exporting...', 'king-addons')); ?>');
504 580
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 581 $.post(ajaxurl, {
509 582 action: 'king_addons_export_security_report',
510 583 nonce: '<?php echo wp_create_nonce('king_addons_security_nonce'); ?>'
511 584 }, function(response) {
512 585 if (response.success) {
513 - // Create download link and trigger download
514 586 const link = document.createElement('a');
515 587 link.href = response.data.download_url;
516 588 link.download = response.data.filename;
517 - link.style.display = 'none';
518 589 document.body.appendChild(link);
519 590 link.click();
520 591 document.body.removeChild(link);
521 -
522 - alert('Security report downloaded successfully!');
523 592 } else {
524 - alert('Failed to generate report: ' + response.data.message);
593 + alert('<?php echo esc_js(__('Failed to generate report', 'king-addons')); ?>');
525 594 }
526 - }).fail(function() {
527 - alert('Network error occurred while generating report.');
528 595 }).always(function() {
529 - // Restore button state
530 596 $button.prop('disabled', false).html(originalText);
531 597 });
532 598 });
533 599 });