168 lines
4.8 KiB
Ruby
168 lines
4.8 KiB
Ruby
# 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 |