beskar 0.0.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +274 -0
  3. data/README.md +412 -204
  4. data/app/channels/concerns/beskar/channels/session_security.rb +46 -0
  5. data/app/controllers/beskar/administrative_actions_controller.rb +16 -0
  6. data/app/controllers/beskar/application_controller.rb +214 -0
  7. data/app/controllers/beskar/banned_ips_controller.rb +255 -0
  8. data/app/controllers/beskar/dashboard_controller.rb +62 -0
  9. data/app/controllers/beskar/security_events_controller.rb +164 -0
  10. data/app/controllers/concerns/beskar/controllers/audit_export.rb +54 -0
  11. data/app/controllers/concerns/beskar/controllers/security_tracking.rb +76 -48
  12. data/app/controllers/concerns/beskar/controllers/session_security.rb +29 -0
  13. data/app/jobs/beskar/notification_job.rb +33 -0
  14. data/app/mailers/beskar/security_mailer.rb +59 -0
  15. data/app/models/beskar/administrative_action.rb +41 -0
  16. data/app/models/beskar/banned_ip.rb +105 -105
  17. data/app/models/beskar/security_event.rb +51 -4
  18. data/app/models/beskar/security_state.rb +58 -0
  19. data/app/services/beskar/banned_ip_manager.rb +88 -0
  20. data/app/views/beskar/administrative_actions/index.html.erb +33 -0
  21. data/app/views/beskar/administrative_actions/show.html.erb +21 -0
  22. data/app/views/beskar/banned_ips/edit.html.erb +195 -0
  23. data/app/views/beskar/banned_ips/index.html.erb +319 -0
  24. data/app/views/beskar/banned_ips/new.html.erb +190 -0
  25. data/app/views/beskar/banned_ips/review.html.erb +24 -0
  26. data/app/views/beskar/banned_ips/show.html.erb +304 -0
  27. data/app/views/beskar/dashboard/index.html.erb +280 -0
  28. data/app/views/beskar/security_events/index.html.erb +302 -0
  29. data/app/views/beskar/security_events/show.html.erb +293 -0
  30. data/app/views/beskar/shared/_export_form.html.erb +10 -0
  31. data/app/views/layouts/beskar/_behavior.html.erb +121 -0
  32. data/app/views/layouts/beskar/application.html.erb +581 -6
  33. data/config/routes.rb +30 -0
  34. data/db/migrate/20251016000001_create_beskar_security_events.rb +3 -3
  35. data/db/migrate/20260910000001_create_beskar_security_states.rb +14 -0
  36. data/db/migrate/20260911000001_create_beskar_administrative_actions.rb +22 -0
  37. data/db/migrate/20260911000002_expand_administrative_action_targets.rb +6 -0
  38. data/docs/README.md +73 -0
  39. data/docs/archive/project-documentation.md +659 -0
  40. data/docs/audits/project-review.md +437 -0
  41. data/docs/audits/repair-status.md +216 -0
  42. data/docs/guides/audit-and-waf.md +175 -0
  43. data/docs/guides/audit-lifecycle.md +172 -0
  44. data/docs/guides/authentication.md +213 -0
  45. data/docs/guides/configuration.md +182 -0
  46. data/docs/guides/dashboard-and-search.md +251 -0
  47. data/docs/guides/notifications-and-recovery.md +157 -0
  48. data/docs/guides/risk-scoring.md +116 -0
  49. data/docs/operations/monitor-only-mode.md +85 -0
  50. data/docs/operations/security-hardening.md +167 -0
  51. data/docs/operations/state-storage.md +144 -0
  52. data/docs/research/rust-performance-assessment.md +69 -0
  53. data/lib/beskar/configuration.rb +105 -20
  54. data/lib/beskar/configuration_validator.rb +188 -0
  55. data/lib/beskar/devise_authentication.rb +24 -0
  56. data/lib/beskar/engine.rb +21 -88
  57. data/lib/beskar/logger.rb +288 -0
  58. data/lib/beskar/middleware/request_analyzer.rb +133 -99
  59. data/lib/beskar/models/security_trackable_authenticable.rb +76 -97
  60. data/lib/beskar/models/security_trackable_devise.rb +34 -25
  61. data/lib/beskar/models/security_trackable_generic.rb +171 -214
  62. data/lib/beskar/risk_level.rb +22 -0
  63. data/lib/beskar/services/account_locker.rb +90 -81
  64. data/lib/beskar/services/administrative_audit.rb +36 -0
  65. data/lib/beskar/services/administrative_bans.rb +104 -0
  66. data/lib/beskar/services/audit_data.rb +72 -0
  67. data/lib/beskar/services/authentication.rb +31 -0
  68. data/lib/beskar/services/authentication_attempt.rb +141 -0
  69. data/lib/beskar/services/ban_expiry.rb +28 -0
  70. data/lib/beskar/services/device_detector.rb +32 -41
  71. data/lib/beskar/services/event_search.rb +58 -0
  72. data/lib/beskar/services/geolocation_service.rb +83 -114
  73. data/lib/beskar/services/ip_whitelist.rb +31 -40
  74. data/lib/beskar/services/location_assessment.rb +109 -0
  75. data/lib/beskar/services/native_account_lock.rb +82 -0
  76. data/lib/beskar/services/notifications.rb +46 -0
  77. data/lib/beskar/services/rate_limiter.rb +99 -125
  78. data/lib/beskar/services/request_context.rb +64 -0
  79. data/lib/beskar/services/risk_assessment.rb +58 -0
  80. data/lib/beskar/services/session_revocation.rb +62 -0
  81. data/lib/beskar/services/waf.rb +311 -198
  82. data/lib/beskar/services/waf_request.rb +60 -0
  83. data/lib/beskar/version.rb +1 -1
  84. data/lib/beskar/warden_authentication.rb +53 -0
  85. data/lib/beskar.rb +54 -4
  86. data/lib/generators/beskar/install/install_generator.rb +158 -0
  87. data/lib/generators/beskar/install/templates/initializer.rb.tt +261 -0
  88. data/lib/tasks/beskar_tasks.rake +25 -20
  89. metadata +93 -12
  90. data/lib/beskar/templates/beskar_initializer.rb +0 -107
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  namespace :beskar do
4
+ desc "Remove expired coordination state (does not remove audit events or active bans)"
5
+ task cleanup_security_state: :environment do
6
+ Beskar::SecurityState.cleanup_expired!
7
+ end
8
+
4
9
  desc "Install Beskar: copy migrations and create initializer"
