Lots of updates

This commit is contained in:
Dan Milne
2025-11-11 16:54:52 +11:00
parent 26216da9ca
commit cc8213f87a
41 changed files with 1463 additions and 614 deletions

View File

@@ -8,7 +8,9 @@ export default class extends Controller {
}
connect() {
this.startRefreshing()
// TEMPORARILY DISABLED: Auto-refresh causes performance issues with slow queries (30s+ load times)
// TODO: Re-enable after optimizing analytics queries
// this.startRefreshing()
}
disconnect() {

View File

@@ -0,0 +1,119 @@
// QuickCreateRuleController - Handles the quick create rule form functionality
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["form", "toggle", "ruleTypeSelect", "actionSelect", "patternFields", "rateLimitFields", "redirectFields", "helpText", "conditionsField"]
connect() {
this.setupEventListeners()
this.initializeFieldVisibility()
}
toggle() {
this.formTarget.classList.toggle("hidden")
if (this.formTarget.classList.contains("hidden")) {
this.resetForm()
}
}
updateRuleTypeFields() {
if (!this.hasRuleTypeSelectTarget || !this.hasActionSelectTarget) return
const ruleType = this.ruleTypeSelectTarget.value
const action = this.actionSelectTarget.value
// Hide all optional fields
this.hideOptionalFields()
// Show relevant fields based on rule type
if (["path_pattern", "header_pattern", "query_pattern", "body_signature"].includes(ruleType)) {
if (this.hasPatternFieldsTarget) {
this.patternFieldsTarget.classList.remove("hidden")
this.updatePatternHelpText(ruleType)
}
} else if (ruleType === "rate_limit") {
if (this.hasRateLimitFieldsTarget) {
this.rateLimitFieldsTarget.classList.remove("hidden")
}
}
// Show redirect fields if action is redirect
if (action === "redirect") {
if (this.hasRedirectFieldsTarget) {
this.redirectFieldsTarget.classList.remove("hidden")
}
}
}
updatePatternHelpText(ruleType) {
if (!this.hasHelpTextTarget || !this.hasConditionsFieldTarget) return
const helpTexts = {
path_pattern: {
text: "Regex pattern to match URL paths (e.g.,\\.env$|wp-admin|phpmyadmin)",
placeholder: "Example: \\.env$|\\.git|config\\.php|wp-admin"
},
header_pattern: {
text: 'JSON with header_name and pattern (e.g., {"header_name": "User-Agent", "pattern": "bot.*"})',
placeholder: 'Example: {"header_name": "User-Agent", "pattern": ".*[Bb]ot.*"}'
},
query_pattern: {
text: "Regex pattern to match query parameters (e.g., union.*select|<script>)",
placeholder: "Example: (?:union|select|insert|update|delete).*\\s+(?:union|select)"
},
body_signature: {
text: "Regex pattern to match request body content (e.g., OR 1=1|<script>)",
placeholder: "Example: (?:OR\\s+1\\s*=\\s*1|AND\\s+1\\s*=\\s*1|UNION\\s+SELECT)"
}
}
const config = helpTexts[ruleType]
if (config) {
this.helpTextTarget.textContent = config.text
this.conditionsFieldTarget.placeholder = config.placeholder
}
}
hideOptionalFields() {
if (this.hasPatternFieldsTarget) this.patternFieldsTarget.classList.add("hidden")
if (this.hasRateLimitFieldsTarget) this.rateLimitFieldsTarget.classList.add("hidden")
if (this.hasRedirectFieldsTarget) this.redirectFieldsTarget.classList.add("hidden")
}
resetForm() {
if (this.formTarget) {
this.formTarget.reset()
// Reset rule type to default
if (this.hasRuleTypeSelectTarget) {
this.ruleTypeSelectTarget.value = "network"
this.updateRuleTypeFields()
}
}
}
// Private methods
setupEventListeners() {
// Set up action change listener to show/hide redirect fields
if (this.hasActionSelectTarget) {
this.actionSelectTarget.addEventListener("change", () => {
this.updateRuleTypeFields()
})
}
// Set up toggle button listener
if (this.hasToggleTarget) {
this.toggleTarget.addEventListener("click", () => {
this.toggle()
})
}
}
initializeFieldVisibility() {
// Initialize field visibility on page load
if (this.hasRuleTypeSelectTarget) {
this.updateRuleTypeFields()
}
}
}