authtrail 0.2.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ca58a6ac201b761a2cf30bed995135a44690ac7616770f9f1d2e74c45e23080
4
- data.tar.gz: 3ab3c476d2b75e1697a0a1e08cdc6e0356c07e266b1839c74eea1c1c4d818023
3
+ metadata.gz: fc8ae231bde9d10834ea6a7fa2fb0cd50a12e351ba2296abb15b743975fad197
4
+ data.tar.gz: c52435deca659cd45a8ed647daccaf8b19e9d7d92374db06be69c63cbcc6b1e3
5
5
  SHA512:
6
- metadata.gz: b7a769b8963f67a9cc0d37e194dd1e9b936271cfbc7c88ee0f1fe72252926fc6184c01bd9abad0420231507bc99e54fc22b85916c9a0cb3cc1611c402e3436f3
7
- data.tar.gz: 5cad0685a4773c31ef10f78380c9e64b4ca56828f9ba9eae8b4471a1b7cdd5d827b6f33c27a4963926003b199bbffad3971c98269e87c7cb850db33ad342a352
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017-2020 Andrew Kane
1
+ Copyright (c) 2017-2021 Andrew Kane
2
2
 
3
3
  MIT License
4
4
 
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
- [![Build Status](https://travis-ci.org/ankane/authtrail.svg?branch=master)](https://travis-ci.org/ankane/authtrail)
9
+ [![Build Status](https://github.com/ankane/authtrail/workflows/build/badge.svg?branch=master)](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
- And run:
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 |info|
46
- info[:identity] == "capybara@example.org"
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 |info|
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
- IP geocoding is performed in a background job so it doesn’t slow down web requests. You can disable it entirely with:
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
- AuthTrail.geocode = false
114
+ gem 'geocoder'
86
115
  ```
87
116
 
88
- Set job queue for geocoding
117
+ And update `config/initializers/authtrail.rb`:
89
118
 
90
119
  ```ruby
91
- AuthTrail.job_queue = :low_priority
120
+ AuthTrail.geocode = true
92
121
  ```
93
122
 
94
- ### Geocoding Performance
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
- To avoid calls to a remote API, download the [GeoLite2 City database](https://dev.maxmind.com/geoip/geoip2/geolite2/) and configure Geocoder to use it.
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
- And create an initializer at `config/initializers/geocoder.rb` with:
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: Rails.root.join("lib", "GeoLite2-City.mmdb")
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
- ## Data Protection
166
+ ### Load Balancer Geocoding
116
167
 
117
- Protect the privacy of your users by encrypting fields that contain personal data, such as `identity` and `ip`. [Lockbox](https://github.com/ankane/lockbox) is great for this. Use [Blind Index](https://github.com/ankane/blind_index) so you can still query the fields.
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
- class LoginActivity < ApplicationRecord
121
- encrypts :identity, :ip
122
- blind_index :identity, :ip
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
  }
@@ -2,34 +2,29 @@ module AuthTrail
2
2
  module Manager
3
3
  class << self
4
4
  def after_set_user(user, auth, opts)
5
- # do not raise an exception for tracking
6
- AuthTrail.safely do
7
- request = ActionDispatch::Request.new(auth.env)
5
+ request = ActionDispatch::Request.new(auth.env)
8
6
 
9
- AuthTrail.track(
10
- strategy: detect_strategy(auth),
11
- scope: opts[:scope].to_s,
12
- identity: AuthTrail.identity_method.call(request, opts, user),
13
- success: true,
14
- request: request,
15
- user: user
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
- AuthTrail.safely do
22
- request = ActionDispatch::Request.new(env)
18
+ request = ActionDispatch::Request.new(env)
23
19
 
24
- AuthTrail.track(
25
- strategy: detect_strategy(env["warden"]),
26
- scope: opts[:scope].to_s,
27
- identity: AuthTrail.identity_method.call(request, opts, nil),
28
- success: false,
29
- request: request,
30
- failure_reason: opts[:message].to_s
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
@@ -1,3 +1,3 @@
1
1
  module AuthTrail
2
- VERSION = "0.2.1"
2
+ VERSION = "0.4.0"
3
3
  end
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 = true
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
- info = {
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
- info[:context] = "#{request.params[:controller]}##{request.params[:action]}"
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(info) }
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(info)
49
+ AuthTrail.track_method.call(data)
47
50
  else
48
51
  login_activity = LoginActivity.new
49
- info.each do |k, v|
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
- template "login_activity_model.rb", "app/models/login_activity.rb"
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
- t.string :identity
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
- t.string :ip
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
@@ -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.2.1
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: 2020-08-17 00:00:00.000000000 Z
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
- - !ruby/object:Gem::Dependency
56
- name: geocoder
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/login_activity_model.rb.tt
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.4'
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.1.2
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: []