feat: initial InformatiQ Toolkit plugin
Merges informatiq-wp-secure + informatiq-utils + HoneypotFields into a single unified plugin with the following improvements: - Fixed deactivation bug: all protection methods now guard themselves with their own option check so toggling off via AJAX takes effect immediately without any hook re-registration. - Added rate-limiting for good/legitimate bots (Googlebot, Bingbot, DuckDuckBot, Yandex, etc.) via transient sliding-window counters; configurable per-bot limits in goodbots.conf (BotName|req/min); returns HTTP 429 with Retry-After: 60 when over limit. - Unified MySQL-backed logging (itk_bot_log + itk_honeypot_log tables) replaces the old wp_options-based 100-entry cap. - New Dashboard tab with terminal-style bot activity monitor: total blocked, today's count, rate-limited hits, top threat sources (bar chart), top IPs, top honeypot form types, active-module status panel. - All optimizations from utils.php merged into Optimization tab as toggleable settings (was always-on before). - Single admin page (Settings → InformatiQ Toolkit) with 8 tabs: Dashboard | Bot Blocker | Protection | Optimization | Honeypot | Bot Logs | Honeypot Logs | Config Files. - Config file editor for badbots.conf, goodbots.conf, referrers.conf, networks.conf, allowed-ips.conf with AJAX save and transient flush. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
310
assets/css/admin.css
Normal file
310
assets/css/admin.css
Normal file
@@ -0,0 +1,310 @@
|
||||
/* ============================================================
|
||||
InformatiQ Toolkit – Admin CSS
|
||||
============================================================ */
|
||||
|
||||
/* ── Page wrapper ─────────────────────────────────────────── */
|
||||
.itk-wrap { max-width: 1400px; }
|
||||
|
||||
.itk-page-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-size: 22px;
|
||||
margin: 20px 0 16px;
|
||||
}
|
||||
.itk-logo {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px; height: 36px;
|
||||
background: #1a4a8a;
|
||||
color: #fff;
|
||||
font-weight: 900;
|
||||
font-size: 14px;
|
||||
border-radius: 6px;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
/* ── Tab navigation ───────────────────────────────────────── */
|
||||
.itk-tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 2px;
|
||||
border-bottom: 2px solid #c3c4c7;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.itk-tab {
|
||||
padding: 8px 16px;
|
||||
text-decoration: none;
|
||||
color: #2c3338;
|
||||
font-size: 13px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
border: 1px solid transparent;
|
||||
border-bottom: none;
|
||||
background: #f0f0f1;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
.itk-tab:hover { background: #fff; color: #1a4a8a; }
|
||||
.itk-tab-active {
|
||||
background: #fff;
|
||||
border-color: #c3c4c7;
|
||||
color: #1a4a8a;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ── Settings grid ────────────────────────────────────────── */
|
||||
.itk-settings-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
.itk-card {
|
||||
background: #fff;
|
||||
border: 1px solid #c3c4c7;
|
||||
border-radius: 6px;
|
||||
padding: 20px 24px;
|
||||
}
|
||||
.itk-card h2 {
|
||||
margin: 0 0 16px;
|
||||
font-size: 15px;
|
||||
color: #1a4a8a;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
/* ── Toggle rows ──────────────────────────────────────────── */
|
||||
.itk-toggle-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #f0f0f1;
|
||||
gap: 12px;
|
||||
}
|
||||
.itk-toggle-row:last-child { border-bottom: none; }
|
||||
.itk-toggle-info { flex: 1; }
|
||||
.itk-toggle-label { display: block; font-weight: 600; font-size: 13px; color: #2c3338; }
|
||||
.itk-toggle-desc { display: block; font-size: 11px; color: #646970; margin-top: 2px; }
|
||||
|
||||
/* ── Toggle switch ────────────────────────────────────────── */
|
||||
.itk-switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 44px;
|
||||
height: 24px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.itk-switch input { opacity: 0; width: 0; height: 0; }
|
||||
.itk-slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
inset: 0;
|
||||
background: #ccc;
|
||||
border-radius: 24px;
|
||||
transition: .25s;
|
||||
}
|
||||
.itk-slider:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 18px; height: 18px;
|
||||
left: 3px; bottom: 3px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
transition: .25s;
|
||||
}
|
||||
input:checked + .itk-slider { background: #2271b1; }
|
||||
input:checked + .itk-slider:before { transform: translateX(20px); }
|
||||
|
||||
/* ── Dashboard ────────────────────────────────────────────── */
|
||||
.itk-dashboard {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 280px;
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
@media (max-width: 960px) { .itk-dashboard { grid-template-columns: 1fr; } }
|
||||
|
||||
/* Monitor panel – terminal style */
|
||||
.itk-monitor-panel {
|
||||
background: #0d1117;
|
||||
color: #58a6ff;
|
||||
border-radius: 8px;
|
||||
padding: 20px 24px;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
.itk-monitor-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #21262d;
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.itk-monitor-title { font-weight: 700; font-size: 13px; letter-spacing: 1px; color: #79c0ff; }
|
||||
.itk-monitor-blink {
|
||||
background: #238636;
|
||||
color: #fff;
|
||||
padding: 2px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
animation: itk-pulse 2s infinite;
|
||||
}
|
||||
@keyframes itk-pulse { 0%,100%{opacity:1} 50%{opacity:.5} }
|
||||
|
||||
/* Stat cards (inside monitor) */
|
||||
.itk-stat-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.itk-stat-card {
|
||||
background: #161b22;
|
||||
border: 1px solid #21262d;
|
||||
border-radius: 6px;
|
||||
padding: 12px 18px;
|
||||
min-width: 110px;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
}
|
||||
.itk-stat-num { font-size: 2em; font-weight: 700; color: #58a6ff; line-height: 1.2; }
|
||||
.itk-stat-lbl { font-size: 10px; color: #8b949e; letter-spacing: .5px; text-transform: uppercase; }
|
||||
.itk-green { color: #3fb950; }
|
||||
.itk-yellow { color: #d29922; }
|
||||
|
||||
/* Chart sections */
|
||||
.itk-chart-section { margin-bottom: 20px; }
|
||||
.itk-chart-title {
|
||||
font-size: 10px;
|
||||
letter-spacing: 1px;
|
||||
color: #8b949e;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.itk-bar-chart { display: flex; flex-direction: column; gap: 6px; }
|
||||
.itk-bar-row { display: flex; align-items: center; gap: 8px; font-size: 12px; }
|
||||
.itk-bar-label { width: 130px; color: #c9d1d9; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.itk-bar-track { flex: 1; background: #21262d; border-radius: 3px; height: 14px; overflow: hidden; }
|
||||
.itk-bar-fill { height: 100%; background: linear-gradient(90deg, #1f6feb, #58a6ff); border-radius: 3px; transition: width .4s; }
|
||||
.itk-bar-hp { background: linear-gradient(90deg, #6e40c9, #a371f7) !important; }
|
||||
.itk-bar-count { width: 40px; text-align: right; color: #8b949e; font-size: 11px; }
|
||||
|
||||
/* Mini table (top IPs) */
|
||||
.itk-mini-table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
||||
.itk-mini-table th { color: #8b949e; font-weight: normal; padding: 4px 8px; border-bottom: 1px solid #21262d; }
|
||||
.itk-mini-table td { color: #c9d1d9; padding: 4px 8px; border-bottom: 1px solid #161b22; }
|
||||
.itk-mini-table a { color: #58a6ff; }
|
||||
.itk-lookup { color: #8b949e; font-size: 10px; }
|
||||
|
||||
/* Quick status sidebar */
|
||||
.itk-quick-status {
|
||||
background: #fff;
|
||||
border: 1px solid #c3c4c7;
|
||||
border-radius: 6px;
|
||||
padding: 16px 20px;
|
||||
}
|
||||
.itk-quick-status .itk-chart-title { color: #1a4a8a; }
|
||||
.itk-module-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 0;
|
||||
border-bottom: 1px solid #f0f0f1;
|
||||
font-size: 12px;
|
||||
}
|
||||
.itk-module-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
|
||||
.itk-dot-on { background: #00a32a; }
|
||||
.itk-dot-off { background: #c3c4c7; }
|
||||
.itk-module-label { flex: 1; color: #2c3338; }
|
||||
.itk-module-status { font-size: 10px; font-weight: 700; letter-spacing: .5px; }
|
||||
.itk-dot-on ~ .itk-module-status { color: #00a32a; }
|
||||
.itk-dot-off ~ .itk-module-status { color: #c3c4c7; }
|
||||
|
||||
/* ── Log tables ───────────────────────────────────────────── */
|
||||
.itk-log-page {}
|
||||
.itk-filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.itk-filters input[type=text],
|
||||
.itk-filters select { height: 32px; padding: 0 8px; }
|
||||
.itk-count { color: #646970; font-size: 13px; margin: 0 0 8px; }
|
||||
.itk-log-table { font-size: 12px; }
|
||||
.itk-log-table th { white-space: nowrap; }
|
||||
.itk-nowrap { white-space: nowrap; }
|
||||
.itk-ua { color: #646970; font-size: 11px; max-width: 220px; word-break: break-all; }
|
||||
.itk-uri { font-size: 11px; color: #646970; max-width: 200px; word-break: break-all; }
|
||||
.itk-no-results { text-align: center; padding: 20px; color: #646970; }
|
||||
.itk-filter-link { font-size: 10px; color: #2271b1; text-decoration: none; }
|
||||
.itk-filter-link:hover { text-decoration: underline; }
|
||||
|
||||
/* Badges */
|
||||
.itk-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
letter-spacing: .5px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.itk-badge-block { background: #ffecec; color: #b32d2e; border: 1px solid #f7c5c5; }
|
||||
.itk-badge-warn { background: #fef3cd; color: #856404; border: 1px solid #fde68a; }
|
||||
.itk-badge-hp { background: #f3e8ff; color: #6e40c9; border: 1px solid #d4a9ff; }
|
||||
|
||||
/* Pager */
|
||||
.itk-pager {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 12px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.itk-pager span { color: #646970; }
|
||||
|
||||
/* Danger button */
|
||||
.itk-btn-danger { color: #b32d2e !important; border-color: #b32d2e !important; }
|
||||
.itk-btn-danger:hover { background: #b32d2e !important; color: #fff !important; }
|
||||
|
||||
/* ── Config editor ────────────────────────────────────────── */
|
||||
.itk-config-editor {}
|
||||
.itk-config-tabs {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-bottom: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.itk-config-tab {
|
||||
padding: 6px 14px;
|
||||
background: #f0f0f1;
|
||||
border: 1px solid #c3c4c7;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
color: #2c3338;
|
||||
font-size: 12px;
|
||||
}
|
||||
.itk-config-tab.active { background: #2271b1; color: #fff; border-color: #2271b1; }
|
||||
.itk-config-editor-area { background: #fff; border: 1px solid #c3c4c7; border-radius: 6px; padding: 20px; }
|
||||
.itk-config-textarea {
|
||||
width: 100%;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 12px;
|
||||
background: #0d1117;
|
||||
color: #c9d1d9;
|
||||
border: 1px solid #30363d;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
resize: vertical;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* ── Toggle feedback ──────────────────────────────────────── */
|
||||
.itk-toggle-saving { opacity: .6; pointer-events: none; }
|
||||
.itk-toggle-saved { color: #00a32a; font-size: 11px; }
|
||||
.itk-toggle-error { color: #b32d2e; font-size: 11px; }
|
||||
Reference in New Issue
Block a user