clearance 2.5.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
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.