5
10
  task install: :environment do
6
11
  puts "=" * 80
@@ -10,25 +15,19 @@ namespace :beskar do
10
15
 
11
16
  # Copy migrations
12
17
  puts "📦 Copying migrations..."
13
- begin
14
- Rake::Task["beskar:install:migrations"].invoke
15
- rescue RuntimeError
16
- # In development/test within the gem, this task might not exist
17
- # In a real app using the gem, it will work fine
18
- puts " (Skipping migration copy in gem development mode)"
19
- end
18
+ Rake::Task["beskar:install:migrations"].invoke
20
19
  puts "✓ Migrations ready"
21
20
  puts
22
21
 
23
22
  # Create initializer
24
23
  initializer_path = Rails.root.join("config/initializers/beskar.rb")
25
-
24
+
26
25
  if File.exist?(initializer_path)
27
26
  puts "⚠️ Initializer already exists at config/initializers/beskar.rb"
28
27
  print " Overwrite? (y/N): "
29
- response = $stdin.gets.chomp.downcase
30
-
31
- unless response == 'y' || response == 'yes'
28
+ response = $stdin.gets.to_s.strip.downcase
29
+
30
+ unless response == "y" || response == "yes"
32
31
  puts " Skipping initializer creation"
33
32
  puts
34
33
  next_steps
@@ -37,8 +36,17 @@ namespace :beskar do
37
36
  end
38
37
 
39
38
  puts "📝 Creating initializer..."
