clearance 2.9.3 → 2.11.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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codeql.yml +39 -0
  3. data/.github/workflows/standardrb.yml +19 -0
  4. data/.github/workflows/tests.yml +4 -8
  5. data/Appraisals +1 -10
  6. data/CHANGELOG.md +26 -1
  7. data/CODEOWNERS +2 -0
  8. data/Gemfile +17 -14
  9. data/Gemfile.lock +139 -105
  10. data/README.md +1 -2
  11. data/Rakefile +1 -1
  12. data/app/controllers/clearance/passwords_controller.rb +6 -6
  13. data/app/mailers/clearance_mailer.rb +1 -1
  14. data/clearance.gemspec +38 -38
  15. data/config/routes.rb +7 -7
  16. data/gemfiles/rails_7.1.gemfile +3 -0
  17. data/gemfiles/rails_7.2.gemfile +3 -0
  18. data/gemfiles/rails_8.0.gemfile +5 -1
  19. data/lib/clearance/authentication.rb +4 -0
  20. data/lib/clearance/back_door.rb +3 -3
  21. data/lib/clearance/configuration.rb +6 -6
  22. data/lib/clearance/constraints.rb +2 -2
  23. data/lib/clearance/controller.rb +2 -2
  24. data/lib/clearance/default_sign_in_guard.rb +1 -1
  25. data/lib/clearance/password_strategies/bcrypt.rb +2 -2
  26. data/lib/clearance/session.rb +4 -6
  27. data/lib/clearance/sign_in_guard.rb +1 -1
  28. data/lib/clearance/testing/deny_access_matcher.rb +4 -4
  29. data/lib/clearance/token.rb +1 -1
  30. data/lib/clearance/user.rb +7 -7
  31. data/lib/clearance/version.rb +1 -1
  32. data/lib/clearance.rb +10 -10
  33. data/lib/generators/clearance/install/install_generator.rb +15 -15
  34. data/lib/generators/clearance/routes/routes_generator.rb +5 -5
  35. data/lib/generators/clearance/routes/templates/routes.rb +10 -10
  36. data/lib/generators/clearance/specs/specs_generator.rb +4 -4
  37. data/lib/generators/clearance/views/views_generator.rb +4 -4
  38. data/spec/acceptance/clearance_installation_spec.rb +3 -3
  39. data/spec/clearance/back_door_spec.rb +5 -5
  40. data/spec/clearance/constraints/signed_in_spec.rb +14 -14
  41. data/spec/clearance/constraints/signed_out_spec.rb +4 -4
  42. data/spec/clearance/default_sign_in_guard_spec.rb +6 -6
  43. data/spec/clearance/rack_session_spec.rb +9 -9
  44. data/spec/clearance/session_spec.rb +60 -62
  45. data/spec/clearance/sign_in_guard_spec.rb +7 -7
  46. data/spec/clearance/testing/controller_helpers_spec.rb +15 -14
  47. data/spec/clearance/testing/deny_access_matcher_spec.rb +1 -1
  48. data/spec/clearance/testing/view_helpers_spec.rb +2 -2
  49. data/spec/clearance/token_spec.rb +3 -3
  50. data/spec/configuration_spec.rb +8 -21
  51. data/spec/controllers/apis_controller_spec.rb +2 -2
  52. data/spec/controllers/forgeries_controller_spec.rb +12 -12
  53. data/spec/controllers/passwords_controller_spec.rb +31 -31
  54. data/spec/controllers/permissions_controller_spec.rb +13 -13
  55. data/spec/controllers/sessions_controller_spec.rb +7 -7
  56. data/spec/controllers/users_controller_spec.rb +5 -5
  57. data/spec/dummy/config/environments/test.rb +3 -3
  58. data/spec/factories/users.rb +3 -3
  59. data/spec/generators/clearance/install/install_generator_spec.rb +11 -11
  60. data/spec/generators/clearance/routes/routes_generator_spec.rb +1 -1
  61. data/spec/generators/clearance/specs/specs_generator_spec.rb +2 -2
  62. data/spec/generators/clearance/views/views_generator_spec.rb +2 -2
  63. data/spec/mailers/clearance_mailer_spec.rb +3 -2
  64. data/spec/models/user_spec.rb +2 -2
  65. data/spec/password_strategies/argon2_spec.rb +3 -3
  66. data/spec/password_strategies/bcrypt_spec.rb +4 -4
  67. data/spec/password_strategies/password_strategies_spec.rb +1 -1
  68. data/spec/requests/authentication_cookie_spec.rb +3 -3
  69. data/spec/requests/backdoor_spec.rb +1 -1
  70. data/spec/requests/cookie_options_spec.rb +2 -2
  71. data/spec/requests/csrf_rotation_spec.rb +1 -1
  72. data/spec/requests/password_maintenance_spec.rb +1 -1
  73. data/spec/requests/token_expiration_spec.rb +2 -2
  74. data/spec/routing/clearance_routes_spec.rb +36 -36
  75. data/spec/support/clearance.rb +1 -1
  76. data/spec/support/fake_model_without_password_strategy.rb +5 -2
  77. data/spec/support/generator_spec_helpers.rb +2 -2
  78. data/spec/support/request_with_remember_token.rb +1 -1
  79. metadata +5 -5
  80. data/gemfiles/rails_7.0.gemfile +0 -24
  81. data/spec/support/html_escape_helper.rb +0 -13
