clearance 1.17.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of clearance might be problematic. Click here for more details.

Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -14
  3. data/Appraisals +11 -3
  4. data/Gemfile +3 -6
  5. data/Gemfile.lock +91 -87
  6. data/NEWS.md +233 -15
  7. data/README.md +54 -28
  8. data/app/controllers/clearance/base_controller.rb +8 -1
  9. data/app/controllers/clearance/passwords_controller.rb +35 -45
  10. data/app/controllers/clearance/sessions_controller.rb +3 -18
  11. data/app/controllers/clearance/users_controller.rb +2 -17
  12. data/clearance.gemspec +15 -9
  13. data/config/locales/clearance.en.yml +1 -0
  14. data/config/routes.rb +1 -1
  15. data/gemfiles/rails_5.0.gemfile +5 -6
  16. data/gemfiles/rails_5.1.gemfile +5 -6
  17. data/gemfiles/rails_5.2.gemfile +5 -6
  18. data/gemfiles/{rails_4.2.gemfile → rails_6.0.gemfile} +7 -7
  19. data/lib/clearance.rb +0 -8
  20. data/lib/clearance/authentication.rb +1 -9
  21. data/lib/clearance/authorization.rb +2 -11
  22. data/lib/clearance/back_door.rb +1 -1
  23. data/lib/clearance/configuration.rb +30 -19
  24. data/lib/clearance/password_strategies.rb +5 -4
  25. data/lib/clearance/password_strategies/argon2.rb +23 -0
  26. data/lib/clearance/password_strategies/bcrypt.rb +17 -11
  27. data/lib/clearance/rack_session.rb +5 -1
  28. data/lib/clearance/session.rb +40 -12
  29. data/lib/clearance/testing/deny_access_matcher.rb +10 -20
  30. data/lib/clearance/user.rb +3 -24
  31. data/lib/clearance/version.rb +1 -1
  32. data/lib/generators/clearance/install/install_generator.rb +12 -12
  33. data/lib/generators/clearance/install/templates/README +10 -4
  34. data/lib/generators/clearance/install/templates/db/migrate/add_clearance_to_users.rb.erb +1 -1
  35. data/lib/generators/clearance/install/templates/db/migrate/create_users.rb.erb +1 -1
  36. data/lib/generators/clearance/routes/templates/routes.rb +1 -1
  37. data/spec/acceptance/clearance_installation_spec.rb +0 -4
  38. data/spec/app_templates/app/models/user.rb +1 -1
  39. data/spec/app_templates/testapp/app/controllers/home_controller.rb +1 -5
  40. data/spec/app_templates/testapp/app/views/layouts/application.html.erb +24 -0
  41. data/spec/clearance/back_door_spec.rb +12 -6
  42. data/spec/clearance/rack_session_spec.rb +2 -0
  43. data/spec/clearance/session_spec.rb +91 -47
  44. data/spec/clearance/testing/deny_access_matcher_spec.rb +32 -0
  45. data/spec/configuration_spec.rb +46 -15
  46. data/spec/controllers/apis_controller_spec.rb +1 -5
  47. data/spec/controllers/forgeries_controller_spec.rb +1 -5
  48. data/spec/controllers/passwords_controller_spec.rb +41 -5
  49. data/spec/controllers/permissions_controller_spec.rb +3 -7
  50. data/spec/controllers/sessions_controller_spec.rb +1 -1
  51. data/spec/dummy/app/controllers/application_controller.rb +1 -5
  52. data/spec/dummy/application.rb +7 -3
  53. data/spec/generators/clearance/install/install_generator_spec.rb +33 -15
  54. data/spec/generators/clearance/views/views_generator_spec.rb +0 -2
  55. data/spec/models/user_spec.rb +5 -5
  56. data/spec/password_strategies/argon2_spec.rb +79 -0
  57. data/spec/password_strategies/bcrypt_spec.rb +18 -1
  58. data/spec/requests/authentication_cookie_spec.rb +55 -0
  59. data/spec/requests/token_expiration_spec.rb +5 -0
  60. data/spec/spec_helper.rb +4 -7
  61. data/spec/support/generator_spec_helpers.rb +1 -9
  62. metadata +51 -33
  63. data/app/views/layouts/application.html.erb +0 -23
  64. data/lib/clearance/password_strategies/bcrypt_migration_from_sha1.rb +0 -77
  65. data/lib/clearance/password_strategies/blowfish.rb +0 -61
  66. data/lib/clearance/password_strategies/sha1.rb +0 -59
  67. data/lib/clearance/testing.rb +0 -11
  68. data/lib/clearance/testing/helpers.rb +0 -15
  69. data/spec/app_templates/app/models/rails5/user.rb +0 -5
  70. data/spec/password_strategies/bcrypt_migration_from_sha1_spec.rb +0 -122
  71. data/spec/password_strategies/blowfish_spec.rb +0 -61
  72. data/spec/password_strategies/sha1_spec.rb +0 -59
  73. data/spec/support/environment.rb +0 -12
  74. data/spec/support/http_method_shim.rb +0 -25