40
- template_path = File.expand_path("../beskar/templates/beskar_initializer.rb", __dir__)
41
- FileUtils.cp(template_path, initializer_path)
39
+ template_path = File.expand_path("../generators/beskar/install/templates/initializer.rb.tt", __dir__)
40
+
41
+ # Read the template and process ERB (Rails will be available in the rake task context)
42
+ template_content = File.read(template_path)
43
+ erb = ERB.new(template_content, trim_mode: "-")
44
+
45
+ # Evaluate the ERB template in a context where Rails is available
46
+ processed_content = erb.result(binding)
47
+
48
+ # Write the processed initializer
49
+ File.write(initializer_path, processed_content)
42
50
  puts "✓ Created config/initializers/beskar.rb"
43
51
  puts
44
52
 
@@ -60,7 +68,7 @@ namespace :beskar do
60
68
  puts
61
69
  puts " # app/models/user.rb"
62
70
  puts " class User < ApplicationRecord"
63
- puts " include Beskar::SecurityTrackable"
71
+ puts " include Beskar::Models::SecurityTrackable"
64
72
  puts " "
65
73
  puts " devise :database_authenticatable, :registerable,"
66
74
  puts " :recoverable, :rememberable, :validatable"
@@ -89,11 +97,8 @@ namespace :beskar do
89
97
  puts "5. When ready to enable blocking:"
90
98
  puts
91
99
  puts " # config/initializers/beskar.rb"
92
- puts " config.waf = {"
93
- puts " enabled: true,"
94
- puts " monitor_only: false, # <-- Change this to false"
95
- puts " # ... rest of config"
96
- puts " }"
100
+ puts " config.waf[:enabled] = true"
101
+ puts " config.monitor_only = false"
97
102
  puts
98
103
  puts "6. Optional: Add IP whitelist for trusted sources:"
99
104
  puts
@@ -106,7 +111,7 @@ namespace :beskar do
106
111
  puts "=" * 80
107
112
  puts "Documentation:"
108
113
  puts " - README: https://github.com/humadroid-io/beskar"
109
- puts " - WAF Monitor Mode: See MONITOR_ONLY_MODE.md"
114
+ puts " - WAF Monitor Mode: See docs/operations/monitor-only-mode.md"
110
115
  puts "=" * 80
111
116
  end
112
117
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beskar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Litwiniuk
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: 8.0.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: csv
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.0'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: maxminddb
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +80,7 @@ dependencies:
66
80
  - !ruby/object:Gem::Version
67
81
  version: '0'
68
82
  - !ruby/object:Gem::Dependency
69
- name: ostruct
83
+ name: factory_bot_rails
70
84
  requirement: !ruby/object:Gem::Requirement
71
85
  requirements:
72
86
  - - ">="
@@ -80,7 +94,7 @@ dependencies:
80
94
  - !ruby/object:Gem::Version
81
95
  version: '0'
82
96
  - !ruby/object:Gem::Dependency
83
- name: factory_bot_rails
97
+ name: mocha
84
98
  requirement: !ruby/object:Gem::Requirement
85
99
  requirements:
86
100
  - - ">="
@@ -94,7 +108,7 @@ dependencies:
94
108
  - !ruby/object:Gem::Version
95
109
  version: '0'
96
110
  - !ruby/object:Gem::Dependency
97
- name: mocha
111
+ name: ostruct
98
112
  requirement: !ruby/object:Gem::Requirement
99
113
  requirements:
100
114
  - - ">="
@@ -107,50 +121,115 @@ dependencies:
107
121
  - - ">="
108
122
  - !ruby/object:Gem::Version
109
123
  version: '0'
110
- description: |-
111
- Rails Security Shield is a comprehensive, Rails-native security engine designed to provide multi-layered protection for modern web applications. It actively defends against common threats by integrating a powerful Web Application Firewall (WAF) to block attacks like SQLi and XSS, an advanced bot detection system using JavaScript challenges and honeypots, and robust account takeover prevention to stop brute-force and credential stuffing attacks.
112
-
113
- Built as a mountable Rails Engine, it leverages core framework features like ActiveJob and Rails.cache to ensure high performance and minimal external dependencies. It includes a real-time dashboard for monitoring security events, giving you immediate insight into the threats your application faces. Drop it in, configure it, and get enterprise-grade security that feels like a natural extension of Rails.
124
+ description: Beskar is a mountable Rails engine with database-coordinated authentication
125
+ admission limits, risk-based account locks, persistent IP bans, scanner-path signatures,
126
+ and an administrative security dashboard. It supports Devise and explicit Rails-native
127
+ authentication integration, optional MaxMind enrichment, User-Agent risk heuristics,
128
+ and monitor-only operation. It does not implement general SQL injection or XSS filtering,
129
+ JavaScript challenges, or honeypots.
114
130
  email:
115
131
  - maciej@litwiniuk.net
116
132
  executables: []
117
133
  extensions: []
118
134
  extra_rdoc_files: []
119
135
  files:
136
+ - CHANGELOG.md
120
137
  - MIT-LICENSE
121
138
  - README.md
122
139
  - Rakefile
123
140
  - app/assets/stylesheets/beskar/application.css
141
+ - app/channels/concerns/beskar/channels/session_security.rb
142
+ - app/controllers/beskar/administrative_actions_controller.rb
124
143
  - app/controllers/beskar/application_controller.rb
144
+ - app/controllers/beskar/banned_ips_controller.rb
145
+ - app/controllers/beskar/dashboard_controller.rb
146
+ - app/controllers/beskar/security_events_controller.rb
147
+ - app/controllers/concerns/beskar/controllers/audit_export.rb
125
148
  - app/controllers/concerns/beskar/controllers/security_tracking.rb
149
+ - app/controllers/concerns/beskar/controllers/session_security.rb
126
150
  - app/helpers/beskar/application_helper.rb
127
151
  - app/jobs/beskar/application_job.rb
152
+ - app/jobs/beskar/notification_job.rb
128
153
  - app/mailers/beskar/application_mailer.rb
154
+ - app/mailers/beskar/security_mailer.rb
155
+ - app/models/beskar/administrative_action.rb
129
156
  - app/models/beskar/application_record.rb
130
157
  - app/models/beskar/banned_ip.rb
131
158
  - app/models/beskar/security_event.rb
159
+ - app/models/beskar/security_state.rb
160
+ - app/services/beskar/banned_ip_manager.rb
161
+ - app/views/beskar/administrative_actions/index.html.erb
162
+ - app/views/beskar/administrative_actions/show.html.erb
163
+ - app/views/beskar/banned_ips/edit.html.erb
164
+ - app/views/beskar/banned_ips/index.html.erb
165
+ - app/views/beskar/banned_ips/new.html.erb
166
+ - app/views/beskar/banned_ips/review.html.erb
167
+ - app/views/beskar/banned_ips/show.html.erb
168
+ - app/views/beskar/dashboard/index.html.erb
169
+ - app/views/beskar/security_events/index.html.erb
170
+ - app/views/beskar/security_events/show.html.erb
171
+ - app/views/beskar/shared/_export_form.html.erb
172
+ - app/views/layouts/beskar/_behavior.html.erb
132
173
  - app/views/layouts/beskar/application.html.erb
133
174
  - config/locales/en.yml
134
175
  - config/routes.rb
135
176
  - db/migrate/20251016000001_create_beskar_security_events.rb
136
177
  - db/migrate/20251016000002_create_beskar_banned_ips.rb
178
+ - db/migrate/20260910000001_create_beskar_security_states.rb
179
+ - db/migrate/20260911000001_create_beskar_administrative_actions.rb
180
+ - db/migrate/20260911000002_expand_administrative_action_targets.rb
181
+ - docs/README.md
182
+ - docs/archive/project-documentation.md
183
+ - docs/audits/project-review.md
184
+ - docs/audits/repair-status.md
185
+ - docs/guides/audit-and-waf.md
186
+ - docs/guides/audit-lifecycle.md
187
+ - docs/guides/authentication.md
188
+ - docs/guides/configuration.md
189
+ - docs/guides/dashboard-and-search.md
190
+ - docs/guides/notifications-and-recovery.md
191
+ - docs/guides/risk-scoring.md
192
+ - docs/operations/monitor-only-mode.md
193
+ - docs/operations/security-hardening.md
194
+ - docs/operations/state-storage.md
195
+ - docs/research/rust-performance-assessment.md
137
196
  - lib/beskar.rb
138
197
  - lib/beskar/configuration.rb
198
+ - lib/beskar/configuration_validator.rb
199
+ - lib/beskar/devise_authentication.rb
139
200
  - lib/beskar/engine.rb
201
+ - lib/beskar/logger.rb
140
202
  - lib/beskar/middleware.rb
141
203
  - lib/beskar/middleware/request_analyzer.rb
142
204
  - lib/beskar/models/security_trackable.rb
143
205
  - lib/beskar/models/security_trackable_authenticable.rb
144
206
  - lib/beskar/models/security_trackable_devise.rb
145
207
  - lib/beskar/models/security_trackable_generic.rb
208
+ - lib/beskar/risk_level.rb
146
209
  - lib/beskar/services/account_locker.rb
210
+ - lib/beskar/services/administrative_audit.rb
211
+ - lib/beskar/services/administrative_bans.rb
212
+ - lib/beskar/services/audit_data.rb
213
+ - lib/beskar/services/authentication.rb
214
+ - lib/beskar/services/authentication_attempt.rb
215
+ - lib/beskar/services/ban_expiry.rb
147
216
  - lib/beskar/services/device_detector.rb
217
+ - lib/beskar/services/event_search.rb
148
218
  - lib/beskar/services/geolocation_service.rb
149
219
  - lib/beskar/services/ip_whitelist.rb
220
+ - lib/beskar/services/location_assessment.rb
221
+ - lib/beskar/services/native_account_lock.rb
222
+ - lib/beskar/services/notifications.rb
150
223
  - lib/beskar/services/rate_limiter.rb
224
+ - lib/beskar/services/request_context.rb
225
+ - lib/beskar/services/risk_assessment.rb
226
+ - lib/beskar/services/session_revocation.rb
151
227
  - lib/beskar/services/waf.rb
152
- - lib/beskar/templates/beskar_initializer.rb
228
+ - lib/beskar/services/waf_request.rb
153
229
  - lib/beskar/version.rb
230
+ - lib/beskar/warden_authentication.rb
231
+ - lib/generators/beskar/install/install_generator.rb
232
+ - lib/generators/beskar/install/templates/initializer.rb.tt
154
233
  - lib/tasks/beskar_tasks.rake
155
234
  homepage: https://humadroid.io/beskar
156
235
  licenses:
@@ -158,6 +237,8 @@ licenses:
158
237
  metadata:
159
238
  homepage_uri: https://humadroid.io/beskar
160
239
  source_code_uri: https://github.com/humadroid-io/beskar
240
+ documentation_uri: https://github.com/humadroid-io/beskar/blob/master/docs/README.md
241
+ changelog_uri: https://github.com/humadroid-io/beskar/blob/master/CHANGELOG.md
161
242
  rdoc_options: []
162
243
  require_paths:
163
244
  - lib
@@ -172,8 +253,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
253
  - !ruby/object:Gem::Version
173
254
  version: '0'
174
255
  requirements: []
175
- rubygems_version: 3.7.2
256
+ rubygems_version: 4.0.20
176
257
  specification_version: 4
