Accepts incoming events and correctly parses them into events. GeoLite2 integration complete"

This commit is contained in:
Dan Milne
2025-11-04 00:11:10 +11:00
parent 0cbd462e7c
commit 5ff166613e
49 changed files with 4489 additions and 322 deletions

168
lib/tasks/geoip.rake Normal file
View File

@@ -0,0 +1,168 @@
# frozen_string_literal: true
namespace :geoip do
desc "Update the GeoIP database"
task update: :environment do
puts "Updating GeoIP database..."
success = GeoIpService.update_database!
if success
puts "✅ GeoIP database successfully updated"
else
puts "❌ Failed to update GeoIP database"
end
end
desc "Lookup country for a specific IP address"
task :lookup, [:ip_address] => :environment do |_t, args|
ip_address = args[:ip_address]
if ip_address.blank?
puts "❌ Please provide an IP address: rails geoip:lookup[8.8.8.8]"
exit 1
end
puts "Looking up country for #{ip_address}..."
begin
country = GeoIpService.lookup_country(ip_address)
if country.present?
puts "📍 #{ip_address}#{country}"
else
puts "❓ No country found for #{ip_address}"
end
rescue => e
puts "❌ Error looking up #{ip_address}: #{e.message}"
end
end
desc "Show GeoIP database status"
task status: :environment do
puts "GeoIP Database Status"
puts "=" * 40
geo_service = GeoIpService.new
database_info = geo_service.database_info
if geo_service.database_available? && database_info
puts "✅ Active database found:"
puts " Type: #{database_info[:type]}"
puts " Version: #{database_info[:version]}"
puts " Size: #{number_to_human_size(database_info[:size])}"
puts " Modified: #{database_info[:modified_at].strftime('%Y-%m-%d %H:%M:%S UTC')}"
puts " Age: #{database_info[:age_days]} days"
puts " Path: #{database_info[:file_path]}"
puts " Valid: #{geo_service.database_available? ? '✅' : '❌'}"
if database_info[:age_days] > Rails.application.config.maxmind.max_age_days
puts " ⚠️ Database is outdated (older than #{Rails.application.config.maxmind.max_age_days} days)"
end
else
puts "❌ No active GeoIP database found"
puts ""
puts "To download the database, run:"
puts " rails geoip:update"
end
puts ""
puts "Configuration:"
config = Rails.application.config.maxmind
puts " Auto-updates: #{config.auto_update_enabled ? '✅' : '❌'}"
puts " Update interval: #{config.update_interval_days} days"
puts " Max age: #{config.max_age_days} days"
puts " Storage path: #{config.storage_path}"
end
desc "Enrich existing events missing country codes"
task enrich_missing: :environment do
puts "Finding events without country codes..."
events_without_country = Event.where(country_code: [nil, ''])
.where.not(ip_address: [nil, ''])
.limit(1000) # Process in batches
if events_without_country.empty?
puts "✅ No events found missing country codes"
exit 0
end
puts "Found #{events_without_country.count} events without country codes"
puts "Processing batch..."
geo_service = GeoIpService.new
updated_count = 0
events_without_country.find_each do |event|
country = geo_service.lookup_country(event.ip_address)
if country.present?
event.update!(country_code: country)
updated_count += 1
end
# Add small delay to avoid overwhelming the service
sleep(0.01) if updated_count % 100 == 0
end
puts "✅ Updated #{updated_count} events with country codes"
end
desc "Test GeoIP service with sample IPs"
task test: :environment do
puts "Testing GeoIP service..."
puts "=" * 30
test_ips = [
'8.8.8.8', # Google DNS (US)
'1.1.1.1', # Cloudflare DNS (US)
'208.67.222.222', # OpenDNS (US)
'9.9.9.9', # Quad9 DNS (US)
'8.8.4.4', # Google DNS (US)
'1.0.0.1', # Cloudflare DNS (AU)
'64.6.64.6', # Verisign DNS (US)
'94.140.14.14', # AdGuard DNS (DE)
'2001:4860:4860::8888', # Google DNS IPv6
'2606:4700:4700::1111' # Cloudflare DNS IPv6
]
geo_service = GeoIpService.new
if !geo_service.database_available?
puts "❌ GeoIP database not available. Please run 'rails geoip:update' first."
exit 1
end
puts "Database info:"
info = geo_service.database_info
puts " Type: #{info[:type]}"
puts " Version: #{info[:version]}"
puts " Size: #{number_to_human_size(info[:size])}"
puts ""
test_ips.each do |ip|
begin
country = geo_service.lookup_country(ip)
puts "#{ip.ljust(30)}#{country || 'Unknown'}"
rescue => e
puts "#{ip.ljust(30)} → Error: #{e.message}"
end
end
end
private
def number_to_human_size(bytes)
units = %w[B KB MB GB TB]
size = bytes.to_f
unit_index = 0
while size >= 1024 && unit_index < units.length - 1
size /= 1024
unit_index += 1
end
"#{size.round(2)} #{units[unit_index]}"
end
end