FIX: staff only mode blocks admin password resets (#29289)

When staff only mode is enabled - Discourse.enable_readonly_mode(Discourse::STAFF_WRITES_ONLY_MODE_KEY)

Staff members couldn't reset their password via the "forgot password" link.

This fixes it.

Internal ref. t/133990
This commit is contained in:
Régis Hanol 2024-10-21 09:29:37 +02:00 committed by GitHub
parent 56df077931
commit 425643bbd8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 4 deletions

View File

@ -12,8 +12,7 @@ class SessionController < ApplicationController
skip_before_action :check_xhr, only: %i[second_factor_auth_show] skip_before_action :check_xhr, only: %i[second_factor_auth_show]
allow_in_staff_writes_only_mode :create allow_in_staff_writes_only_mode :create, :email_login, :forgot_password
allow_in_staff_writes_only_mode :email_login
ACTIVATE_USER_KEY = "activate_user" ACTIVATE_USER_KEY = "activate_user"
FORGOT_PASSWORD_EMAIL_LIMIT_PER_DAY = 6 FORGOT_PASSWORD_EMAIL_LIMIT_PER_DAY = 6
@ -634,6 +633,7 @@ class SessionController < ApplicationController
end end
if user if user
raise Discourse::ReadOnly if staff_writes_only_mode? && !user.staff?
enqueue_password_reset_for_user(user) enqueue_password_reset_for_user(user)
else else
RateLimiter.new( RateLimiter.new(

View File

@ -107,8 +107,7 @@ class UsersController < ApplicationController
before_action :add_noindex_header, only: %i[show my_redirect] before_action :add_noindex_header, only: %i[show my_redirect]
allow_in_staff_writes_only_mode :admin_login allow_in_staff_writes_only_mode :admin_login, :email_login, :password_reset_update
allow_in_staff_writes_only_mode :email_login
MAX_RECENT_SEARCHES = 5 MAX_RECENT_SEARCHES = 5
@ -866,6 +865,8 @@ class UsersController < ApplicationController
# no point doing anything else if we can't even find # no point doing anything else if we can't even find
# a user from the token # a user from the token
if @user if @user
raise Discourse::ReadOnly if staff_writes_only_mode? && !@user.staff?
if !secure_session["second-factor-#{token}"] if !secure_session["second-factor-#{token}"]
second_factor_authentication_result = second_factor_authentication_result =
@user.authenticate_second_factor(params, secure_session) @user.authenticate_second_factor(params, secure_session)

View File

@ -2841,6 +2841,23 @@ RSpec.describe SessionController do
expect(Jobs::CriticalUserEmail.jobs.size).to eq(0) expect(Jobs::CriticalUserEmail.jobs.size).to eq(0)
end end
end end
context "when in staff writes only mode" do
before { Discourse.enable_readonly_mode(Discourse::STAFF_WRITES_ONLY_MODE_KEY) }
it "allows staff to forget their password" do
post "/session/forgot_password.json", params: { login: admin.username }
expect(response.status).to eq(200)
expect(response.parsed_body["error"]).not_to be_present
expect(Jobs::CriticalUserEmail.jobs.size).to eq(1)
end
it "doesn't allow non-staff to forget their password" do
post "/session/forgot_password.json", params: { login: user.username }
expect(response.status).to eq(503)
expect(Jobs::CriticalUserEmail.jobs.size).to eq(0)
end
end
end end
describe "#current" do describe "#current" do

View File

@ -600,6 +600,30 @@ RSpec.describe UsersController do
expect(response.parsed_body["errors"]).to be_blank expect(response.parsed_body["errors"]).to be_blank
expect(session[:current_user_id]).to be_blank expect(session[:current_user_id]).to be_blank
end end
context "when in staff writes only mode" do
before { Discourse.enable_readonly_mode(Discourse::STAFF_WRITES_ONLY_MODE_KEY) }
it "allows staff to reset their password" do
admin = Fabricate(:admin)
email_token =
Fabricate(:email_token, user: admin, scope: EmailToken.scopes[:password_reset])
put "/u/password-reset/#{email_token.token}.json",
params: {
password: "hg9ow8yhg98oadminlonger",
}
expect(response.parsed_body["errors"]).to be_blank
expect(session[:current_user_id]).to eq(admin.id)
end
it "doesn't allow non-staff to reset their password" do
put "/u/password-reset/#{email_token.token}.json", params: { password: "ksjafh928r" }
expect(response.parsed_body["errors"]).to_not be_blank
expect(session[:current_user_id]).to be_blank
end
end
end end
end end