@@ -5,7 +5,7 @@ describe Clearance::Generators::ViewsGenerator, :generator do
5
5
  it "copies clearance views to the host application" do
6
6
  run_generator
7
7
 
8
- views = %w(
8
+ views = %w[
9
9
  clearance_mailer/change_password.html.erb
10
10
  clearance_mailer/change_password.text.erb
11
11
  passwords/create.html.erb
@@ -15,7 +15,7 @@ describe Clearance::Generators::ViewsGenerator, :generator do
15
15
  sessions/new.html.erb
16
16
  users/_form.html.erb
17
17
  users/new.html.erb
18
- )
18
+ ]
19
19
 
20
20
  view_files = views.map { |view| file("app/views/#{view}") }
21
21
 
@@ -1,5 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
+ Person = Class.new(User)
4
+
3
5
  describe ClearanceMailer do
4
6
  it "is from DO_NOT_REPLY" do
5
7
  user = create(:user)
@@ -59,7 +61,6 @@ describe ClearanceMailer do
59
61
  context "when using a custom model" do
60
62
  it "contains a link for a custom model" do
61
63
  define_people_routes
62
- Person = Class.new(User)
63
64
  person = Person.new(email: "person@example.com", password: "password")
64
65
 
65
66
  person.forgot_password!
@@ -82,7 +83,7 @@ describe ClearanceMailer do
82
83
  resource(
83
84
  :password,
84
85
  controller: "clearance/passwords",
85
- only: %i[edit update],
86
+ only: %i[edit update]
86
87
  )
87
88
  end
88
89
  end
@@ -60,7 +60,7 @@ describe User do
60
60
  User.authenticate("bad_email@example.com", password)
61
61
  end
62
62
 
63
- expect(user_does_not_exist_time). to be_within(0.01).of(user_exists_time)
63
+ expect(user_does_not_exist_time).to be_within(0.01).of(user_exists_time)
64
64
  end
65
65
 
66
66
  it "takes the same amount of time to fail authentication regardless of whether user exists" do
@@ -74,7 +74,7 @@ describe User do
74
74
  User.authenticate("bad_email@example.com", "bad_password")
75
75
  end
76
76
 
77
- expect(user_does_not_exist_time). to be_within(0.01).of(user_exists_time)
77
+ expect(user_does_not_exist_time).to be_within(0.01).of(user_exists_time)
78
78
  end
79
79
 
80
80
  it "is retrieved via a case-insensitive search" do
@@ -16,8 +16,8 @@ describe Clearance::PasswordStrategies::Argon2 do
16
16
  it "encrypts with Argon2 using default cost in non test environments" do
17
17
  hasher = stub_argon2_password
18
18
  model_instance = fake_model_with_argon2_strategy
19
- allow(Rails).to receive(:env).
20
- and_return(ActiveSupport::StringInquirer.new("production"))
19
+ allow(Rails).to receive(:env)
20
+ .and_return(ActiveSupport::StringInquirer.new("production"))
21
21
 
22
22
  model_instance.password = password
23
23
 
@@ -69,7 +69,7 @@ describe Clearance::PasswordStrategies::Argon2 do
69
69
 
70
70
  def fake_model_with_argon2_strategy
71
71
  @fake_model_with_argon2_strategy ||= fake_model_with_password_strategy(
72
- Clearance::PasswordStrategies::Argon2,
72
+ Clearance::PasswordStrategies::Argon2
73
73
  )
74
74
  end
75
75
 
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
- include FakeModelWithPasswordStrategy
3
2
 
4
3
  describe Clearance::PasswordStrategies::BCrypt do
4
+ include FakeModelWithPasswordStrategy
5
5
  describe "#password=" do
6
6
  it "encrypts the password into encrypted_password" do
7
7
  stub_bcrypt_password
