First commit!

This commit is contained in:
Dan Milne
2025-11-03 17:37:28 +11:00
commit 429d41eead
141 changed files with 5890 additions and 0 deletions

108
app/models/rule_set.rb Normal file
View File

@@ -0,0 +1,108 @@
# frozen_string_literal: true
class RuleSet < ApplicationRecord
has_many :rules, dependent: :destroy
validates :name, presence: true, uniqueness: true
validates :slug, presence: true, uniqueness: true
scope :enabled, -> { where(enabled: true) }
scope :by_priority, -> { order(priority: :desc, created_at: :desc) }
before_validation :generate_slug, if: :name?
before_validation :set_default_values
# Rule Types
RULE_TYPES = %w[ip cidr path user_agent parameter method rate_limit country].freeze
ACTIONS = %w[allow deny challenge rate_limit].freeze
def to_waf_rules
return [] unless enabled?
rules.enabled.by_priority.map do |rule|
{
id: rule.id,
type: rule.rule_type,
target: rule.target,
action: rule.action,
conditions: rule.conditions,
priority: rule.priority,
expires_at: rule.expires_at
}
end
end
def add_rule(rule_type, target, action, conditions: {}, expires_at: nil, priority: 100)
rules.create!(
rule_type: rule_type,
target: target,
action: action,
conditions: conditions,
expires_at: expires_at,
priority: priority
)
end
def remove_rule(rule_id)
rules.find(rule_id).destroy
end
def block_ip(ip_address, expires_at: nil, reason: nil)
add_rule('ip', ip_address, 'deny', expires_at: expires_at, priority: 1000)
end
def allow_ip(ip_address, expires_at: nil)
add_rule('ip', ip_address, 'allow', expires_at: expires_at, priority: 1000)
end
def block_cidr(cidr, expires_at: nil, reason: nil)
add_rule('cidr', cidr, 'deny', expires_at: expires_at, priority: 900)
end
def block_path(path, conditions: {}, expires_at: nil)
add_rule('path', path, 'deny', conditions: conditions, expires_at: expires_at, priority: 500)
end
def block_user_agent(user_agent_pattern, expires_at: nil)
add_rule('user_agent', user_agent_pattern, 'deny', expires_at: expires_at, priority: 600)
end
def push_to_agents!
# This would integrate with the agent distribution system
Rails.logger.info "Pushing rule set '#{name}' with #{rules.count} rules to agents"
# Broadcast update to connected projects
projects = Project.where(id: projects_subscription || [])
projects.each(&:broadcast_rules_refresh)
end
def active_projects
return Project.none unless projects_subscription.present?
Project.where(id: projects_subscription).enabled
end
def subscribe_project(project)
subscriptions = projects_subscription || []
subscriptions << project.id unless subscriptions.include?(project.id)
update(projects_subscription: subscriptions.uniq)
end
def unsubscribe_project(project)
subscriptions = projects_subscription || []
subscriptions.delete(project.id)
update(projects_subscription: subscriptions)
end
private
def generate_slug
self.slug = name&.parameterize&.downcase
end
def set_default_values
self.enabled = true if enabled.nil?
self.priority = 100 if priority.nil?
self.projects_subscription = [] if projects_subscription.nil?
end
end