Tidy up homepage and navigation
This commit is contained in:
18
app/models/dsn.rb
Normal file
18
app/models/dsn.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
class Dsn < ApplicationRecord
|
||||
validates :key, presence: true, uniqueness: true
|
||||
validates :name, presence: true
|
||||
|
||||
before_validation :generate_key, on: :create
|
||||
|
||||
scope :enabled, -> { where(enabled: true) }
|
||||
|
||||
def self.authenticate(key)
|
||||
enabled.find_by(key: key)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_key
|
||||
self.key ||= SecureRandom.hex(32)
|
||||
end
|
||||
end
|
||||
@@ -1,8 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Event < ApplicationRecord
|
||||
belongs_to :project
|
||||
|
||||
# Normalized association for hosts (most valuable compression)
|
||||
belongs_to :request_host, optional: true
|
||||
|
||||
@@ -87,13 +85,12 @@ class Event < ApplicationRecord
|
||||
# Normalize event fields after extraction
|
||||
after_validation :normalize_event_fields, if: :should_normalize?
|
||||
|
||||
def self.create_from_waf_payload!(event_id, payload, project)
|
||||
def self.create_from_waf_payload!(event_id, payload)
|
||||
# Normalize headers in payload during import phase
|
||||
normalized_payload = normalize_payload_headers(payload)
|
||||
|
||||
# Create the WAF request event
|
||||
create!(
|
||||
project: project,
|
||||
event_id: event_id,
|
||||
timestamp: parse_timestamp(normalized_payload["timestamp"]),
|
||||
payload: normalized_payload,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Issue < ApplicationRecord
|
||||
belongs_to :project
|
||||
has_many :events, dependent: :nullify
|
||||
|
||||
enum :status, { open: 0, resolved: 1, ignored: 2 }
|
||||
@@ -17,18 +16,18 @@ class Issue < ApplicationRecord
|
||||
|
||||
# Real-time updates
|
||||
after_create_commit do
|
||||
broadcast_refresh_to(project)
|
||||
broadcast_refresh
|
||||
end
|
||||
|
||||
after_update_commit do
|
||||
broadcast_refresh # Refreshes the issue show page
|
||||
broadcast_refresh_to(project, "issues") # Refreshes the project's issues index
|
||||
broadcast_refresh_to("issues") # Refreshes the issues index
|
||||
end
|
||||
|
||||
def self.group_event(event_payload, project)
|
||||
def self.group_event(event_payload)
|
||||
fingerprint = generate_fingerprint(event_payload)
|
||||
|
||||
find_or_create_by(project: project, fingerprint: fingerprint) do |issue|
|
||||
find_or_create_by(fingerprint: fingerprint) do |issue|
|
||||
issue.title = extract_title(event_payload)
|
||||
issue.exception_type = extract_exception_type(event_payload)
|
||||
issue.first_seen = Time.current
|
||||
|
||||
@@ -29,6 +29,8 @@ class NetworkRange < ApplicationRecord
|
||||
scope :vpn, -> { where(is_vpn: true) }
|
||||
scope :user_created, -> { where(source: 'user_created') }
|
||||
scope :api_imported, -> { where(source: 'api_imported') }
|
||||
scope :with_events, -> { where("events_count > 0") }
|
||||
scope :most_active, -> { order(events_count: :desc) }
|
||||
|
||||
# Callbacks
|
||||
before_validation :set_default_source
|
||||
@@ -237,9 +239,10 @@ class NetworkRange < ApplicationRecord
|
||||
cidr.to_s.gsub('/', '_')
|
||||
end
|
||||
|
||||
# Analytics methods
|
||||
# Analytics methods - events_count is now a counter cache column maintained by database triggers
|
||||
# This is much more performant than the previous implementation that did complex network queries
|
||||
def events_count
|
||||
Event.where(ip_address: child_ranges.pluck(:network_address) + [network_address]).count
|
||||
self[:events_count] || 0
|
||||
end
|
||||
|
||||
def recent_events(limit: 100)
|
||||
|
||||
Reference in New Issue
Block a user