Load site settings from config/site_settings.yml

This commit is contained in:
Neil Lalonde 2013-11-06 15:47:26 -05:00
parent 968c0672ef
commit 791f5ac94e
10 changed files with 525 additions and 266 deletions

View File

@ -1,4 +1,5 @@
require 'site_setting_extension'
require_dependency 'site_settings/yaml_loader'
class SiteSetting < ActiveRecord::Base
extend SiteSettingExtension
@ -6,273 +7,15 @@ class SiteSetting < ActiveRecord::Base
validates_presence_of :name
validates_presence_of :data_type
# settings available in javascript under Discourse.SiteSettings
client_setting(:title, "Discourse")
setting(:site_description, '')
client_setting(:logo_url, '/assets/d-logo-sketch.png')
client_setting(:logo_small_url, '/assets/d-logo-sketch-small.png')
setting(:contact_email, '')
setting(:company_full_name, 'My Unconfigured Forum Ltd.')
setting(:company_short_name, 'Unconfigured Forum')
setting(:company_domain, 'www.example.com')
client_setting(:tos_url, '')
client_setting(:faq_url, '')
client_setting(:privacy_policy_url, '')
client_setting(:traditional_markdown_linebreaks, false)
client_setting(:top_menu, 'latest|new|unread|favorited|categories')
client_setting(:post_menu, 'like|edit|flag|delete|share|bookmark|reply')
client_setting(:share_links, 'twitter|facebook|google+|email')
client_setting(:track_external_right_clicks, false)
client_setting(:must_approve_users, false)
client_setting(:ga_tracking_code, "")
client_setting(:ga_domain_name, "")
client_setting(:enable_escaped_fragments, false)
client_setting(:enable_noscript_support, true)
client_setting(:enable_long_polling, true)
client_setting(:polling_interval, 3000)
client_setting(:anon_polling_interval, 30000)
client_setting(:min_post_length, Rails.env.test? ? 5 : 20)
client_setting(:min_private_message_post_length, Rails.env.test? ? 5 : 10)
client_setting(:max_post_length, 32000)
client_setting(:min_topic_title_length, 15)
client_setting(:max_topic_title_length, 255)
client_setting(:min_private_message_title_length, 2)
client_setting(:allow_uncategorized_topics, true)
client_setting(:min_search_term_length, 3)
client_setting(:flush_timings_secs, 5)
client_setting(:suppress_reply_directly_below, true)
client_setting(:suppress_reply_directly_above, true)
client_setting(:email_domains_blacklist, 'mailinator.com')
client_setting(:email_domains_whitelist)
client_setting(:version_checks, true)
setting(:new_version_emails, true)
client_setting(:min_title_similar_length, 10)
client_setting(:min_body_similar_length, 15)
# cf. https://github.com/discourse/discourse/pull/462#issuecomment-14991562
client_setting(:category_colors, 'BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|283890')
client_setting(:enable_wide_category_list, false)
SiteSettings::YamlLoader.new("#{Rails.root}/config/site_settings.yml").load do |category, name, default, opts|
# TODO: category support
if opts.delete(:client)
client_setting(name.to_sym, default)
else
setting(name.to_sym, default, opts)
end
end
# auto-replace rules for title
setting(:title_prettify, true)
client_setting(:max_image_size_kb, 2048)
client_setting(:max_attachment_size_kb, 1.kilobyte)
client_setting(:authorized_extensions, '.jpg|.jpeg|.png|.gif')
# settings only available server side
setting(:auto_track_topics_after, 240000)
setting(:new_topic_duration_minutes, 60 * 48)
setting(:long_polling_interval, 15000)
setting(:flags_required_to_hide_post, 3)
setting(:cooldown_minutes_after_hiding_posts, 10)
setting(:max_topics_in_first_day, 5)
setting(:max_replies_in_first_day, 10)
setting(:num_flags_to_block_new_user, 3)
setting(:num_users_to_block_new_user, 3)
setting(:notify_mods_when_user_blocked, false)
setting(:flag_sockpuppets, true)
# used mainly for dev, force hostname for Discourse.base_url
# You would usually use multisite for this
setting(:force_hostname, '')
setting(:port, Rails.env.development? ? 3000 : '')
setting(:enable_private_messages, true)
setting(:use_ssl, false)
setting(:queue_jobs, !Rails.env.test?)
setting(:crawl_images, !Rails.env.test?)
client_setting(:max_image_width, 690)
client_setting(:max_image_height, 500)
setting(:create_thumbnails, true)
client_setting(:category_featured_topics, 6)
setting(:topics_per_page, 30)
client_setting(:posts_per_page, 20)
setting(:invite_expiry_days, 14)
setting(:active_user_rate_limit_secs, 60)
setting(:previous_visit_timeout_hours, 1)
client_setting(:favicon_url, '/assets/default-favicon.ico')
setting(:apple_touch_icon_url, '/assets/default-apple-touch-icon.png')
setting(:ninja_edit_window, 5.minutes.to_i)
client_setting(:edit_history_visible_to_public, true)
client_setting(:delete_removed_posts_after, 24) # hours
setting(:post_undo_action_window_mins, 10)
setting(:site_contact_username, '')
setting(:max_mentions_per_post, 10)
setting(:newuser_max_mentions_per_post, 2)
setting(:unique_posts_mins, Rails.env.test? ? 0 : 5)
# Rate Limits
setting(:rate_limit_create_topic, 5)
setting(:rate_limit_create_post, 5)
setting(:max_topics_per_day, 20)
setting(:max_private_messages_per_day, 20)
setting(:max_likes_per_day, 50)
setting(:max_bookmarks_per_day, 20)
setting(:max_flags_per_day, 20)
setting(:max_edits_per_day, 30)
setting(:max_favorites_per_day, 20)
setting(:email_time_window_mins, 10)
setting(:email_posts_context, 5)
setting(:default_digest_email_frequency, '7', enum: 'DigestEmailSiteSetting')
# How many characters we can import into a onebox
setting(:onebox_max_chars, 5000)
setting(:suggested_topics, 5)
setting(:allow_duplicate_topic_titles, false)
setting(:staff_like_weight, 3)
setting(:add_rel_nofollow_to_user_content, true)
setting(:exclude_rel_nofollow_domains, '')
setting(:post_excerpt_maxlength, 300)
setting(:post_onebox_maxlength, 500)
setting(:best_of_score_threshold, 15)
setting(:best_of_posts_required, 50)
setting(:best_of_likes_required, 1)
setting(:best_of_percent_filter, 20)
# we need to think of a way to force users to enter certain settings, this is a minimal config thing
setting(:notification_email, 'info@discourse.org')
setting(:email_custom_headers, 'Auto-Submitted: auto-generated')
setting(:allow_index_in_robots_txt, true)
setting(:send_welcome_message, true)
client_setting(:invite_only, false)
client_setting(:login_required, false)
client_setting(:enable_local_logins, true)
client_setting(:enable_local_account_create, true)
client_setting(:enable_google_logins, true)
client_setting(:enable_yahoo_logins, true)
client_setting(:enable_twitter_logins, true)
setting(:twitter_consumer_key, '')
setting(:twitter_consumer_secret, '')
# note we set this (and twitter to true for 2 reasons)
# 1. its an upgrade nightmare to change it to false, lots of people will complain
# 2. it advertises the feature (even though it is broken)
client_setting(:enable_facebook_logins, true)
setting(:facebook_app_id, '')
setting(:facebook_app_secret, '')
client_setting(:enable_cas_logins, false)
setting(:cas_hostname, '')
setting(:cas_domainname, '')
client_setting(:enable_github_logins, false)
setting(:github_client_id, '')
setting(:github_client_secret, '')
client_setting(:enable_persona_logins, false)
setting(:enforce_global_nicknames, true)
setting(:discourse_org_access_key, '')
setting(:clean_up_uploads, false)
setting(:uploads_grace_period_in_hours, 1)
setting(:enable_s3_uploads, false)
setting(:s3_access_key_id, '')
setting(:s3_secret_access_key, '')
setting(:s3_region, '', enum: 'S3RegionSiteSetting')
setting(:s3_upload_bucket, '')
setting(:enable_flash_video_onebox, false)
setting(:default_trust_level, 0)
setting(:default_invitee_trust_level, 1)
# Import/Export settings
setting(:allow_import, false)
# Trust related
setting(:basic_requires_topics_entered, 5)
setting(:basic_requires_read_posts, 50)
setting(:basic_requires_time_spent_mins, 15)
setting(:regular_requires_topics_entered, 20)
setting(:regular_requires_read_posts, 100)
setting(:regular_requires_time_spent_mins, 60)
setting(:regular_requires_days_visited, 15)
setting(:regular_requires_likes_received, 1)
setting(:regular_requires_likes_given, 1)
setting(:regular_requires_topic_reply_count, 3)
setting(:min_trust_to_create_topic, 0, enum: 'MinTrustToCreateTopicSetting')
# Reply by Email Settings
setting(:reply_by_email_enabled, false)
setting(:reply_by_email_address, '')
setting(:pop3s_polling_enabled, false)
setting(:pop3s_polling_host, '')
setting(:pop3s_polling_port, 995)
setting(:pop3s_polling_username, '')
setting(:pop3s_polling_password, '')
# Entropy checks
setting(:title_min_entropy, 10)
setting(:body_min_entropy, 7)
setting(:max_word_length, 30)
setting(:newuser_max_links, 2)
client_setting(:newuser_max_images, 0)
client_setting(:newuser_max_attachments, 0)
setting(:newuser_spam_host_threshold, 3)
setting(:title_fancy_entities, true)
# The default locale for the site
setting(:default_locale, 'en', enum: 'LocaleSiteSetting')
client_setting(:educate_until_posts, 2)
setting(:max_similar_results, 7)
# Settings for topic heat
client_setting(:topic_views_heat_low, 1000)
client_setting(:topic_views_heat_medium, 2000)
client_setting(:topic_views_heat_high, 5000)
setting(:minimum_topics_similar, 50)
client_setting(:relative_date_duration, 30)
client_setting(:delete_user_max_age, 14)
setting(:delete_all_posts_max, 15)
setting(:username_change_period, 3) # days
setting(:email_editable, true)
client_setting(:allow_uploaded_avatars, true)
client_setting(:allow_animated_avatars, false)
setting(:detect_custom_avatars, true)
setting(:max_daily_gravatar_crawls, 500)
setting(:sequential_replies_threshold, 2)
client_setting(:enable_mobile_theme, true)
setting(:dominating_topic_minimum_percent, 20)
# hidden setting only used by system
setting(:uncategorized_category_id, -1, hidden: true)
client_setting(:display_name_on_posts, false)
client_setting(:enable_names, true)
client_setting(:invites_shown, 30)
def self.call_discourse_hub?
self.enforce_global_nicknames? && self.discourse_org_access_key.present?

363
config/site_settings.yml Normal file
View File

@ -0,0 +1,363 @@
all:
title:
client: true
default: 'Discourse'
site_description: ''
logo_url:
client: true
default: '/assets/d-logo-sketch.png'
logo_small_url:
client: true
default: '/assets/d-logo-sketch-small.png'
contact_email: ''
company_full_name: 'My Unconfigured Forum Ltd.'
company_short_name: 'Unconfigured Forum'
company_domain: 'www.example.com'
tos_url:
client: true
default: ''
faq_url:
client: true
default: ''
privacy_policy_url:
client: true
default: ''
traditional_markdown_linebreaks:
client: true
default: false
top_menu:
client: true
default: 'latest|new|unread|favorited|categories'
post_menu:
client: true
default: 'like|edit|flag|delete|share|bookmark|reply'
share_links:
client: true
default: 'twitter|facebook|google+|email'
track_external_right_clicks:
client: true
default: false
must_approve_users:
client: true
default: false
ga_tracking_code:
client: true
default: ''
ga_domain_name:
client: true
default: ''
enable_escaped_fragments:
client: true
default: false
enable_noscript_support:
client: true
default: true
enable_long_polling:
client: true
default: true
polling_interval:
client: true
default: 3000
anon_polling_interval:
client: true
default: 30000
min_post_length:
client: true
default:
test: 5
default: 20
min_private_message_post_length:
client: true
default:
test: 5
default: 10
max_post_length:
client: true
default: 32000
min_topic_title_length:
client: true
default: 15
max_topic_title_length:
client: true
default: 255
min_private_message_title_length:
client: true
default: 2
allow_uncategorized_topics:
client: true
default: true
min_search_term_length:
client: true
default: 3
flush_timings_secs:
client: true
default: 5
suppress_reply_directly_below:
client: true
default: true
suppress_reply_directly_above:
client: true
default: true
email_domains_blacklist:
client: true
default: 'mailinator.com'
email_domains_whitelist:
client: true
default: ''
version_checks:
client: true
default: true
new_version_emails: true
min_title_similar_length:
client: true
default: 10
min_body_similar_length:
client: true
default: 15
category_colors:
client: true
default: 'BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|283890'
enable_wide_category_list:
client: true
default: false
title_prettify: true
max_image_size_kb:
client: true
default: 2048
max_attachment_size_kb:
client: true
default: 1024
authorized_extensions:
client: true
default: '.jpg|.jpeg|.png|.gif'
auto_track_topics_after: 240000
new_topic_duration_minutes: 2880
long_polling_interval: 15000
flags_required_to_hide_post: 3
cooldown_minutes_after_hiding_posts: 10
max_topics_in_first_day: 5
max_replies_in_first_day: 10
num_flags_to_block_new_user: 3
num_users_to_block_new_user: 3
notify_mods_when_user_blocked: false
flag_sockpuppets: true
force_hostname: ''
port:
default:
development: 3000
default: ''
enable_private_messages: true
use_ssl: false
queue_jobs:
default:
test: false
default: true
crawl_images:
default:
test: false
default: true
max_image_width:
client: true
default: 690
max_image_height:
client: true
default: 500
create_thumbnails: true
category_featured_topics:
client: true
default: 6
topics_per_page: 30
posts_per_page:
client: true
default: 20
invite_expiry_days: 14
active_user_rate_limit_secs: 60
previous_visit_timeout_hours: 1
favicon_url:
client: true
default: '/assets/default-favicon.ico'
apple_touch_icon_url: /assets/default-apple-touch-icon.png'
ninja_edit_window: 300
edit_history_visible_to_public:
client: true
default: true
delete_removed_posts_after:
client: true
default: 24
post_undo_action_window_mins: 10
site_contact_username: ''
max_mentions_per_post: 10
newuser_max_mentions_per_post: 2
unique_posts_mins:
default:
test: 0
default: 5
rate_limit_create_topic: 5
rate_limit_create_post: 5
max_topics_per_day: 20
max_private_messages_per_day: 20
max_likes_per_day: 50
max_bookmarks_per_day: 20
max_flags_per_day: 20
max_edits_per_day: 30
max_favorites_per_day: 20
email_time_window_mins: 10
email_posts_context: 5
default_digest_email_frequency:
default: 7
enum: 'DigestEmailSiteSetting'
onebox_max_chars: 5000
suggested_topics: 5
allow_duplicate_topic_titles: false
staff_like_weight: 3
add_rel_nofollow_to_user_content: true
exclude_rel_nofollow_domains: ''
post_excerpt_maxlength: 300
post_onebox_maxlength: 500
best_of_score_threshold: 15
best_of_posts_required: 50
best_of_likes_required: 1
best_of_percent_filter: 20
notification_email: 'info@discourse.org'
email_custom_headers: 'Auto-Submitted: auto-generated'
allow_index_in_robots_txt: true
send_welcome_message: true
invite_only:
client: true
default: false
login_required:
client: true
default: false
enable_local_logins:
client: true
default: true
enable_local_account_create:
client: true
default: true
enable_google_logins:
client: true
default: true
enable_yahoo_logins:
client: true
default: true
enable_twitter_logins:
client: true
default: true
twitter_consumer_key: ''
twitter_consumer_secret: ''
enable_facebook_logins:
client: true
default: true
facebook_app_id: ''
facebook_app_secret: ''
enable_cas_logins:
client: true
default: false
cas_hostname: ''
cas_domainname: ''
enable_github_logins:
client: true
default: false
github_client_id: ''
github_client_secret: ''
enable_persona_logins:
client: true
default: false
enforce_global_nicknames: true
discourse_org_access_key: ''
clean_up_uploads: false
uploads_grace_period_in_hours: 1
enable_s3_uploads: false
s3_access_key_id: ''
s3_secret_access_key: ''
s3_region:
default: ''
enum: 'S3RegionSiteSetting'
s3_upload_bucket: ''
enable_flash_video_onebox: false
default_trust_level: 0
default_invitee_trust_level: 1
allow_import: false
basic_requires_topics_entered: 5
basic_requires_read_posts: 50
basic_requires_time_spent_mins: 15
regular_requires_topics_entered: 20
regular_requires_read_posts: 100
regular_requires_time_spent_mins: 60
regular_requires_days_visited: 15
regular_requires_likes_received: 1
regular_requires_likes_given: 1
regular_requires_topic_reply_count: 3
min_trust_to_create_topic:
default: 0
enum: 'MinTrustToCreateTopicSetting'
reply_by_email_enabled: false
reply_by_email_address: ''
pop3s_polling_enabled: false
pop3s_polling_host: ''
pop3s_polling_port: 995
pop3s_polling_username: ''
pop3s_polling_password: ''
title_min_entropy: 10
body_min_entropy: 7
max_word_length: 30
newuser_max_links: 2
newuser_max_images:
client: true
default: 0
newuser_max_attachments:
client: true
default: 0
newuser_spam_host_threshold: 3
title_fancy_entities: true
default_locale:
default: 'en'
enum: 'LocaleSiteSetting'
educate_until_posts:
client: true
default: 2
max_similar_results: 7
topic_views_heat_low:
client: true
default: 1000
topic_views_heat_medium:
client: true
default: 2000
topic_views_heat_high:
client: true
default: 5000
minimum_topics_similar: 50
relative_date_duration:
client: true
default: 30
delete_user_max_age:
client: true
default: 14
delete_all_posts_max: 15
username_change_period: 3
email_editable: true
allow_uploaded_avatars:
client: true
default: true
allow_animated_avatars:
client: true
default: false
detect_custom_avatars: true
max_daily_gravatar_crawls: 500
sequential_replies_threshold: 2
enable_mobile_theme:
client: true
default: true
dominating_topic_minimum_percent: 20
uncategorized_category_id:
default: -1
hidden: true
display_name_on_posts:
client: true
default: false
enable_names:
client: true
default: true
invites_shown:
client: true
default: 30

View File

@ -0,0 +1,30 @@
module SiteSettings; end
class SiteSettings::YamlLoader
def initialize(file)
@file = file
end
def load
yaml = YAML.load_file(@file)
yaml.keys.each do |category|
yaml[category].each do |setting_name, hash|
if hash.is_a?(Hash)
# Get default value for the site setting:
value = hash.delete('default')
# If there's a different default value for each environment, choose the right one:
if value.is_a?(Hash)
value = value.has_key?(Rails.env) ? value[Rails.env] : value['default']
end
yield category, setting_name, value, hash.symbolize_keys!
else
# Simplest case. site_setting_name: 'default value'
yield category, setting_name, hash, {}
end
end
end
end
end

View File

@ -0,0 +1,83 @@
require 'spec_helper'
require 'site_settings/yaml_loader'
describe SiteSettings::YamlLoader do
class Receiver
attr_reader :settings, :client_settings, :categories
def load_yaml(file_arg)
SiteSettings::YamlLoader.new(file_arg).load do |category, name, default, opts|
if opts.delete(:client)
client_setting(category, name, default, opts)
else
setting(category, name, default, opts)
end
end
end
def setting(category, name, default = nil, opts = {})
@settings ||= []
@settings << name
@categories ||= []
@categories << category
@categories.uniq!
end
def client_setting(category, name, default = nil)
@client_settings ||= []
@client_settings << name
setting(category, name, default)
end
end
let!(:receiver) { Receiver.new }
let(:simple) { "#{Rails.root}/spec/fixtures/site_settings/simple.yml" }
let(:client) { "#{Rails.root}/spec/fixtures/site_settings/client.yml" }
let(:enum) { "#{Rails.root}/spec/fixtures/site_settings/enum.yml" }
let(:enum_client) { "#{Rails.root}/spec/fixtures/site_settings/enum_client.yml" }
let(:env) { "#{Rails.root}/spec/fixtures/site_settings/env.yml" }
it "loads simple settings" do
receiver.expects(:setting).with('category1', 'title', 'My Site', {}).once
receiver.expects(:setting).with('category1', 'contact_email', 'webmaster@example.com', {}).once
receiver.expects(:setting).with('category2', 'ninja_edit_window', true, {}).once
receiver.expects(:setting).with('category3', 'reply_by_email_address', '', {}).once
receiver.load_yaml(simple)
end
it 'can take a File argument' do
receiver.expects(:setting).at_least_once
receiver.load_yaml( File.new(simple) )
end
it "maintains order of categories" do
receiver.load_yaml(simple)
receiver.categories.should == ['category1', 'category2', 'category3']
end
it "can load client settings" do
receiver.expects(:client_setting).with('category1', 'title', 'Discourse', {})
receiver.expects(:client_setting).with('category2', 'tos_url', '', {})
receiver.expects(:client_setting).with('category2', 'must_approve_users', false, {})
receiver.load_yaml(client)
end
it "can load enum settings" do
receiver.expects(:setting).with('email', 'default_digest_email_frequency', 7, {enum: 'DigestEmailSiteSetting'})
receiver.load_yaml(enum)
end
it "can load enum client settings" do
receiver.expects(:client_setting).with do |category, name, default, opts|
category == 'basics' and name == 'default_locale' and default == 'en' and opts[:enum] == 'LocaleSiteSetting'
end
receiver.load_yaml(enum_client)
end
it "can load settings based on environment" do
receiver.expects(:setting).with('misc', 'port', '', {})
receiver.expects(:client_setting).with('misc', 'crawl_images', false, {})
receiver.load_yaml(env)
end
end

12
spec/fixtures/site_settings/client.yml vendored Normal file
View File

@ -0,0 +1,12 @@
category1:
title:
default: Discourse
client: true
category2:
tos_url:
default: ''
client: true
must_approve_users:
default: false
client: true

4
spec/fixtures/site_settings/enum.yml vendored Normal file
View File

@ -0,0 +1,4 @@
email:
default_digest_email_frequency:
default: 7
enum: 'DigestEmailSiteSetting'

View File

@ -0,0 +1,5 @@
basics:
default_locale:
client: true
default: 'en'
enum: 'LocaleSiteSetting'

10
spec/fixtures/site_settings/env.yml vendored Normal file
View File

@ -0,0 +1,10 @@
misc:
port:
default:
development: 3000
default: ''
crawl_images:
client: true
default:
test: false
default: true

View File

@ -0,0 +1,9 @@
category1:
title: 'My Site'
contact_email: 'webmaster@example.com'
category2:
ninja_edit_window: true
category3:
reply_by_email_address: ''