authtrail 0.1.1 → 0.1.2
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 +5 -0
- data/README.md +70 -10
- data/app/jobs/auth_trail/geocode_job.rb +4 -4
- data/lib/auth_trail/manager.rb +3 -8
- data/lib/auth_trail/version.rb +1 -1
- data/lib/authtrail.rb +13 -2
- data/lib/generators/authtrail/templates/login_activities_migration.rb +7 -7
- metadata +7 -11
- data/.gitignore +0 -9
- data/Gemfile +0 -6
- data/Rakefile +0 -10
- data/authtrail.gemspec +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 686cc3a7c96d52e4cf5ac79c4268bdb0cd9b670978ac23668af4e8e0d4f11b08
|
4
|
+
data.tar.gz: 073fd3fefbe1cee4eca8daa2ee3fe13ea2aefd1c3f3d1d868daafa1fe40b7511
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b2afdc6ab493f2d8c3759d9d0d145b518f3447250889ce5013f737629d3bd89248ddb7413d8f75c2452a221ed950404355a9763814bdcfffe158bb89a7a2da7
|
7
|
+
data.tar.gz: ac21a072dd8328cb749a65aedd12188de9cc93501d5ad54bb4ada4b0a56e24bc1cc1116f8d32dfeb3c8a3d28a066258ffc05bbec655c94ec08a30c3ff7e1fee0
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -16,7 +16,7 @@ And run:
|
|
16
16
|
|
17
17
|
```sh
|
18
18
|
rails generate authtrail:install
|
19
|
-
|
19
|
+
rails db:migrate
|
20
20
|
```
|
21
21
|
|
22
22
|
## How It Works
|
@@ -35,40 +35,100 @@ A `LoginActivity` record is created every time a user tries to login. You can th
|
|
35
35
|
- `city`, `region`, and `country` - from IP
|
36
36
|
- `created_at` - time of event
|
37
37
|
|
38
|
-
IP geocoding is performed in a background job so it doesn’t slow down web requests. You can disable it entirely with:
|
39
|
-
|
40
|
-
```ruby
|
41
|
-
AuthTrail.geocode = false
|
42
|
-
```
|
43
|
-
|
44
38
|
## Features
|
45
39
|
|
46
40
|
Exclude certain attempts from tracking - useful if you run acceptance tests
|
47
41
|
|
48
42
|
```ruby
|
49
|
-
AuthTrail.exclude_method =
|
43
|
+
AuthTrail.exclude_method = lambda do |info|
|
50
44
|
info[:identity] == "capybara@example.org"
|
51
45
|
end
|
52
46
|
```
|
53
47
|
|
54
|
-
Write data somewhere other than the `login_activities` table
|
48
|
+
Write data somewhere other than the `login_activities` table
|
55
49
|
|
56
50
|
```ruby
|
57
|
-
AuthTrail.track_method =
|
51
|
+
AuthTrail.track_method = lambda do |info|
|
58
52
|
# code
|
59
53
|
end
|
60
54
|
```
|
61
55
|
|
56
|
+
Use a custom identity method [master]
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
AuthTrail.identity_method = lambda do |request, opts, user|
|
60
|
+
if user
|
61
|
+
user.email
|
62
|
+
else
|
63
|
+
request.params.dig(opts[:scope], :email)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
Associate login activity with your user model
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
class User < ApplicationRecord
|
72
|
+
has_many :login_activities, as: :user # use :user no matter what your model name
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
The `LoginActivity` model uses a [polymorphic association](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations) so it can be associated with different user models.
|
77
|
+
|
78
|
+
## Geocoding
|
79
|
+
|
80
|
+
IP geocoding is performed in a background job so it doesn’t slow down web requests. You can disable it entirely with:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
AuthTrail.geocode = false
|
84
|
+
```
|
85
|
+
|
62
86
|
Set job queue for geocoding
|
63
87
|
|
64
88
|
```ruby
|
65
89
|
AuthTrail::GeocodeJob.queue_as :low
|
66
90
|
```
|
67
91
|
|
92
|
+
### Geocoding Performance
|
93
|
+
|
94
|
+
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.
|
95
|
+
|
96
|
+
Add this line to your application’s Gemfile:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
gem 'maxminddb'
|
100
|
+
```
|
101
|
+
|
102
|
+
And create an initializer at `config/initializers/geocoder.rb` with:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
Geocoder.configure(
|
106
|
+
ip_lookup: :geoip2,
|
107
|
+
geoip2: {
|
108
|
+
file: Rails.root.join("lib", "GeoLite2-City.mmdb")
|
109
|
+
}
|
110
|
+
)
|
111
|
+
```
|
112
|
+
|
113
|
+
## Data Protection
|
114
|
+
|
115
|
+
Protect the privacy of your users by encrypting fields that contain personal information, such as `identity` and `ip`. [attr_encrypted](https://github.com/attr-encrypted/attr_encrypted) is great for this.
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
class LoginActivity < ApplicationRecord
|
119
|
+
attr_encrypted :identity, ...
|
120
|
+
attr_encrypted :ip, ...
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
You should also make it clear that you collect this information in your privacy policy.
|
125
|
+
|
68
126
|
## Other Notes
|
69
127
|
|
70
128
|
We recommend using this in addition to Devise’s `Lockable` module and [Rack::Attack](https://github.com/kickstarter/rack-attack).
|
71
129
|
|
130
|
+
Check out [Hardening Devise](https://github.com/ankane/shorts/blob/master/Hardening-Devise.md) and [Secure Rails](https://github.com/ankane/secure_rails) for more best practices.
|
131
|
+
|
72
132
|
Works with Rails 5+
|
73
133
|
|
74
134
|
## History
|
@@ -3,7 +3,7 @@ module AuthTrail
|
|
3
3
|
def perform(login_activity)
|
4
4
|
result =
|
5
5
|
begin
|
6
|
-
Geocoder.search(login_activity.ip).first
|
6
|
+
Geocoder.search(login_activity.ip).first
|
7
7
|
rescue => e
|
8
8
|
Rails.logger.info "Geocode failed: #{e.message}"
|
9
9
|
nil
|
@@ -11,9 +11,9 @@ module AuthTrail
|
|
11
11
|
|
12
12
|
if result
|
13
13
|
login_activity.update!(
|
14
|
-
city: result
|
15
|
-
region: result
|
16
|
-
country: result
|
14
|
+
city: result.try(:city).presence,
|
15
|
+
region: result.try(:state).presence,
|
16
|
+
country: result.try(:country).presence
|
17
17
|
)
|
18
18
|
end
|
19
19
|
end
|
data/lib/auth_trail/manager.rb
CHANGED
@@ -6,12 +6,10 @@ module AuthTrail
|
|
6
6
|
AuthTrail.safely do
|
7
7
|
request = ActionDispatch::Request.new(auth.env)
|
8
8
|
|
9
|
-
identity = user.try(:email)
|
10
|
-
|
11
9
|
AuthTrail.track(
|
12
10
|
strategy: detect_strategy(auth),
|
13
11
|
scope: opts[:scope].to_s,
|
14
|
-
identity:
|
12
|
+
identity: AuthTrail.identity_method.call(request, opts, user),
|
15
13
|
success: true,
|
16
14
|
request: request,
|
17
15
|
user: user
|
@@ -24,13 +22,10 @@ module AuthTrail
|
|
24
22
|
if opts[:message]
|
25
23
|
request = ActionDispatch::Request.new(env)
|
26
24
|
|
27
|
-
scope = opts[:scope]
|
28
|
-
identity = request.params[scope] && request.params[scope][:email] rescue nil
|
29
|
-
|
30
25
|
AuthTrail.track(
|
31
26
|
strategy: detect_strategy(env["warden"]),
|
32
|
-
scope: scope.to_s,
|
33
|
-
identity:
|
27
|
+
scope: opts[:scope].to_s,
|
28
|
+
identity: AuthTrail.identity_method.call(request, opts, nil),
|
34
29
|
success: false,
|
35
30
|
request: request,
|
36
31
|
failure_reason: opts[:message].to_s
|
data/lib/auth_trail/version.rb
CHANGED
data/lib/authtrail.rb
CHANGED
@@ -9,9 +9,17 @@ require "auth_trail/version"
|
|
9
9
|
|
10
10
|
module AuthTrail
|
11
11
|
class << self
|
12
|
-
attr_accessor :exclude_method, :geocode, :track_method
|
12
|
+
attr_accessor :exclude_method, :geocode, :track_method, :identity_method
|
13
13
|
end
|
14
14
|
self.geocode = true
|
15
|
+
self.identity_method = lambda do |request, opts, user|
|
16
|
+
if user
|
17
|
+
user.try(:email)
|
18
|
+
else
|
19
|
+
scope = opts[:scope]
|
20
|
+
request.params[scope] && request.params[scope][:email] rescue nil
|
21
|
+
end
|
22
|
+
end
|
15
23
|
|
16
24
|
def self.track(strategy:, scope:, identity:, success:, request:, user: nil, failure_reason: nil)
|
17
25
|
info = {
|
@@ -21,12 +29,15 @@ module AuthTrail
|
|
21
29
|
success: success,
|
22
30
|
failure_reason: failure_reason,
|
23
31
|
user: user,
|
24
|
-
context: "#{request.params[:controller]}##{request.params[:action]}",
|
25
32
|
ip: request.remote_ip,
|
26
33
|
user_agent: request.user_agent,
|
27
34
|
referrer: request.referrer
|
28
35
|
}
|
29
36
|
|
37
|
+
if request.params[:controller]
|
38
|
+
info[:context] = "#{request.params[:controller]}##{request.params[:action]}"
|
39
|
+
end
|
40
|
+
|
30
41
|
# if exclude_method throws an exception, default to not excluding
|
31
42
|
exclude = AuthTrail.exclude_method && AuthTrail.safely(default: false) { AuthTrail.exclude_method.call(info) }
|
32
43
|
|
@@ -1,19 +1,19 @@
|
|
1
1
|
class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def change
|
3
3
|
create_table :login_activities do |t|
|
4
|
-
t.
|
5
|
-
t.
|
4
|
+
t.string :scope
|
5
|
+
t.string :strategy
|
6
6
|
t.string :identity
|
7
7
|
t.boolean :success
|
8
|
-
t.
|
8
|
+
t.string :failure_reason
|
9
9
|
t.references :user, polymorphic: true
|
10
|
-
t.
|
10
|
+
t.string :context
|
11
11
|
t.string :ip
|
12
12
|
t.text :user_agent
|
13
13
|
t.text :referrer
|
14
|
-
t.
|
15
|
-
t.
|
16
|
-
t.
|
14
|
+
t.string :city
|
15
|
+
t.string :region
|
16
|
+
t.string :country
|
17
17
|
t.datetime :created_at
|
18
18
|
end
|
19
19
|
|
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.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -109,20 +109,15 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
description:
|
112
|
-
email:
|
113
|
-
- andrew@chartkick.com
|
112
|
+
email: andrew@chartkick.com
|
114
113
|
executables: []
|
115
114
|
extensions: []
|
116
115
|
extra_rdoc_files: []
|
117
116
|
files:
|
118
|
-
- ".gitignore"
|
119
117
|
- CHANGELOG.md
|
120
|
-
- Gemfile
|
121
118
|
- LICENSE.txt
|
122
119
|
- README.md
|
123
|
-
- Rakefile
|
124
120
|
- app/jobs/auth_trail/geocode_job.rb
|
125
|
-
- authtrail.gemspec
|
126
121
|
- lib/auth_trail/engine.rb
|
127
122
|
- lib/auth_trail/manager.rb
|
128
123
|
- lib/auth_trail/version.rb
|
@@ -131,7 +126,8 @@ files:
|
|
131
126
|
- lib/generators/authtrail/templates/login_activities_migration.rb
|
132
127
|
- lib/generators/authtrail/templates/login_activity_model.rb
|
133
128
|
homepage: https://github.com/ankane/authtrail
|
134
|
-
licenses:
|
129
|
+
licenses:
|
130
|
+
- MIT
|
135
131
|
metadata: {}
|
136
132
|
post_install_message:
|
137
133
|
rdoc_options: []
|
@@ -141,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
137
|
requirements:
|
142
138
|
- - ">="
|
143
139
|
- !ruby/object:Gem::Version
|
144
|
-
version: '
|
140
|
+
version: '2.2'
|
145
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
142
|
requirements:
|
147
143
|
- - ">="
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
data/authtrail.gemspec
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "auth_trail/version"
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "authtrail"
|
8
|
-
spec.version = AuthTrail::VERSION
|
9
|
-
spec.authors = ["Andrew Kane"]
|
10
|
-
spec.email = ["andrew@chartkick.com"]
|
11
|
-
|
12
|
-
spec.summary = "Track Devise login activity"
|
13
|
-
spec.homepage = "https://github.com/ankane/authtrail"
|
14
|
-
|
15
|
-
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
-
f.match(%r{^(test|spec|features)/})
|
17
|
-
end
|
18
|
-
spec.bindir = "exe"
|
19
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
-
spec.require_paths = ["lib"]
|
21
|
-
|
22
|
-
spec.add_dependency "railties", ">= 5"
|
23
|
-
spec.add_dependency "activerecord", ">= 5"
|
24
|
-
spec.add_dependency "warden"
|
25
|
-
spec.add_dependency "geocoder"
|
26
|
-
|
27
|
-
spec.add_development_dependency "bundler"
|
28
|
-
spec.add_development_dependency "rake"
|
29
|
-
spec.add_development_dependency "minitest"
|
30
|
-
end
|