clearance 2.5.0 → 2.6.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +4 -12
  3. data/Appraisals +9 -13
  4. data/{NEWS.md → CHANGELOG.md} +21 -2
  5. data/Gemfile.lock +118 -90
  6. data/README.md +3 -1
  7. data/app/controllers/clearance/passwords_controller.rb +6 -6
  8. data/app/controllers/clearance/sessions_controller.rb +1 -1
  9. data/app/controllers/clearance/users_controller.rb +1 -1
  10. data/app/views/passwords/new.html.erb +1 -1
  11. data/app/views/sessions/_form.html.erb +1 -1
  12. data/app/views/users/_form.html.erb +1 -1
  13. data/clearance.gemspec +2 -1
  14. data/db/schema.rb +2 -2
  15. data/gemfiles/rails_6.0.gemfile +2 -0
  16. data/gemfiles/rails_6.1.gemfile +1 -0
  17. data/gemfiles/rails_7.0.gemfile +21 -0
  18. data/lib/clearance/authentication.rb +3 -1
  19. data/lib/clearance/authorization.rb +2 -2
  20. data/lib/clearance/configuration.rb +18 -1
  21. data/lib/clearance/sign_in_guard.rb +2 -2
  22. data/lib/clearance/user.rb +2 -2
  23. data/lib/clearance/version.rb +1 -1
  24. data/lib/generators/clearance/install/install_generator.rb +10 -6
  25. data/lib/generators/clearance/install/templates/db/migrate/add_clearance_to_users.rb.erb +14 -15
  26. data/lib/generators/clearance/install/templates/db/migrate/create_users.rb.erb +2 -1
  27. data/lib/generators/clearance/specs/templates/support/features/clearance_helpers.rb +1 -0
  28. data/spec/acceptance/clearance_installation_spec.rb +1 -0
  29. data/spec/app_templates/testapp/Gemfile +2 -0
  30. data/spec/configuration_spec.rb +8 -1
  31. data/spec/controllers/passwords_controller_spec.rb +86 -3
  32. data/spec/controllers/sessions_controller_spec.rb +9 -0
  33. data/spec/controllers/users_controller_spec.rb +14 -0
  34. data/spec/dummy/application.rb +6 -21
  35. data/spec/dummy/db/.keep +0 -0
  36. data/spec/generators/clearance/install/install_generator_spec.rb +6 -0
  37. data/spec/requests/password_maintenance_spec.rb +1 -0
  38. data/spec/spec_helper.rb +1 -5
  39. metadata +7 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d60bf1a6126821259c777a4d6c34169e0ac643d4c88f74133b13400b99c9140f
4
- data.tar.gz: 42a4077da0d6bca303752a3ef9b224167b3510f3ea9649c3439148c6242591d5
3
+ metadata.gz: cd4f8ec16fd316714fb0f5020e634855d109e260bd164f7b68947f3e36f9d7c7
4
+ data.tar.gz: 5a78cfeca3fc95dee50bba6bd81026f32692de107d6be1d7aca4541837f5d579
5
5
  SHA512:
6
- metadata.gz: a62015195770da36e79c06e228a9e368d20fb3c2e91c92f3bf168f5a2706bbaef4fc98c28bcde3cb5a80bf3eb16f2acc589cb7da920e151cb0060290cea5cc44
7
- data.tar.gz: cec9f3ce0c48cadd04b43b0a5280fd34db24c532ea1f01e92b76b7acd3413220fb568f7d4e3f180b4aa80669264af0d0216da3c4806bc2d24af59276e4d50635
6
+ metadata.gz: 6cdabe74719baedad2e9f8c221fd0abdd377856936fee0aa5b1572dd67c6a5b7925f01641116e0213ed2fcbe07cda870582acebd198aa57228fe4c0a2f90af9c
7
+ data.tar.gz: d0c1c9298dfdc961798bb65170f0b9b43d5eb6a25c956428cfa12ab7375be820e405d72e2c4ad34ed15c487bf7912bb6c17bb311e4a7768f302b6276f85e5920
@@ -16,21 +16,13 @@ jobs:
16
16
  fail-fast: false
17
17
  matrix:
18
18
  gemfile:
19
- - "5.0"
20
- - "5.1"
21
- - "5.2"
22
19
  - "6.0"
23
20
  - "6.1"
21
+ - "7.0"
24
22
  ruby:
25
- - "2.4.9"
26
- - "2.5.7"
27
- - "2.6.5"
28
- - "2.7.2"
29
- exclude:
30
- - gemfile: "6.0"
31
- ruby: "2.4.9"
32
- - gemfile: "6.1"
33
- ruby: "2.4.9"
23
+ - "2.7.6"
24
+ - "3.0.4"
25
+ - "3.1.2"
34
26
 
35
27
  env:
36
28
  BUNDLE_GEMFILE: gemfiles/rails_${{ matrix.gemfile }}.gemfile
data/Appraisals CHANGED
@@ -1,18 +1,14 @@
1
- appraise "rails_5.0" do
2
- gem "railties", "~> 5.0"
3
- gem 'rspec-rails', '~> 3.1'
4
- gem 'capybara', '>= 2.6.2', '< 3.33.0'
5
- gem 'sqlite3', '~> 1.3.13'
6
- end
7
-
8
- appraise "rails_5.1" do
9
- gem "railties", "~> 5.1"
1
+ appraise "rails_6.0" do
2
+ gem "railties", "~> 6.0"
3
+ gem "net-smtp", require: false # not bundled in ruby 3.1
4
+ gem "psych", "< 4" # psych 4 switched from unsafe load to safe load
10
5
  end
11
6
 
12
- appraise "rails_5.2" do
13
- gem "railties", "~> 5.2"
7
+ appraise "rails_6.1" do
8
+ gem "railties", "~> 6.1"
9
+ gem "net-smtp", require: false # not bundled in ruby 3.1
14
10
  end
15
11
 
16
- appraise "rails_6.0" do
17
- gem "railties", "~> 6.0"
12
+ appraise "rails_7.0" do
13
+ gem "railties", "~> 7.0"
18
14
  end
@@ -1,8 +1,27 @@
1
- # News
1
+ # CHANGELOG
2
2
 
