From dbfe55dcf465b6f15e825353cdfaf8b1f81720c2 Mon Sep 17 00:00:00 2001 From: Jos O'shea Date: Fri, 9 Aug 2024 10:55:07 -0400 Subject: [PATCH] Add allow_password_resets config option (#1019) solves #993 added config option to disallow password reset routes in cases where its not needed. allow_password_resets defaults to true but can be set to false in instances where it is not needed. --- README.md | 1 + app/views/sessions/_form.html.erb | 4 +++- config/routes.rb | 8 ++++--- lib/clearance/configuration.rb | 14 ++++++++++++ spec/configuration_spec.rb | 15 +++++++++++++ spec/routing/clearance_routes_spec.rb | 32 +++++++++++++++++++++++++++ 6 files changed, 70 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9698f393e..8fe714858 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ Override any of these defaults in `config/initializers/clearance.rb`: ```ruby Clearance.configure do |config| config.allow_sign_up = true + config.allow_password_reset = true config.cookie_domain = ".example.com" config.cookie_expiration = lambda { |cookies| 1.year.from_now.utc } config.cookie_name = "remember_token" diff --git a/app/views/sessions/_form.html.erb b/app/views/sessions/_form.html.erb index 31dc415ac..8fb2e9abe 100644 --- a/app/views/sessions/_form.html.erb +++ b/app/views/sessions/_form.html.erb @@ -17,6 +17,8 @@ <% if Clearance.configuration.allow_sign_up? %> <%= link_to t(".sign_up"), sign_up_path %> <% end %> - <%= link_to t(".forgot_password"), new_password_path %> + <% if Clearance.configuration.allow_password_reset? %> + <%= link_to t(".forgot_password"), new_password_path %> + <% end %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 700f7b3e0..08de03e34 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,9 +11,11 @@ resources :users, controller: 'clearance/users', only: Clearance.configuration.user_actions do - resource :password, - controller: 'clearance/passwords', - only: [:edit, :update] + if Clearance.configuration.allow_password_reset? + resource :password, + controller: 'clearance/passwords', + only: [:edit, :update] + end end get '/sign_in' => 'clearance/sessions#new', as: 'sign_in' diff --git a/lib/clearance/configuration.rb b/lib/clearance/configuration.rb index 8a2c70280..75e564f06 100644 --- a/lib/clearance/configuration.rb +++ b/lib/clearance/configuration.rb @@ -7,6 +7,13 @@ class Configuration # @return [Boolean] attr_writer :allow_sign_up + # Controls whether the password reset routes are enabled + # Defaults to `true`. Set to False to disable password reset routes + # The setting is ignored if routes are disabled. + # @param [Boolean] value + # @return [Boolean] + attr_writer :allow_password_reset + # The domain to use for the clearance remember token cookie. # Defaults to `nil`, which causes the cookie domain to default to the # domain of the request. For more, see @@ -145,6 +152,7 @@ class Configuration def initialize @allow_sign_up = true + @allow_password_reset = true @allowed_backdoor_environments = ["test", "ci", "development"] @cookie_domain = nil @cookie_expiration = ->(cookies) { 1.year.from_now.utc } @@ -195,6 +203,12 @@ def allow_sign_up? @allow_sign_up end + # Are the password reset routes enabled? + # @return [Boolean] + def allow_password_reset? + @allow_password_reset + end + # Specifies which controller actions are allowed for user resources. # This will be `[:create]` is `allow_sign_up` is true (the default), and # empty otherwise. diff --git a/spec/configuration_spec.rb b/spec/configuration_spec.rb index 446365023..c6436ece7 100644 --- a/spec/configuration_spec.rb +++ b/spec/configuration_spec.rb @@ -179,6 +179,21 @@ end end + describe "#allow_password_reset?" do + context "when allow_password_reset is configured to false" do + it "returns false" do + Clearance.configure { |config| config.allow_password_reset = false } + expect(Clearance.configuration.allow_password_reset?).to eq false + end + end + + context "when allow_sign_up has not been configured" do + it "returns true" do + expect(Clearance.configuration.allow_password_reset?).to eq true + end + end + end + describe "#user_actions" do context "when allow_sign_up is configured to false" do it "returns empty array" do diff --git a/spec/routing/clearance_routes_spec.rb b/spec/routing/clearance_routes_spec.rb index 960c1ba90..633824b95 100644 --- a/spec/routing/clearance_routes_spec.rb +++ b/spec/routing/clearance_routes_spec.rb @@ -62,4 +62,36 @@ expect(post: 'users').to be_routable end end + + context 'password reset disabled' do + around do |example| + Clearance.configure { |config| config.allow_password_reset = false } + Rails.application.reload_routes! + example.run + Clearance.configuration = Clearance::Configuration.new + Rails.application.reload_routes! + end + + it 'does not route password edit' do + user = create(:user) + expect(get: "users/#{user.id}/password/edit").not_to be_routable + end + + it 'does not route to clearance/passwords#update' do + user = create(:user) + expect(patch: "/users/#{user.id}/password").not_to be_routable + end + end + + context 'reset enabled' do + it 'does route password edit' do + user = create(:user) + expect(get: "users/#{user.id}/password/edit").to be_routable + end + + it 'does route to clearance/passwords#update' do + user = create(:user) + expect(patch: "/users/#{user.id}/password").to be_routable + end + end end