data/README.md CHANGED
@@ -19,7 +19,7 @@ monitored by contributors.
19
19
 
20
20
  ## Getting Started
21
21
 
22
- Clearance is a Rails engine tested against Rails `>= 3.2` and Ruby `>= 1.9.3`.
22
+ Clearance is a Rails engine tested against Rails `>= 5.0` and Ruby `>= 2.4.0`.
23
23
 
24
24
  You can add it to your Gemfile with:
25
25
 
@@ -31,8 +31,8 @@ Run the bundle command to install it.
31
31
 
32
32
  After you install Clearance, you need to run the generator:
33
33
 
34
- ```sh
35
- $ rails generate clearance:install
34
+ ```shell
35
+ rails generate clearance:install
36
36
  ```
37
37
 
38
38
  The Clearance install generator:
@@ -59,17 +59,14 @@ Clearance.configure do |config|
59
59
  config.mailer_sender = "reply@example.com"
60
60
  config.password_strategy = Clearance::PasswordStrategies::BCrypt
61
61
  config.redirect_url = "/"
62
- config.rotate_csrf_on_sign_in = false
62
+ config.rotate_csrf_on_sign_in = true
63
63
  config.secure_cookie = false
64
64
  config.sign_in_guards = []
65
- config.user_model = User
65
+ config.user_model = "User"
66
+ config.parent_controller = "ApplicationController"
66
67
  end
67
68
  ```
68
69
 
69
- The install generator will set `rotate_csrf_on_sign_in` to `true`, so new
70
- installations will get this behavior from the start. This helps avoid session
71
- fixation attacks, and will become the default in Clearance 2.0.
72
-
73
70
  ## Use
74
71
 
75
72
  ### Access Control
@@ -130,6 +127,18 @@ Clearance.configure do |config|
130
127
  end
131
128
  ```
132
129
 
130
+ ### Multiple Domain Support
131
+
132
+ You can support multiple domains, or other special domain configurations by
133
+ optionally setting `cookie_domain` as a callable object. The first argument
134
+ passed to the method is an ActionDispatch::Request object.
135
+
136
+ ```ruby
137
+ Clearance.configure do |config|
138
+ config.cookie_domain = lambda { |request| request.host }
139
+ end
140
+ ```
141
+
133
142
  ### Integrating with Rack Applications
134
143
 
135
144
  Clearance adds its session to the Rack environment hash so middleware and other
@@ -161,15 +170,16 @@ As of Clearance 1.5 it is recommended that you disable Clearance routes and take
161
170
  full control over routing and URL design. This ensures that your app's URL design
162
171
  won't be affected if the gem's routes and URL design are changed.
163
172
 
164
- To disable the routes, change the `routes` configuration option to false:
173
+ To disable the routes, change the `routes` configuration option to false:
165
174
 
166
175
  ```ruby
167
176
  Clearance.configure do |config|
168
177
  config.routes = false
169
178
  end