3
3
  The noteworthy changes for each Clearance version are included here. For a
4
4
  complete changelog, see the git history for each version via the version links.
5
5
 
6
+ ## [Unreleased]
7
+
8
+ [Unreleased]: https://github.com/thoughtbot/clearance/compare/v2.6.0...main
9
+
10
+ ## [2.6.0] - June 12, 2022
11
+
12
+ - Drops support for Rails 5.0, 5.1 and 5.2, see https://endoflife.date/rails #964
13
+ - Drops support for Ruby 2.4, 2.5 and 2.6, see https://endoflife.date/ruby #964
14
+ - Adds support for Turbo with appropriate status codes #965
15
+ - Adds unique constraints on `remember_token` and `confirmation_token` #966
16
+ - Allows `user_parameter` to be configuration, e.g. `params[:custom_id]` instead of
17
+ `params[:user_id]` #782 (Bryan Marble)
18
+ - Updates SignInGuard documentation #950 (Matthew LS)
19
+ - Forward options in redirect_back_or helper (#968) (Matthew LS)
20
+ - Add configuration option to disable sign in after password reset (#969) (Till
21
+ Prochaska)
22
+
23
+ [2.6.0]: https://github.com/thoughtbot/clearance/compare/v2.5.0...v2.6.0
24
+
6
25
  ## [2.5.0] - September 10, 2021
7
26
 
8
27
  ### Fixed
@@ -13,7 +32,7 @@ complete changelog, see the git history for each version via the version links.
13
32
 
14
33
  - Rename default branch to `main`
15
34
 
16
- [2.4.0]: https://github.com/thoughtbot/clearance/compare/v2.3.1...v2.4.0
35
+ [2.5.0]: https://github.com/thoughtbot/clearance/compare/v2.4.0...v2.5.0
17
36
 
18
37
  ## [2.4.0] - March 5, 2021
19
38
 
data/Gemfile.lock CHANGED
@@ -13,55 +13,57 @@ PATH
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- actionmailer (6.1.3)
17
- actionpack (= 6.1.3)
18
- actionview (= 6.1.3)
19
- activejob (= 6.1.3)
20
- activesupport (= 6.1.3)
16
+ actionmailer (7.0.3)
17
+ actionpack (= 7.0.3)
18
+ actionview (= 7.0.3)
19
+ activejob (= 7.0.3)
20
+ activesupport (= 7.0.3)
21
21
  mail (~> 2.5, >= 2.5.4)
22
+ net-imap
23
+ net-pop
24
+ net-smtp
22
25
  rails-dom-testing (~> 2.0)
23
- actionpack (6.1.3)
24
- actionview (= 6.1.3)
25
- activesupport (= 6.1.3)
26
- rack (~> 2.0, >= 2.0.9)
26
+ actionpack (7.0.3)
27
+ actionview (= 7.0.3)
28
+ activesupport (= 7.0.3)
29
+ rack (~> 2.0, >= 2.2.0)
27
30
  rack-test (>= 0.6.3)
28
31
  rails-dom-testing (~> 2.0)
29
32
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
30
- actionview (6.1.3)
31
- activesupport (= 6.1.3)
33
+ actionview (7.0.3)
34
+ activesupport (= 7.0.3)
32
35
  builder (~> 3.1)
33
36
  erubi (~> 1.4)
34
37
  rails-dom-testing (~> 2.0)
35
38
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
36
- activejob (6.1.3)
37
- activesupport (= 6.1.3)
39
+ activejob (7.0.3)
40
+ activesupport (= 7.0.3)
38
41
  globalid (>= 0.3.6)
39
- activemodel (6.1.3)
40
- activesupport (= 6.1.3)
41
- activerecord (6.1.3)
42
- activemodel (= 6.1.3)
43
- activesupport (= 6.1.3)
44
- activesupport (6.1.3)
42
+ activemodel (7.0.3)
43
+ activesupport (= 7.0.3)
44
+ activerecord (7.0.3)
45
+ activemodel (= 7.0.3)
46
+ activesupport (= 7.0.3)
47
+ activesupport (7.0.3)
45
48
  concurrent-ruby (~> 1.0, >= 1.0.2)
46
49
  i18n (>= 1.6, < 2)
47
50
  minitest (>= 5.1)
48
51
  tzinfo (~> 2.0)
49
- zeitwerk (~> 2.3)
50
- addressable (2.7.0)
52
+ addressable (2.8.0)
51
53
  public_suffix (>= 2.0.2, < 5.0)
52
- ammeter (1.1.4)
54
+ ammeter (1.1.5)
53
55
  activesupport (>= 3.0)
54
56
  railties (>= 3.0)
55
57
  rspec-rails (>= 2.2)
56
- appraisal (2.3.0)
58
+ appraisal (2.4.1)
57
59
  bundler
58
60
  rake
59
61
  thor (>= 0.14.0)
60
- argon2 (2.0.3)
62
+ argon2 (2.1.1)
61
63
  ffi (~> 1.14)
62
64
  ffi-compiler (~> 1.0)
63
65
  ast (2.4.2)
64
- bcrypt (3.1.16)
66
+ bcrypt (3.1.18)
65
67
  better_html (1.0.16)
66
68
  actionview (>= 4.0)
67
69
  activesupport (>= 4.0)
@@ -71,64 +73,87 @@ GEM
71
73
  parser (>= 2.4)
72
74
  smart_properties
73
75
  builder (3.2.4)
74
- capybara (3.33.0)
76
+ capybara (3.37.1)
75
77
  addressable
78
+ matrix
76
79
  mini_mime (>= 0.1.3)
77
80
  nokogiri (~> 1.8)
78
81
  rack (>= 1.6.0)
79
82
  rack-test (>= 0.6.3)
80
- regexp_parser (~> 1.5)
83
+ regexp_parser (>= 1.5, < 3.0)
81
84
  xpath (~> 3.2)
82
85
  coderay (1.1.3)
83
- concurrent-ruby (1.1.8)
86
+ concurrent-ruby (1.1.10)
84
87
  crass (1.0.6)
85
- database_cleaner (1.8.5)
86
- diff-lcs (1.4.4)
88
+ database_cleaner (2.0.1)
89
+ database_cleaner-active_record (~> 2.0.0)
90
+ database_cleaner-active_record (2.0.1)
91
+ activerecord (>= 5.a)
92
+ database_cleaner-core (~> 2.0.0)
93
+ database_cleaner-core (2.0.1)
94
+ diff-lcs (1.5.0)
95
+ digest (3.1.0)
87
96
  email_validator (2.2.3)
88
97
  activemodel
89
- erb_lint (0.0.34)
98
+ erb_lint (0.1.1)
90
99
  activesupport
91
100
  better_html (~> 1.0.7)
92
101
  html_tokenizer
102
+ parser (>= 2.7.1.4)
93
103
  rainbow
94
- rubocop (~> 0.79)
104
+ rubocop
95
105
  smart_properties
96
106
  erubi (1.10.0)
97
- factory_bot (6.1.0)
107
+ factory_bot (6.2.1)
98
108
  activesupport (>= 5.0.0)
99
- factory_bot_rails (6.1.0)
100
- factory_bot (~> 6.1.0)
109
+ factory_bot_rails (6.2.0)
110
+ factory_bot (~> 6.2.0)
101
111
  railties (>= 5.0.0)
102
- ffi (1.15.4)
112
+ ffi (1.15.5)
103
113
  ffi-compiler (1.0.1)
104
114
  ffi (>= 1.0.0)
105
115
  rake
106
- globalid (0.5.2)
116
+ globalid (1.0.0)
107
117
  activesupport (>= 5.0)
108
118
  html_tokenizer (0.0.7)
109
- i18n (1.8.9)
119
+ i18n (1.10.0)
110
120
  concurrent-ruby (~> 1.0)
111
- loofah (2.9.0)
121
+ loofah (2.18.0)
112
122
  crass (~> 1.0.2)
113
123
  nokogiri (>= 1.5.9)
114
124
  mail (2.7.1)
115
125
  mini_mime (>= 0.1.1)
126
+ matrix (0.4.2)
116
127
  method_source (1.0.0)
117
- mini_mime (1.0.2)
118
- mini_portile2 (2.5.0)
119
- minitest (5.14.4)
120
- nokogiri (1.11.1)
121
- mini_portile2 (~> 2.5.0)
128
+ mini_mime (1.1.2)
129
+ mini_portile2 (2.8.0)
130
+ minitest (5.15.0)
131
+ net-imap (0.2.3)
132
+ digest
133
+ net-protocol
134
+ strscan
135
+ net-pop (0.1.1)
136
+ digest
137
+ net-protocol
138
+ timeout
139
+ net-protocol (0.1.3)
140
+ timeout
141
+ net-smtp (0.3.1)
142
+ digest
143
+ net-protocol
144
+ timeout
145
+ nokogiri (1.13.6)
146
+ mini_portile2 (~> 2.8.0)
122
147
  racc (~> 1.4)
123
- parallel (1.19.2)
124
- parser (3.0.0.0)
148
+ parallel (1.22.1)
149
+ parser (3.1.2.0)
125
150
  ast (~> 2.4.1)
126
- pry (0.13.1)
151
+ pry (0.14.1)
127
152
  coderay (~> 1.1)
128
153
  method_source (~> 1.0)
129
- public_suffix (4.0.5)
130
- racc (1.5.2)
131
- rack (2.2.3)
154
+ public_suffix (4.0.7)
155
+ racc (1.6.0)
156
+ rack (2.2.3.1)
132
157
  rack-test (1.1.0)
133
158
  rack (>= 1.0, < 3)
134
159
  rails-controller-testing (1.0.5)
@@ -138,59 +163,62 @@ GEM
138
163
  rails-dom-testing (2.0.3)
139
164
  activesupport (>= 4.2.0)
140
165
  nokogiri (>= 1.6)
141
- rails-html-sanitizer (1.3.0)
166
+ rails-html-sanitizer (1.4.3)
142
167
  loofah (~> 2.3)
143
- railties (6.1.3)
144
- actionpack (= 6.1.3)
145
- activesupport (= 6.1.3)
168
+ railties (7.0.3)
169
+ actionpack (= 7.0.3)
170
+ activesupport (= 7.0.3)
146
171
  method_source
147
- rake (>= 0.8.7)
172
+ rake (>= 12.2)
148
173
  thor (~> 1.0)
149
- rainbow (3.0.0)
150
- rake (13.0.3)
151
- regexp_parser (1.7.1)
174
+ zeitwerk (~> 2.5)
175
+ rainbow (3.1.1)
176
+ rake (13.0.6)
177
+ regexp_parser (2.5.0)
152
178
  rexml (3.2.5)
153
- rspec-core (3.9.2)
154
- rspec-support (~> 3.9.3)
155
- rspec-expectations (3.9.2)
179
+ rspec-core (3.11.0)
180
+ rspec-support (~> 3.11.0)
181
+ rspec-expectations (3.11.0)
156
182
  diff-lcs (>= 1.2.0, < 2.0)
157
- rspec-support (~> 3.9.0)
158
- rspec-mocks (3.9.1)
183
+ rspec-support (~> 3.11.0)
184
+ rspec-mocks (3.11.1)
159
185
  diff-lcs (>= 1.2.0, < 2.0)
160
- rspec-support (~> 3.9.0)
161
- rspec-rails (4.0.1)
162
- actionpack (>= 4.2)
163
- activesupport (>= 4.2)
164
- railties (>= 4.2)
165
- rspec-core (~> 3.9)
166
- rspec-expectations (~> 3.9)
167
- rspec-mocks (~> 3.9)
168
- rspec-support (~> 3.9)
169
- rspec-support (3.9.3)
170
- rubocop (0.88.0)
186
+ rspec-support (~> 3.11.0)
187
+ rspec-rails (5.1.2)
188
+ actionpack (>= 5.2)
189
+ activesupport (>= 5.2)
190
+ railties (>= 5.2)
191
+ rspec-core (~> 3.10)
192
+ rspec-expectations (~> 3.10)
193
+ rspec-mocks (~> 3.10)
194
+ rspec-support (~> 3.10)
195
+ rspec-support (3.11.0)
196
+ rubocop (1.30.1)
171
197
  parallel (~> 1.10)
172
- parser (>= 2.7.1.1)
198
+ parser (>= 3.1.0.0)
173
199
  rainbow (>= 2.2.2, < 4.0)
174
- regexp_parser (>= 1.7)
175
- rexml
176
- rubocop-ast (>= 0.1.0, < 1.0)
200
+ regexp_parser (>= 1.8, < 3.0)
201
+ rexml (>= 3.2.5, < 4.0)
202
+ rubocop-ast (>= 1.18.0, < 2.0)
177
203
  ruby-progressbar (~> 1.7)
178
- unicode-display_width (>= 1.4.0, < 2.0)
179
- rubocop-ast (0.3.0)
180
- parser (>= 2.7.1.4)
181
- ruby-progressbar (1.10.1)
182
- shoulda-matchers (4.3.0)
183
- activesupport (>= 4.2.0)
184
- smart_properties (1.15.0)
204
+ unicode-display_width (>= 1.4.0, < 3.0)
205
+ rubocop-ast (1.18.0)
206
+ parser (>= 3.1.1.0)
207
+ ruby-progressbar (1.11.0)
208
+ shoulda-matchers (5.1.0)
209
+ activesupport (>= 5.2.0)
210
+ smart_properties (1.17.0)
185
211
  sqlite3 (1.4.2)
186
- thor (1.1.0)
187
- timecop (0.9.1)
212
+ strscan (3.0.3)
213
+ thor (1.2.1)
214
+ timecop (0.9.5)
215
+ timeout (0.3.0)
188
216
  tzinfo (2.0.4)
189
217
  concurrent-ruby (~> 1.0)
190
- unicode-display_width (1.7.0)
218
+ unicode-display_width (2.1.0)
191
219
  xpath (3.2.0)
192
220
  nokogiri (~> 1.8)
193
- zeitwerk (2.4.2)
221
+ zeitwerk (2.5.4)
194
222
 
195
223
  PLATFORMS
196
224
  ruby
@@ -213,4 +241,4 @@ DEPENDENCIES
213
241
  timecop
214
242
 
215
243
  BUNDLED WITH
216
- 2.1.4
244
+ 2.3.15
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 `>= 5.0` and Ruby `>= 2.4.0`.
22
+ Clearance is a Rails engine tested against Rails `>= 6.0` and Ruby `>= 2.7.0`.
23
23
 
24
24
  You can add it to your Gemfile with:
25
25
 
@@ -66,6 +66,7 @@ Clearance.configure do |config|
66
66
  config.sign_in_guards = []
67
67
  config.user_model = "User"
68
68
  config.parent_controller = "ApplicationController"
69
+ config.sign_in_on_password_reset = false
69
70
  end
70
71
  ```
71
72
 
@@ -349,6 +350,7 @@ end
349
350
  ```
350
351
 
351
352
  ```ruby
353
+ # app/guards/email_confirmation_guard.rb
352
354
  class EmailConfirmationGuard < Clearance::SignInGuard
353
355
  def call
354
356
  if unconfirmed?
@@ -15,7 +15,7 @@ class Clearance::PasswordsController < Clearance::BaseController
15
15
  deliver_email(user)
16
16
  end
17
17
 
18
- render template: "passwords/create"
18
+ render template: "passwords/create", status: :accepted
19
19
  end
20
20
 
21
21
  def edit
@@ -33,12 +33,12 @@ class Clearance::PasswordsController < Clearance::BaseController
33
33
  @user = find_user_for_update
34
34
 
35
35
  if @user.update_password(password_from_password_reset_params)
36
- sign_in @user
37
- redirect_to url_after_update
36
+ sign_in @user if Clearance.configuration.sign_in_on_password_reset?
37
+ redirect_to url_after_update, status: :see_other
38
38
  session[:password_reset_token] = nil
39
39
  else
40
40
  flash_failure_after_update
41
- render template: "passwords/edit"
41
+ render template: "passwords/edit", status: :unprocessable_entity
42
42
  end
43
43
  end
44
44
 
@@ -80,14 +80,14 @@ class Clearance::PasswordsController < Clearance::BaseController
80
80
  def ensure_email_present
81
81
  if email_from_password_params.blank?
82
82
  flash_failure_when_missing_email
83
- render template: "passwords/new"
83
+ render template: "passwords/new", status: :unprocessable_entity
84
84
  end
85
85
  end
86
86
 
87
87
  def ensure_existing_user
88
88
  unless find_user_by_id_and_confirmation_token
89
89
  flash_failure_when_forbidden
90
- render template: "passwords/new"
90
+ render template: "passwords/new", status: :unprocessable_entity
91
91
  end
92
92
  end
93
93
 
@@ -17,7 +17,7 @@ class Clearance::SessionsController < Clearance::BaseController
17
17
 
18
18
  def destroy
19
19
  sign_out
20
- redirect_to url_after_destroy
20
+ redirect_to url_after_destroy, status: :see_other
21
21
  end
22
22
 
23
23
  def new
@@ -14,7 +14,7 @@ class Clearance::UsersController < Clearance::BaseController
14
14
  sign_in @user
15
15
  redirect_back_or url_after_create
16
16
  else
17
- render template: "users/new"
17
+ render template: "users/new", status: :unprocessable_entity
18
18
  end
19
19
  end
20
20
 
@@ -6,7 +6,7 @@
6
6
  <%= form_for :password, url: passwords_path do |form| %>
7
7
  <div class="text-field">
8
8
  <%= form.label :email %>
9
- <%= form.text_field :email, type: 'email' %>
9
+ <%= form.email_field :email %>
10
10
  </div>
11
11
 
12
12
  <div class="submit-field">
@@ -1,7 +1,7 @@
1
1
  <%= form_for :session, url: session_path do |form| %>
2
2
  <div class="text-field">
3
3
  <%= form.label :email %>
4
- <%= form.text_field :email, type: 'email' %>
4
+ <%= form.email_field :email %>
5
5
  </div>
6
6
 
7
7
  <div class="password-field">
@@ -1,6 +1,6 @@
1
1
  <div class="text-field">
2
2
  <%= form.label :email %>
3
- <%= form.text_field :email, type: 'email' %>
3
+ <%= form.email_field :email %>
4
4
  </div>
5
5
 
6
6
  <div class="password-field">
data/clearance.gemspec CHANGED
@@ -27,7 +27,8 @@ Gem::Specification.new do |s|
27
27
  'Derek Prior',
28
28
  'Jason Morrison',
29
29
  'Galen Frechette',
30
- 'Josh Steiner'
30
+ 'Josh Steiner',
31
+ 'Dorian Marié'
31
32
  ]
32
33
  s.description = <<-DESCRIPTION
33
34
  Clearance is built to support authentication and authorization via an
data/db/schema.rb CHANGED
@@ -23,6 +23,6 @@ ActiveRecord::Schema.define(version: 20110111224543) do
23
23
  end
24
24
 
25
25
  add_index "users", ["email"], name: "index_users_on_email"
26
- add_index "users", ["remember_token"], name: "index_users_on_remember_token"
27
-
26
+ add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
27
+ add_index "users", ["remember_token"], name: "index_users_on_remember_token", unique: true
28
28
  end
@@ -17,5 +17,7 @@ gem "shoulda-matchers"
17
17
  gem "sqlite3"
18
18
  gem "timecop"
19
19
  gem "railties", "~> 6.0"
20
+ gem "net-smtp", require: false
21
+ gem "psych", "< 4"
20
22
 
21
23
  gemspec path: "../"
@@ -17,5 +17,6 @@ gem "shoulda-matchers"
17
17
  gem "sqlite3"
18
18
  gem "timecop"
19
19
  gem "railties", "~> 6.1"
20
+ gem "net-smtp", require: false
20
21
 
21
22
  gemspec path: "../"
@@ -0,0 +1,21 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "addressable"
6
+ gem "ammeter"
7
+ gem "appraisal"
8
+ gem "capybara"
9
+ gem "database_cleaner"
10
+ gem "erb_lint", require: false
11
+ gem "factory_bot_rails"
12
+ gem "nokogiri"
13
+ gem "pry", require: false
14
+ gem "rails-controller-testing"
15
+ gem "rspec-rails"
16
+ gem "shoulda-matchers"
17
+ gem "sqlite3"
18
+ gem "timecop"
19
+ gem "railties", "~> 7.0"
20
+
21
+ gemspec path: "../"
@@ -24,8 +24,10 @@ module Clearance
24
24
  # `params[:session][:password]` are required.
25
25
  # @return [User, nil] The user or nil if authentication fails.
26
26
  def authenticate(params)
27
+ session_params = params.require(:session)
28
+
27
29
  Clearance.configuration.user_model.authenticate(
28
- params[:session][:email], params[:session][:password]
30
+ session_params[:email], session_params[:password]
29
31
  )
30
32
  end
31
33
 
@@ -77,8 +77,8 @@ module Clearance
77
77
  end
78
78
 
79
79
  # @api private
80
- def redirect_back_or(default)
81
- redirect_to(return_to || default)
80
+ def redirect_back_or(default, **options)
81
+ redirect_to(return_to || default, **options)
82
82
  clear_return_to
83
83
  end
84
84
 
@@ -118,6 +118,17 @@ module Clearance
118
118
  # @return [Array<String>]
119
119
  attr_accessor :allowed_backdoor_environments
120
120
 
121
+ # The parameter for user routes. By default this is derived from the user
122
+ # model.
123
+ # @return [Symbol]
124
+ attr_accessor :user_parameter
125
+
126
+ # Controls wether users are automatically signed in after successfully
127
+ # resetting their password.
128
+ # Defaults to `true`.
129
+ # @return [Boolean]
130
+ attr_writer :sign_in_on_password_reset
131
+
121
132
  def initialize
122
133
  @allow_sign_up = true
123
134
  @allowed_backdoor_environments = ["test", "ci", "development"]
@@ -134,6 +145,8 @@ module Clearance
134
145
  @secure_cookie = false
135
146
  @signed_cookie = false
136
147
  @sign_in_guards = []
148
+ @user_parameter = nil
149
+ @sign_in_on_password_reset = true
137
150
  end
138
151
 
139
152
  def signed_cookie=(value)
@@ -183,7 +196,7 @@ module Clearance
183
196
  # In the default configuration, this is `user`.
184
197
  # @return [Symbol]
185
198
  def user_parameter
186
- user_model.model_name.singular.to_sym
199
+ @user_parameter ||= user_model.model_name.singular.to_sym
187
200
  end
188
201
 
189
202
  # The name of foreign key parameter for the configured user model.
@@ -214,6 +227,10 @@ module Clearance
214
227
  def rotate_csrf_on_sign_in?
215
228
  !!rotate_csrf_on_sign_in
216
229
  end
230
+
231
+ def sign_in_on_password_reset?
232
+ @sign_in_on_password_reset
233
+ end
217
234
  end
218
235
 
219
236
  # @return [Clearance::Configuration] Clearance's current configuration
@@ -16,10 +16,10 @@ module Clearance
16
16
  #
17
17
  # # in config/initializers/clearance.rb
18
18
  # Clearance.configure do |config|
19
- # config.sign_in_guards = [ConfirmationGuard]
19
+ # config.sign_in_guards = ["ConfirmationGuard"]
20
20
  # end
21
21
  #
22
- # # in lib/guards/confirmation_guard.rb
22
+ # # in app/guards/confirmation_guard.rb
23
23
  # class ConfirmationGuard < Clearance::SignInGuard
24
24
  # def call
25
25
  # if signed_in? && current_user.email_confirmed?
@@ -234,7 +234,7 @@ module Clearance
234
234
  # Always false. Override this method in your user model to allow for other
235
235
  # forms of user authentication (username, Facebook, etc).
236
236
  #
237
- # @return [false]
237
+ # @return [Boolean]
238
238
  def email_optional?
239
239
  false
240
240
  end
@@ -242,7 +242,7 @@ module Clearance
242
242
  # Always false. Override this method in your user model to allow for other
243
243
  # forms of user authentication (username, Facebook, etc).
244
244
  #
245
- # @return [false]
245
+ # @return [Boolean]
246
246
  def password_optional?
247
247
  false
248
248
  end
@@ -1,3 +1,3 @@
1
1
  module Clearance
2
- VERSION = "2.5.0".freeze
2
+ VERSION = "2.6.0".freeze
3
3
  end
@@ -73,17 +73,21 @@ module Clearance
73
73
 
74
74
  def new_columns
75
75
  @new_columns ||= {
76
- email: 't.string :email',
77
- encrypted_password: 't.string :encrypted_password, limit: 128',
78
- confirmation_token: 't.string :confirmation_token, limit: 128',
79
- remember_token: 't.string :remember_token, limit: 128'
76
+ email: "t.string :email",
77
+ encrypted_password: "t.string :encrypted_password, limit: 128",
78
+ confirmation_token: "t.string :confirmation_token, limit: 128",
79
+ remember_token: "t.string :remember_token, limit: 128",
80
80
  }.reject { |column| existing_users_columns.include?(column.to_s) }
81
81
  end
82
82
 
83
83
  def new_indexes
84
84
  @new_indexes ||= {
85
- index_users_on_email: 'add_index :users, :email',
86
- index_users_on_remember_token: 'add_index :users, :remember_token'
85
+ index_users_on_email:
86
+ "add_index :users, :email",
87
+ index_users_on_confirmation_token:
88
+ "add_index :users, :confirmation_token, unique: true",
89
+ index_users_on_remember_token:
90
+ "add_index :users, :remember_token, unique: true",
87
91
  }.reject { |index| existing_users_indexes.include?(index.to_s) }
88
92
  end
89
93
 
@@ -1,35 +1,34 @@
1
1
  class AddClearanceToUsers < ActiveRecord::Migration<%= migration_version %>
2
2
  def self.up
3
+ <% if config[:new_columns].any? -%>
3
4
  change_table :users do |t|
4
5
  <% config[:new_columns].values.each do |column| -%>
5
6
  <%= column %>
6
7
  <% end -%>
7
8
  end
8
-
9
+ <% end -%>
10
+ <% if config[:new_indexes].any? -%>
9
11
  <% config[:new_indexes].values.each do |index| -%>
10
12
  <%= index %>
11
13
  <% end -%>
12
-
13
- users = select_all("SELECT id FROM users WHERE remember_token IS NULL")
14
-
15
- users.each do |user|
16
- update <<-SQL.squish
17
- UPDATE users
18
- SET remember_token = '#{Clearance::Token.new}'
19
- WHERE id = '#{user['id']}'
20
- SQL
14
+ <% end -%>
15
+ <% if config[:new_columns].keys.include?(:remember_token) -%>
16
+ Clearance.configuration.user_model.where(remember_token: nil).each do |user|
17
+ user.update_columns(remember_token: Clearance::Token.new)
21
18
  end
19
+ <% end -%>
22
20
  end
23
21
 
24
- def self.down
22
+ def self.down
25
23
  <% config[:new_indexes].values.each do |index| -%>
26
- <%= index.gsub("add_index", "remove_index") %>
24
+ <%= index.sub("add_index", "remove_index") %>
27
25
  <% end -%>
28
-
29
- change_table :users do |t|
30
26
  <% if config[:new_columns].any? -%>
31
- t.remove <%= new_columns.keys.map { |column| ":#{column}" }.join(", ") %>
27
+ change_table :users do |t|
28
+ <% config[:new_columns].keys.each do |key| -%>
29
+ t.remove <%= key.inspect %>
32
30
  <% end -%>
33
31
  end
32
+ <% end -%>
34
33
  end
35
34
  end
@@ -9,6 +9,7 @@ class CreateUsers < ActiveRecord::Migration<%= migration_version %>
9
9
  end
10
10
 
11
11
  add_index :users, :email
12
- add_index :users, :remember_token
12
+ add_index :users, :confirmation_token, unique: true
13
+ add_index :users, :remember_token, unique: true
13
14
  end
14
15
  end
@@ -36,6 +36,7 @@ module Features
36
36
  end
37
37
 
38
38
  def expect_user_to_be_signed_out
39
+ visit root_path
39
40
  expect(page).to have_content I18n.t("layouts.application.sign_in")
40
41
  end
41
42
 
@@ -35,6 +35,7 @@ describe "Clearance Installation" do
35
35
  --skip-javascript
36
36
  --skip-keeps
37
37
  --skip-sprockets
38
+ --skip-asset-pipeline
38
39
  CMD
39
40
  end
40
41
 
@@ -1,3 +1,5 @@
1
+ source "https://rubygems.org"
2
+
1
3
  gem "rails"
2
4
  gem "sqlite3"
3
5
  gem "rspec-rails"
@@ -167,7 +167,14 @@ describe Clearance::Configuration do
167
167
  end
168
168
 
169
169
  describe "#user_parameter" do
170
- it "returns the parameter key to use based on the user_model" do
170
+ context "when user_parameter is configured" do
171
+ it "returns the configured parameter" do
172
+ Clearance.configure { |config| config.user_parameter = :custom_param }
173
+ expect(Clearance.configuration.user_parameter).to eq :custom_param
174
+ end
175
+ end
176
+
177
+ it "returns the parameter key to use based on the user_model by default" do
171
178
  Account = Class.new(ActiveRecord::Base)
172
179
  Clearance.configure { |config| config.user_model = Account }
173
180
 
@@ -35,6 +35,16 @@ describe Clearance::PasswordsController do
35
35
  email = ActionMailer::Base.deliveries.last
36
36
  expect(email.subject).to match(/change your password/i)
37
37
  end
38
+
39
+ it "re-renders the page when turbo is enabled" do
40
+ user = create(:user)
41
+
42
+ post :create, params: {
43
+ password: { email: user.email.upcase },
44
+ }
45
+
46
+ expect(response).to have_http_status(:accepted)
47
+ end
38
48
  end
39
49
 
40
50
  context "email param is missing" do
@@ -46,6 +56,14 @@ describe Clearance::PasswordsController do
46
56
  expect(flash.now[:alert]).to match(/email can't be blank/i)
47
57
  expect(response).to render_template(:new)
48
58
  end
59
+
60
+ it "re-renders the page when turbo is enabled" do
61
+ post :create, params: {
62
+ password: {},
63
+ }
64
+
65
+ expect(response).to have_http_status(:unprocessable_entity)
66
+ end
49
67
  end
50
68
 
51
69
  context "email param is blank" do
@@ -53,12 +71,22 @@ describe Clearance::PasswordsController do
53
71
  post :create, params: {
54
72
  password: {
55
73
  email: "",
56
- }
74
+ },
57
75
  }
58
76
 
59
77
  expect(flash.now[:alert]).to match(/email can't be blank/i)
60
78
  expect(response).to render_template(:new)
61
79
  end
80
+
81
+ it "re-renders the page when turbo is enabled" do
82
+ post :create, params: {
83
+ password: {
84
+ email: "",
85
+ },
86
+ }
87
+
88
+ expect(response).to have_http_status(:unprocessable_entity)
89
+ end
62
90
  end
63
91
 
64
92
  context "email does not belong to an existing user" do
@@ -73,7 +101,7 @@ describe Clearance::PasswordsController do
73
101
  expect(ActionMailer::Base.deliveries).to be_empty
74
102
  end
75
103
 
76
- it "still responds with success so as not to leak registered users" do
104
+ it "still responds with error so as not to leak registered users" do
77
105
  email = "this_user_does_not_exist@non_existent_domain.com"
78
106
 
79
107
  post :create, params: {
@@ -83,6 +111,16 @@ describe Clearance::PasswordsController do
83
111
  expect(response).to be_successful
84
112
  expect(response).to render_template "passwords/create"
85
113
  end
114
+
115
+ it "has the same status code as a successful request" do
116
+ email = "this_user_does_not_exist@non_existent_domain.com"
117
+
118
+ post :create, params: {
119
+ password: { email: email },
120
+ }
121
+
122
+ expect(response).to have_http_status(:accepted)
123
+ end
86
124
  end
87
125
  end
88
126
 
@@ -97,6 +135,7 @@ describe Clearance::PasswordsController do
97
135
  }
98
136
 
99
137
  expect(response).to be_redirect
138
+ expect(response).to have_http_status(:found)
100
139
  expect(response).to redirect_to edit_user_password_url(user)
101
140
  expect(session[:password_reset_token]).to eq user.confirmation_token
102
141
  end
@@ -172,6 +211,35 @@ describe Clearance::PasswordsController do
172
211
  )
173
212
 
174
213
  expect(user.reload.encrypted_password).not_to eq old_encrypted_password
214
+ expect(response).to have_http_status(:see_other)
215
+ end
216
+
217
+ it "signs in the user" do
218
+ user = create(:user, :with_forgotten_password)
219
+
220
+ put :update, params: update_parameters(
221
+ user,
222
+ new_password: "my_new_password",
223
+ )
224
+
225
+ expect(current_user).to eq(user)
226
+ end
227
+
228
+ context "when Clearance is configured to not sign in the user" do
229
+ it "doesn't sign in the user" do
230
+ Clearance.configure do |config|
231
+ config.sign_in_on_password_reset = false
232
+ end
233
+
234
+ user = create(:user, :with_forgotten_password)
235
+
236
+ put :update, params: update_parameters(
237
+ user,
238
+ new_password: "my_new_password",
239
+ )
240
+
241
+ expect(current_user).to be_nil
242
+ end
175
243
  end
176
244
  end
177
245
 
@@ -211,8 +279,19 @@ describe Clearance::PasswordsController do
211
279
  )
212
280
 
213
281
  expect(flash.now[:alert]).to match(/password can't be blank/i)
282
+ expect(response).to have_http_status(:unprocessable_entity)
214
283
  expect(response).to render_template(:edit)
215
- expect(cookies[:remember_token]).to be_nil
284
+ end
285
+
286
+ it "doesn't sign in the user" do
287
+ user = create(:user, :with_forgotten_password)
288
+
289
+ put :update, params: update_parameters(
290
+ user,
291
+ new_password: "",
292
+ )
293
+
294
+ expect(current_user).to be_nil
216
295
  end
217
296
  end
218
297
  end
@@ -226,4 +305,8 @@ describe Clearance::PasswordsController do
226
305
  password_reset: { password: new_password }
227
306
  }
228
307
  end
308
+
309
+ def current_user
310
+ request.env[:clearance].current_user
311
+ end
229
312
  end
@@ -24,6 +24,14 @@ describe Clearance::SessionsController do
24
24
  end
25
25
 
26
26
  describe "on POST to #create" do
27
+ context "when missing parameters" do
28
+ it "raises an error" do
29
+ expect do
30
+ post :create
31
+ end.to raise_error(ActionController::ParameterMissing)
32
+ end
33
+ end
34
+
27
35
  context "when password is optional" do
28
36
  it "renders the page with error" do
29
37
  user = create(:user_with_optional_password)
@@ -117,6 +125,7 @@ describe Clearance::SessionsController do
117
125
  end
118
126
 
119
127
  it { should redirect_to_url_after_destroy }
128
+ it { expect(response).to have_http_status(:see_other) }
120
129
  end
121
130
 
122
131
  context "with a cookie" do
@@ -67,6 +67,20 @@ describe Clearance::UsersController do
67
67
  expect(response).to redirect_to(return_url)
68
68
  end
69
69
  end
70
+
71
+ context "with invalid attributes" do
72
+ it "renders the page with error" do
73
+ user_attributes = FactoryBot.attributes_for(:user, email: nil)
74
+ old_user_count = User.count
75
+
76
+ post :create, params: {
77
+ user: user_attributes,
78
+ }
79
+
80
+ expect(User.count).to eq old_user_count
81
+ expect(response).to have_http_status(:unprocessable_entity)
82
+ end
83
+ end
70
84
  end
71
85
 
72
86
  context "when signed in" do
@@ -1,50 +1,35 @@
1
1
  require "rails/all"
2
+
2
3
  require "clearance"
3
4
 
4
5
  module Dummy
5
6
  APP_ROOT = File.expand_path("..", __FILE__).freeze
6
7
 
7
- I18n.enforce_available_locales = true
8
-
9
8
  class Application < Rails::Application
10
- config.action_controller.allow_forgery_protection = false
11
9
  config.action_controller.perform_caching = false
12
- config.action_dispatch.show_exceptions = false
13
10
  config.action_mailer.default_url_options = { host: "dummy.example.com" }
14
11
  config.action_mailer.delivery_method = :test
15
12
  config.active_support.deprecation = :stderr
16
- config.active_support.test_order = :random
17
- config.cache_classes = true
18
- config.consider_all_requests_local = true
19
13
  config.eager_load = false
20
- config.encoding = "utf-8"
14
+
21
15
  config.paths["app/controllers"] << "#{APP_ROOT}/app/controllers"
22
16
  config.paths["app/models"] << "#{APP_ROOT}/app/models"
23
17
  config.paths["app/views"] << "#{APP_ROOT}/app/views"
24
18
  config.paths["config/database"] = "#{APP_ROOT}/config/database.yml"
25
19
  config.paths["log"] = "tmp/log/development.log"
26
-
27
20
  config.paths.add "config/routes.rb", with: "#{APP_ROOT}/config/routes.rb"
28
- config.secret_key_base = "SECRET_KEY_BASE"
29
21
 
30
- if config.active_record.sqlite3.respond_to?(:represent_boolean_as_integer)
31
- if Rails::VERSION::MAJOR < 6
32
- config.active_record.sqlite3.represent_boolean_as_integer = true
33
- end
22
+ if Rails.version.match?(/^6.0/)
23
+ config.active_record.sqlite3.represent_boolean_as_integer = true
24
+ else
25
+ config.active_record.legacy_connection_handling = false
34
26
  end
35
27
 
36
- if Rails::VERSION::MAJOR >= 6
37
- config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
38
- end
39
-
40
- config.active_job.queue_adapter = :inline
41
-
42
28
  def require_environment!
43
29
  initialize!
44
30
  end
45
31
 
46
32
  def initialize!(&block)
47
- FileUtils.mkdir_p(Rails.root.join("db").to_s)
48
33
  super unless @initialized
49
34
  end
50
35
  end
File without changes
@@ -135,6 +135,12 @@ describe Clearance::Generators::InstallGenerator, :generator do
135
135
  expect(migration).to contain("add_index :users, :email")
136
136
  expect(migration).not_to contain("t.string :remember_token")
137
137
  expect(migration).not_to contain("add_index :users, :remember_token")
138
+ expect(migration).to(
139
+ contain("add_index :users, :confirmation_token, unique: true"),
140
+ )
141
+ expect(migration).to(
142
+ contain("remove_index :users, :confirmation_token, unique: true"),
143
+ )
138
144
  end
139
145
  end
140
146
  end
@@ -12,6 +12,7 @@ describe "Password maintenance" do
12
12
  }
13
13
 
14
14
  expect(response).to redirect_to(Clearance.configuration.redirect_url)
15
+ expect(response).to have_http_status(:see_other)
15
16
  expect(cookies["remember_token"]).to be_present
16
17
  end
17
18
  end
data/spec/spec_helper.rb CHANGED
@@ -5,6 +5,7 @@ require "dummy/application"
5
5
 
6
6
  require "clearance/rspec"
7
7
  require "factory_bot_rails"
8
+ require "rails-controller-testing"
8
9
  require "rspec/rails"
9
10
  require "shoulda-matchers"
10
11
  require "timecop"
@@ -28,11 +29,6 @@ RSpec.configure do |config|
28
29
  end
29
30
 
30
31
  config.before { restore_default_warning_free_config }
31
-
32
- require 'rails-controller-testing'
33
- config.include Rails::Controller::Testing::TestProcess
34
- config.include Rails::Controller::Testing::TemplateAssertions
35
- config.include Rails::Controller::Testing::Integration
36
32
  end
37
33
 
38
34
  Shoulda::Matchers.configure do |config|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clearance
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Croak
@@ -22,10 +22,11 @@ authors:
22
22
  - Jason Morrison
23
23
  - Galen Frechette
24
24
  - Josh Steiner
25
+ - Dorian Marié
25
26
  autorequire:
26
27
  bindir: bin
27
28
  cert_chain: []
28
- date: 2021-09-10 00:00:00.000000000 Z
29
+ date: 2022-06-12 00:00:00.000000000 Z
29
30
  dependencies:
30
31
  - !ruby/object:Gem::Dependency
31
32
  name: bcrypt
@@ -149,11 +150,11 @@ files:
149
150
  - ".gitignore"
150
151
  - ".yardopts"
151
152
  - Appraisals
153
+ - CHANGELOG.md
152
154
  - CONTRIBUTING.md
153
155
  - Gemfile
154
156
  - Gemfile.lock
155
157
  - LICENSE
156
- - NEWS.md
157
158
  - README.md
158
159
  - RELEASING.md
159
160
  - Rakefile
@@ -185,6 +186,7 @@ files:
185
186
  - gemfiles/rails_5.2.gemfile
186
187
  - gemfiles/rails_6.0.gemfile
187
188
  - gemfiles/rails_6.1.gemfile
189
+ - gemfiles/rails_7.0.gemfile
188
190
  - lib/clearance.rb
189
191
  - lib/clearance/authentication.rb
190
192
  - lib/clearance/authorization.rb
@@ -266,6 +268,7 @@ files:
266
268
  - spec/dummy/application.rb
267
269
  - spec/dummy/config/database.yml
268
270
  - spec/dummy/config/routes.rb
271
+ - spec/dummy/db/.keep
269
272
  - spec/factories.rb
270
273
  - spec/generators/clearance/install/install_generator_spec.rb
271
274
  - spec/generators/clearance/routes/routes_generator_spec.rb
@@ -311,7 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
311
314
  - !ruby/object:Gem::Version
312
315
  version: '0'
313
316
  requirements: []
314
- rubygems_version: 3.1.4
317
+ rubygems_version: 3.1.6
315
318
  signing_key:
316
319
  specification_version: 4
317
320
  summary: Rails authentication & authorization with email & password.