Tidy up homepage and navigation

This commit is contained in:
Dan Milne
2025-11-09 20:58:13 +11:00
parent c9e2992fe0
commit 1f4428348d
56 changed files with 2822 additions and 955 deletions

View File

@@ -0,0 +1,12 @@
class CreateDsns < ActiveRecord::Migration[8.1]
def change
create_table :dsns do |t|
t.string :key
t.string :name
t.boolean :enabled, default: true, null: false
t.timestamps
end
add_index :dsns, :key, unique: true
end
end

View File

@@ -0,0 +1,5 @@
class RemoveProjectIdFromEvents < ActiveRecord::Migration[8.1]
def change
remove_reference :events, :project, null: false, foreign_key: true
end
end

View File

@@ -0,0 +1,5 @@
class DropProjectsTable < ActiveRecord::Migration[8.1]
def change
drop_table :projects
end
end

View File

@@ -0,0 +1,67 @@
class AddEventsCountToNetworkRanges < ActiveRecord::Migration[8.1]
def up
# Add the column with default value
add_column :network_ranges, :events_count, :integer, null: false, default: 0
# Add index for faster queries
add_index :network_ranges, :events_count
# Create trigger function to update counter cache
execute <<-SQL
CREATE OR REPLACE FUNCTION update_network_range_events_count()
RETURNS TRIGGER AS $$
BEGIN
-- Update all network ranges that contain the IP address
UPDATE network_ranges
SET events_count = events_count +
CASE
WHEN TG_OP = 'INSERT' THEN 1
WHEN TG_OP = 'DELETE' THEN -1
ELSE 0
END
WHERE network >>= NEW.ip_address::inet;
RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;
SQL
# Create triggers for events table
execute <<-SQL
CREATE TRIGGER update_network_ranges_events_count_after_insert
AFTER INSERT ON events
FOR EACH ROW
EXECUTE FUNCTION update_network_range_events_count();
SQL
execute <<-SQL
CREATE TRIGGER update_network_ranges_events_count_after_delete
AFTER DELETE ON events
FOR EACH ROW
EXECUTE FUNCTION update_network_range_events_count();
SQL
# Backfill existing counts
execute <<-SQL
UPDATE network_ranges
SET events_count = (
SELECT COUNT(*)
FROM events
WHERE events.ip_address <<= network_ranges.network
);
SQL
end
def down
# Drop triggers first
execute <<-SQL
DROP TRIGGER IF EXISTS update_network_ranges_events_count_after_insert ON events;
DROP TRIGGER IF EXISTS update_network_ranges_events_count_after_delete ON events;
DROP FUNCTION IF EXISTS update_network_range_events_count();
SQL
# Remove column and index
remove_index :network_ranges, :events_count
remove_column :network_ranges, :events_count
end
end

View File

@@ -0,0 +1,20 @@
class CreateDefaultDsn < ActiveRecord::Migration[8.1]
def change
reversible do |dir|
dir.up do
# Only create if no DSNs exist
if Dsn.count == 0
Dsn.create!(
name: 'Development DSN',
key: 'dev-test-key-1234567890abcdef',
enabled: true
)
end
end
dir.down do
# Remove the default DSN if it exists
Dsn.where(key: 'dev-test-key-1234567890abcdef').delete_all
end
end
end
end

View File

@@ -10,10 +10,19 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.1].define(version: 7) do
ActiveRecord::Schema[8.1].define(version: 2025_11_08_042936) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
create_table "dsns", force: :cascade do |t|
t.datetime "created_at", null: false
t.boolean "enabled", default: true, null: false
t.string "key"
t.string "name"
t.datetime "updated_at", null: false
t.index ["key"], name: "index_dsns_on_key", unique: true
end
create_table "events", force: :cascade do |t|
t.string "agent_name"
t.string "agent_version"
@@ -25,7 +34,6 @@ ActiveRecord::Schema[8.1].define(version: 7) do
t.string "event_id", null: false
t.inet "ip_address"
t.json "payload"
t.bigint "project_id", null: false
t.bigint "request_host_id"
t.integer "request_method", default: 0
t.string "request_path"
@@ -42,10 +50,6 @@ ActiveRecord::Schema[8.1].define(version: 7) do
t.integer "waf_action", default: 0, null: false
t.index ["event_id"], name: "index_events_on_event_id", unique: true
t.index ["ip_address"], name: "index_events_on_ip_address"
t.index ["project_id", "ip_address"], name: "idx_events_project_ip"
t.index ["project_id", "timestamp"], name: "idx_events_project_time"
t.index ["project_id", "waf_action"], name: "idx_events_project_action"
t.index ["project_id"], name: "index_events_on_project_id"
t.index ["request_host_id", "request_method", "request_segment_ids"], name: "idx_events_host_method_path"
t.index ["request_host_id"], name: "index_events_on_request_host_id"
t.index ["request_segment_ids"], name: "index_events_on_request_segment_ids"
@@ -62,6 +66,7 @@ ActiveRecord::Schema[8.1].define(version: 7) do
t.string "country"
t.datetime "created_at", null: false
t.text "creation_reason"
t.integer "events_count"
t.boolean "is_datacenter", default: false
t.boolean "is_proxy", default: false
t.boolean "is_vpn", default: false
@@ -91,23 +96,6 @@ ActiveRecord::Schema[8.1].define(version: 7) do
t.index ["segment"], name: "index_path_segments_on_segment", unique: true
end
create_table "projects", force: :cascade do |t|
t.integer "blocked_ip_count", default: 0, null: false
t.datetime "created_at", null: false
t.text "custom_rules", default: "{}", null: false
t.boolean "enabled", default: true, null: false
t.string "name", null: false
t.string "public_key", null: false
t.integer "rate_limit_threshold", default: 100, null: false
t.text "settings", default: "{}", null: false
t.string "slug", null: false
t.datetime "updated_at", null: false
t.index ["enabled"], name: "index_projects_on_enabled"
t.index ["name"], name: "index_projects_on_name"
t.index ["public_key"], name: "index_projects_on_public_key", unique: true
t.index ["slug"], name: "index_projects_on_slug", unique: true
end
create_table "request_actions", force: :cascade do |t|
t.string "action", null: false
t.datetime "created_at", null: false
@@ -182,7 +170,6 @@ ActiveRecord::Schema[8.1].define(version: 7) do
t.index ["email_address"], name: "index_users_on_email_address", unique: true
end
add_foreign_key "events", "projects"
add_foreign_key "events", "request_hosts"
add_foreign_key "network_ranges", "users"
add_foreign_key "rules", "network_ranges"