authenticate 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +27 -0
  3. data/CHANGELOG.md +6 -0
  4. data/CONTRIBUTING.md +59 -0
  5. data/Gemfile +0 -1
  6. data/Gemfile.lock +11 -11
  7. data/README.md +37 -4
  8. data/Rakefile +2 -4
  9. data/app/controllers/authenticate/passwords_controller.rb +3 -3
  10. data/app/controllers/authenticate/sessions_controller.rb +4 -4
  11. data/app/controllers/authenticate/users_controller.rb +5 -7
  12. data/app/mailers/authenticate_mailer.rb +6 -8
  13. data/authenticate.gemspec +8 -9
  14. data/lib/authenticate.rb +1 -1
  15. data/lib/authenticate/callbacks/authenticatable.rb +1 -2
  16. data/lib/authenticate/callbacks/brute_force.rb +1 -3
  17. data/lib/authenticate/callbacks/lifetimed.rb +2 -1
  18. data/lib/authenticate/callbacks/timeoutable.rb +3 -2
  19. data/lib/authenticate/callbacks/trackable.rb +1 -1
  20. data/lib/authenticate/configuration.rb +11 -7
  21. data/lib/authenticate/controller.rb +32 -23
  22. data/lib/authenticate/crypto/bcrypt.rb +3 -3
  23. data/lib/authenticate/debug.rb +7 -7
  24. data/lib/authenticate/engine.rb +4 -2
  25. data/lib/authenticate/lifecycle.rb +12 -22
  26. data/lib/authenticate/login_status.rb +4 -3
  27. data/lib/authenticate/model/brute_force.rb +4 -6
  28. data/lib/authenticate/model/db_password.rb +5 -14
  29. data/lib/authenticate/model/email.rb +7 -9
  30. data/lib/authenticate/model/lifetimed.rb +1 -2
  31. data/lib/authenticate/model/password_reset.rb +1 -3
  32. data/lib/authenticate/model/timeoutable.rb +14 -15
  33. data/lib/authenticate/model/trackable.rb +5 -4
  34. data/lib/authenticate/model/username.rb +3 -5
  35. data/lib/authenticate/modules.rb +37 -39
  36. data/lib/authenticate/session.rb +15 -23
  37. data/lib/authenticate/token.rb +3 -0
  38. data/lib/authenticate/user.rb +2 -6
  39. data/lib/authenticate/version.rb +1 -1
  40. data/lib/generators/authenticate/controllers/controllers_generator.rb +1 -2
  41. data/lib/generators/authenticate/helpers.rb +1 -2
  42. data/lib/generators/authenticate/install/install_generator.rb +31 -32
  43. data/lib/generators/authenticate/install/templates/authenticate.rb +0 -1
  44. data/lib/generators/authenticate/routes/routes_generator.rb +1 -2
  45. data/lib/generators/authenticate/views/USAGE +3 -2
  46. data/lib/generators/authenticate/views/views_generator.rb +1 -2
  47. data/spec/controllers/passwords_controller_spec.rb +5 -7
  48. data/spec/controllers/secured_controller_spec.rb +6 -6
  49. data/spec/controllers/sessions_controller_spec.rb +2 -2
  50. data/spec/controllers/users_controller_spec.rb +4 -4
  51. data/spec/features/brute_force_spec.rb +0 -2
  52. data/spec/features/max_session_lifetime_spec.rb +0 -1
  53. data/spec/features/password_reset_spec.rb +10 -19
  54. data/spec/features/password_update_spec.rb +0 -2
  55. data/spec/features/sign_out_spec.rb +0 -1
  56. data/spec/features/sign_up_spec.rb +0 -1
  57. data/spec/features/timeoutable_spec.rb +0 -1
  58. data/spec/model/brute_force_spec.rb +2 -3
  59. data/spec/model/configuration_spec.rb +2 -7
  60. data/spec/model/db_password_spec.rb +4 -6
  61. data/spec/model/email_spec.rb +1 -3
  62. data/spec/model/lifetimed_spec.rb +0 -3
  63. data/spec/model/modules_spec.rb +22 -0
  64. data/spec/model/password_reset_spec.rb +3 -10
  65. data/spec/model/session_spec.rb +4 -5
  66. data/spec/model/timeoutable_spec.rb +0 -1
  67. data/spec/model/token_spec.rb +1 -3
  68. data/spec/model/trackable_spec.rb +1 -2
  69. data/spec/model/user_spec.rb +0 -1
  70. data/spec/orm/active_record.rb +1 -1
  71. data/spec/spec_helper.rb +3 -11
  72. data/spec/support/controllers/controller_helpers.rb +1 -2
  73. data/spec/support/features/feature_helpers.rb +2 -4
  74. metadata +29 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f9f51572691eba2fb35eb46618d2235898149f5
4
- data.tar.gz: 69fb6dcf45f900f7433f43e11feb8b69ec966bba
3
+ metadata.gz: 880f3ddf3bf73620d2ad00b9fa97961e0b9572cb
4
+ data.tar.gz: 6f8552c11692b6ed41b86bc11d9ad325c54a3b63
5
5
  SHA512:
6
- metadata.gz: 195b410e9982a6a410bd53abf79ff90aba67d7ab9eca23f7fa00ab278aa28de5a592577783820d15e2bd3a2f752338c8bf2b4c695be515dd09efa2753548eac3
7
- data.tar.gz: 0a06b879d4f468e62bf22037d94338a384987e5e1bc4ee72752c038700f87dfb5214d50436e5bd2a69a713fc419e3b5377ea14b7a726ec988f107a32b5d27df9
6
+ metadata.gz: f8ed33e95016c51092e3b082d51d04c8ab0787cf1f4d98d03a3aafe9f70aaef320beb5acc2653932053970c55c14db0b2d0cacd6deb7f6d26ec882564b113ed6
7
+ data.tar.gz: 401d92cb7b48b1ce32c961c42901ff20ae586648d1e266b9d0f954a76fb6449a057d12a34fdb52a6e5e9f590297f39cf7a9a93d0b1eca340f6adfb1a57192cba
data/.rubocop.yml ADDED
@@ -0,0 +1,27 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bin/rails'
4
+ - 'spec/dummy/**/*'
5
+ - 'lib/generators/authenticate/install/templates/db/migrate/**/*'
6
+ - 'lib/generators/authenticate/routes/templates/routes.rb'
7
+
8
+ Metrics/LineLength:
9
+ Max: 120
10
+
11
+ Documentation:
12
+ Exclude:
13
+ - 'lib/generators/**/*'
14
+
15
+ Metrics/MethodLength:
16
+ Max: 16
17
+
18
+ Metrics/ClassLength:
19
+ Exclude:
20
+ - 'lib/generators/authenticate/install/install_generator.rb'
21
+
22
+ Metrics/AbcSize:
23
+ Max: 18
24
+
25
+ Lint/IneffectiveAccessModifier:
26
+ Exclude:
27
+ - 'lib/generators/authenticate/**/*'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Authenticate Changelog
2
2
 
3
+ ## [0.3.2] - April 28, 2016
4
+
5
+ Error now raised if User model is missing required attributes.
6
+ All code now conforms to a rubocode profile.
7
+
8
+
3
9
  ## [0.3.1] - March 10, 2016
4
10
 
