2019-05-02 18:17:27 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
class SiteSetting < ActiveRecord::Base
|
2018-12-19 04:20:48 -05:00
|
|
|
extend GlobalPath
|
2013-02-05 14:16:51 -05:00
|
|
|
extend SiteSettingExtension
|
|
|
|
|
2022-06-08 19:24:30 -04:00
|
|
|
has_many :upload_references, as: :target, dependent: :destroy
|
|
|
|
|
2013-02-05 14:16:51 -05:00
|
|
|
validates_presence_of :name
|
|
|
|
validates_presence_of :data_type
|
|
|
|
|
2022-06-08 19:24:30 -04:00
|
|
|
after_save do
|
|
|
|
if saved_change_to_value?
|
|
|
|
if self.data_type == SiteSettings::TypeSupervisor.types[:upload]
|
|
|
|
UploadReference.ensure_exist!(upload_ids: [self.value], target: self)
|
|
|
|
elsif self.data_type == SiteSettings::TypeSupervisor.types[:uploaded_image_list]
|
|
|
|
upload_ids = self.value.split("|").compact.uniq
|
|
|
|
UploadReference.ensure_exist!(upload_ids: upload_ids, target: self)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-11-19 14:43:01 -05:00
|
|
|
load_settings(File.join(Rails.root, "config", "site_settings.yml"))
|
|
|
|
|
2023-05-24 19:53:57 -04:00
|
|
|
if Rails.env.test?
|
|
|
|
SAMPLE_TEST_PLUGIN =
|
|
|
|
Plugin::Instance.new(
|
|
|
|
Plugin::Metadata.new.tap { |metadata| metadata.name = "discourse-sample-plugin" },
|
|
|
|
)
|
|
|
|
|
|
|
|
Discourse.plugins_by_name[SAMPLE_TEST_PLUGIN.name] = SAMPLE_TEST_PLUGIN
|
|
|
|
|
|
|
|
load_settings(
|
|
|
|
File.join(Rails.root, "spec", "support", "sample_plugin_site_settings.yml"),
|
|
|
|
plugin: SAMPLE_TEST_PLUGIN.name,
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2022-01-11 07:30:22 -05:00
|
|
|
if GlobalSetting.load_plugins?
|
2014-12-11 11:08:47 -05:00
|
|
|
Dir[File.join(Rails.root, "plugins", "*", "config", "settings.yml")].each do |file|
|
2020-05-10 07:07:45 -04:00
|
|
|
load_settings(file, plugin: file.split("/")[-3])
|
2014-12-11 11:08:47 -05:00
|
|
|
end
|
2013-11-19 14:43:01 -05:00
|
|
|
end
|
|
|
|
|
2018-11-14 04:32:32 -05:00
|
|
|
setup_deprecated_methods
|
2014-03-28 01:36:17 -04:00
|
|
|
client_settings << :available_locales
|
2014-02-07 22:24:10 -05:00
|
|
|
|
|
|
|
def self.available_locales
|
2017-12-13 16:17:36 -05:00
|
|
|
LocaleSiteSetting.values.to_json
|
2014-02-07 22:24:10 -05:00
|
|
|
end
|
2013-11-19 14:43:01 -05:00
|
|
|
|
2013-02-26 11:27:59 -05:00
|
|
|
def self.topic_title_length
|
|
|
|
min_topic_title_length..max_topic_title_length
|
|
|
|
end
|
|
|
|
|
2013-06-04 17:58:25 -04:00
|
|
|
def self.private_message_title_length
|
2018-01-31 00:56:00 -05:00
|
|
|
min_personal_message_title_length..max_topic_title_length
|
2013-06-04 17:58:25 -04:00
|
|
|
end
|
|
|
|
|
2013-02-28 13:54:12 -05:00
|
|
|
def self.post_length
|
|
|
|
min_post_length..max_post_length
|
|
|
|
end
|
2013-03-28 09:01:13 -04:00
|
|
|
|
2015-03-19 10:17:55 -04:00
|
|
|
def self.first_post_length
|
|
|
|
min_first_post_length..max_post_length
|
|
|
|
end
|
|
|
|
|
2013-06-13 04:18:17 -04:00
|
|
|
def self.private_message_post_length
|
2018-01-31 00:56:00 -05:00
|
|
|
min_personal_message_post_length..max_post_length
|
2013-06-13 04:18:17 -04:00
|
|
|
end
|
|
|
|
|
2013-06-21 16:31:40 -04:00
|
|
|
def self.top_menu_items
|
|
|
|
top_menu.split("|").map { |menu_item| TopMenuItem.new(menu_item) }
|
|
|
|
end
|
|
|
|
|
2013-03-28 09:01:13 -04:00
|
|
|
def self.homepage
|
2013-06-21 16:31:40 -04:00
|
|
|
top_menu_items[0].name
|
2013-03-28 09:01:13 -04:00
|
|
|
end
|
|
|
|
|
2013-07-15 19:59:23 -04:00
|
|
|
def self.anonymous_menu_items
|
2013-12-23 18:50:36 -05:00
|
|
|
@anonymous_menu_items ||= Set.new Discourse.anonymous_filters.map(&:to_s)
|
2013-07-15 19:59:23 -04:00
|
|
|
end
|
|
|
|
|
2013-03-28 09:01:13 -04:00
|
|
|
def self.anonymous_homepage
|
2013-07-15 19:59:23 -04:00
|
|
|
top_menu_items
|
|
|
|
.map { |item| item.name }
|
|
|
|
.select { |item| anonymous_menu_items.include?(item) }
|
|
|
|
.first
|
|
|
|
end
|
|
|
|
|
2014-04-21 16:59:53 -04:00
|
|
|
def self.should_download_images?(src)
|
|
|
|
setting = disabled_image_download_domains
|
2019-06-03 14:17:25 -04:00
|
|
|
return true if setting.blank?
|
2014-04-21 16:59:53 -04:00
|
|
|
|
2014-05-07 13:49:16 -04:00
|
|
|
host = URI.parse(src).host
|
2019-06-03 14:17:25 -04:00
|
|
|
!setting.split("|").include?(host)
|
2018-08-14 06:23:32 -04:00
|
|
|
rescue URI::Error
|
2019-06-03 14:17:25 -04:00
|
|
|
true
|
2014-04-21 16:59:53 -04:00
|
|
|
end
|
|
|
|
|
2013-12-16 05:44:59 -05:00
|
|
|
def self.scheme
|
2016-06-27 05:26:43 -04:00
|
|
|
force_https? ? "https" : "http"
|
2013-12-16 05:44:59 -05:00
|
|
|
end
|
|
|
|
|
2016-10-11 13:22:43 -04:00
|
|
|
def self.min_redirected_to_top_period(duration)
|
2019-06-03 14:17:25 -04:00
|
|
|
ListController.best_period_with_topics_for(duration)
|
2015-09-21 14:28:20 -04:00
|
|
|
end
|
|
|
|
|
2019-03-14 11:39:10 -04:00
|
|
|
def self.queue_jobs=(val)
|
2021-11-12 09:52:59 -05:00
|
|
|
Discourse.deprecate(
|
|
|
|
"queue_jobs is deprecated. Please use Jobs.run_immediately! instead",
|
|
|
|
drop_from: "2.9.0",
|
|
|
|
)
|
2019-03-14 11:39:10 -04:00
|
|
|
val ? Jobs.run_later! : Jobs.run_immediately!
|
|
|
|
end
|
|
|
|
|
2016-03-16 17:28:01 -04:00
|
|
|
def self.email_polling_enabled?
|
|
|
|
SiteSetting.manual_polling_enabled? || SiteSetting.pop3_polling_enabled?
|
|
|
|
end
|
2016-08-03 11:55:54 -04:00
|
|
|
|
2020-07-26 20:23:54 -04:00
|
|
|
def self.blocked_attachment_content_types_regex
|
2022-03-11 10:16:56 -05:00
|
|
|
current_db = RailsMultisite::ConnectionManagement.current_db
|
|
|
|
|
|
|
|
@blocked_attachment_content_types_regex ||= {}
|
|
|
|
@blocked_attachment_content_types_regex[current_db] ||= begin
|
|
|
|
Regexp.union(SiteSetting.blocked_attachment_content_types.split("|"))
|
|
|
|
end
|
2016-08-03 11:55:54 -04:00
|
|
|
end
|
|
|
|
|
2020-07-26 20:23:54 -04:00
|
|
|
def self.blocked_attachment_filenames_regex
|
2022-03-11 10:16:56 -05:00
|
|
|
current_db = RailsMultisite::ConnectionManagement.current_db
|
|
|
|
|
|
|
|
@blocked_attachment_filenames_regex ||= {}
|
|
|
|
@blocked_attachment_filenames_regex[current_db] ||= begin
|
|
|
|
Regexp.union(SiteSetting.blocked_attachment_filenames.split("|"))
|
|
|
|
end
|
2016-08-03 11:55:54 -04:00
|
|
|
end
|
2017-10-06 01:20:01 -04:00
|
|
|
|
2020-07-26 20:23:54 -04:00
|
|
|
def self.allowed_unicode_username_characters_regex
|
2022-03-11 10:16:56 -05:00
|
|
|
current_db = RailsMultisite::ConnectionManagement.current_db
|
|
|
|
|
|
|
|
@allowed_unicode_username_regex ||= {}
|
|
|
|
@allowed_unicode_username_regex[current_db] ||= begin
|
|
|
|
if SiteSetting.allowed_unicode_username_characters.present?
|
|
|
|
Regexp.new(SiteSetting.allowed_unicode_username_characters)
|
|
|
|
end
|
|
|
|
end
|
2019-04-23 06:22:47 -04:00
|
|
|
end
|
|
|
|
|
2017-10-06 01:20:01 -04:00
|
|
|
# helpers for getting s3 settings that fallback to global
|
|
|
|
class Upload
|
|
|
|
def self.s3_cdn_url
|
|
|
|
SiteSetting.enable_s3_uploads ? SiteSetting.s3_cdn_url : GlobalSetting.s3_cdn_url
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.s3_region
|
|
|
|
SiteSetting.enable_s3_uploads ? SiteSetting.s3_region : GlobalSetting.s3_region
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.s3_upload_bucket
|
|
|
|
SiteSetting.enable_s3_uploads ? SiteSetting.s3_upload_bucket : GlobalSetting.s3_bucket
|
|
|
|
end
|
|
|
|
|
2018-07-16 00:44:55 -04:00
|
|
|
def self.s3_endpoint
|
|
|
|
SiteSetting.enable_s3_uploads ? SiteSetting.s3_endpoint : GlobalSetting.s3_endpoint
|
|
|
|
end
|
|
|
|
|
2017-10-06 01:20:01 -04:00
|
|
|
def self.enable_s3_uploads
|
|
|
|
SiteSetting.enable_s3_uploads || GlobalSetting.use_s3?
|
|
|
|
end
|
|
|
|
|
2018-07-06 03:52:23 -04:00
|
|
|
def self.s3_base_url
|
|
|
|
path = self.s3_upload_bucket.split("/", 2)[1]
|
|
|
|
"#{self.absolute_base_url}#{path ? "/" + path : ""}"
|
|
|
|
end
|
|
|
|
|
2017-10-06 01:20:01 -04:00
|
|
|
def self.absolute_base_url
|
2018-07-16 00:44:55 -04:00
|
|
|
url_basename = SiteSetting.s3_endpoint.split("/")[-1]
|
2018-05-16 16:10:15 -04:00
|
|
|
bucket =
|
2023-01-09 07:20:10 -05:00
|
|
|
(
|
2018-05-16 16:10:15 -04:00
|
|
|
if SiteSetting.enable_s3_uploads
|
|
|
|
Discourse.store.s3_bucket_name
|
2023-01-09 07:20:10 -05:00
|
|
|
else
|
2018-05-16 16:10:15 -04:00
|
|
|
GlobalSetting.s3_bucket_name
|
2023-01-09 07:20:10 -05:00
|
|
|
end
|
|
|
|
)
|
2017-10-06 01:20:01 -04:00
|
|
|
|
2018-07-06 18:15:28 -04:00
|
|
|
# cf. http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
|
2019-02-05 11:50:27 -05:00
|
|
|
if SiteSetting.s3_endpoint.blank? || SiteSetting.s3_endpoint.end_with?("amazonaws.com")
|
2018-12-26 11:34:49 -05:00
|
|
|
if SiteSetting.Upload.s3_region.start_with?("cn-")
|
2018-08-26 21:22:46 -04:00
|
|
|
"//#{bucket}.s3.#{SiteSetting.Upload.s3_region}.amazonaws.com.cn"
|
2018-07-16 00:44:55 -04:00
|
|
|
else
|
2018-08-26 21:22:46 -04:00
|
|
|
"//#{bucket}.s3.dualstack.#{SiteSetting.Upload.s3_region}.amazonaws.com"
|
2018-07-16 00:44:55 -04:00
|
|
|
end
|
2018-07-06 18:15:28 -04:00
|
|
|
else
|
2018-07-16 00:44:55 -04:00
|
|
|
"//#{bucket}.#{url_basename}"
|
2018-07-06 18:15:28 -04:00
|
|
|
end
|
2017-10-06 01:20:01 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.Upload
|
|
|
|
SiteSetting::Upload
|
|
|
|
end
|
|
|
|
|
2022-06-29 20:18:12 -04:00
|
|
|
def self.whispers_allowed_group_ids
|
2022-12-16 11:42:51 -05:00
|
|
|
if SiteSetting.whispers_allowed_groups.present?
|
2022-11-08 16:48:05 -05:00
|
|
|
SiteSetting.whispers_allowed_groups_map
|
2022-06-29 20:18:12 -04:00
|
|
|
else
|
|
|
|
[]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-03-15 06:17:28 -04:00
|
|
|
def self.require_invite_code
|
|
|
|
invite_code.present?
|
|
|
|
end
|
|
|
|
client_settings << :require_invite_code
|
|
|
|
|
2018-11-14 02:03:02 -05:00
|
|
|
%i[
|
|
|
|
site_logo_url
|
|
|
|
site_logo_small_url
|
|
|
|
site_mobile_logo_url
|
|
|
|
site_favicon_url
|
2020-08-17 15:43:20 -04:00
|
|
|
site_logo_dark_url
|
|
|
|
site_logo_small_dark_url
|
|
|
|
site_mobile_logo_dark_url
|
2018-11-14 02:03:02 -05:00
|
|
|
].each { |client_setting| client_settings << client_setting }
|
|
|
|
|
2019-01-02 02:29:17 -05:00
|
|
|
%i[
|
|
|
|
logo
|
|
|
|
logo_small
|
|
|
|
digest_logo
|
|
|
|
mobile_logo
|
2020-08-17 15:43:20 -04:00
|
|
|
logo_dark
|
|
|
|
logo_small_dark
|
|
|
|
mobile_logo_dark
|
2019-01-02 02:29:17 -05:00
|
|
|
large_icon
|
2019-05-01 09:44:45 -04:00
|
|
|
manifest_icon
|
2019-01-02 02:29:17 -05:00
|
|
|
favicon
|
|
|
|
apple_touch_icon
|
|
|
|
twitter_summary_large_image
|
|
|
|
opengraph_image
|
|
|
|
push_notifications_icon
|
|
|
|
].each do |setting_name|
|
|
|
|
define_singleton_method("site_#{setting_name}_url") do
|
2019-05-01 09:44:45 -04:00
|
|
|
if SiteIconManager.respond_to?("#{setting_name}_url")
|
|
|
|
return SiteIconManager.public_send("#{setting_name}_url")
|
|
|
|
end
|
|
|
|
|
2019-01-02 02:29:17 -05:00
|
|
|
upload = self.public_send(setting_name)
|
|
|
|
upload ? full_cdn_url(upload.url) : ""
|
2019-01-11 02:46:31 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-03-13 15:59:12 -04:00
|
|
|
def self.shared_drafts_enabled?
|
|
|
|
c = SiteSetting.shared_drafts_category
|
|
|
|
c.present? && c.to_i != SiteSetting.uncategorized_category_id.to_i
|
|
|
|
end
|
|
|
|
|
2022-12-07 20:44:29 -05:00
|
|
|
def self.legacy_navigation_menu?
|
|
|
|
SiteSetting.navigation_menu == "legacy"
|
|
|
|
end
|
|
|
|
|
2020-07-26 20:23:54 -04:00
|
|
|
ALLOWLIST_DEPRECATED_SITE_SETTINGS = {
|
|
|
|
email_domains_blacklist: "blocked_email_domains",
|
|
|
|
email_domains_whitelist: "allowed_email_domains",
|
|
|
|
unicode_username_character_whitelist: "allowed_unicode_username_characters",
|
|
|
|
user_website_domains_whitelist: "allowed_user_website_domains",
|
|
|
|
whitelisted_link_domains: "allowed_link_domains",
|
|
|
|
embed_whitelist_selector: "allowed_embed_selectors",
|
|
|
|
auto_generated_whitelist: "auto_generated_allowlist",
|
|
|
|
attachment_content_type_blacklist: "blocked_attachment_content_types",
|
|
|
|
attachment_filename_blacklist: "blocked_attachment_filenames",
|
|
|
|
use_admin_ip_whitelist: "use_admin_ip_allowlist",
|
|
|
|
blacklist_ip_blocks: "blocked_ip_blocks",
|
|
|
|
whitelist_internal_hosts: "allowed_internal_hosts",
|
|
|
|
whitelisted_crawler_user_agents: "allowed_crawler_user_agents",
|
|
|
|
blacklisted_crawler_user_agents: "blocked_crawler_user_agents",
|
|
|
|
onebox_domains_blacklist: "blocked_onebox_domains",
|
|
|
|
inline_onebox_domains_whitelist: "allowed_inline_onebox_domains",
|
|
|
|
white_listed_spam_host_domains: "allowed_spam_host_domains",
|
|
|
|
embed_blacklist_selector: "blocked_embed_selectors",
|
|
|
|
embed_classname_whitelist: "allowed_embed_classnames",
|
|
|
|
}
|
|
|
|
|
|
|
|
ALLOWLIST_DEPRECATED_SITE_SETTINGS.each_pair do |old_method, new_method|
|
DEV: Stop polluting `Class` with deprecated settings methods (#10736)
`self.class` here evaluates to `Class` and then we're calling `define_method` on it which means all classes will have those methods defined in them. For example:
```
~/discourse(master*) » rails c
Loading development environment (Rails 6.0.3.3)
[1] pry(main)> Integer.methods
=> [:sqrt,
:yaml_tag,
:email_domains_blacklist=,
:email_domains_whitelist=,
:unicode_username_character_whitelist=,
:user_website_domains_whitelist=,
:whitelisted_link_domains=,
:email_domains_blacklist,
:email_domains_whitelist,
:unicode_username_character_whitelist,
...
...
```
Fix here is to use `self.define_singleton_method`.
2020-09-23 18:58:53 -04:00
|
|
|
self.define_singleton_method(old_method) do
|
2021-12-02 13:16:55 -05:00
|
|
|
Discourse.deprecate(
|
|
|
|
"#{old_method.to_s} is deprecated, use the #{new_method.to_s}.",
|
|
|
|
drop_from: "2.6",
|
|
|
|
raise_error: true,
|
|
|
|
)
|
2020-07-26 20:23:54 -04:00
|
|
|
send(new_method)
|
|
|
|
end
|
DEV: Stop polluting `Class` with deprecated settings methods (#10736)
`self.class` here evaluates to `Class` and then we're calling `define_method` on it which means all classes will have those methods defined in them. For example:
```
~/discourse(master*) » rails c
Loading development environment (Rails 6.0.3.3)
[1] pry(main)> Integer.methods
=> [:sqrt,
:yaml_tag,
:email_domains_blacklist=,
:email_domains_whitelist=,
:unicode_username_character_whitelist=,
:user_website_domains_whitelist=,
:whitelisted_link_domains=,
:email_domains_blacklist,
:email_domains_whitelist,
:unicode_username_character_whitelist,
...
...
```
Fix here is to use `self.define_singleton_method`.
2020-09-23 18:58:53 -04:00
|
|
|
self.define_singleton_method("#{old_method}=") do |args|
|
2021-12-02 13:16:55 -05:00
|
|
|
Discourse.deprecate(
|
|
|
|
"#{old_method.to_s} is deprecated, use the #{new_method.to_s}.",
|
|
|
|
drop_from: "2.6",
|
|
|
|
raise_error: true,
|
|
|
|
)
|
2020-07-26 20:23:54 -04:00
|
|
|
send("#{new_method}=", args)
|
|
|
|
end
|
|
|
|
end
|
2022-03-11 10:16:56 -05:00
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
def self.clear_cache!
|
|
|
|
super
|
|
|
|
|
|
|
|
@blocked_attachment_content_types_regex = nil
|
|
|
|
@blocked_attachment_filenames_regex = nil
|
|
|
|
@allowed_unicode_username_regex = nil
|
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
2013-05-23 22:48:32 -04:00
|
|
|
|
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: site_settings
|
|
|
|
#
|
|
|
|
# id :integer not null, primary key
|
2019-01-11 14:29:56 -05:00
|
|
|
# name :string not null
|
2013-05-23 22:48:32 -04:00
|
|
|
# data_type :integer not null
|
|
|
|
# value :text
|
2014-08-27 01:30:17 -04:00
|
|
|
# created_at :datetime not null
|
|
|
|
# updated_at :datetime not null
|
2013-05-23 22:48:32 -04:00
|
|
|
#
|
2019-04-02 01:17:55 -04:00
|
|
|
# Indexes
|
|
|
|
#
|
|
|
|
# index_site_settings_on_name (name) UNIQUE
|
|
|
|
#
|