177
- summary: An all-in-one security engine for Rails providing WAF, bot detection, and
178
- account takeover prevention.
258
+ summary: A Rails security engine for authentication limits, risk-based locks, IP bans,
259
+ and audit events.
179
260
  test_files: []
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Beskar.configure do |config|
4
- # ============================================================================
5
- # Web Application Firewall (WAF) - ENABLED IN MONITOR MODE BY DEFAULT
6
- # ============================================================================
7
- # Detects and logs vulnerability scanning attempts (WordPress, phpMyAdmin, etc.)
8
- # Start in monitor-only mode to observe patterns before enabling blocking.
9
- #
10
- config.waf = {
11
- enabled: true, # Master switch for WAF
12
- monitor_only: true, # LOG ONLY - does not block (recommended to start)
13
- auto_block: true, # Auto-block IPs after threshold (when monitor_only=false)
14
- block_threshold: 3, # Number of violations before blocking
15
- violation_window: 1.hour, # Time window for counting violations
16
- block_durations: [1.hour, 6.hours, 24.hours, 7.days], # Escalating ban durations
17
- permanent_block_after: 5, # Permanent ban after N violations (nil = never)
18
- create_security_events: true # Log violations to SecurityEvent table
19
- }
20
-
21
- # After monitoring for 24-48 hours, review logs and disable monitor_only:
22
- # config.waf[:monitor_only] = false
23
-
24
- # View WAF activity in logs:
25
- # tail -f log/production.log | grep "Beskar::WAF"
26
-
27
- # Query violations that would be blocked:
28
- # Beskar::SecurityEvent.where(event_type: 'waf_violation')
29
- # .where("metadata->>'would_be_blocked' = ?", 'true').count
30
-
31
- # ============================================================================
32
- # IP Whitelisting (RECOMMENDED)
33
- # ============================================================================
34
- # Trusted IPs bypass all blocking (bans, rate limits, WAF) while still
35
- # logging activity for audit purposes.
36
- #
37
- # config.ip_whitelist = [
38
- # "192.168.1.100", # Single IP address
39
- # "10.0.0.0/24", # CIDR notation - entire subnet
40
- # "172.16.0.0/16" # Larger CIDR range
41
- # # Add your office IPs, monitoring services, trusted partners, etc.
42
- # ]
43
-
44
- # ============================================================================
45
- # Security Event Tracking (OPTIONAL)
46
- # ============================================================================
47
- # Track authentication events for risk analysis and threat detection.
48
- # Disable if you don't need historical security event data.
49
- #
50
- # config.security_tracking = {
51
- # enabled: true, # Master switch for all tracking
52
- # track_successful_logins: true, # Track successful authentications
53
- # track_failed_logins: true, # Track failed authentication attempts
54
- # auto_analyze_patterns: true # Enable automatic pattern analysis
55
- # }
56
-
57
- # ============================================================================
58
- # Rate Limiting (OPTIONAL)
59
- # ============================================================================
60
- # Protect against brute force attacks by limiting authentication attempts.
61
- #
62
- # config.rate_limiting = {
63
- # ip_attempts: {
64
- # limit: 10, # Max attempts per IP
65
- # period: 1.hour, # Time window
66
- # exponential_backoff: true # Increase delay after each attempt
67
- # },
68
- # account_attempts: {
69
- # limit: 5, # Max attempts per account
70
- # period: 15.minutes,
71
- # exponential_backoff: true
72
- # },
73
- # global_attempts: {
74
- # limit: 100, # System-wide limit (DDoS protection)
75
- # period: 1.minute,
76
- # exponential_backoff: false
77
- # }
78
- # }
79
-
80
- # ============================================================================
81
- # Risk-Based Account Locking (OPTIONAL)
82
- # ============================================================================
83
- # Automatically lock accounts when authentication risk score is too high.
84
- # Requires Devise :lockable module.
85
- #
86
- # config.risk_based_locking = {
87
- # enabled: false, # Disabled by default
88
- # risk_threshold: 75, # Lock if risk score >= this (0-100)
89
- # lock_strategy: :devise_lockable, # Strategy: :devise_lockable, :custom, :none
90
- # auto_unlock_time: 1.hour, # Time until automatic unlock
91
- # notify_user: true, # Send notification on lock
92
- # log_lock_events: true # Create security events for locks
93
- # }
94
-
95
- # ============================================================================
96
- # IP Geolocation (OPTIONAL)
97
- # ============================================================================
98
- # Enhance risk assessment with geographic information.
99
- # Requires MaxMind GeoLite2-City database (free with registration).
100
- # Download from: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
101
- #
102
- # config.geolocation = {
103
- # provider: :maxmind,
104
- # maxmind_city_db_path: Rails.root.join('db', 'geoip', 'GeoLite2-City.mmdb').to_s,
105
- # cache_ttl: 4.hours
106
- # }
107
- end