Lots of updates
This commit is contained in:
@@ -12,14 +12,14 @@ class Dsn < ApplicationRecord
|
||||
|
||||
def full_dsn_url
|
||||
# Generate a complete DSN URL like Sentry does
|
||||
# Format: https://{key}@{domain}/api/events
|
||||
# Format: https://{key}@{domain}
|
||||
domain = ENV['BAFFLE_HOST'] ||
|
||||
Rails.application.config.action_mailer.default_url_options[:host] ||
|
||||
ENV['RAILS_HOST'] ||
|
||||
'localhost:3000'
|
||||
|
||||
protocol = Rails.env.development? ? 'http' : 'https'
|
||||
"#{protocol}://#{key}@#{domain}/api/events"
|
||||
"#{protocol}://#{key}@#{domain}"
|
||||
end
|
||||
|
||||
def api_endpoint_url
|
||||
@@ -30,7 +30,7 @@ class Dsn < ApplicationRecord
|
||||
'localhost:3000'
|
||||
|
||||
protocol = Rails.env.development? ? 'http' : 'https'
|
||||
"#{protocol}://#{domain}/api/events"
|
||||
"#{protocol}://#{domain}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -133,25 +133,11 @@ class NetworkRange < ApplicationRecord
|
||||
|
||||
# Find nearest parent with intelligence data
|
||||
def parent_with_intelligence
|
||||
# Use Postgres network operators to find parent ranges directly
|
||||
cidr_str = network.to_s
|
||||
if cidr_str.include?('/')
|
||||
addr_parts = network_address.split('.')
|
||||
case addr_parts.length
|
||||
when 4 # IPv4
|
||||
new_prefix = [prefix_length - 8, 16].max
|
||||
parent_cidr = "#{addr_parts[0]}.#{addr_parts[1]}.#{addr_parts[2]}.0/#{new_prefix}"
|
||||
else # IPv6 - skip for now
|
||||
nil
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
return nil unless parent_cidr
|
||||
|
||||
NetworkRange.where("network <<= ?::inet AND masklen(network) < ?", parent_cidr, prefix_length)
|
||||
.where.not(asn: nil)
|
||||
# Find all parent ranges (networks that contain this network)
|
||||
# and look for any with intelligence data, ordered by specificity
|
||||
NetworkRange.where("?::inet <<= network", network.to_s)
|
||||
.where("masklen(network) < ?", prefix_length)
|
||||
.where("(asn IS NOT NULL OR company IS NOT NULL OR country IS NOT NULL OR is_datacenter = true OR is_vpn = true OR is_proxy = true)")
|
||||
.order("masklen(network) DESC")
|
||||
.first
|
||||
end
|
||||
@@ -238,6 +224,28 @@ class NetworkRange < ApplicationRecord
|
||||
self.additional_data = hash.to_json
|
||||
end
|
||||
|
||||
# Network data accessors for different data sources
|
||||
# network_data is a JSONB column with namespaced data:
|
||||
# {
|
||||
# geolite: {...}, # MaxMind GeoLite2 data
|
||||
# ipapi: {...}, # IPAPI.is enrichment data
|
||||
# abuseipdb: {...}, # Future: AbuseIPDB data
|
||||
# shodan: {...} # Future: Shodan data
|
||||
# }
|
||||
def network_data_for(source)
|
||||
network_data&.dig(source.to_s) || {}
|
||||
end
|
||||
|
||||
def set_network_data(source, data)
|
||||
self.network_data ||= {}
|
||||
self.network_data[source.to_s] = data
|
||||
end
|
||||
|
||||
# Check if we have network data from a specific source
|
||||
def has_network_data_from?(source)
|
||||
network_data&.key?(source.to_s) && network_data[source.to_s].present?
|
||||
end
|
||||
|
||||
# String representations
|
||||
def to_s
|
||||
cidr
|
||||
@@ -267,6 +275,19 @@ class NetworkRange < ApplicationRecord
|
||||
rules.enabled.where("expires_at IS NULL OR expires_at > ?", Time.current)
|
||||
end
|
||||
|
||||
# Check if this network range needs WAF policy evaluation
|
||||
# Returns true if:
|
||||
# - Never been evaluated, OR
|
||||
# - Any WafPolicy has been updated since last evaluation
|
||||
def needs_policy_evaluation?
|
||||
return true if policies_evaluated_at.nil?
|
||||
|
||||
latest_policy_update = WafPolicy.maximum(:updated_at)
|
||||
return false if latest_policy_update.nil? # No policies exist
|
||||
|
||||
policies_evaluated_at < latest_policy_update
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_default_source
|
||||
|
||||
18
app/models/setting.rb
Normal file
18
app/models/setting.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
class Setting < ApplicationRecord
|
||||
validates :key, presence: true, uniqueness: true
|
||||
|
||||
# Get a setting value by key, with optional fallback
|
||||
def self.get(key, default = nil)
|
||||
find_by(key: key)&.value || default
|
||||
end
|
||||
|
||||
# Set a setting value by key
|
||||
def self.set(key, value)
|
||||
find_or_initialize_by(key: key).update(value: value)
|
||||
end
|
||||
|
||||
# Convenience method for ipapi.is API key
|
||||
def self.ipapi_key
|
||||
get('ipapi_key', ENV['IPAPI_KEY'])
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user