DEV: Add configurable? helper to Plugin::Instance (#20767)

This can be used to forcibly disable plugins.
This commit is contained in:
Bianca Nenciu 2023-05-10 12:16:37 +02:00 committed by GitHub
parent c6b43ce68b
commit 3073e5cfb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 100 additions and 16 deletions

View File

@ -259,10 +259,18 @@ class Admin::SiteSettingsController < Admin::AdminController
end end
def raise_access_hidden_setting(id) def raise_access_hidden_setting(id)
# note, as of Ruby 2.3 symbols are GC'd so this is considered safe id = id.to_sym
if SiteSetting.hidden_settings.include?(id.to_sym)
if SiteSetting.hidden_settings.include?(id)
raise Discourse::InvalidParameters, "You are not allowed to change hidden settings" raise Discourse::InvalidParameters, "You are not allowed to change hidden settings"
end end
if SiteSetting.plugins[id]
plugin = Discourse.plugins_by_name[SiteSetting.plugins[id]]
if !plugin.configurable?
raise Discourse::InvalidParameters, "You are not allowed to change unconfigurable settings"
end
end
end end
def tag_notification_level(id) def tag_notification_level(id)

View File

@ -346,7 +346,11 @@ class ApplicationController < ActionController::Base
# disabled. This allows plugins to be disabled programmatically. # disabled. This allows plugins to be disabled programmatically.
def self.requires_plugin(plugin_name) def self.requires_plugin(plugin_name)
before_action do before_action do
raise PluginDisabled.new if Discourse.disabled_plugin_names.include?(plugin_name) if plugin = Discourse.plugins_by_name[plugin_name]
raise PluginDisabled.new if !plugin.enabled?
else
Rails.logger.warn("Required plugin '#{plugin_name}' not found")
end
end end
end end

View File

@ -344,6 +344,7 @@ module Discourse
def self.activate_plugins! def self.activate_plugins!
@plugins = [] @plugins = []
@plugins_by_name = {}
Plugin::Instance Plugin::Instance
.find_all("#{Rails.root}/plugins") .find_all("#{Rails.root}/plugins")
.each do |p| .each do |p|
@ -351,6 +352,7 @@ module Discourse
if Discourse.has_needed_version?(Discourse::VERSION::STRING, v) if Discourse.has_needed_version?(Discourse::VERSION::STRING, v)
p.activate! p.activate!
@plugins << p @plugins << p
@plugins_by_name[p.name] = p
else else
STDERR.puts "Could not activate #{p.metadata.name}, discourse does not meet required version (#{v})" STDERR.puts "Could not activate #{p.metadata.name}, discourse does not meet required version (#{v})"
end end
@ -358,20 +360,16 @@ module Discourse
DiscourseEvent.trigger(:after_plugin_activation) DiscourseEvent.trigger(:after_plugin_activation)
end end
def self.disabled_plugin_names
plugins.select { |p| !p.enabled? }.map(&:name)
end
def self.plugins def self.plugins
@plugins ||= [] @plugins ||= []
end end
def self.hidden_plugins def self.plugins_by_name
@hidden_plugins ||= [] @plugins_by_name ||= {}
end end
def self.visible_plugins def self.visible_plugins
self.plugins - self.hidden_plugins plugins.filter(&:visible?)
end end
def self.plugin_themes def self.plugin_themes

View File

@ -103,7 +103,16 @@ class Plugin::Instance
@admin_route = { label: label, location: location } @admin_route = { label: label, location: location }
end end
def configurable?
true
end
def visible?
configurable? && !@hidden
end
def enabled? def enabled?
return false if !configurable?
@enabled_site_setting ? SiteSetting.get(@enabled_site_setting) : true @enabled_site_setting ? SiteSetting.get(@enabled_site_setting) : true
end end
@ -825,11 +834,7 @@ class Plugin::Instance
end end
def hide_plugin def hide_plugin
Discourse.hidden_plugins << self @hidden = true
end
def enabled_site_setting_filter(filter = nil)
STDERR.puts("`enabled_site_setting_filter` is deprecated")
end end
def enabled_site_setting(setting = nil) def enabled_site_setting(setting = nil)

View File

@ -166,6 +166,20 @@ module SiteSettingExtension
end end
end end
def remove_setting(name_arg)
raise if !Rails.env.test?
name = name_arg.to_sym
categories.delete(name)
hidden_settings.delete(name)
refresh_settings.delete(name)
client_settings.delete(name)
previews.delete(name)
secret_settings.delete(name)
plugins.delete(name)
end
def settings_hash def settings_hash
result = {} result = {}
deprecated_settings = Set.new deprecated_settings = Set.new
@ -224,6 +238,9 @@ module SiteSettingExtension
defaults defaults
.all(default_locale) .all(default_locale)
.filter do |setting_name, _|
!plugins[setting_name] || Discourse.plugins_by_name[plugins[setting_name]].configurable?
end
.reject { |setting_name, _| !include_hidden && hidden_settings.include?(setting_name) } .reject { |setting_name, _| !include_hidden && hidden_settings.include?(setting_name) }
.map do |s, v| .map do |s, v|
type_hash = type_supervisor.type_hash(s) type_hash = type_supervisor.type_hash(s)
@ -544,6 +561,11 @@ module SiteSettingExtension
end end
else else
define_singleton_method clean_name do define_singleton_method clean_name do
if plugins[name]
plugin = Discourse.plugins_by_name[plugins[name]]
return false if !plugin.configurable? && plugin.enabled_site_setting == name
end
if (c = current[name]).nil? if (c = current[name]).nil?
refresh! refresh!
current[name] current[name]

View File

@ -20,7 +20,7 @@ hide_plugin
after_initialize do after_initialize do
module ::DiscoursePoll module ::DiscoursePoll
PLUGIN_NAME ||= "discourse_poll" PLUGIN_NAME ||= "poll"
DATA_PREFIX ||= "data-poll-" DATA_PREFIX ||= "data-poll-"
HAS_POLLS ||= "has_polls" HAS_POLLS ||= "has_polls"
DEFAULT_POLL_NAME ||= "poll" DEFAULT_POLL_NAME ||= "poll"

View File

@ -608,6 +608,53 @@ RSpec.describe Admin::SiteSettingsController do
expect(response.status).to eq(422) expect(response.status).to eq(422)
end end
it "does not allow changing of hidden settings" do
SiteSetting.setting(:hidden_setting, "hidden", hidden: true)
SiteSetting.refresh!
put "/admin/site_settings/hidden_setting.json", params: { hidden_setting: "not allowed" }
expect(SiteSetting.hidden_setting).to eq("hidden")
expect(response.status).to eq(422)
end
context "with an plugin" do
let(:plugin) do
metadata = Plugin::Metadata.new
metadata.name = "discourse-plugin"
Plugin::Instance.new(metadata)
end
before do
Discourse.plugins_by_name[plugin.name] = plugin
SiteSetting.setting(:plugin_setting, "default value", plugin: "discourse-plugin")
SiteSetting.refresh!
end
after do
Discourse.plugins_by_name.delete(plugin.name)
SiteSetting.remove_setting(:plugin_setting)
end
it "allows changing settings of configurable plugins" do
plugin.stubs(:configurable?).returns(true)
put "/admin/site_settings/plugin_setting.json", params: { plugin_setting: "new value" }
expect(SiteSetting.plugin_setting).to eq("new value")
expect(response.status).to eq(200)
end
it "does not allow changing of unconfigurable settings" do
plugin.stubs(:configurable?).returns(false)
put "/admin/site_settings/plugin_setting.json", params: { plugin_setting: "not allowed" }
expect(SiteSetting.plugin_setting).to eq("default value")
expect(response.status).to eq(422)
end
end
it "fails when a setting does not exist" do it "fails when a setting does not exist" do
put "/admin/site_settings/provider.json", params: { provider: "gotcha" } put "/admin/site_settings/provider.json", params: { provider: "gotcha" }
expect(response.status).to eq(422) expect(response.status).to eq(422)