170
179
  ```
171
- You can optionally run `rails generate clearance:routes` to dump a copy of the default routes into your
172
- application for modification.
180
+
181
+ You can optionally run `rails generate clearance:routes` to dump a copy of the
182
+ default routes into your application for modification.
173
183
 
174
184
  ### Controllers
175
185
 
@@ -188,22 +198,29 @@ class UsersController < Clearance::UsersController
188
198
 
189
199
  ### Redirects
190
200
 
191
- All of these controller methods redirect to
201
+ The post-action redirects in Clearance are simple methods which can be
202
+ overridden one by one, or configured globally.
203
+
204
+ These "success" methods are called for signed in users, and redirect to
192
205
  `Clearance.configuration.redirect_url` (which is `/` by default):
193
206
 
194
- ```
195
- passwords#url_after_update
196
- sessions#url_after_create
197
- sessions#url_for_signed_in_users
198
- users#url_after_create
199
- application#url_after_denied_access_when_signed_in
200
- ```
207
+ - `passwords#url_after_update`
208
+ - `sessions#url_after_create`
209
+ - `sessions#url_for_signed_in_users`
210
+ - `users#url_after_create`
211
+ - `application#url_after_denied_access_when_signed_in`
201
212
 
202
213
  To override them all at once, change the global configuration of `redirect_url`.
203
- To change individual URLs, override the appropriate method.
214
+ To change individual URLs, override the appropriate method in your subclassed
215
+ controller.
204
216
 
205
- `application#url_after_denied_access_when_signed_out` defaults to `sign_in_url`.
206
- Override this method to change this.
217
+ These "failure" methods are called for signed out sessions:
218
+
219
+ - `application#url_after_denied_access_when_signed_out`
220
+ - `sessions#url_after_destroy`
221
+
222
+ They both default to `sign_in_url`. Override this method to change both of their
223
+ behavior, or override them individually to just change one.
207
224
 
208
225
  ### Views
209
226
 
@@ -226,7 +243,7 @@ You can use the Clearance views generator to copy the default views to your
226
243
  application for modification.
227
244
 
228
245
  ```shell
229
- $ rails generate clearance:views
246
+ rails generate clearance:views
230
247
  ```
231
248
 
232
249
  ### Layouts
@@ -245,8 +262,10 @@ end
245
262
 
246
263
  ### Translations
247
264
 