5
11
  User controller now allows arbitrary parameters without having to explicitly declare
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,59 @@
1
+ # Contributing
2
+
3
+ I love pull requests. I'm trying to keep it as easy as possible to contribute changes. There
4
+ are just a couple of guidelines to follow to help me stay on top of things.
5
+
6
+
7
+ ## Let's talk
8
+
9
+ Whether you're fixing a bug or adding a feature, feel free to talk to me first on
10
+ [twitter](https://twitter.com/JustinTomich). We can make sure the change isn't already
11
+ underway somewhere else.
12
+
13
+
14
+ ## Getting started
15
+
16
+ * Make sure you have a [GitHub account](https://github.com/signup/free)
17
+ * Open a [New Issue](https://github.com/tomichj/authenticate/issues) on github for your change,
18
+ assuming one does not already exist. If one already exists, join the conversation.
19
+ * Fork the repository on GitHub.
20
+
21
+ ## Setup
22
+
23
+ Clone the repo:
24
+
25
+ `git clone https://github.com/<your-username>/authenticate`
26
+
27
+ CD into your clone and run bundler install:
28
+
29
+ `cd authenticate && bundle install`
30
+
31
+ Make sure the tests pass:
32
+
33
+ `rake`
34
+
35
+ Make your change. Add tests for your change. Make sure the tests pass:
36
+
37
+ `rake`
38
+
39
+ I use `rubocop` to maintain ruby coding style. Install and run it like so:
40
+
41
+ ```sh
42
+ gem install rubocop
43
+ rubocop
44
+ ```
45
+
46
+ Once you resolve any issues rubocop finds, you're ready to go. Push your fork and
47
+ [submit a pull request](https://github.com/tomichj/authenticate/compare/).
48
+
49
+ The ball is now in my court. I'll try to comment on your pull request within a couple of business days
50
+ (hopefully the same day).
51
+
52
+ Things you can do to increase the speed of acceptance:
53
+
54
+ * talk to me ahead of time
55
+ * write tests
56
+ * follow the [ruby style guide](https://github.com/bbatsov/ruby-style-guide)
57
+ * write a good [commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
58
+
59
+ Thanks very much!
data/Gemfile CHANGED
@@ -15,4 +15,3 @@ gemspec
15
15
 
16
16
  # To use a debugger
17
17
  # gem 'byebug', group: [:development, :test]
18
-
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- authenticate (0.3.0)
5
- bcrypt
4
+ authenticate (0.3.1)
5
+ bcrypt (~> 3.1)
6
6
  email_validator (~> 1.6)
7
7
  rails (>= 4.0, < 5.1)
8
8
 
@@ -56,7 +56,7 @@ GEM
56
56
  rack-test (>= 0.5.4)
57
57
  xpath (~> 2.0)
58
58
  coderay (1.1.0)
59
- concurrent-ruby (1.0.0)
59
+ concurrent-ruby (1.0.1)
60
60
  database_cleaner (1.5.1)
61
61
  diff-lcs (1.2.5)
62
62
  email_validator (1.6.0)
@@ -132,7 +132,7 @@ GEM
132
132
  sprockets (3.5.2)
133
133
  concurrent-ruby (~> 1.0)
134
134
  rack (> 1, < 3)
135
- sprockets-rails (3.0.1)
135
+ sprockets-rails (3.0.4)
136
136
  actionpack (>= 4.0)
137
137
  activesupport (>= 4.0)
138
138
  sprockets (>= 3.0.0)
@@ -150,14 +150,14 @@ PLATFORMS
150
150
 
151
151
  DEPENDENCIES
152
152
  authenticate!
153
- capybara (~> 2.6.2)
154
- database_cleaner (~> 1.5.1)
155
- factory_girl
156
- pry
157
- rspec-rails (~> 3.1.0)
153
+ capybara (~> 2.6)
154
+ database_cleaner (~> 1.5)
155
+ factory_girl (~> 4.4)
156
+ pry (~> 0.10)
157
+ rspec-rails (~> 3.1)
158
158
  shoulda-matchers (~> 2.8)
159
- sqlite3
160
- timecop (~> 0.8.0)
159
+ sqlite3 (~> 1.3)
160
+ timecop (~> 0.8)
161
161
 
162
162
  BUNDLED WITH
163
163
  1.11.2
data/README.md CHANGED
@@ -7,11 +7,13 @@ open to significant modification.
7
7
 
8
8
  Authenticate is inspired by, and draws from, Devise, Warden, Authlogic, Clearance, Sorcery, and restful_authentication.
9
9
 
10
- Please use [GitHub Issues] to report bugs.
10
+ Please use [GitHub Issues] to report bugs. You can contact me directly on twitter
11
+ [@JustinTomich](https://twitter.com/justintomich).
11
12
 
12
13
  [GitHub Issues]: https://github.com/tomichj/authenticate/issues
13
14
 
14
- ![Build status](https://travis-ci.org/tomichj/authenticate.svg?branch=master) ![Code Climate](https://codeclimate.com/github/tomichj/authenticate/badges/gpa.svg)
15
+ [![Gem Version](https://badge.fury.io/rb/authenticate.svg)](https://badge.fury.io/rb/authenticate) ![Build status](https://travis-ci.org/tomichj/authenticate.svg?branch=master) ![Code Climate](https://codeclimate.com/github/tomichj/authenticate/badges/gpa.svg)
16
+
15
17
 
16
18
  ## Philosophy
17
19
 
@@ -59,7 +61,7 @@ The generator does the following:
59
61
 
60
62
  * Insert `include Authenticate::User` into your `User` model. If you don't have a User model, one is created.
61
63
  * Insert `include Authenticate::Controller` into your `ApplicationController`
62
- * Add an initializer at `config/intializers/authenticate.rb`.
64
+ * Add an initializer at `config/initializers/authenticate.rb`.
63
65
  * Create migrations to create a users table or add columns to your existing table.
64
66
 
65
67
 
@@ -213,7 +215,38 @@ If the customization at the views level is not enough, you can customize each co
213
215
  authenticate mailer. See [app/controllers](/app/controllers) for the default controllers, and
214
216
  [app/mailers](/app/mailers) for the default mailer.
215
217
 
216
- You can use the Authenticate controller generator to copy the default controllers and mailer into your application:
218
+ To override an authenticate controller, subclass an authenticate controller and update your routes to point to it.
219
+
220
+ For example, to customize `Authenticate::SessionController`:
221
+
222
+ * subclass the controller:
223
+
224
+ ```ruby
225
+ class SessionsController < Authenticate::SessionController
226
+ # render sign in screen
227
+ def new
228
+ # ...
229
+ end
230
+ ...
231
+ end
232
+ ```
233
+
234
+ * update your routes to use your new controller.
235
+
236
+ Start by dumping a copy of authenticate routes to your `config/routes.rb`:
237
+
238
+ ```sh
239
+ $ rails generate authenticate:routes
240
+ ```
241
+
242
+ Now update `config/routes.rb` to point to your new controller:
243
+ ```ruby
244
+ resource :session, controller: 'sessions', only: [:create, :new, :destroy]
245
+ ...
246
+ ```
247
+
248
+ You can also use the Authenticate controller generator to copy the default controllers and mailer into
249
+ your application:
217
250
 
218
251
  ```sh
219
252
  $ rails generate authenticate:controllers
data/Rakefile CHANGED
@@ -1,6 +1,4 @@
1
- require "bundler/gem_tasks"
2
-
1
+ require 'bundler/gem_tasks'
3
2
  require 'rspec/core/rake_task'
4
3
  RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
4
+ task default: :spec
@@ -14,7 +14,7 @@ class Authenticate::PasswordsController < Authenticate::AuthenticateController
14
14
  #
15
15
  # POST /users/password
16
16
  def create
17
- if user = find_user_for_create
17
+ if (user = find_user_for_create)
18
18
  user.forgot_password!
19
19
  deliver_email(user)
20
20
  end
@@ -41,11 +41,11 @@ class Authenticate::PasswordsController < Authenticate::AuthenticateController
41
41
 
42
42
  if !@user.reset_password_period_valid?
43
43
  redirect_to sign_in_path, notice: flash_failure_token_expired
44
- elsif @user.update_password password_reset_params
44
+ elsif @user.update_password password_reset_params # password changed, log user back in!
45
45
  login @user
46
46
  redirect_to url_after_update, notice: flash_success_password_changed
47
47
  else
48
- # failed to update password for some reason
48
+ # failed to update password for some reason, perhaps password was too short or otherwise sucked.
49
49
  flash.now[:notice] = flash_failure_after_update
50
50
  render template: 'passwords/edit'
51
51
  end
@@ -1,8 +1,10 @@
1
+ #
2
+ # Allow authenticate users to log in and log out.
3
+ #
1
4
  class Authenticate::SessionsController < Authenticate::AuthenticateController
2
5
  before_action :redirect_signed_in_users, only: [:new]
3
6
  skip_before_action :require_authentication, only: [:create, :new, :destroy], raise: false
4
7
 
5
-
6
8
  def new
7
9
  render template: 'sessions/new'
8
10
  end
@@ -27,9 +29,7 @@ class Authenticate::SessionsController < Authenticate::AuthenticateController
27
29
  private
28
30
 
29
31
  def redirect_signed_in_users
30
- if authenticated?
31
- redirect_to url_for_signed_in_users
32
- end
32
+ redirect_to url_for_signed_in_users if authenticated?
33
33
  end
34
34
 
35
35
  def url_after_create
@@ -1,3 +1,6 @@
1
+ #
2
+ # Controller to reate new users.
3
+ #
1
4
  class Authenticate::UsersController < Authenticate::AuthenticateController
2
5
  before_action :redirect_signed_in_users, only: [:create, :new]
3
6
  skip_before_action :require_authentication, only: [:create, :new], raise: false
@@ -21,16 +24,13 @@ class Authenticate::UsersController < Authenticate::AuthenticateController
21
24
  private
22
25
 
23
26
  def redirect_signed_in_users
24
- if authenticated?
25
- redirect_to Authenticate.configuration.redirect_url
26
- end
27
+ redirect_to Authenticate.configuration.redirect_url if authenticated?
27
28
  end
28
29
 
29
30
  def url_after_create
30
31
  Authenticate.configuration.redirect_url
31
32
  end
32
33
 
33
-
34
34
  def user_from_params
35
35
  email = user_params.delete(:email)
36
36
  password = user_params.delete(:password)
@@ -42,8 +42,6 @@ class Authenticate::UsersController < Authenticate::AuthenticateController
42
42
  end
43
43
 
44
44
  def user_params
45
- params[Authenticate.configuration.user_model_param_key] || Hash.new
45
+ params[Authenticate.configuration.user_model_param_key] || {}
46
46
  end
47
-
48
-
49
47
  end
@@ -1,13 +1,11 @@
1
+ # Authenticate mailer.
2
+ #
3
+ # Handles password change requests.
1
4
  class AuthenticateMailer < ActionMailer::Base
2
5
  def change_password(user)
3
6
  @user = user
4
- mail(
5
- from: Authenticate.configuration.mailer_sender,
6
- to: @user.email,
7
- subject: I18n.t(
8
- :change_password,
9
- scope: [:authenticate, :models, :authenticate_mailer]
10
- ),
11
- )
7
+ mail from: Authenticate.configuration.mailer_sender,
8
+ to: @user.email,
9
+ subject: I18n.t(:change_password, scope: [:authenticate, :models, :authenticate_mailer])
12
10
  end
13
11
  end
data/authenticate.gemspec CHANGED
@@ -21,19 +21,18 @@ Gem::Specification.new do |s|
21
21
  s.extra_rdoc_files = %w(LICENSE README.md CHANGELOG.md)
22
22
  s.rdoc_options = ['--charset=UTF-8']
23
23
 
24
- s.add_dependency 'bcrypt'
24
+ s.add_dependency 'bcrypt', '~> 3.1'
25
25
  s.add_dependency 'email_validator', '~> 1.6'
26
26
  s.add_dependency 'rails', '>= 4.0', '< 5.1'
27
27
 
28
- # s.add_development_dependency 'factory_girl_rails', '~> 4.4.1'
29
- s.add_development_dependency 'factory_girl'
30
- s.add_development_dependency 'rspec-rails', '~> 3.1.0'
31
- s.add_development_dependency 'pry'
32
- s.add_development_dependency 'sqlite3'
28
+ s.add_development_dependency 'factory_girl', '~> 4.4'
29
+ s.add_development_dependency 'rspec-rails', '~> 3.1'
30
+ s.add_development_dependency 'pry', '~> 0.10'
31
+ s.add_development_dependency 'sqlite3', '~> 1.3'
33
32
  s.add_development_dependency 'shoulda-matchers', '~> 2.8'
34
- s.add_development_dependency 'capybara', '~> 2.6.2'
35
- s.add_development_dependency 'database_cleaner', '~> 1.5.1'
36
- s.add_development_dependency 'timecop', '~> 0.8.0'
33
+ s.add_development_dependency 'capybara', '~> 2.6'
34
+ s.add_development_dependency 'database_cleaner', '~> 1.5'
35
+ s.add_development_dependency 'timecop', '~> 0.8'
37
36
 
38
37
  s.required_ruby_version = Gem::Requirement.new('>= 2.0')
39
38
  end
data/lib/authenticate.rb CHANGED
@@ -7,6 +7,6 @@ require 'authenticate/user'
7
7
  require 'authenticate/engine'
8
8
  require 'authenticate/modules'
9
9
 
10
+ # Top level module of authenticate gem.
10
11
  module Authenticate
11
- # Your code goes here...
12
12
  end
@@ -1,7 +1,6 @@
1
1
  # Callback to check that the session has been authenticated.
2
2
  #
3
-
4
3
  # If user failed to authenticate, toss them out.
5
- Authenticate.lifecycle.after_authentication name: 'authenticatable' do |user, session, opts|
4
+ Authenticate.lifecycle.after_authentication name: 'authenticatable' do |_user, session, _opts|
6
5
  throw(:failure, I18n.t('callbacks.authenticatable.failure')) unless session && session.authenticated?
7
6
  end
@@ -1,8 +1,7 @@
1
1
  # Prevents a locked user from logging in, and unlocks users that expired their lock time.
2
2
  # Runs as a hook after authentication.
3
- Authenticate.lifecycle.prepend_after_authentication name: 'brute force protection' do |user, session, options|
3
+ Authenticate.lifecycle.prepend_after_authentication name: 'brute force protection' do |user, session, _options|
4
4
  include ActionView::Helpers::DateHelper
5
-
6
5
  unless session.authenticated? || Authenticate.configuration.max_consecutive_bad_logins_allowed.nil?
7
6
  user_credentials = User.credentials(session.request.params)
8
7
  user ||= User.find_by_credentials(user_credentials)
@@ -23,5 +22,4 @@ Authenticate.lifecycle.prepend_after_authentication name: 'brute force protectio
23
22
  remaining = time_ago_in_words(user.lock_expires_at)
24
23
  throw(:failure, I18n.t('callbacks.brute_force.failure', time_remaining: remaining.to_s))
25
24
  end
26
-
27
25
  end
@@ -1,5 +1,6 @@
1
1
  # Catch sessions that have been live for too long and kill them, forcing the user to reauthenticate.
2
- Authenticate.lifecycle.after_set_user name: 'lifetimed after set_user', except: :authentication do |user, session, options|
2
+ Authenticate.lifecycle.after_set_user name: 'lifetimed after set_user',
3
+ except: :authentication do |user, _session, _options|
3
4
  if user && user.respond_to?(:max_session_lifetime_exceeded?)
4
5
  throw(:failure, I18n.t('callbacks.lifetimed.failure')) if user.max_session_lifetime_exceeded?
5
6
  end
@@ -1,5 +1,5 @@
1
1
  # Update last_access_at on every authentication
2
- Authenticate.lifecycle.after_authentication name: 'timeoutable after authentication' do |user, session, options|
2
+ Authenticate.lifecycle.after_authentication name: 'timeoutable after authentication' do |user, _session, _options|
3
3
  if user && user.respond_to?(:last_access_at)
4
4
  user.last_access_at = Time.now.utc
5
5
  user.save!
@@ -7,7 +7,8 @@ Authenticate.lifecycle.after_authentication name: 'timeoutable after authenticat
7
7
  end
8
8
 
9
9
  # Fail users that have timed out. Otherwise update last_access_at.
10
- Authenticate.lifecycle.after_set_user name: 'timeoutable after set_user', except: :authentication do |user, session, options|
10
+ Authenticate.lifecycle.after_set_user name: 'timeoutable after set_user',
11
+ except: :authentication do |user, _session, _options|
11
12
  if user && user.respond_to?(:timedout?)
12
13
  throw(:failure, I18n.t('callbacks.timeoutable.failure')) if user.timedout?
13
14
  user.last_access_at = Time.now.utc
@@ -1,5 +1,5 @@
1
1
  # Update all standard tracked stats at each authentication.
2
- Authenticate.lifecycle.after_authentication name: 'trackable' do |user, session, options|
2
+ Authenticate.lifecycle.after_authentication name: 'trackable' do |user, session, _options|
3
3
  if user && user.respond_to?(:update_tracked_fields!)
4
4
  user.update_tracked_fields!(session.request)
5
5
  end