0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-14 13:58:53 +08:00
discourse/app/services/site_setting/update.rb
Martin Brennan 75a9a3ca13
FEATURE: Show editable category type settings in tab(s) (#38143)
Builds on top of 97bd00d707

When creating or editing a category, we need to show an individual
tab for each matching category type so the admin can see and change
those settings. These settings are defined server-side in a schema
and added to the FormKit form in the UI.

At first, we expect in most cases to only really match one type,
but it's possible to match more than one.

The only tab we are adding for now is the Support type for the
discourse-solved plugin, but this will allow us to easily add more in
the
future if we want to.

This commit also adds server-side code to determine the category
types for any given category based on the type registry, and adds
functionality
to load the setting schema into the form and save the results when
submitted,
along with a lot of other glue code

For new Support categories we will also prefill the name and style type
as an emoji

---------

Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
Co-authored-by: awesomerobot <kris.aubuchon@discourse.org>
Co-authored-by: Sam Saffron <sam.saffron@gmail.com>
2026-03-05 11:44:43 +10:00

120 lines
3.3 KiB
Ruby
Vendored

# frozen_string_literal: true
class SiteSetting::Update
include Service::Base
Setting = Struct.new(:name, :value, :backfill, :change)
options do
attribute :allow_changing_hidden, :array, default: []
attribute :overridden_setting_names, default: {}
end
policy :current_user_is_admin
params do
attribute :settings
before_validation do
dependent_order = SiteSetting.type_supervisor.dependencies.order
self.settings =
self
.settings
.to_a
.map do |setting|
Setting.new(
setting[:setting_name].to_sym,
setting[:value].to_s.strip,
!!setting[:backfill],
nil,
)
end
.sort_by { |s| dependent_order.index(s.name) }
end
validates :settings, presence: true
after_validation do
self.settings =
self.settings.map do |setting|
raw_value = setting.value
setting.value =
case SiteSetting.type_supervisor.get_type(setting.name)
when :integer
raw_value.tr("^-0-9", "").to_i
when :file_size_restriction
raw_value.tr("^0-9", "").to_i
when :uploaded_image_list
raw_value.blank? ? "" : Upload.get_from_urls(raw_value.split("|")).to_a
when :upload
Upload.get_from_url(raw_value) || ""
else
raw_value
end
# Make sure to get the correct value here based on type, otherwise
# we can end up inserting a staff action log when e.g. setting the value
# to "false" when the setting value is already false.
setting.value = SiteSetting.type_supervisor.to_rb_value(setting.name, setting.value)
setting
end
end
end
policy :settings_are_not_deprecated, class_name: SiteSetting::Policy::SettingsAreNotDeprecated
policy :settings_are_unshadowed_globally,
class_name: SiteSetting::Policy::SettingsAreUnshadowedGlobally
policy :settings_are_visible, class_name: SiteSetting::Policy::SettingsAreVisible
policy :settings_are_configurable, class_name: SiteSetting::Policy::SettingsAreConfigurable
try do
transaction do
step :save
step :backfill
end
end
private
def current_user_is_admin(guardian:)
guardian.is_admin?
end
def save(params:, options:, guardian:)
params.settings.each do |setting|
detailed_message =
if default_user_preference?(setting)
value =
setting.backfill ? I18n.t("csv_export.boolean_yes") : I18n.t("csv_export.boolean_no")
I18n.t("staff_action_logs.site_setting.update_existing_users", value:)
end
setting.change =
SiteSetting.set_and_log(
options.overridden_setting_names[setting.name] || setting.name,
setting.value,
guardian.user,
detailed_message,
)
end
end
def backfill(params:)
params.settings.each do |setting|
next if !setting.backfill || !default_user_preference?(setting)
SiteSettingUpdateExistingUsers.call(
setting.name.to_s,
setting.change.new_value,
setting.change.previous_value,
)
end
end
def default_user_preference?(setting)
SiteSetting::DEFAULT_USER_PREFERENCES.include?(setting.name.to_s)
end
end