@@ -15,14 +15,14 @@ describe Clearance::PasswordStrategies::BCrypt do
15
15
  it "encrypts with BCrypt using default cost in non test environments" do
16
16
  stub_bcrypt_password
17
17
  model_instance = fake_model_with_bcrypt_strategy
18
- allow(Rails).to receive(:env).
19
- and_return(ActiveSupport::StringInquirer.new("production"))
18
+ allow(Rails).to receive(:env)
19
+ .and_return(ActiveSupport::StringInquirer.new("production"))
20
20
 
21
21
  model_instance.password = password
22
22
 
23
23
  expect(BCrypt::Password).to have_received(:create).with(
24
24
  password,
25
- cost: ::BCrypt::Engine::DEFAULT_COST,
25
+ cost: ::BCrypt::Engine::DEFAULT_COST
26
26
  )
27
27
  end
28
28
 
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
- include FakeModelWithoutPasswordStrategy
3
2
 
4
3
  describe "Password strategy configuration" do
4
+ include FakeModelWithoutPasswordStrategy
5
5
  describe "when Clearance.configuration.password_strategy is set" do
6
6
  it "includes the value it is set to" do
7
7
  mock_password_strategy = Module.new
@@ -39,8 +39,8 @@ describe "Authentication cookies in the response" do
39
39
 
40
40
  def draw_test_routes
41
41
  Rails.application.routes.draw do
42
- get "/private" => "pages#private", as: :private
43
- get "/public" => "pages#public", as: :public
42
+ get "/private" => "pages#private", :as => :private
43
+ get "/public" => "pages#public", :as => :public
44
44
  resource :session, controller: "clearance/sessions", only: [:create]
45
45
  end
46
46
  end
@@ -49,7 +49,7 @@ describe "Authentication cookies in the response" do
49
49
  user = create(:user, password: "password")
50
50
 
51
51
  post session_path, params: {
52
- session: { email: user.email, password: "password" },
52
+ session: {email: user.email, password: "password"}
53
53
  }
54
54
  end
55
55
  end
@@ -12,7 +12,7 @@ describe "Backdoor Middleware" do
12
12
  it "removes the `as` param but leaves other parameters unchanged" do
13
13
  user = create(:user)
14
14
 
15
- get root_path(as: user.to_param, foo: 'bar')
15
+ get root_path(as: user.to_param, foo: "bar")
16
16
 
17
17
  expect(response.body).to include('{"foo":"bar","controller":"application","action":"show"}')
18
18
  end
@@ -13,7 +13,7 @@ describe "Cookie options" do
13
13
  get sign_in_path
14
14
 
15
15
  post session_path, params: {
16
- session: { email: user.email, password: "password" },
16
+ session: {email: user.email, password: "password"}
17
17
  }
18
18
  end
19
19
 
@@ -33,7 +33,7 @@ describe "Cookie options" do
33
33
  get sign_in_path
34
34
 
35
35
  post session_path, params: {
36
- session: { email: user.email, password: "password" },
36
+ session: {email: user.email, password: "password"}
37
37
  }
38
38
  end
39
39
 
@@ -16,7 +16,7 @@ describe "CSRF Rotation" do
16
16
  original_token = csrf_token
17
17
 
18
18
  post session_path, params: {
19
- authenticity_token: csrf_token, session: { email: user.email, password: "password" }
19
+ authenticity_token: csrf_token, session: {email: user.email, password: "password"}
20
20
  }
21
21
 
22
22
  expect(csrf_token).not_to eq original_token
@@ -8,7 +8,7 @@ describe "Password maintenance" do
8
8
  put user_password_url(user), params: {
9
9
  user_id: user,
10
10
  token: user.confirmation_token,
11
- password_reset: { password: "my_new_password" },
11
+ password_reset: {password: "my_new_password"}
12
12
  }
13
13
 
14
14
  expect(response).to redirect_to(Clearance.configuration.redirect_url)
@@ -15,7 +15,7 @@ describe "Token expiration" do
15
15
  it "should have a remember_token cookie with a future expiration" do
16
16
  expect(first_cookie.expires).to be_between(
17
17
  1.years.from_now - 1.second,
18
- 1.years.from_now,
18
+ 1.years.from_now
19
19
  )
20
20
  end
21
21
  end
@@ -53,7 +53,7 @@ describe "Token expiration" do
53
53
  get sign_in_path
54
54
 
55
55
  post session_path, params: {
56
- session: { email: user.email, password: "password" },
56
+ session: {email: user.email, password: "password"}
57
57
  }
58
58
  end
59
59
  end
