598 lines
33 KiB
PHP
598 lines
33 KiB
PHP
<table class="table checker-setting" data-toggle="table" id="checker-security" style="display:none;">
|
|
<tbody>
|
|
<tr class="has-link" style="display: none;">
|
|
<th>Rate Limiting</th>
|
|
<td>
|
|
<p class="text-muted small mb-3">Limit the number of searches per IP address to prevent abuse and bot attacks</p>
|
|
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" value="yes" id="security-rate-limit-enabled" name="checker[security][rate_limit][enabled]" <?= isset(
|
|
$checker["security"]["rate_limit"]["enabled"],
|
|
) && $checker["security"]["rate_limit"]["enabled"] == "yes"
|
|
? "checked"
|
|
: "" ?>>
|
|
<label class="form-check-label fw-bold" for="security-rate-limit-enabled">
|
|
Enable Rate Limiting
|
|
</label>
|
|
</div>
|
|
|
|
<div class="rate-limit-settings" style="<?= isset(
|
|
$checker["security"]["rate_limit"]["enabled"],
|
|
) && $checker["security"]["rate_limit"]["enabled"] == "yes"
|
|
? ""
|
|
: "display:none;" ?>">
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Max Attempts</label>
|
|
<input type="number" name="checker[security][rate_limit][max_attempts]" value="<?= $checker[
|
|
"security"
|
|
]["rate_limit"]["max_attempts"] ??
|
|
5 ?>" class="form-control" min="1" max="100">
|
|
<small class="text-muted">Maximum searches allowed per time window (1-100)</small>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Time Window (minutes)</label>
|
|
<input type="number" name="checker[security][rate_limit][time_window]" value="<?= $checker[
|
|
"security"
|
|
]["rate_limit"]["time_window"] ??
|
|
15 ?>" class="form-control" min="1" max="1440">
|
|
<small class="text-muted">Reset attempts after this duration (1-1440 minutes)</small>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Block Duration (minutes)</label>
|
|
<input type="number" name="checker[security][rate_limit][block_duration]" value="<?= $checker[
|
|
"security"
|
|
]["rate_limit"]["block_duration"] ??
|
|
60 ?>" class="form-control" min="1" max="10080">
|
|
<small class="text-muted">How long to block after exceeding limit (1-10080 minutes)</small>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Error Message</label>
|
|
<input type="text" name="checker[security][rate_limit][error_message]" value="<?= $checker[
|
|
"security"
|
|
]["rate_limit"]["error_message"] ??
|
|
"Too many attempts. Please try again later." ?>" class="form-control">
|
|
<small class="text-muted">Message shown when blocked</small>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" value="yes" id="security-rate-limit-whitelist" name="checker[security][rate_limit][whitelist_enabled]" <?= isset(
|
|
$checker["security"]["rate_limit"][
|
|
"whitelist_enabled"
|
|
],
|
|
) &&
|
|
$checker["security"]["rate_limit"][
|
|
"whitelist_enabled"
|
|
] == "yes"
|
|
? "checked"
|
|
: "" ?>>
|
|
<label class="form-check-label" for="security-rate-limit-whitelist">
|
|
Enable IP Whitelist
|
|
</label>
|
|
</div>
|
|
<div id="whitelist-ips" style="<?= isset(
|
|
$checker["security"]["rate_limit"][
|
|
"whitelist_enabled"
|
|
],
|
|
) &&
|
|
$checker["security"]["rate_limit"][
|
|
"whitelist_enabled"
|
|
] == "yes"
|
|
? ""
|
|
: "display:none;" ?>" class="mt-3">
|
|
<label class="form-label">Whitelisted IPs (one per line)</label>
|
|
<textarea name="checker[security][rate_limit][whitelist_ips]" class="form-control" rows="3"><?= $checker[
|
|
"security"
|
|
]["rate_limit"]["whitelist_ips"] ??
|
|
"" ?></textarea>
|
|
<small class="text-muted">IPs that bypass rate limiting (supports CIDR notation like 192.168.1.0/24)</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr class="has-link" style="display: none;">
|
|
<th>Google reCAPTCHA v3</th>
|
|
<td>
|
|
<div class="alert alert-info small mb-3">
|
|
<strong>How to get keys:</strong><br>
|
|
1. Go to <a href="https://www.google.com/recaptcha/admin/create" target="_blank" rel="noopener">reCAPTCHA Admin Console</a><br>
|
|
2. Create a new site with <strong>Score based (v3)</strong> type<br>
|
|
3. Add your domain (e.g., dwindi.com)<br>
|
|
4. Copy the <strong>Site Key</strong> and <strong>Secret Key</strong> shown after creation<br>
|
|
<em class="text-muted">Note: If using Google Cloud Console, click "Use Legacy Key" under Integration tab to get the secret key</em>
|
|
</div>
|
|
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" value="yes" id="security-recaptcha-enabled" name="checker[security][recaptcha][enabled]" <?= isset(
|
|
$checker["security"]["recaptcha"]["enabled"],
|
|
) && $checker["security"]["recaptcha"]["enabled"] == "yes"
|
|
? "checked"
|
|
: "" ?>>
|
|
<label class="form-check-label fw-bold" for="security-recaptcha-enabled">
|
|
Enable reCAPTCHA v3
|
|
</label>
|
|
</div>
|
|
|
|
<div class="recaptcha-settings" style="<?= isset(
|
|
$checker["security"]["recaptcha"]["enabled"],
|
|
) && $checker["security"]["recaptcha"]["enabled"] == "yes"
|
|
? ""
|
|
: "display:none;" ?>">
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Site Key <span class="text-danger">*</span></label>
|
|
<input type="text" name="checker[security][recaptcha][site_key]" value="<?= esc_attr($checker["security"]["recaptcha"]["site_key"] ?? "") ?>" class="form-control" placeholder="6Lc...">
|
|
<small class="text-muted">Public key for frontend - shown after creating reCAPTCHA site</small>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Secret Key (Server) <span class="text-danger">*</span></label>
|
|
<input type="text" name="checker[security][recaptcha][secret_key]" value="<?= esc_attr($checker["security"]["recaptcha"]["secret_key"] ?? "") ?>" class="form-control" placeholder="Secret key from Google admin console">
|
|
<small class="text-muted">Server-side secret from Google reCAPTCHA admin console (required for verification)</small>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Minimum Score</label>
|
|
<input type="number" name="checker[security][recaptcha][min_score]" value="<?= $checker[
|
|
"security"
|
|
]["recaptcha"]["min_score"] ??
|
|
0.5 ?>" class="form-control" min="0" max="1" step="0.1" <?= isset(
|
|
$checker["security"]["recaptcha"]["enabled"],
|
|
) && $checker["security"]["recaptcha"]["enabled"] == "yes"
|
|
? "required"
|
|
: "" ?>>
|
|
<small class="text-muted">0.0 (likely bot) to 1.0 (likely human). Recommended: 0.5</small>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Action Name</label>
|
|
<input type="text" name="checker[security][recaptcha][action]" value="<?= $checker[
|
|
"security"
|
|
]["recaptcha"]["action"] ??
|
|
"checker_validate" ?>" class="form-control" <?= isset(
|
|
$checker["security"]["recaptcha"]["enabled"],
|
|
) && $checker["security"]["recaptcha"]["enabled"] == "yes"
|
|
? "required"
|
|
: "" ?>>
|
|
<small class="text-muted">Action name for reCAPTCHA tracking (letters only)</small>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" value="yes" id="security-recaptcha-hide-badge" name="checker[security][recaptcha][hide_badge]" <?= isset(
|
|
$checker["security"]["recaptcha"][
|
|
"hide_badge"
|
|
],
|
|
) &&
|
|
$checker["security"]["recaptcha"][
|
|
"hide_badge"
|
|
] == "yes"
|
|
? "checked"
|
|
: "" ?>>
|
|
<label class="form-check-label" for="security-recaptcha-hide-badge">
|
|
Hide reCAPTCHA Badge
|
|
</label>
|
|
</div>
|
|
<small class="text-muted">Hides the "protected by reCAPTCHA" badge. You must add attribution elsewhere on the page.</small>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<label class="form-label">Custom Error Message</label>
|
|
<input type="text" name="checker[security][recaptcha][error_message]" value="<?= esc_attr($checker["security"]["recaptcha"]["error_message"] ?? "") ?>" class="form-control" placeholder="<?= esc_attr__('Leave empty for default message', 'sheet-data-checker-pro') ?>">
|
|
<small class="text-muted"><?= esc_html__('Custom message shown when reCAPTCHA verification fails (leave empty for default)', 'sheet-data-checker-pro') ?></small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr class="has-link" style="display: none;">
|
|
<th>Cloudflare Turnstile</th>
|
|
<td>
|
|
<div class="alert alert-info small mb-3">
|
|
<strong>How to get keys:</strong><br>
|
|
1. Go to <a href="https://dash.cloudflare.com/?to=/:account/turnstile" target="_blank" rel="noopener">Cloudflare Turnstile Dashboard</a><br>
|
|
2. Click "Add Widget" and enter your site name<br>
|
|
3. Add your domain (e.g., dwindi.com)<br>
|
|
4. Choose Widget Mode: <strong>Managed</strong> (recommended) or Non-interactive<br>
|
|
5. Copy the <strong>Site Key</strong> and <strong>Secret Key</strong> shown after creation
|
|
</div>
|
|
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" value="yes" id="security-turnstile-enabled" name="checker[security][turnstile][enabled]" <?= isset(
|
|
$checker["security"]["turnstile"]["enabled"],
|
|
) && $checker["security"]["turnstile"]["enabled"] == "yes"
|
|
? "checked"
|
|
: "" ?>>
|
|
<label class="form-check-label fw-bold" for="security-turnstile-enabled">
|
|
Enable Cloudflare Turnstile
|
|
</label>
|
|
</div>
|
|
|
|
<div class="turnstile-settings" style="<?= isset(
|
|
$checker["security"]["turnstile"]["enabled"],
|
|
) && $checker["security"]["turnstile"]["enabled"] == "yes"
|
|
? ""
|
|
: "display:none;" ?>">
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Site Key <span class="text-danger">*</span></label>
|
|
<input type="text" name="checker[security][turnstile][site_key]" value="<?= esc_attr($checker["security"]["turnstile"]["site_key"] ?? "") ?>" class="form-control" placeholder="0x4AAA...">
|
|
<small class="text-muted">Public key for frontend (starts with 0x4AAA...)</small>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Secret Key <span class="text-danger">*</span></label>
|
|
<input type="text" name="checker[security][turnstile][secret_key]" value="<?= esc_attr($checker["security"]["turnstile"]["secret_key"] ?? "") ?>" class="form-control" placeholder="0x4AAA...">
|
|
<small class="text-muted">Private key for backend verification (starts with 0x4AAA...)</small>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Theme</label>
|
|
<select name="checker[security][turnstile][theme]" class="form-select">
|
|
<option value="light" <?= isset(
|
|
$checker["security"]["turnstile"]["theme"],
|
|
) &&
|
|
$checker["security"]["turnstile"]["theme"] ==
|
|
"light"
|
|
? "selected"
|
|
: "" ?>>Light</option>
|
|
<option value="dark" <?= isset(
|
|
$checker["security"]["turnstile"]["theme"],
|
|
) &&
|
|
$checker["security"]["turnstile"]["theme"] ==
|
|
"dark"
|
|
? "selected"
|
|
: "" ?>>Dark</option>
|
|
<option value="auto" <?= isset(
|
|
$checker["security"]["turnstile"]["theme"],
|
|
) &&
|
|
$checker["security"]["turnstile"]["theme"] ==
|
|
"auto"
|
|
? "selected"
|
|
: "" ?>>Auto</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Size</label>
|
|
<select name="checker[security][turnstile][size]" class="form-select">
|
|
<option value="normal" <?= isset(
|
|
$checker["security"]["turnstile"]["size"],
|
|
) &&
|
|
$checker["security"]["turnstile"]["size"] ==
|
|
"normal"
|
|
? "selected"
|
|
: "" ?>>Normal</option>
|
|
<option value="compact" <?= isset(
|
|
$checker["security"]["turnstile"]["size"],
|
|
) &&
|
|
$checker["security"]["turnstile"]["size"] ==
|
|
"compact"
|
|
? "selected"
|
|
: "" ?>>Compact</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<label class="form-label">Custom Error Message</label>
|
|
<input type="text" name="checker[security][turnstile][error_message]" value="<?= esc_attr($checker["security"]["turnstile"]["error_message"] ?? "") ?>" class="form-control" placeholder="<?= esc_attr__('Leave empty for default message', 'sheet-data-checker-pro') ?>">
|
|
<small class="text-muted"><?= esc_html__('Custom message shown when Turnstile verification fails (leave empty for default)', 'sheet-data-checker-pro') ?></small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr class="has-link" style="display: none;">
|
|
<th>Honeypot Protection</th>
|
|
<td>
|
|
<p class="text-muted small mb-3"><?= esc_html__('Invisible spam protection that catches automated bots without affecting real users', 'sheet-data-checker-pro') ?></p>
|
|
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" value="yes" id="security-honeypot-enabled" name="checker[security][honeypot][enabled]" <?= isset($checker["security"]["honeypot"]["enabled"]) && $checker["security"]["honeypot"]["enabled"] == "yes" ? "checked" : "" ?>>
|
|
<label class="form-check-label fw-bold" for="security-honeypot-enabled">
|
|
<?= esc_html__('Enable Honeypot Field', 'sheet-data-checker-pro') ?>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="honeypot-settings" style="<?= isset($checker["security"]["honeypot"]["enabled"]) && $checker["security"]["honeypot"]["enabled"] == "yes" ? "" : "display:none;" ?>">
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<label class="form-label"><?= esc_html__('Custom Error Message', 'sheet-data-checker-pro') ?></label>
|
|
<input type="text" name="checker[security][honeypot][error_message]" value="<?= esc_attr($checker["security"]["honeypot"]["error_message"] ?? "") ?>" class="form-control" placeholder="<?= esc_attr__('Leave empty for default message', 'sheet-data-checker-pro') ?>">
|
|
<small class="text-muted"><?= esc_html__('Message shown when honeypot is triggered (leave empty for default)', 'sheet-data-checker-pro') ?></small>
|
|
</div>
|
|
</div>
|
|
<div class="alert alert-info small">
|
|
<i class="bi bi-info-circle"></i> <?= esc_html__('Honeypot adds an invisible field that bots will fill out, allowing easy detection without user interaction.', 'sheet-data-checker-pro') ?>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr class="has-link" style="display: none;">
|
|
<th>IP Detection Method</th>
|
|
<td>
|
|
<p class="text-muted small mb-3">Configure how to detect visitor IP addresses</p>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<label class="form-label">IP Detection Priority</label>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" id="ip-auto" name="checker[security][ip_detection]" value="auto" <?= !isset(
|
|
$checker["security"]["ip_detection"],
|
|
) || $checker["security"]["ip_detection"] == "auto"
|
|
? "checked"
|
|
: "" ?>>
|
|
<label class="form-check-label" for="ip-auto">
|
|
Automatic (Recommended)
|
|
</label>
|
|
<small class="d-block text-muted">Automatically detect IP through Cloudflare, proxies, and standard headers</small>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" id="ip-remote-addr" name="checker[security][ip_detection]" value="remote_addr" <?= isset(
|
|
$checker["security"]["ip_detection"],
|
|
) &&
|
|
$checker["security"]["ip_detection"] ==
|
|
"remote_addr"
|
|
? "checked"
|
|
: "" ?>>
|
|
<label class="form-check-label" for="ip-remote-addr">
|
|
REMOTE_ADDR Only
|
|
</label>
|
|
<small class="d-block text-muted">Only use REMOTE_ADDR (less accurate but more predictable)</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr class="has-link" style="display: none;">
|
|
<th>Nonce Verification</th>
|
|
<td>
|
|
<p class="text-muted small mb-3">WordPress security token to prevent CSRF attacks</p>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" value="yes" id="security-nonce-enabled" name="checker[security][nonce_enabled]" value="yes" checked disabled>
|
|
<label class="form-check-label" for="security-nonce-enabled">
|
|
Enable Nonce Verification (Always Active)
|
|
</label>
|
|
</div>
|
|
<small class="text-muted">
|
|
<i class="fas fa-info-circle"></i>
|
|
Nonce verification is always enabled for security. This protects against Cross-Site Request Forgery (CSRF) attacks.
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr class="has-link" style="display: none;">
|
|
<th>Security Status</th>
|
|
<td>
|
|
<div id="security-status" class="alert alert-warning mb-3">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
<strong>Security Check:</strong> Please configure at least one protection method (Rate Limiting, reCAPTCHA, or Turnstile).
|
|
</div>
|
|
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="test-security-btn">
|
|
<i class="fas fa-shield-alt"></i> Test Security Settings
|
|
</button>
|
|
|
|
<div id="security-test-results" style="display:none;" class="mt-3"></div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr class="has-link" style="display: none;">
|
|
<th colspan="2">
|
|
<div class="alert alert-info mb-0">
|
|
<strong>Security Recommendations:</strong>
|
|
<ul class="mb-0 mt-2">
|
|
<li>Enable at least one protection method (Rate Limiting, reCAPTCHA, or Turnstile)</li>
|
|
<li>Only enable ONE CAPTCHA solution at a time (reCAPTCHA or Turnstile)</li>
|
|
<li>For high-traffic sites, use Rate Limiting with reCAPTCHA v3</li>
|
|
<li>Regularly review rate limiting logs for suspicious activity</li>
|
|
</ul>
|
|
</div>
|
|
</th>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<script>
|
|
jQuery(document).ready(function($){
|
|
// Toggle rate limit settings
|
|
$('#security-rate-limit-enabled').on('change', function(){
|
|
if($(this).is(':checked')){
|
|
$('.rate-limit-settings').slideDown();
|
|
}else{
|
|
$('.rate-limit-settings').slideUp();
|
|
}
|
|
});
|
|
|
|
// Toggle IP whitelist
|
|
$('#security-rate-limit-whitelist').on('change', function(){
|
|
if($(this).is(':checked')){
|
|
$('#whitelist-ips').slideDown();
|
|
}else{
|
|
$('#whitelist-ips').slideUp();
|
|
}
|
|
});
|
|
|
|
// Toggle reCAPTCHA settings
|
|
$('#security-recaptcha-enabled').on('change', function(){
|
|
if($(this).is(':checked')){
|
|
$('.recaptcha-settings').slideDown();
|
|
// Disable Turnstile if reCAPTCHA is enabled
|
|
if($('#security-turnstile-enabled').is(':checked')){
|
|
if(confirm('reCAPTCHA will be enabled. Do you want to disable Turnstile?')){
|
|
$('#security-turnstile-enabled').prop('checked', false).trigger('change');
|
|
} else {
|
|
$(this).prop('checked', false);
|
|
alert('Only one CAPTCHA solution can be active at a time.');
|
|
return false;
|
|
}
|
|
}
|
|
}else{
|
|
$('.recaptcha-settings').slideUp();
|
|
}
|
|
updateSecurityStatus();
|
|
});
|
|
|
|
// Toggle Turnstile settings
|
|
$('#security-turnstile-enabled').on('change', function(){
|
|
if($(this).is(':checked')){
|
|
$('.turnstile-settings').slideDown();
|
|
// Disable reCAPTCHA if Turnstile is enabled
|
|
if($('#security-recaptcha-enabled').is(':checked')){
|
|
if(confirm('Turnstile will be enabled. Do you want to disable reCAPTCHA?')){
|
|
$('#security-recaptcha-enabled').prop('checked', false).trigger('change');
|
|
} else {
|
|
$(this).prop('checked', false);
|
|
alert('Only one CAPTCHA solution can be active at a time.');
|
|
return false;
|
|
}
|
|
}
|
|
}else{
|
|
$('.turnstile-settings').slideUp();
|
|
}
|
|
updateSecurityStatus();
|
|
});
|
|
|
|
// Honeypot toggle
|
|
$('#security-honeypot-enabled').on('change', function(){
|
|
if($(this).is(':checked')){
|
|
$('.honeypot-settings').slideDown();
|
|
}else{
|
|
$('.honeypot-settings').slideUp();
|
|
}
|
|
updateSecurityStatus();
|
|
});
|
|
|
|
// Update security status when any setting changes
|
|
$('input[type="checkbox"]').on('change', function(){
|
|
updateSecurityStatus();
|
|
});
|
|
|
|
function updateSecurityStatus() {
|
|
var rateLimitEnabled = $('#security-rate-limit-enabled').is(':checked');
|
|
var recaptchaEnabled = $('#security-recaptcha-enabled').is(':checked');
|
|
var turnstileEnabled = $('#security-turnstile-enabled').is(':checked');
|
|
var honeypotEnabled = $('#security-honeypot-enabled').is(':checked');
|
|
|
|
var statusEl = $('#security-status');
|
|
var protectionCount = 0;
|
|
var protections = [];
|
|
|
|
if(rateLimitEnabled) { protectionCount++; protections.push('Rate Limiting'); }
|
|
if(recaptchaEnabled) { protectionCount++; protections.push('reCAPTCHA'); }
|
|
if(turnstileEnabled) { protectionCount++; protections.push('Turnstile'); }
|
|
if(honeypotEnabled) { protectionCount++; protections.push('Honeypot'); }
|
|
|
|
if(protectionCount > 0) {
|
|
statusEl.removeClass('alert-warning alert-danger').addClass('alert-success');
|
|
statusEl.html('<i class="fas fa-check-circle"></i> <strong>Security Status:</strong> ' + protectionCount + ' protection(s) active: ' + protections.join(', '));
|
|
} else {
|
|
statusEl.removeClass('alert-success alert-danger').addClass('alert-warning');
|
|
statusEl.html('<i class="fas fa-exclamation-triangle"></i> <strong>Security Status:</strong> No protection enabled. Please configure at least one protection method.');
|
|
}
|
|
|
|
// Check for CAPTCHA conflict
|
|
if(recaptchaEnabled && turnstileEnabled) {
|
|
statusEl.removeClass('alert-success alert-warning').addClass('alert-danger');
|
|
statusEl.html('<i class="fas fa-exclamation-circle"></i> <strong>Security Warning:</strong> Both reCAPTCHA and Turnstile are enabled. Please disable one of them.');
|
|
}
|
|
}
|
|
|
|
// Test security settings
|
|
$('#test-security-btn').on('click', function(){
|
|
var btn = $(this);
|
|
var resultsEl = $('#security-test-results');
|
|
|
|
btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Testing...');
|
|
|
|
resultsEl.removeClass('alert-success alert-danger alert-warning').addClass('alert-info')
|
|
.html('<i class="fas fa-info-circle"></i> Running security tests...').show();
|
|
|
|
// Simulate security test
|
|
setTimeout(function(){
|
|
var issues = [];
|
|
|
|
// Check rate limiting
|
|
if(!$('#security-rate-limit-enabled').is(':checked')) {
|
|
issues.push('Rate limiting is not enabled');
|
|
}
|
|
|
|
// Check CAPTCHA
|
|
if(!$('#security-recaptcha-enabled').is(':checked') && !$('#security-turnstile-enabled').is(':checked')) {
|
|
issues.push('No CAPTCHA solution is enabled');
|
|
}
|
|
|
|
// Check for CAPTCHA conflict
|
|
if($('#security-recaptcha-enabled').is(':checked') && $('#security-turnstile-enabled').is(':checked')) {
|
|
issues.push('Both reCAPTCHA and Turnstile are enabled (conflict)');
|
|
}
|
|
|
|
// Check reCAPTCHA keys
|
|
if($('#security-recaptcha-enabled').is(':checked')) {
|
|
var siteKey = $('input[name="checker[security][recaptcha][site_key]"]').val();
|
|
var secretKey = $('input[name="checker[security][recaptcha][secret_key]"]').val();
|
|
|
|
if(!siteKey || !siteKey.startsWith('6Lc')) {
|
|
issues.push('reCAPTCHA site key is missing or invalid');
|
|
}
|
|
|
|
if(!secretKey || !secretKey.startsWith('6Lc')) {
|
|
issues.push('reCAPTCHA secret key is missing or invalid');
|
|
}
|
|
}
|
|
|
|
// Check Turnstile keys
|
|
if($('#security-turnstile-enabled').is(':checked')) {
|
|
var siteKey = $('input[name="checker[security][turnstile][site_key]"]').val();
|
|
var secretKey = $('input[name="checker[security][turnstile][secret_key]"]').val();
|
|
|
|
if(!siteKey || !siteKey.startsWith('0x4AAA')) {
|
|
issues.push('Turnstile site key is missing or invalid');
|
|
}
|
|
|
|
if(!secretKey || !secretKey.startsWith('0x4AAA')) {
|
|
issues.push('Turnstile secret key is missing or invalid');
|
|
}
|
|
}
|
|
|
|
// Display results
|
|
btn.prop('disabled', false).html('<i class="fas fa-shield-alt"></i> Test Security Settings');
|
|
|
|
if(issues.length === 0) {
|
|
resultsEl.removeClass('alert-info alert-danger alert-warning').addClass('alert-success')
|
|
.html('<i class="fas fa-check-circle"></i> <strong>All security checks passed!</strong> Your configuration is secure.');
|
|
} else {
|
|
var issuesHtml = '<ul class="mb-0">';
|
|
issues.forEach(function(issue) {
|
|
issuesHtml += '<li>' + issue + '</li>';
|
|
});
|
|
issuesHtml += '</ul>';
|
|
|
|
resultsEl.removeClass('alert-info alert-success alert-warning').addClass('alert-danger')
|
|
.html('<i class="fas fa-exclamation-circle"></i> <strong>Security issues found:</strong> ' + issuesHtml);
|
|
}
|
|
}, 1500);
|
|
});
|
|
|
|
// Initial security status update
|
|
updateSecurityStatus();
|
|
});
|
|
</script>
|