mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-24 06:29:24 +08:00
Previously, the SiteSetting::Update service allowed to update of a single site setting. In the About controller, we were using the loop through all settings - https://github.com/discourse/discourse/blob/main/app/controllers/admin/config/about_controller.rb#L39 It is suboptimal because if the 3 first settings are saved and the fourth is invalid, we will end with partially updated data. Changing SiteSetting::Update to accept hash means that we will check upfront if none of the settings are hidden or invalid and update all or none. Custom policies are used to report which settings are failing.
99 lines
3 KiB
Ruby
Vendored
99 lines
3 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe SiteSetting::Update do
|
|
describe described_class::Contract, type: :model do
|
|
it { is_expected.to validate_presence_of :settings }
|
|
end
|
|
|
|
describe ".call" do
|
|
subject(:result) { described_class.call(params:, options:, **dependencies) }
|
|
|
|
fab!(:admin)
|
|
let(:params) { { settings: } }
|
|
let(:settings) { { setting_name => new_value } }
|
|
let(:options) { { allow_changing_hidden: } }
|
|
let(:dependencies) { { guardian: } }
|
|
let(:setting_name) { :title }
|
|
let(:new_value) { "blah whatever" }
|
|
let(:guardian) { admin.guardian }
|
|
let(:allow_changing_hidden) { [] }
|
|
|
|
context "when settings is blank" do
|
|
let(:settings) { nil }
|
|
|
|
it { is_expected.to fail_a_contract }
|
|
end
|
|
|
|
context "when a non-admin user tries to change a setting" do
|
|
let(:guardian) { Guardian.new }
|
|
|
|
it { is_expected.to fail_a_policy(:current_user_is_admin) }
|
|
end
|
|
|
|
context "when the user changes a hidden setting" do
|
|
let(:setting_name) { :max_category_nesting }
|
|
let(:new_value) { 3 }
|
|
|
|
context "when allow_changing_hidden is empty array" do
|
|
it { is_expected.to fail_a_policy(:settings_are_visible) }
|
|
end
|
|
|
|
context "when allow_changing_hidden is including setting" do
|
|
let(:allow_changing_hidden) { [:max_category_nesting] }
|
|
|
|
it { is_expected.to run_successfully }
|
|
|
|
it "updates the specified setting" do
|
|
expect { result }.to change { SiteSetting.max_category_nesting }.to(3)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when a user changes a setting shadowed by a global variable" do
|
|
let(:setting_name) { :max_category_nesting }
|
|
let(:new_value) { 3 }
|
|
|
|
before { SiteSetting.stubs(:shadowed_settings).returns(Set.new([:max_category_nesting])) }
|
|
|
|
it { is_expected.to fail_a_policy(:settings_are_unshadowed_globally) }
|
|
end
|
|
|
|
context "when the user changes a visible setting" do
|
|
let(:new_value) { "hello this is title" }
|
|
|
|
it { is_expected.to run_successfully }
|
|
|
|
it "updates the specified setting" do
|
|
expect { result }.to change { SiteSetting.title }.to(new_value)
|
|
end
|
|
|
|
it "creates an entry in the staff action logs" do
|
|
expect { result }.to change {
|
|
UserHistory.where(
|
|
action: UserHistory.actions[:change_site_setting],
|
|
subject: "title",
|
|
).count
|
|
}.by(1)
|
|
end
|
|
|
|
context "when value needs cleanup" do
|
|
let(:setting_name) { :max_image_size_kb }
|
|
let(:new_value) { "8zf843" }
|
|
|
|
it "cleans up the new setting value before using it" do
|
|
expect { result }.to change { SiteSetting.max_image_size_kb }.to(8843)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when one setting is having invalid value" do
|
|
let(:settings) { { title: "hello this is title", default_categories_watching: "999999" } }
|
|
|
|
it { is_expected.to fail_a_policy(:values_are_valid) }
|
|
|
|
it "does not update valid setting" do
|
|
expect { result }.not_to change { SiteSetting.title }
|
|
end
|
|
end
|
|
end
|
|
end
|