@@ -1,18 +1,18 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
- describe 'routes for Clearance' do
4
- context 'routes enabled' do
5
- it 'draws the default routes' do
6
- expect(get: 'sign_up').to be_routable
7
- expect(get: 'sign_in').to be_routable
8
- expect(get: 'passwords/new').to be_routable
9
- expect(post: 'session').to be_routable
10
- expect(post: 'passwords').to be_routable
11
- expect(post: 'users').to be_routable
3
+ describe "routes for Clearance" do
4
+ context "routes enabled" do
5
+ it "draws the default routes" do
6
+ expect(get: "sign_up").to be_routable
7
+ expect(get: "sign_in").to be_routable
8
+ expect(get: "passwords/new").to be_routable
9
+ expect(post: "session").to be_routable
10
+ expect(post: "passwords").to be_routable
11
+ expect(post: "users").to be_routable
12
12
  end
13
13
  end
14
14
 
15
- context 'routes disabled' do
15
+ context "routes disabled" do
16
16
  around do |example|
17
17
  Clearance.configure { |config| config.routes = false }
18
18
  Rails.application.reload_routes!
@@ -21,17 +21,17 @@ describe 'routes for Clearance' do
21
21
  Rails.application.reload_routes!
22
22
  end
23
23
 
24
- it 'does not draw any routes' do
25
- expect(get: 'sign_up').not_to be_routable
26
- expect(get: 'sign_in').not_to be_routable
27
- expect(get: 'passwords/new').not_to be_routable
28
- expect(post: 'session').not_to be_routable
29
- expect(post: 'passwords').not_to be_routable
30
- expect(post: 'users').not_to be_routable
24
+ it "does not draw any routes" do
25
+ expect(get: "sign_up").not_to be_routable
26
+ expect(get: "sign_in").not_to be_routable
27
+ expect(get: "passwords/new").not_to be_routable
28
+ expect(post: "session").not_to be_routable
29
+ expect(post: "passwords").not_to be_routable
30
+ expect(post: "users").not_to be_routable
31
31
  end
32
32
  end
33
33
 
34
- context 'signup disabled' do
34
+ context "signup disabled" do
35
35
  around do |example|
36
36
  Clearance.configure { |config| config.allow_sign_up = false }
37
37
  Rails.application.reload_routes!
@@ -40,30 +40,30 @@ describe 'routes for Clearance' do
40
40
  Rails.application.reload_routes!
41
41
  end
42
42
 
43
- it 'does not route sign_up' do
44
- expect(get: 'sign_up').not_to be_routable
43
+ it "does not route sign_up" do
44
+ expect(get: "sign_up").not_to be_routable
45
45
  end
46
46
 
47
- it 'does not route to users#create' do
48
- expect(post: 'users').not_to be_routable
47
+ it "does not route to users#create" do
48
+ expect(post: "users").not_to be_routable
49
49
  end
50
50
 
51
- it 'does not route to users#new' do
52
- expect(get: 'users/new').not_to be_routable
51
+ it "does not route to users#new" do
52
+ expect(get: "users/new").not_to be_routable
53
53
  end
54
54
  end
55
55
 
56
- context 'signup enabled' do
57
- it 'does route sign_up' do
58
- expect(get: 'sign_up').to be_routable
56
+ context "signup enabled" do
57
+ it "does route sign_up" do
58
+ expect(get: "sign_up").to be_routable
59
59
  end
60
60
 
61
- it 'does route to users#create' do
62
- expect(post: 'users').to be_routable
61
+ it "does route to users#create" do
62
+ expect(post: "users").to be_routable
63
63
  end
64
64
  end
65
65
 
66
- context 'password reset disabled' do
66
+ context "password reset disabled" do
67
67
  around do |example|
68
68
  Clearance.configure { |config| config.allow_password_reset = false }
69
69
  Rails.application.reload_routes!
@@ -72,24 +72,24 @@ describe 'routes for Clearance' do
72
72
  Rails.application.reload_routes!
73
73
  end
74
74
 
75
- it 'does not route password edit' do
75
+ it "does not route password edit" do
76
76
  user = create(:user)
77
77
  expect(get: "users/#{user.id}/password/edit").not_to be_routable
78
78
  end
79
79
 
80
- it 'does not route to clearance/passwords#update' do
80
+ it "does not route to clearance/passwords#update" do
81
81
  user = create(:user)
82
82
  expect(patch: "/users/#{user.id}/password").not_to be_routable
83
83
  end
84
84
  end
85
85
 
86
- context 'reset enabled' do
87
- it 'does route password edit' do
86
+ context "reset enabled" do
87
+ it "does route password edit" do
88
88
  user = create(:user)
89
89
  expect(get: "users/#{user.id}/password/edit").to be_routable
