clean build for version 1.4.5 with fixes of security funtionalities, logic branches, etc. Already tested and working fine
This commit is contained in:
@@ -3,120 +3,407 @@
|
||||
<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</p>
|
||||
|
||||
<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' : '' ?>>
|
||||
<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="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</small>
|
||||
<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</small>
|
||||
<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</small>
|
||||
<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">
|
||||
<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>
|
||||
<p class="text-muted small mb-3">Invisible CAPTCHA protection. <a href="https://www.google.com/recaptcha/admin" target="_blank">Get keys here</a></p>
|
||||
|
||||
<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' : '' ?>>
|
||||
<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="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</label>
|
||||
<input type="text" name="checker[security][recaptcha][site_key]" value="<?= $checker['security']['recaptcha']['site_key'] ?? '' ?>" class="form-control" placeholder="6Lc...">
|
||||
<small class="text-muted">Public key for frontend</small>
|
||||
<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</label>
|
||||
<input type="text" name="checker[security][recaptcha][secret_key]" value="<?= $checker['security']['recaptcha']['secret_key'] ?? '' ?>" class="form-control" placeholder="6Lc...">
|
||||
<small class="text-muted">Private key for backend verification</small>
|
||||
<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">
|
||||
<small class="text-muted">0.0 (bot) to 1.0 (human). Recommended: 0.5</small>
|
||||
<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>
|
||||
<p class="text-muted small mb-3">Privacy-friendly CAPTCHA alternative. <a href="https://dash.cloudflare.com/?to=/:account/turnstile" target="_blank">Get keys here</a></p>
|
||||
|
||||
<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' : '' ?>>
|
||||
<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="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</label>
|
||||
<input type="text" name="checker[security][turnstile][site_key]" value="<?= $checker['security']['turnstile']['site_key'] ?? '' ?>" class="form-control" placeholder="0x4AAA...">
|
||||
<small class="text-muted">Public key for frontend</small>
|
||||
<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</label>
|
||||
<input type="text" name="checker[security][turnstile][secret_key]" value="<?= $checker['security']['turnstile']['secret_key'] ?? '' ?>" class="form-control" placeholder="0x4AAA...">
|
||||
<small class="text-muted">Private key for backend verification</small>
|
||||
<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>
|
||||
<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>Note:</strong> Only enable ONE CAPTCHA solution at a time. reCAPTCHA and Turnstile cannot be used together.
|
||||
<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>
|
||||
@@ -133,33 +420,178 @@ jQuery(document).ready(function($){
|
||||
$('.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')){
|
||||
$('#security-turnstile-enabled').prop('checked', false).trigger('change');
|
||||
alert('reCAPTCHA enabled. Turnstile has been disabled.');
|
||||
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')){
|
||||
$('#security-recaptcha-enabled').prop('checked', false).trigger('change');
|
||||
alert('Turnstile enabled. reCAPTCHA has been disabled.');
|
||||
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>
|
||||
|
||||
Reference in New Issue
Block a user