authtrail 0.2.1 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/LICENSE.txt +1 -1
- data/README.md +90 -19
- data/app/jobs/auth_trail/geocode_job.rb +4 -0
- data/lib/auth_trail/manager.rb +18 -23
- data/lib/auth_trail/version.rb +1 -1
- data/lib/authtrail.rb +11 -8
- data/lib/generators/authtrail/install_generator.rb +31 -1
- data/lib/generators/authtrail/templates/initializer.rb.tt +14 -0
- data/lib/generators/authtrail/templates/login_activities_migration.rb.tt +2 -5
- data/lib/generators/authtrail/templates/{login_activity_model.rb.tt → model.rb.tt} +0 -0
- data/lib/generators/authtrail/templates/model_lockbox.rb.tt +14 -0
- metadata +16 -126
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fc8ae231bde9d10834ea6a7fa2fb0cd50a12e351ba2296abb15b743975fad197
|
|
4
|
+
data.tar.gz: c52435deca659cd45a8ed647daccaf8b19e9d7d92374db06be69c63cbcc6b1e3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8531404800e70b37e0f6bca1fd79f690bfe36434efe768c926fa7248f1f50d803de16aa3324ecaa656c142940e69de35f80d2c5f4699f5408fbd92f41e5c24b0
|
|
7
|
+
data.tar.gz: bd4daf16b7ad615477cdbf0592f45d789fa7b6b0ba759c417f6e4e89888e2b4014dae6a2b48333a9863b6b1b0670082f9b9808da327dc790f2e0f173d6d63714
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 0.4.0 (2021-08-13)
|
|
2
|
+
|
|
3
|
+
- Disabled geocoding by default
|
|
4
|
+
- Made the `geocoder` gem an optional dependency
|
|
5
|
+
- Added `country_code` to geocoding
|
|
6
|
+
|
|
7
|
+
## 0.3.1 (2021-03-03)
|
|
8
|
+
|
|
9
|
+
- Added `--lockbox` option to install generator
|
|
10
|
+
|
|
11
|
+
## 0.3.0 (2021-03-01)
|
|
12
|
+
|
|
13
|
+
- Disabled geocoding by default for new installations
|
|
14
|
+
- Raise an exception instead of logging when auditing fails
|
|
15
|
+
- Removed support for Rails < 5.2 and Ruby < 2.6
|
|
16
|
+
|
|
17
|
+
## 0.2.2 (2020-11-21)
|
|
18
|
+
|
|
19
|
+
- Added `transform_method` option
|
|
20
|
+
|
|
1
21
|
## 0.2.1 (2020-08-17)
|
|
2
22
|
|
|
3
23
|
- Added `job_queue` option
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Track Devise login activity
|
|
4
4
|
|
|
5
|
+
**AuthTrail 0.4.0 was recently released** - see [how to upgrade](#upgrading)
|
|
6
|
+
|
|
5
7
|
:tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
|
|
6
8
|
|
|
7
|
-
[](https://github.com/ankane/authtrail/actions)
|
|
8
10
|
|
|
9
11
|
## Installation
|
|
10
12
|
|
|
@@ -14,13 +16,22 @@ Add this line to your application’s Gemfile:
|
|
|
14
16
|
gem 'authtrail'
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
To encrypt email and IP addresses, install [Lockbox](https://github.com/ankane/lockbox) and [Blind Index](https://github.com/ankane/blind_index) and run:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
rails generate authtrail:install --lockbox
|
|
23
|
+
rails db:migrate
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
If you prefer not to encrypt data, run:
|
|
18
27
|
|
|
19
28
|
```sh
|
|
20
29
|
rails generate authtrail:install
|
|
21
30
|
rails db:migrate
|
|
22
31
|
```
|
|
23
32
|
|
|
33
|
+
To enable geocoding, see the [Geocoding section](#geocoding).
|
|
34
|
+
|
|
24
35
|
## How It Works
|
|
25
36
|
|
|
26
37
|
A `LoginActivity` record is created every time a user tries to login. You can then use this information to detect suspicious behavior. Data includes:
|
|
@@ -42,15 +53,31 @@ A `LoginActivity` record is created every time a user tries to login. You can th
|
|
|
42
53
|
Exclude certain attempts from tracking - useful if you run acceptance tests
|
|
43
54
|
|
|
44
55
|
```ruby
|
|
45
|
-
AuthTrail.exclude_method = lambda do |
|
|
46
|
-
|
|
56
|
+
AuthTrail.exclude_method = lambda do |data|
|
|
57
|
+
data[:identity] == "capybara@example.org"
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Add or modify data - also add new fields to the `login_activities` table if needed
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
AuthTrail.transform_method = lambda do |data, request|
|
|
65
|
+
data[:request_id] = request.request_id
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Store the user on failed attempts
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
AuthTrail.transform_method = lambda do |data, request|
|
|
73
|
+
data[:user] ||= User.find_by(email: data[:identity])
|
|
47
74
|
end
|
|
48
75
|
```
|
|
49
76
|
|
|
50
77
|
Write data somewhere other than the `login_activities` table
|
|
51
78
|
|
|
52
79
|
```ruby
|
|
53
|
-
AuthTrail.track_method = lambda do |
|
|
80
|
+
AuthTrail.track_method = lambda do |data|
|
|
54
81
|
# code
|
|
55
82
|
end
|
|
56
83
|
```
|
|
@@ -79,50 +106,82 @@ The `LoginActivity` model uses a [polymorphic association](https://guides.rubyon
|
|
|
79
106
|
|
|
80
107
|
## Geocoding
|
|
81
108
|
|
|
82
|
-
|
|
109
|
+
AuthTrail uses [Geocoder](https://github.com/alexreisner/geocoder) for geocoding. We recommend configuring [local geocoding](#local-geocoding) or [load balancer geocoding](#load-balancer-geocoding) so IP addresses are not sent to a 3rd party service. If you do use a 3rd party service and adhere to GDPR, be sure to add it to your subprocessor list.
|
|
110
|
+
|
|
111
|
+
To enable geocoding, add this line to your application’s Gemfile:
|
|
83
112
|
|
|
84
113
|
```ruby
|
|
85
|
-
|
|
114
|
+
gem 'geocoder'
|
|
86
115
|
```
|
|
87
116
|
|
|
88
|
-
|
|
117
|
+
And update `config/initializers/authtrail.rb`:
|
|
89
118
|
|
|
90
119
|
```ruby
|
|
91
|
-
AuthTrail.
|
|
120
|
+
AuthTrail.geocode = true
|
|
92
121
|
```
|
|
93
122
|
|
|
94
|
-
|
|
123
|
+
Geocoding is performed in a background job so it doesn’t slow down web requests. Set the job queue with:
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
AuthTrail.job_queue = :low_priority
|
|
127
|
+
```
|
|
95
128
|
|
|
96
|
-
|
|
129
|
+
### Local Geocoding
|
|
97
130
|
|
|
98
|
-
Add this line to your application’s Gemfile:
|
|
131
|
+
For privacy and performance, we recommend geocoding locally. Add this line to your application’s Gemfile:
|
|
99
132
|
|
|
100
133
|
```ruby
|
|
101
134
|
gem 'maxminddb'
|
|
102
135
|
```
|
|
103
136
|
|
|
104
|
-
|
|
137
|
+
For city-level geocoding, download the [GeoLite2 City database](https://dev.maxmind.com/geoip/geoip2/geolite2/) and create `config/initializers/geocoder.rb` with:
|
|
105
138
|
|
|
106
139
|
```ruby
|
|
107
140
|
Geocoder.configure(
|
|
108
141
|
ip_lookup: :geoip2,
|
|
109
142
|
geoip2: {
|
|
110
|
-
file:
|
|
143
|
+
file: "path/to/GeoLite2-City.mmdb"
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
For country-level geocoding, install the `geoip-database` package. It’s preinstalled on Heroku. For Ubuntu, use:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
sudo apt-get install geoip-database
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
And create `config/initializers/geocoder.rb` with:
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
Geocoder.configure(
|
|
158
|
+
ip_lookup: :maxmind_local,
|
|
159
|
+
maxmind_local: {
|
|
160
|
+
file: "/usr/share/GeoIP/GeoIP.dat",
|
|
161
|
+
package: :country
|
|
111
162
|
}
|
|
112
163
|
)
|
|
113
164
|
```
|
|
114
165
|
|
|
115
|
-
|
|
166
|
+
### Load Balancer Geocoding
|
|
116
167
|
|
|
117
|
-
|
|
168
|
+
Some load balancers can add geocoding information to request headers.
|
|
169
|
+
|
|
170
|
+
- [nginx](https://nginx.org/en/docs/http/ngx_http_geoip_module.html)
|
|
171
|
+
- [Google Cloud](https://cloud.google.com/load-balancing/docs/custom-headers)
|
|
172
|
+
- [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/200168236-Configuring-Cloudflare-IP-Geolocation)
|
|
118
173
|
|
|
119
174
|
```ruby
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
175
|
+
AuthTrail.geocode = false
|
|
176
|
+
AuthTrail.transform_method = lambda do |data, request|
|
|
177
|
+
data[:country] = request.headers["<country-header>"]
|
|
178
|
+
data[:region] = request.headers["<region-header>"]
|
|
179
|
+
data[:city] = request.headers["<city-header>"]
|
|
123
180
|
end
|
|
124
181
|
```
|
|
125
182
|
|
|
183
|
+
Check out [this example](https://github.com/ankane/authtrail/issues/40)
|
|
184
|
+
|
|
126
185
|
## Other Notes
|
|
127
186
|
|
|
128
187
|
We recommend using this in addition to Devise’s `Lockable` module and [Rack::Attack](https://github.com/kickstarter/rack-attack).
|
|
@@ -131,6 +190,18 @@ Check out [Hardening Devise](https://ankane.org/hardening-devise) and [Secure Ra
|
|
|
131
190
|
|
|
132
191
|
## Upgrading
|
|
133
192
|
|
|
193
|
+
### 0.4.0
|
|
194
|
+
|
|
195
|
+
There are two notable changes to geocoding:
|
|
196
|
+
|
|
197
|
+
1. Geocoding is now disabled by default (this was already the case for new installations with 0.3.0+). Check out the instructions for [how to enable it](#geocoding) (you may need to create `config/initializers/authtrail.rb`).
|
|
198
|
+
|
|
199
|
+
2. The `geocoder` gem is now an optional dependency. To use geocoding, add it to your Gemfile:
|
|
200
|
+
|
|
201
|
+
```ruby
|
|
202
|
+
gem 'geocoder'
|
|
203
|
+
```
|
|
204
|
+
|
|
134
205
|
### 0.2.0
|
|
135
206
|
|
|
136
207
|
To store latitude and longitude, create a migration with:
|
|
@@ -8,6 +8,9 @@ module AuthTrail
|
|
|
8
8
|
result =
|
|
9
9
|
begin
|
|
10
10
|
Geocoder.search(login_activity.ip).first
|
|
11
|
+
rescue NameError
|
|
12
|
+
# geocoder gem not installed
|
|
13
|
+
raise
|
|
11
14
|
rescue => e
|
|
12
15
|
Rails.logger.info "Geocode failed: #{e.message}"
|
|
13
16
|
nil
|
|
@@ -18,6 +21,7 @@ module AuthTrail
|
|
|
18
21
|
city: result.try(:city),
|
|
19
22
|
region: result.try(:state),
|
|
20
23
|
country: result.try(:country),
|
|
24
|
+
country_code: result.try(:country_code),
|
|
21
25
|
latitude: result.try(:latitude),
|
|
22
26
|
longitude: result.try(:longitude)
|
|
23
27
|
}
|
data/lib/auth_trail/manager.rb
CHANGED
|
@@ -2,34 +2,29 @@ module AuthTrail
|
|
|
2
2
|
module Manager
|
|
3
3
|
class << self
|
|
4
4
|
def after_set_user(user, auth, opts)
|
|
5
|
-
|
|
6
|
-
AuthTrail.safely do
|
|
7
|
-
request = ActionDispatch::Request.new(auth.env)
|
|
5
|
+
request = ActionDispatch::Request.new(auth.env)
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
7
|
+
AuthTrail.track(
|
|
8
|
+
strategy: detect_strategy(auth),
|
|
9
|
+
scope: opts[:scope].to_s,
|
|
10
|
+
identity: AuthTrail.identity_method.call(request, opts, user),
|
|
11
|
+
success: true,
|
|
12
|
+
request: request,
|
|
13
|
+
user: user
|
|
14
|
+
)
|
|
18
15
|
end
|
|
19
16
|
|
|
20
17
|
def before_failure(env, opts)
|
|
21
|
-
|
|
22
|
-
request = ActionDispatch::Request.new(env)
|
|
18
|
+
request = ActionDispatch::Request.new(env)
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end
|
|
20
|
+
AuthTrail.track(
|
|
21
|
+
strategy: detect_strategy(env["warden"]),
|
|
22
|
+
scope: opts[:scope].to_s,
|
|
23
|
+
identity: AuthTrail.identity_method.call(request, opts, nil),
|
|
24
|
+
success: false,
|
|
25
|
+
request: request,
|
|
26
|
+
failure_reason: opts[:message].to_s
|
|
27
|
+
)
|
|
33
28
|
end
|
|
34
29
|
|
|
35
30
|
private
|
data/lib/auth_trail/version.rb
CHANGED
data/lib/authtrail.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
# dependencies
|
|
2
|
-
require "geocoder"
|
|
3
2
|
require "warden"
|
|
4
3
|
|
|
5
4
|
# modules
|
|
@@ -9,9 +8,9 @@ require "auth_trail/version"
|
|
|
9
8
|
|
|
10
9
|
module AuthTrail
|
|
11
10
|
class << self
|
|
12
|
-
attr_accessor :exclude_method, :geocode, :track_method, :identity_method, :job_queue
|
|
11
|
+
attr_accessor :exclude_method, :geocode, :track_method, :identity_method, :job_queue, :transform_method
|
|
13
12
|
end
|
|
14
|
-
self.geocode =
|
|
13
|
+
self.geocode = false
|
|
15
14
|
self.identity_method = lambda do |request, opts, user|
|
|
16
15
|
if user
|
|
17
16
|
user.try(:email)
|
|
@@ -22,7 +21,7 @@ module AuthTrail
|
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def self.track(strategy:, scope:, identity:, success:, request:, user: nil, failure_reason: nil)
|
|
25
|
-
|
|
24
|
+
data = {
|
|
26
25
|
strategy: strategy,
|
|
27
26
|
scope: scope,
|
|
28
27
|
identity: identity,
|
|
@@ -35,18 +34,22 @@ module AuthTrail
|
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
if request.params[:controller]
|
|
38
|
-
|
|
37
|
+
data[:context] = "#{request.params[:controller]}##{request.params[:action]}"
|
|
39
38
|
end
|
|
40
39
|
|
|
40
|
+
# add request data before exclude_method since exclude_method doesn't have access to request
|
|
41
|
+
# could also add 2nd argument to exclude_method when arity > 1
|
|
42
|
+
AuthTrail.transform_method.call(data, request) if AuthTrail.transform_method
|
|
43
|
+
|
|
41
44
|
# if exclude_method throws an exception, default to not excluding
|
|
42
|
-
exclude = AuthTrail.exclude_method && AuthTrail.safely(default: false) { AuthTrail.exclude_method.call(
|
|
45
|
+
exclude = AuthTrail.exclude_method && AuthTrail.safely(default: false) { AuthTrail.exclude_method.call(data) }
|
|
43
46
|
|
|
44
47
|
unless exclude
|
|
45
48
|
if AuthTrail.track_method
|
|
46
|
-
AuthTrail.track_method.call(
|
|
49
|
+
AuthTrail.track_method.call(data)
|
|
47
50
|
else
|
|
48
51
|
login_activity = LoginActivity.new
|
|
49
|
-
|
|
52
|
+
data.each do |k, v|
|
|
50
53
|
login_activity.try("#{k}=", v)
|
|
51
54
|
end
|
|
52
55
|
login_activity.save!
|
|
@@ -6,17 +6,47 @@ module Authtrail
|
|
|
6
6
|
include ActiveRecord::Generators::Migration
|
|
7
7
|
source_root File.join(__dir__, "templates")
|
|
8
8
|
|
|
9
|
+
class_option :lockbox, type: :boolean
|
|
10
|
+
|
|
9
11
|
def copy_migration
|
|
10
12
|
migration_template "login_activities_migration.rb", "db/migrate/create_login_activities.rb", migration_version: migration_version
|
|
11
13
|
end
|
|
12
14
|
|
|
15
|
+
def copy_templates
|
|
16
|
+
template "initializer.rb", "config/initializers/authtrail.rb"
|
|
17
|
+
end
|
|
18
|
+
|
|
13
19
|
def generate_model
|
|
14
|
-
|
|
20
|
+
if lockbox?
|
|
21
|
+
template "model_lockbox.rb", "app/models/login_activity.rb"
|
|
22
|
+
else
|
|
23
|
+
template "model.rb", "app/models/login_activity.rb"
|
|
24
|
+
end
|
|
15
25
|
end
|
|
16
26
|
|
|
17
27
|
def migration_version
|
|
18
28
|
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
19
29
|
end
|
|
30
|
+
|
|
31
|
+
def identity_column
|
|
32
|
+
if lockbox?
|
|
33
|
+
"t.text :identity_ciphertext\n t.string :identity_bidx, index: true"
|
|
34
|
+
else
|
|
35
|
+
"t.string :identity, index: true"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def ip_column
|
|
40
|
+
if lockbox?
|
|
41
|
+
"t.text :ip_ciphertext\n t.string :ip_bidx, index: true"
|
|
42
|
+
else
|
|
43
|
+
"t.string :ip, index: true"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def lockbox?
|
|
48
|
+
options[:lockbox]
|
|
49
|
+
end
|
|
20
50
|
end
|
|
21
51
|
end
|
|
22
52
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# set to true for geocoding (and add the geocoder gem to your Gemfile)
|
|
2
|
+
# we recommend configuring local geocoding as well
|
|
3
|
+
# see https://github.com/ankane/authtrail#geocoding
|
|
4
|
+
AuthTrail.geocode = false
|
|
5
|
+
|
|
6
|
+
# add or modify data
|
|
7
|
+
# AuthTrail.transform_method = lambda do |data, request|
|
|
8
|
+
# data[:request_id] = request.request_id
|
|
9
|
+
# end
|
|
10
|
+
|
|
11
|
+
# exclude certain attempts from tracking
|
|
12
|
+
# AuthTrail.exclude_method = lambda do |data|
|
|
13
|
+
# data[:identity] == "capybara@example.org"
|
|
14
|
+
# end
|
|
@@ -3,12 +3,12 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
|
|
|
3
3
|
create_table :login_activities do |t|
|
|
4
4
|
t.string :scope
|
|
5
5
|
t.string :strategy
|
|
6
|
-
|
|
6
|
+
<%= identity_column %>
|
|
7
7
|
t.boolean :success
|
|
8
8
|
t.string :failure_reason
|
|
9
9
|
t.references :user, polymorphic: true
|
|
10
10
|
t.string :context
|
|
11
|
-
|
|
11
|
+
<%= ip_column %>
|
|
12
12
|
t.text :user_agent
|
|
13
13
|
t.text :referrer
|
|
14
14
|
t.string :city
|
|
@@ -18,8 +18,5 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
|
|
|
18
18
|
t.float :longitude
|
|
19
19
|
t.datetime :created_at
|
|
20
20
|
end
|
|
21
|
-
|
|
22
|
-
add_index :login_activities, :identity
|
|
23
|
-
add_index :login_activities, :ip
|
|
24
21
|
end
|
|
25
22
|
end
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class LoginActivity < ApplicationRecord
|
|
2
|
+
belongs_to :user, polymorphic: true, optional: true
|
|
3
|
+
|
|
4
|
+
encrypts :identity, :ip
|
|
5
|
+
blind_index :identity, :ip
|
|
6
|
+
|
|
7
|
+
before_save :reduce_precision
|
|
8
|
+
|
|
9
|
+
# reduce precision to city level to protect IP
|
|
10
|
+
def reduce_precision
|
|
11
|
+
self.latitude = latitude&.round(1) if try(:latitude_changed?)
|
|
12
|
+
self.longitude = longitude&.round(1) if try(:longitude_changed?)
|
|
13
|
+
end
|
|
14
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: authtrail
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Kane
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-08-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: railties
|
|
@@ -16,28 +16,28 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '5'
|
|
19
|
+
version: '5.2'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '5'
|
|
26
|
+
version: '5.2'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: activerecord
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '5'
|
|
33
|
+
version: '5.2'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '5'
|
|
40
|
+
version: '5.2'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: warden
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,120 +52,8 @@ dependencies:
|
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - ">="
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '0'
|
|
62
|
-
type: :runtime
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - ">="
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '0'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: bundler
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - ">="
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '0'
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - ">="
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '0'
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: rake
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - ">="
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '0'
|
|
90
|
-
type: :development
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - ">="
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: '0'
|
|
97
|
-
- !ruby/object:Gem::Dependency
|
|
98
|
-
name: minitest
|
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
|
100
|
-
requirements:
|
|
101
|
-
- - ">="
|
|
102
|
-
- !ruby/object:Gem::Version
|
|
103
|
-
version: '5'
|
|
104
|
-
type: :development
|
|
105
|
-
prerelease: false
|
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
-
requirements:
|
|
108
|
-
- - ">="
|
|
109
|
-
- !ruby/object:Gem::Version
|
|
110
|
-
version: '5'
|
|
111
|
-
- !ruby/object:Gem::Dependency
|
|
112
|
-
name: combustion
|
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
|
114
|
-
requirements:
|
|
115
|
-
- - ">="
|
|
116
|
-
- !ruby/object:Gem::Version
|
|
117
|
-
version: '0'
|
|
118
|
-
type: :development
|
|
119
|
-
prerelease: false
|
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
-
requirements:
|
|
122
|
-
- - ">="
|
|
123
|
-
- !ruby/object:Gem::Version
|
|
124
|
-
version: '0'
|
|
125
|
-
- !ruby/object:Gem::Dependency
|
|
126
|
-
name: rails
|
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
|
128
|
-
requirements:
|
|
129
|
-
- - ">="
|
|
130
|
-
- !ruby/object:Gem::Version
|
|
131
|
-
version: '0'
|
|
132
|
-
type: :development
|
|
133
|
-
prerelease: false
|
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
-
requirements:
|
|
136
|
-
- - ">="
|
|
137
|
-
- !ruby/object:Gem::Version
|
|
138
|
-
version: '0'
|
|
139
|
-
- !ruby/object:Gem::Dependency
|
|
140
|
-
name: sqlite3
|
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
|
142
|
-
requirements:
|
|
143
|
-
- - ">="
|
|
144
|
-
- !ruby/object:Gem::Version
|
|
145
|
-
version: '0'
|
|
146
|
-
type: :development
|
|
147
|
-
prerelease: false
|
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
-
requirements:
|
|
150
|
-
- - ">="
|
|
151
|
-
- !ruby/object:Gem::Version
|
|
152
|
-
version: '0'
|
|
153
|
-
- !ruby/object:Gem::Dependency
|
|
154
|
-
name: devise
|
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
|
156
|
-
requirements:
|
|
157
|
-
- - ">="
|
|
158
|
-
- !ruby/object:Gem::Version
|
|
159
|
-
version: '0'
|
|
160
|
-
type: :development
|
|
161
|
-
prerelease: false
|
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
-
requirements:
|
|
164
|
-
- - ">="
|
|
165
|
-
- !ruby/object:Gem::Version
|
|
166
|
-
version: '0'
|
|
167
|
-
description:
|
|
168
|
-
email: andrew@chartkick.com
|
|
55
|
+
description:
|
|
56
|
+
email: andrew@ankane.org
|
|
169
57
|
executables: []
|
|
170
58
|
extensions: []
|
|
171
59
|
extra_rdoc_files: []
|
|
@@ -179,13 +67,15 @@ files:
|
|
|
179
67
|
- lib/auth_trail/version.rb
|
|
180
68
|
- lib/authtrail.rb
|
|
181
69
|
- lib/generators/authtrail/install_generator.rb
|
|
70
|
+
- lib/generators/authtrail/templates/initializer.rb.tt
|
|
182
71
|
- lib/generators/authtrail/templates/login_activities_migration.rb.tt
|
|
183
|
-
- lib/generators/authtrail/templates/
|
|
72
|
+
- lib/generators/authtrail/templates/model.rb.tt
|
|
73
|
+
- lib/generators/authtrail/templates/model_lockbox.rb.tt
|
|
184
74
|
homepage: https://github.com/ankane/authtrail
|
|
185
75
|
licenses:
|
|
186
76
|
- MIT
|
|
187
77
|
metadata: {}
|
|
188
|
-
post_install_message:
|
|
78
|
+
post_install_message:
|
|
189
79
|
rdoc_options: []
|
|
190
80
|
require_paths:
|
|
191
81
|
- lib
|
|
@@ -193,15 +83,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
193
83
|
requirements:
|
|
194
84
|
- - ">="
|
|
195
85
|
- !ruby/object:Gem::Version
|
|
196
|
-
version: '2.
|
|
86
|
+
version: '2.6'
|
|
197
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
88
|
requirements:
|
|
199
89
|
- - ">="
|
|
200
90
|
- !ruby/object:Gem::Version
|
|
201
91
|
version: '0'
|
|
202
92
|
requirements: []
|
|
203
|
-
rubygems_version: 3.
|
|
204
|
-
signing_key:
|
|
93
|
+
rubygems_version: 3.2.22
|
|
94
|
+
signing_key:
|
|
205
95
|
specification_version: 4
|
|
206
96
|
summary: Track Devise login activity
|
|
207
97
|
test_files: []
|