90
90
  end
91
91
 
92
- it 'does route to clearance/passwords#update' do
92
+ it "does route to clearance/passwords#update" do
93
93
  user = create(:user)
94
94
  expect(patch: "/users/#{user.id}/password").to be_routable
95
95
  end
@@ -1,4 +1,4 @@
1
- require 'clearance'
1
+ require "clearance"
2
2
 
3
3
  Clearance.configure do |config|
4
4
  # need an empty block to initialize the configuration object
@@ -5,8 +5,11 @@ module FakeModelWithoutPasswordStrategy
5
5
 
6
6
  validates_with UniquenessValidator
7
7
 
8
- def self.before_validation(*); end
9
- def self.before_create(*); end
8
+ def self.before_validation(*)
9
+ end
10
+
11
+ def self.before_create(*)
12
+ end
10
13
 
11
14
  include Clearance::User
12
15
  end.new
@@ -1,5 +1,5 @@
1
- require "ammeter/rspec/generator/example.rb"
2
- require "ammeter/rspec/generator/matchers.rb"
1
+ require "ammeter/rspec/generator/example"
2
+ require "ammeter/rspec/generator/matchers"
3
3
  require "ammeter/init"
4
4
 
5
5
  module GeneratorSpecHelpers
@@ -7,7 +7,7 @@ module RememberTokenHelpers
7
7
  cookies[Clearance.configuration.cookie_name] = remember_token
8
8
  end
9
9
 
10
- env = { clearance: Clearance::Session.new(cookies.request.env) }
10
+ env = {clearance: Clearance::Session.new(cookies.request.env)}
11
11
  Rack::Request.new env
12
12
  end
13
13
 
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.9.3
4
+ version: 2.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Croak
@@ -27,7 +27,7 @@ authors:
27
27
  autorequire:
28
28
  bindir: bin
29
29
  cert_chain: []
30
- date: 2024-11-26 00:00:00.000000000 Z
30
+ date: 2025-09-26 00:00:00.000000000 Z
31
31
  dependencies:
32
32
  - !ruby/object:Gem::Dependency
33
33
  name: bcrypt
@@ -148,8 +148,10 @@ extra_rdoc_files:
148
148
  files:
149
149
  - ".erb_lint.yml"
150
150
  - ".github/dependabot.yml"
151
+ - ".github/workflows/codeql.yml"
151
152
  - ".github/workflows/dynamic-readme.yml"
152
153
  - ".github/workflows/dynamic-security.yml"
154
+ - ".github/workflows/standardrb.yml"
153
155
  - ".github/workflows/tests.yml"
154
156
  - ".gitignore"
155
157
  - ".yardopts"
@@ -185,7 +187,6 @@ files:
185
187
  - clearance.gemspec
186
188
  - config/locales/clearance.en.yml
187
189
  - config/routes.rb
188
- - gemfiles/rails_7.0.gemfile
189
190
  - gemfiles/rails_7.1.gemfile
190
191
  - gemfiles/rails_7.2.gemfile
191
192
  - gemfiles/rails_8.0.gemfile
@@ -302,7 +303,6 @@ files:
302
303
  - spec/support/fake_model_with_password_strategy.rb
303
304
  - spec/support/fake_model_without_password_strategy.rb
304
305
  - spec/support/generator_spec_helpers.rb
305
- - spec/support/html_escape_helper.rb
306
306
  - spec/support/request_with_remember_token.rb
307
307
  - spec/views/view_helpers_spec.rb
308
308
  homepage: https://github.com/thoughtbot/clearance
@@ -325,7 +325,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
325
325
  - !ruby/object:Gem::Version
326
326
  version: '0'
327
327
  requirements: []
328
- rubygems_version: 3.5.22
328
+ rubygems_version: 3.4.19
329
329
  signing_key:
330
330
  specification_version: 4
331
331
  summary: Rails authentication & authorization with email & password.
@@ -1,24 +0,0 @@
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", "~> 1.7"
18
- gem "railties", "~> 7.0.0"
19
- gem "base64", require: false
20
- gem "bigdecimal", require: false
21
- gem "drb", require: false
22
- gem "mutex_m", require: false
23
-
24
- gemspec path: "../"
@@ -1,13 +0,0 @@
1
- module HTMLEscapeHelper
2
- def translated_string(key)
3
- if [7.0].include?(Rails::VERSION::STRING.to_f)
4
- ERB::Util.html_escape_once(I18n.t(key))
5
- else
6
- I18n.t(key)
7
- end
8
- end
9
- end
10
-
11
- RSpec.configure do |config|
12
- config.include HTMLEscapeHelper
13
- end