mirror of
https://github.com/discourse/discourse.git
synced 2026-08-14 13:58:53 +08:00
We often need to change site setting defaults when we would like to change default behaviour for the Discourse software. However, we want to be non-disruptive to existing sites, as some default changes can modify the behaviour of existing features quite a lot. In the past, when we did this we would write the old default to the database for anyone who hadn't changed the setting, and then change it for new sites going forward. However in practice means that there are large portions of Discourse sites with "bad" defaults that we no longer agree with, that slows adoption of best practices and makes it harder to reason about our different features. This change adds a way for upcoming changes to control the rollout of changes to site setting defaults via additional metadata attached to the setting whose default is changing. This way, we can have a more gradual rollout of new defaults, and we can also inform site admins about the upcoming change and give them a chance to opt in early if they want to.
81 lines
2.1 KiB
Ruby
Vendored
81 lines
2.1 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
class UpcomingChanges::Toggle
|
|
include Service::Base
|
|
|
|
# For cases like the UpcomingChanges::Promote where we don't want to log
|
|
# the change again since it's already being logged there.
|
|
options { attribute :log_change, default: true }
|
|
|
|
params do
|
|
attribute :setting_name, :symbol
|
|
attribute :enabled, :boolean
|
|
validates :setting_name, presence: true
|
|
validates :enabled, inclusion: [true, false]
|
|
|
|
def upcoming_change_event
|
|
enabled ? :upcoming_change_enabled : :upcoming_change_disabled
|
|
end
|
|
end
|
|
|
|
policy :current_user_is_admin
|
|
policy :setting_is_available
|
|
transaction { step :toggle }
|
|
|
|
step :clear_groups_if_disallowed
|
|
|
|
only_if(:should_log_change) do
|
|
step :log_change
|
|
step :log_event
|
|
end
|
|
|
|
step :trigger_event
|
|
|
|
private
|
|
|
|
def current_user_is_admin(guardian:)
|
|
guardian.is_admin?
|
|
end
|
|
|
|
def setting_is_available(params:)
|
|
SiteSetting.respond_to?(params.setting_name)
|
|
end
|
|
|
|
def toggle(params:, guardian:, options:)
|
|
context[:previous_value] = SiteSetting.public_send(params.setting_name)
|
|
SiteSetting.send("#{params.setting_name}=", params.enabled)
|
|
end
|
|
|
|
def clear_groups_if_disallowed(params:)
|
|
metadata = SiteSetting.upcoming_change_metadata[params.setting_name]
|
|
return if !metadata || !metadata[:disallow_enabled_for_groups]
|
|
|
|
SiteSettingGroup.find_by(name: params.setting_name)&.destroy!
|
|
SiteSetting.refresh_site_setting_group_ids!
|
|
end
|
|
|
|
def should_log_change(options:)
|
|
options.log_change
|
|
end
|
|
|
|
def log_change(params:, guardian:, options:)
|
|
StaffActionLogger.new(guardian.user).log_upcoming_change_toggle(
|
|
params.setting_name,
|
|
context[:previous_value],
|
|
params.enabled,
|
|
{ context: I18n.t("staff_action_logs.upcoming_changes.log_manually_toggled") },
|
|
)
|
|
end
|
|
|
|
def log_event(params:, guardian:, options:)
|
|
UpcomingChangeEvent.create!(
|
|
event_type: params.enabled ? :manual_opt_in : :manual_opt_out,
|
|
upcoming_change_name: params.setting_name,
|
|
acting_user: guardian.user,
|
|
)
|
|
end
|
|
|
|
def trigger_event(params:)
|
|
DiscourseEvent.trigger(params.upcoming_change_event, params.setting_name)
|
|
end
|
|
end
|