248
- All flash messages and email subject lines are stored in [i18n translations](http://guides.rubyonrails.org/i18n.html). Override them like any other
249
- translation.
265
+ All flash messages and email subject lines are stored in [i18n translations].
266
+ Override them like any other translation.
267
+
268
+ [i18n translations]: http://guides.rubyonrails.org/i18n.html
250
269
 
251
270
  See [config/locales/clearance.en.yml](/config/locales/clearance.en.yml) for the
252
271
  default behavior.
@@ -259,6 +278,13 @@ for access to additional, user-contributed translations.
259
278
  See [lib/clearance/user.rb](/lib/clearance/user.rb) for the default behavior.
260
279
  You can override those methods as needed.
261
280
 
281
+ Note that there are some model-level validations (see above link for detail)
282
+ which the `Clearance::User` module will add to the configured model class and
283
+ which may conflict with or duplicate already present validations on the `email`
284
+ and `password` attributes. Over-riding the `email_optional?` or
285
+ `skip_password_validation?` methods to return `true` will disable those
286
+ validations from being added.
287
+
262
288
  ### Deliver Email in Background Job
263
289
 
264
290
  Clearance has a password reset mailer. If you are using Rails 4.2 and Clearance
@@ -307,7 +333,7 @@ Here's an example custom guard to handle email confirmation:
307
333
 
308
334
  ```ruby
309
335
  Clearance.configure do |config|
310
- config.sign_in_guards = [EmailConfirmationGuard]
336
+ config.sign_in_guards = ["EmailConfirmationGuard"]
311
337
  end
312
338
  ```
313
339
 
@@ -377,7 +403,7 @@ feature specs, will also require `factory_bot_rails`.
377
403
  To Generate the clearance specs, run:
378
404
 
379
405
  ```shell
380
- $ rails generate clearance:specs
406
+ rails generate clearance:specs
381
407
  ```
382
408
 
383
409
  ### Controller Test Helpers
@@ -1,2 +1,9 @@
1
- class Clearance::BaseController < ApplicationController
1
+ module Clearance
2
+ # Top-level base class that all Clearance controllers inherit from.
3
+ # Inherits from `ApplicationController` by default and can be overridden by
4
+ # setting a new value with {Configuration#parent_controller=}.
5
+ # @!parse
6
+ # class BaseController < ApplicationController; end
7
+ class BaseController < Clearance.configuration.parent_controller
8
+ end
2
9
  end
@@ -1,22 +1,12 @@
1
1
  require 'active_support/deprecation'
2
2
 
3
3
  class Clearance::PasswordsController < Clearance::BaseController
4
- if respond_to?(:before_action)
5
- skip_before_action :require_login,
6
- only: [:create, :edit, :new, :update],
7
- raise: false
8
- skip_before_action :authorize,
9
- only: [:create, :edit, :new, :update],
10
- raise: false
11
- before_action :ensure_existing_user, only: [:edit, :update]
12
- else
13
- skip_before_filter :require_login,
14
- only: [:create, :edit, :new, :update],
15
- raise: false
16
- skip_before_filter :authorize,
17
- only: [:create, :edit, :new, :update],
18
- raise: false
19
- before_filter :ensure_existing_user, only: [:edit, :update]
4
+ before_action :ensure_existing_user, only: [:edit, :update]
5
+ before_action :ensure_email_present, only: [:create]
6
+ skip_before_action :require_login, only: [:create, :edit, :new, :update], raise: false
7
+
8
+ def new
9
+ render template: "passwords/new"
20
10
  end
21
11
 
22
12
  def create
@@ -24,7 +14,8 @@ class Clearance::PasswordsController < Clearance::BaseController
24
14
  user.forgot_password!
25
15
  deliver_email(user)
26
16
  end
27
- render template: 'passwords/create'
17
+
18
+ render template: "passwords/create"
28
19
  end
29
20
 
30
21
  def edit
@@ -34,24 +25,20 @@ class Clearance::PasswordsController < Clearance::BaseController
34
25
  session[:password_reset_token] = params[:token]
35
26
  redirect_to url_for
36
27
  else
37
- render template: 'passwords/edit'
28
+ render template: "passwords/edit"
38
29
  end
39
30
  end
40
31
 
41
- def new
42
- render template: 'passwords/new'
43
- end
44
-
45
32
  def update
46
33
  @user = find_user_for_update
47
34
 
48
- if @user.update_password password_reset_params
35
+ if @user.update_password(password_from_password_reset_params)
49
36
  sign_in @user
50
37
  redirect_to url_after_update
51
38
  session[:password_reset_token] = nil
52
39
  else
53
40
  flash_failure_after_update
54
- render template: 'passwords/edit'
41
+ render template: "passwords/edit"
55
42
  end
56
43
  end
57
44
 
@@ -59,21 +46,11 @@ class Clearance::PasswordsController < Clearance::BaseController
59
46
 
60
47
  def deliver_email(user)
61
48
  mail = ::ClearanceMailer.change_password(user)
62
-
63
- if mail.respond_to?(:deliver_later)
64
- mail.deliver_later
65
- else
66
- mail.deliver
67
- end
49
+ mail.deliver_later
68
50
  end
69
51
 
70
- def password_reset_params
71
- if params.has_key? :user
72
- ActiveSupport::Deprecation.warn %{Since locales functionality was added, accessing params[:user] is no longer supported.}
73
- params[:user][:password]
74
- else
75
- params[:password_reset][:password]
76
- end
52
+ def password_from_password_reset_params
53
+ params.dig(:password_reset, :password)
77
54
  end
78
55
 
79
56
  def find_user_by_id_and_confirmation_token
@@ -81,12 +58,16 @@ class Clearance::PasswordsController < Clearance::BaseController
81
58
  token = params[:token] || session[:password_reset_token]
82
59
 
83
60
  Clearance.configuration.user_model.
84
- find_by_id_and_confirmation_token params[user_param], token.to_s
61
+ find_by(id: params[user_param], confirmation_token: token.to_s)
62
+ end
63
+
64
+ def email_from_password_params
65
+ params.dig(:password, :email)
85
66
  end
86
67
 
87
68
  def find_user_for_create
88
69
  Clearance.configuration.user_model.
89
- find_by_normalized_email params[:password][:email]
70
+ find_by_normalized_email(email_from_password_params)
90
71
  end
91
72
 
92
73
  def find_user_for_edit
@@ -97,6 +78,13 @@ class Clearance::PasswordsController < Clearance::BaseController
97
78
  find_user_by_id_and_confirmation_token
98
79
  end
99
80
 
81
+ def ensure_email_present
82
+ if email_from_password_params.blank?
83
+ flash_failure_when_missing_email
84
+ render template: "passwords/new"
85
+ end
86
+ end
87
+
100
88
  def ensure_existing_user
101
89
  unless find_user_by_id_and_confirmation_token
102
90
  flash_failure_when_forbidden
@@ -105,19 +93,21 @@ class Clearance::PasswordsController < Clearance::BaseController
105
93
  end
106
94
 
107
95
  def flash_failure_when_forbidden
108
- flash.now[:notice] = translate(:forbidden,
96
+ flash.now[:alert] = translate(:forbidden,
109
97
  scope: [:clearance, :controllers, :passwords],
110
- default: t('flashes.failure_when_forbidden'))
98
+ default: t("flashes.failure_when_forbidden"))
111
99
  end
112
100
 
113
101
  def flash_failure_after_update
114
- flash.now[:notice] = translate(:blank_password,
102
+ flash.now[:alert] = translate(:blank_password,
115
103
  scope: [:clearance, :controllers, :passwords],
116
- default: t('flashes.failure_after_update'))
104
+ default: t("flashes.failure_after_update"))
117
105
  end
118
106
 
119
- def url_after_create
120
- sign_in_url
107
+ def flash_failure_when_missing_email
108
+ flash.now[:alert] = translate(:missing_email,
109
+ scope: [:clearance, :controllers, :passwords],
110
+ default: t("flashes.failure_when_missing_email"))
121
111
  end
122
112
 
123
113
  def url_after_update
@@ -1,21 +1,6 @@
1
1
  class Clearance::SessionsController < Clearance::BaseController
2
- if respond_to?(:before_action)
3
- before_action :redirect_signed_in_users, only: [:new]
4
- skip_before_action :require_login,
5
- only: [:create, :new, :destroy],
6
- raise: false
7
- skip_before_action :authorize,
8
- only: [:create, :new, :destroy],
9
- raise: false
10
- else
11
- before_filter :redirect_signed_in_users, only: [:new]
12
- skip_before_filter :require_login,
13
- only: [:create, :new, :destroy],
14
- raise: false
15
- skip_before_filter :authorize,
16
- only: [:create, :new, :destroy],
17
- raise: false
18
- end
2
+ before_action :redirect_signed_in_users, only: [:new]
3
+ skip_before_action :require_login, only: [:create, :new, :destroy], raise: false
19
4
 
20
5
  def create
21
6
  @user = authenticate(params)
@@ -24,7 +9,7 @@ class Clearance::SessionsController < Clearance::BaseController
24
9
  if status.success?
25
10
  redirect_back_or url_after_create
26
11
  else
27
- flash.now.notice = status.failure_message
12
+ flash.now.alert = status.failure_message
28
13
  render template: "sessions/new", status: :unauthorized
29
14
  end
30
15
  end
@@ -1,13 +1,6 @@
1
1
  class Clearance::UsersController < Clearance::BaseController
2
- if respond_to?(:before_action)
3
- before_action :redirect_signed_in_users, only: [:create, :new]
4
- skip_before_action :require_login, only: [:create, :new], raise: false
5
- skip_before_action :authorize, only: [:create, :new], raise: false
6
- else
7
- before_filter :redirect_signed_in_users, only: [:create, :new]
8
- skip_before_filter :require_login, only: [:create, :new], raise: false
9
- skip_before_filter :authorize, only: [:create, :new], raise: false
10
- end
2
+ before_action :redirect_signed_in_users, only: [:create, :new]
3
+ skip_before_action :require_login, only: [:create, :new], raise: false
11
4
 
12
5
  def new
13
6
  @user = user_from_params
@@ -27,14 +20,6 @@ class Clearance::UsersController < Clearance::BaseController
27
20
 
28
21
  private
29
22
 
30
- def avoid_sign_in
31
- warn "[DEPRECATION] Clearance's `avoid_sign_in` before_filter is " +
32
- "deprecated. Use `redirect_signed_in_users` instead. " +
33
- "Be sure to update any instances of `skip_before_filter :avoid_sign_in`" +
34
- " or `skip_before_action :avoid_sign_in` as well"
35
- redirect_signed_in_users
36
- end
37
-
38
23
  def redirect_signed_in_users
39
24
  if signed_in?
40
25
  redirect_to Clearance.configuration.redirect_url
@@ -1,14 +1,14 @@
1
1
  $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
2
  require 'clearance/version'
3
- require 'date'
4
3
 
5
4
  Gem::Specification.new do |s|
6
- s.add_dependency 'bcrypt'
7
- s.add_dependency 'email_validator', '~> 1.4'
8
- s.add_dependency 'railties', '>= 3.1'
9
- s.add_dependency 'activemodel', '>= 3.1'
10
- s.add_dependency 'activerecord', '>= 3.1'
11
- s.add_dependency 'actionmailer', '>= 3.1'
5
+ s.add_dependency 'bcrypt', '>= 3.1.1'
6
+ s.add_dependency 'argon2', '~> 2.0', '>= 2.0.2'
7
+ s.add_dependency 'email_validator', '~> 2.0'
8
+ s.add_dependency 'railties', '>= 5.0'
9
+ s.add_dependency 'activemodel', '>= 5.0'
10
+ s.add_dependency 'activerecord', '>= 5.0'
11
+ s.add_dependency 'actionmailer', '>= 5.0'
12
12
  s.authors = [
13
13
  'Dan Croak',
14
14
  'Eugene Bolshakov',
@@ -29,7 +29,13 @@ Gem::Specification.new do |s|
29
29
  'Galen Frechette',
30
30
  'Josh Steiner'
31
31
  ]
32
- s.description = 'Rails authentication & authorization with email & password.'
32
+ s.description = <<-DESCRIPTION
33
+ Clearance is built to support authentication and authorization via an
34
+ email/password sign-in mechanism in applications.
35
+
36
+ It provides some core classes commonly used for these features, along with
37
+ some opinionated defaults - but is intended to be easy to override.
38
+ DESCRIPTION
33
39
  s.email = 'support@thoughtbot.com'
34
40
  s.extra_rdoc_files = %w(LICENSE README.md)
35
41
  s.files = `git ls-files`.split("\n")
@@ -38,7 +44,7 @@ Gem::Specification.new do |s|
38
44
  s.name = %q{clearance}
39
45
  s.rdoc_options = ['--charset=UTF-8']
40
46
  s.require_paths = ['lib']
41
- s.required_ruby_version = Gem::Requirement.new('>= 1.9.2')
47
+ s.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
42
48
  s.summary = 'Rails authentication & authorization with email & password.'
43
49
  s.test_files = `git ls-files -- {spec}/*`.split("\n")
44
50
  s.version = Clearance::VERSION
@@ -17,6 +17,7 @@ en:
17
17
  failure_when_forbidden: Please double check the URL or try submitting
18
18
  the form again.
19
19
  failure_when_not_signed_in: Please sign in to continue.
20
+ failure_when_missing_email: Email can't be blank.
20
21
  helpers:
21
22
  label:
22
23
  password: