DEV: Apply syntax_tree formatting to `config/*`

This commit is contained in:
David Taylor 2023-01-07 11:59:28 +00:00
parent 436b3b392b
commit 7c77cc6a58
No known key found for this signature in database
GPG Key ID: 46904C18B1D3F434
47 changed files with 1627 additions and 1091 deletions

View File

@ -2,7 +2,6 @@
--plugins=plugin/trailing_comma,disable_ternary
--ignore-files=Gemfile
--ignore-files=app/*
--ignore-files=config/*
--ignore-files=db/*
--ignore-files=lib/*
--ignore-files=spec/*

View File

@ -5,12 +5,12 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7.0")
exit 1
end
require File.expand_path('../boot', __FILE__)
require 'active_record/railtie'
require 'action_controller/railtie'
require 'action_view/railtie'
require 'action_mailer/railtie'
require 'sprockets/railtie'
require File.expand_path("../boot", __FILE__)
require "active_record/railtie"
require "action_controller/railtie"
require "action_view/railtie"
require "action_mailer/railtie"
require "sprockets/railtie"
if !Rails.env.production?
recommended = File.read(".ruby-version.sample").strip
@ -20,66 +20,59 @@ if !Rails.env.production?
end
# Plugin related stuff
require_relative '../lib/plugin'
require_relative '../lib/discourse_event'
require_relative '../lib/discourse_plugin_registry'
require_relative "../lib/plugin"
require_relative "../lib/discourse_event"
require_relative "../lib/discourse_plugin_registry"
require_relative '../lib/plugin_gem'
require_relative "../lib/plugin_gem"
# Global config
require_relative '../app/models/global_setting'
require_relative "../app/models/global_setting"
GlobalSetting.configure!
if GlobalSetting.load_plugins?
# Support for plugins to register custom setting providers. They can do this
# by having a file, `register_provider.rb` in their root that will be run
# at this point.
Dir.glob(File.join(File.dirname(__FILE__), '../plugins', '*', "register_provider.rb")) do |p|
Dir.glob(File.join(File.dirname(__FILE__), "../plugins", "*", "register_provider.rb")) do |p|
require p
end
end
GlobalSetting.load_defaults
if GlobalSetting.try(:cdn_url).present? && GlobalSetting.cdn_url !~ /^https?:\/\//
if GlobalSetting.try(:cdn_url).present? && GlobalSetting.cdn_url !~ %r{^https?://}
STDERR.puts "WARNING: Your CDN URL does not begin with a protocol like `https://` - this is probably not going to work"
end
if ENV['SKIP_DB_AND_REDIS'] == '1'
if ENV["SKIP_DB_AND_REDIS"] == "1"
GlobalSetting.skip_db = true
GlobalSetting.skip_redis = true
end
if !GlobalSetting.skip_db?
require 'rails_failover/active_record'
end
require "rails_failover/active_record" if !GlobalSetting.skip_db?
if !GlobalSetting.skip_redis?
require 'rails_failover/redis'
end
require "rails_failover/redis" if !GlobalSetting.skip_redis?
require 'pry-rails' if Rails.env.development?
require 'pry-byebug' if Rails.env.development?
require "pry-rails" if Rails.env.development?
require "pry-byebug" if Rails.env.development?
require 'discourse_fonts'
require "discourse_fonts"
require_relative '../lib/ember_cli'
require_relative "../lib/ember_cli"
if defined?(Bundler)
bundler_groups = [:default]
if !Rails.env.production?
bundler_groups = bundler_groups.concat(Rails.groups(
assets: %w(development test profile)
))
bundler_groups = bundler_groups.concat(Rails.groups(assets: %w[development test profile]))
end
Bundler.require(*bundler_groups)
end
require_relative '../lib/require_dependency_backward_compatibility'
require_relative "../lib/require_dependency_backward_compatibility"
module Discourse
class Application < Rails::Application
def config.database_configuration
if Rails.env.production?
GlobalSetting.database_config
@ -91,18 +84,23 @@ module Discourse
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
require 'discourse'
require 'js_locale_helper'
require "discourse"
require "js_locale_helper"
# tiny file needed by site settings
require 'highlight_js'
require "highlight_js"
config.load_defaults 6.1
config.active_record.cache_versioning = false # our custom cache class doesnt support this
config.action_controller.forgery_protection_origin_check = false
config.active_record.belongs_to_required_by_default = false
config.active_record.legacy_connection_handling = true
config.active_record.yaml_column_permitted_classes = [Hash, HashWithIndifferentAccess, Time, Symbol]
config.active_record.yaml_column_permitted_classes = [
Hash,
HashWithIndifferentAccess,
Time,
Symbol,
]
# we skip it cause we configure it in the initializer
# the railtie for message_bus would insert it in the
@ -111,7 +109,8 @@ module Discourse
config.skip_multisite_middleware = true
config.skip_rails_failover_active_record_middleware = true
multisite_config_path = ENV['DISCOURSE_MULTISITE_CONFIG_PATH'] || GlobalSetting.multisite_config_path
multisite_config_path =
ENV["DISCOURSE_MULTISITE_CONFIG_PATH"] || GlobalSetting.multisite_config_path
config.multisite_config_path = File.absolute_path(multisite_config_path, Rails.root)
# Custom directories with classes and modules you want to be autoloadable.
@ -129,14 +128,14 @@ module Discourse
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = 'UTC'
config.time_zone = "UTC"
# auto-load locales in plugins
# NOTE: we load both client & server locales since some might be used by PrettyText
config.i18n.load_path += Dir["#{Rails.root}/plugins/*/config/locales/*.yml"]
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = 'utf-8'
config.encoding = "utf-8"
# see: http://stackoverflow.com/questions/11894180/how-does-one-correctly-add-custom-sql-dml-in-migrations/11894420#11894420
config.active_record.schema_format = :sql
@ -145,7 +144,7 @@ module Discourse
config.active_record.use_schema_cache_dump = false
# per https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
config.pbkdf2_iterations = 64000
config.pbkdf2_iterations = 64_000
config.pbkdf2_algorithm = "sha256"
# rack lock is nothing but trouble, get rid of it
@ -160,32 +159,39 @@ module Discourse
# supports etags (post 1.7)
config.middleware.delete Rack::ETag
if !(Rails.env.development? || ENV['SKIP_ENFORCE_HOSTNAME'] == "1")
require 'middleware/enforce_hostname'
if !(Rails.env.development? || ENV["SKIP_ENFORCE_HOSTNAME"] == "1")
require "middleware/enforce_hostname"
config.middleware.insert_after Rack::MethodOverride, Middleware::EnforceHostname
end
require 'content_security_policy/middleware'
config.middleware.swap ActionDispatch::ContentSecurityPolicy::Middleware, ContentSecurityPolicy::Middleware
require "content_security_policy/middleware"
config.middleware.swap ActionDispatch::ContentSecurityPolicy::Middleware,
ContentSecurityPolicy::Middleware
require 'middleware/discourse_public_exceptions'
require "middleware/discourse_public_exceptions"
config.exceptions_app = Middleware::DiscoursePublicExceptions.new(Rails.public_path)
require 'discourse_js_processor'
require 'discourse_sourcemapping_url_processor'
require "discourse_js_processor"
require "discourse_sourcemapping_url_processor"
Sprockets.register_mime_type 'application/javascript', extensions: ['.js', '.es6', '.js.es6'], charset: :unicode
Sprockets.register_postprocessor 'application/javascript', DiscourseJsProcessor
Sprockets.register_mime_type "application/javascript",
extensions: %w[.js .es6 .js.es6],
charset: :unicode
Sprockets.register_postprocessor "application/javascript", DiscourseJsProcessor
Discourse::Application.initializer :prepend_ember_assets do |app|
# Needs to be in its own initializer so it runs after the append_assets_path initializer defined by Sprockets
app.config.assets.paths.unshift "#{app.config.root}/app/assets/javascripts/discourse/dist/assets"
Sprockets.unregister_postprocessor 'application/javascript', Sprockets::Rails::SourcemappingUrlProcessor
Sprockets.register_postprocessor 'application/javascript', DiscourseSourcemappingUrlProcessor
app
.config
.assets
.paths.unshift "#{app.config.root}/app/assets/javascripts/discourse/dist/assets"
Sprockets.unregister_postprocessor "application/javascript",
Sprockets::Rails::SourcemappingUrlProcessor
Sprockets.register_postprocessor "application/javascript", DiscourseSourcemappingUrlProcessor
end
require 'discourse_redis'
require 'logster/redis_store'
require "discourse_redis"
require "logster/redis_store"
# Use redis for our cache
config.cache_store = DiscourseRedis.new_redis_store
Discourse.redis = DiscourseRedis.new
@ -198,7 +204,7 @@ module Discourse
# our setup does not use rack cache and instead defers to nginx
config.action_dispatch.rack_cache = nil
require 'auth'
require "auth"
if GlobalSetting.relative_url_root.present?
config.relative_url_root = GlobalSetting.relative_url_root
@ -207,38 +213,28 @@ module Discourse
if Rails.env.test? && GlobalSetting.load_plugins?
Discourse.activate_plugins!
elsif GlobalSetting.load_plugins?
Plugin.initialization_guard do
Discourse.activate_plugins!
end
Plugin.initialization_guard { Discourse.activate_plugins! }
end
# Use discourse-fonts gem to symlink fonts and generate .scss file
fonts_path = File.join(config.root, 'public/fonts')
fonts_path = File.join(config.root, "public/fonts")
Discourse::Utils.atomic_ln_s(DiscourseFonts.path_for_fonts, fonts_path)
require 'stylesheet/manager'
require 'svg_sprite'
require "stylesheet/manager"
require "svg_sprite"
config.after_initialize do
# Load plugins
Plugin.initialization_guard do
Discourse.plugins.each(&:notify_after_initialize)
end
Plugin.initialization_guard { Discourse.plugins.each(&:notify_after_initialize) }
# we got to clear the pool in case plugins connect
ActiveRecord::Base.connection_handler.clear_active_connections!
end
if ENV['RBTRACE'] == "1"
require 'rbtrace'
end
require "rbtrace" if ENV["RBTRACE"] == "1"
if ENV['RAILS_QUERY_LOG_TAGS'] == "1"
config.active_record.query_log_tags_enabled = true
end
config.active_record.query_log_tags_enabled = true if ENV["RAILS_QUERY_LOG_TAGS"] == "1"
config.generators do |g|
g.test_framework :rspec, fixture: false
end
config.generators { |g| g.test_framework :rspec, fixture: false }
end
end

View File

@ -1,48 +1,49 @@
# frozen_string_literal: true
if ENV['DISCOURSE_DUMP_HEAP'] == "1"
require 'objspace'
if ENV["DISCOURSE_DUMP_HEAP"] == "1"
require "objspace"
ObjectSpace.trace_object_allocations_start
end
require 'rubygems'
require "rubygems"
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
if (ENV['DISABLE_BOOTSNAP'] != '1')
if (ENV["DISABLE_BOOTSNAP"] != "1")
begin
require 'bootsnap'
require "bootsnap"
rescue LoadError
# not a strong requirement
end
if defined? Bootsnap
if defined?(Bootsnap)
Bootsnap.setup(
cache_dir: 'tmp/cache', # Path to your cache
load_path_cache: true, # Should we optimize the LOAD_PATH with a cache?
compile_cache_iseq: true, # Should compile Ruby code into ISeq cache?
compile_cache_yaml: false # Skip YAML cache for now, cause we were seeing issues with it
cache_dir: "tmp/cache", # Path to your cache
load_path_cache: true, # Should we optimize the LOAD_PATH with a cache?
compile_cache_iseq: true, # Should compile Ruby code into ISeq cache?
compile_cache_yaml: false, # Skip YAML cache for now, cause we were seeing issues with it
)
end
end
# Parallel spec system
if ENV['RAILS_ENV'] == "test" && ENV['TEST_ENV_NUMBER']
if ENV['TEST_ENV_NUMBER'] == ''
if ENV["RAILS_ENV"] == "test" && ENV["TEST_ENV_NUMBER"]
if ENV["TEST_ENV_NUMBER"] == ""
n = 1
else
n = ENV['TEST_ENV_NUMBER'].to_i
n = ENV["TEST_ENV_NUMBER"].to_i
end
port = 10000 + n
port = 10_000 + n
STDERR.puts "Setting up parallel test mode - starting Redis #{n} on port #{port}"
`rm -rf tmp/test_data_#{n} && mkdir -p tmp/test_data_#{n}/redis`
pid = Process.spawn("redis-server --dir tmp/test_data_#{n}/redis --port #{port}", out: "/dev/null")
pid =
Process.spawn("redis-server --dir tmp/test_data_#{n}/redis --port #{port}", out: "/dev/null")
ENV["DISCOURSE_REDIS_PORT"] = port.to_s
ENV["RAILS_DB"] = "discourse_test_#{n}"

View File

@ -7,7 +7,7 @@ Discourse::Application.configure do
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
@ -23,19 +23,20 @@ Discourse::Application.configure do
config.assets.digest = true
# Specifies the header that your server uses for sending files
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for nginx
# you may use other configuration here for mail eg: sendgrid
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: ENV['SMTP_ADDRESS'],
port: ENV['SMTP_PORT'],
domain: ENV['SMTP_DOMAIN'],
user_name: ENV['SMTP_USERNAME'],
password: ENV['SMTP_PASSWORD'],
authentication: 'plain',
enable_starttls_auto: true }
address: ENV["SMTP_ADDRESS"],
port: ENV["SMTP_PORT"],
domain: ENV["SMTP_DOMAIN"],
user_name: ENV["SMTP_USERNAME"],
password: ENV["SMTP_PASSWORD"],
authentication: "plain",
enable_starttls_auto: true,
}
#config.action_mailer.delivery_method = :sendmail
#config.action_mailer.sendmail_settings = {arguments: '-i'}
@ -59,5 +60,4 @@ Discourse::Application.configure do
# Discourse strongly recommend you use a CDN.
# For origin pull cdns all you need to do is register an account and configure
# config.action_controller.asset_host = "http://YOUR_CDN_HERE"
end

View File

@ -7,6 +7,7 @@ require_relative "application"
Rails.application.initialize!
# When in "dev" mode, ensure we won't be sending any emails
if Rails.env.development? && ActionMailer::Base.smtp_settings.slice(:address, :port) != { address: "localhost", port: 1025 }
if Rails.env.development? &&
ActionMailer::Base.smtp_settings.slice(:address, :port) != { address: "localhost", port: 1025 }
fail "In development mode, you should be using mailhog otherwise you might end up sending thousands of digest emails"
end

View File

@ -16,7 +16,7 @@ Discourse::Application.configure do
config.active_record.use_schema_cache_dump = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_controller.asset_host = GlobalSetting.cdn_url
@ -32,27 +32,23 @@ Discourse::Application.configure do
config.assets.debug = false
config.public_file_server.headers = {
'Access-Control-Allow-Origin' => '*'
}
config.public_file_server.headers = { "Access-Control-Allow-Origin" => "*" }
# Raise an error on page load if there are pending migrations
config.active_record.migration_error = :page_load
config.watchable_dirs['lib'] = [:rb]
config.watchable_dirs["lib"] = [:rb]
# we recommend you use mailhog https://github.com/mailhog/MailHog
config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
config.action_mailer.raise_delivery_errors = true
config.log_level = ENV['DISCOURSE_DEV_LOG_LEVEL'] if ENV['DISCOURSE_DEV_LOG_LEVEL']
config.log_level = ENV["DISCOURSE_DEV_LOG_LEVEL"] if ENV["DISCOURSE_DEV_LOG_LEVEL"]
if ENV['RAILS_VERBOSE_QUERY_LOGS'] == "1"
config.active_record.verbose_query_logs = true
end
config.active_record.verbose_query_logs = true if ENV["RAILS_VERBOSE_QUERY_LOGS"] == "1"
if defined?(BetterErrors)
BetterErrors::Middleware.allow_ip! ENV['TRUSTED_IP'] if ENV['TRUSTED_IP']
BetterErrors::Middleware.allow_ip! ENV["TRUSTED_IP"] if ENV["TRUSTED_IP"]
if defined?(Unicorn) && ENV["UNICORN_WORKERS"].to_i != 1
# BetterErrors doesn't work with multiple unicorn workers. Disable it to avoid confusion
@ -60,51 +56,44 @@ Discourse::Application.configure do
end
end
if !ENV["DISABLE_MINI_PROFILER"]
config.load_mini_profiler = true
end
config.load_mini_profiler = true if !ENV["DISABLE_MINI_PROFILER"]
if hosts = ENV['DISCOURSE_DEV_HOSTS']
if hosts = ENV["DISCOURSE_DEV_HOSTS"]
Discourse.deprecate("DISCOURSE_DEV_HOSTS is deprecated. Use RAILS_DEVELOPMENT_HOSTS instead.")
config.hosts.concat(hosts.split(","))
end
require 'middleware/turbo_dev'
require "middleware/turbo_dev"
config.middleware.insert 0, Middleware::TurboDev
require 'middleware/missing_avatars'
require "middleware/missing_avatars"
config.middleware.insert 1, Middleware::MissingAvatars
config.enable_anon_caching = false
if RUBY_ENGINE == "ruby"
require 'rbtrace'
end
require "rbtrace" if RUBY_ENGINE == "ruby"
if emails = GlobalSetting.developer_emails
config.developer_emails = emails.split(",").map(&:downcase).map(&:strip)
end
if ENV["DISCOURSE_SKIP_CSS_WATCHER"] != "1" && (defined?(Rails::Server) || defined?(Puma) || defined?(Unicorn))
require 'stylesheet/watcher'
if ENV["DISCOURSE_SKIP_CSS_WATCHER"] != "1" &&
(defined?(Rails::Server) || defined?(Puma) || defined?(Unicorn))
require "stylesheet/watcher"
STDERR.puts "Starting CSS change watcher"
@watcher = Stylesheet::Watcher.watch
end
config.after_initialize do
if ENV["RAILS_COLORIZE_LOGGING"] == "1"
config.colorize_logging = true
end
config.colorize_logging = true if ENV["RAILS_COLORIZE_LOGGING"] == "1"
if ENV["RAILS_VERBOSE_QUERY_LOGS"] == "1"
ActiveRecord::LogSubscriber.backtrace_cleaner.add_silencer do |line|
line =~ /lib\/freedom_patches/
line =~ %r{lib/freedom_patches}
end
end
if ENV["RAILS_DISABLE_ACTIVERECORD_LOGS"] == "1"
ActiveRecord::Base.logger = nil
end
ActiveRecord::Base.logger = nil if ENV["RAILS_DISABLE_ACTIVERECORD_LOGS"] == "1"
if ENV['BULLET']
if ENV["BULLET"]
Bullet.enable = true
Bullet.rails_logger = true
end

View File

@ -8,7 +8,7 @@ Discourse::Application.configure do
config.eager_load = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
@ -34,19 +34,19 @@ Discourse::Application.configure do
authentication: GlobalSetting.smtp_authentication,
enable_starttls_auto: GlobalSetting.smtp_enable_start_tls,
open_timeout: GlobalSetting.smtp_open_timeout,
read_timeout: GlobalSetting.smtp_read_timeout
read_timeout: GlobalSetting.smtp_read_timeout,
}
settings[:openssl_verify_mode] = GlobalSetting.smtp_openssl_verify_mode if GlobalSetting.smtp_openssl_verify_mode
settings[
:openssl_verify_mode
] = GlobalSetting.smtp_openssl_verify_mode if GlobalSetting.smtp_openssl_verify_mode
if GlobalSetting.smtp_force_tls
settings[:tls] = true
end
settings[:tls] = true if GlobalSetting.smtp_force_tls
config.action_mailer.smtp_settings = settings.compact
else
config.action_mailer.delivery_method = :sendmail
config.action_mailer.sendmail_settings = { arguments: '-i' }
config.action_mailer.sendmail_settings = { arguments: "-i" }
end
# Send deprecation notices to registered listeners

View File

@ -11,7 +11,7 @@ Discourse::Application.configure do
config.log_level = :info
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# in profile mode we serve static assets
@ -27,7 +27,7 @@ Discourse::Application.configure do
config.assets.digest = true
# Specifies the header that your server uses for sending files
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for nginx
# we recommend you use mailhog https://github.com/mailhog/MailHog
config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
@ -39,9 +39,7 @@ Discourse::Application.configure do
config.load_mini_profiler = false
# we don't need full logster support, but need to keep it working
config.after_initialize do
Logster.logger = Rails.logger
end
config.after_initialize { Logster.logger = Rails.logger }
# for profiling with perftools
# config.middleware.use ::Rack::PerftoolsProfiler, default_printer: 'gif'

View File

@ -46,21 +46,22 @@ Discourse::Application.configure do
config.eager_load = false
if ENV['RAILS_ENABLE_TEST_LOG']
if ENV["RAILS_ENABLE_TEST_LOG"]
config.logger = Logger.new(STDOUT)
config.log_level = ENV['RAILS_TEST_LOG_LEVEL'].present? ? ENV['RAILS_TEST_LOG_LEVEL'].to_sym : :info
config.log_level =
ENV["RAILS_TEST_LOG_LEVEL"].present? ? ENV["RAILS_TEST_LOG_LEVEL"].to_sym : :info
else
config.logger = Logger.new(nil)
config.log_level = :fatal
end
if defined? RspecErrorTracker
if defined?(RspecErrorTracker)
config.middleware.insert_after ActionDispatch::Flash, RspecErrorTracker
end
config.after_initialize do
SiteSetting.defaults.tap do |s|
s.set_regardless_of_locale(:s3_upload_bucket, 'bucket')
s.set_regardless_of_locale(:s3_upload_bucket, "bucket")
s.set_regardless_of_locale(:min_post_length, 5)
s.set_regardless_of_locale(:min_first_post_length, 5)
s.set_regardless_of_locale(:min_personal_message_post_length, 10)
@ -73,7 +74,7 @@ Discourse::Application.configure do
s.set_regardless_of_locale(:allow_uncategorized_topics, true)
# disable plugins
if ENV['LOAD_PLUGINS'] == '1'
if ENV["LOAD_PLUGINS"] == "1"
s.set_regardless_of_locale(:discourse_narrative_bot_enabled, false)
end
end

View File

@ -8,25 +8,35 @@ if Rails.env.development? && !Rails.configuration.cache_classes && Discourse.run
*Dir["#{Rails.root}/app/*"].reject { |path| path.end_with? "/assets" },
"#{Rails.root}/config",
"#{Rails.root}/lib",
"#{Rails.root}/plugins"
"#{Rails.root}/plugins",
]
Listen.to(*paths, only: /\.rb$/) do |modified, added, removed|
supervisor_pid = UNICORN_DEV_SUPERVISOR_PID
auto_restart = supervisor_pid && ENV["AUTO_RESTART"] != "0"
Listen
.to(*paths, only: /\.rb$/) do |modified, added, removed|
supervisor_pid = UNICORN_DEV_SUPERVISOR_PID
auto_restart = supervisor_pid && ENV["AUTO_RESTART"] != "0"
files = modified + added + removed
files = modified + added + removed
not_autoloaded = files.filter_map do |file|
autoloaded = Rails.autoloaders.main.autoloads.key? file
Pathname.new(file).relative_path_from(Rails.root) if !autoloaded
not_autoloaded =
files.filter_map do |file|
autoloaded = Rails.autoloaders.main.autoloads.key? file
Pathname.new(file).relative_path_from(Rails.root) if !autoloaded
end
if not_autoloaded.length > 0
message =
(
if auto_restart
"Restarting server..."
else
"Server restart required. Automate this by setting AUTO_RESTART=1."
end
)
STDERR.puts "[DEV]: Edited files which are not autoloaded. #{message}"
STDERR.puts not_autoloaded.map { |path| "- #{path}".indent(7) }.join("\n")
Process.kill("USR2", supervisor_pid) if auto_restart
end
end
if not_autoloaded.length > 0
message = auto_restart ? "Restarting server..." : "Server restart required. Automate this by setting AUTO_RESTART=1."
STDERR.puts "[DEV]: Edited files which are not autoloaded. #{message}"
STDERR.puts not_autoloaded.map { |path| "- #{path}".indent(7) }.join("\n")
Process.kill("USR2", supervisor_pid) if auto_restart
end
end.start
.start
end

View File

@ -1,4 +1,4 @@
# frozen_string_literal: true
require 'mini_sql_multisite_connection'
require "mini_sql_multisite_connection"
::DB = MiniSqlMultisiteConnection.instance

View File

@ -1,7 +1,8 @@
# frozen_string_literal: true
unless Discourse.skip_post_deployment_migrations?
ActiveRecord::Tasks::DatabaseTasks.migrations_paths << Rails.root.join(
Discourse::DB_POST_MIGRATE_PATH
).to_s
ActiveRecord::Tasks::DatabaseTasks.migrations_paths << Rails
.root
.join(Discourse::DB_POST_MIGRATE_PATH)
.to_s
end

View File

@ -15,31 +15,32 @@
# Warning: this could create some very large files!
if ENV["TRACE_PG_CONNECTIONS"]
PG::Connection.prepend(Module.new do
TRACE_DIR = "tmp/pgtrace"
PG::Connection.prepend(
Module.new do
TRACE_DIR = "tmp/pgtrace"
def initialize(*args)
super(*args).tap do
next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
FileUtils.mkdir_p(TRACE_DIR)
@trace_filename = "#{TRACE_DIR}/#{Process.pid}_#{self.object_id}.txt"
trace File.new(@trace_filename, "w")
def initialize(*args)
super(*args).tap do
next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
FileUtils.mkdir_p(TRACE_DIR)
@trace_filename = "#{TRACE_DIR}/#{Process.pid}_#{self.object_id}.txt"
trace File.new(@trace_filename, "w")
end
@access_log_mutex = Mutex.new
@accessor_thread = nil
end
@access_log_mutex = Mutex.new
@accessor_thread = nil
end
def close
super.tap do
next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
File.delete(@trace_filename)
def close
super.tap do
next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
File.delete(@trace_filename)
end
end
end
def log_access(&blk)
@access_log_mutex.synchronize do
if !@accessor_thread.nil?
Rails.logger.error <<~TEXT
def log_access(&blk)
@access_log_mutex.synchronize do
if !@accessor_thread.nil?
Rails.logger.error <<~TEXT
PG Clash: A connection is being accessed from two locations
#{@accessor_thread} was using the connection. Backtrace:
@ -51,37 +52,38 @@ if ENV["TRACE_PG_CONNECTIONS"]
#{Thread.current&.backtrace&.join("\n")}
TEXT
if ENV["ON_PG_CLASH"] == "byebug"
require "byebug"
byebug # rubocop:disable Lint/Debugger
if ENV["ON_PG_CLASH"] == "byebug"
require "byebug"
byebug # rubocop:disable Lint/Debugger
end
end
@accessor_thread = Thread.current
end
@accessor_thread = Thread.current
yield
ensure
@access_log_mutex.synchronize { @accessor_thread = nil }
end
yield
ensure
@access_log_mutex.synchronize do
@accessor_thread = nil
end
end
end)
end,
)
class PG::Connection
LOG_ACCESS_METHODS = [:exec, :sync_exec, :async_exec,
:sync_exec_params, :async_exec_params,
:sync_prepare, :async_prepare,
:sync_exec_prepared, :async_exec_prepared,
]
LOG_ACCESS_METHODS = %i[
exec
sync_exec
async_exec
sync_exec_params
async_exec_params
sync_prepare
async_prepare
sync_exec_prepared
async_exec_prepared
]
LOG_ACCESS_METHODS.each do |method|
new_method = "#{method}_without_logging".to_sym
alias_method new_method, method
define_method(method) do |*args, &blk|
log_access { send(new_method, *args, &blk) }
end
define_method(method) { |*args, &blk| log_access { send(new_method, *args, &blk) } }
end
end
end

View File

@ -11,7 +11,7 @@ module DiscourseInflector
def self.camelize(basename, abspath)
return basename.camelize if abspath.ends_with?("onceoff.rb")
return 'Jobs' if abspath.ends_with?("jobs/base.rb")
return "Jobs" if abspath.ends_with?("jobs/base.rb")
@overrides[basename] || basename.camelize
end
@ -26,27 +26,29 @@ Rails.autoloaders.each do |autoloader|
# We have filenames that do not follow Zeitwerk's camelization convention. Maintain an inflections for these files
# for now until we decide to fix them one day.
autoloader.inflector.inflect(
'canonical_url' => 'CanonicalURL',
'clean_up_unmatched_ips' => 'CleanUpUnmatchedIPs',
'homepage_constraint' => 'HomePageConstraint',
'ip_addr' => 'IPAddr',
'onpdiff' => 'ONPDiff',
'pop3_polling_enabled_setting_validator' => 'POP3PollingEnabledSettingValidator',
'version' => 'Discourse',
'onceoff' => 'Jobs',
'regular' => 'Jobs',
'scheduled' => 'Jobs',
'google_oauth2_authenticator' => 'GoogleOAuth2Authenticator',
'omniauth_strategies' => 'OmniAuthStrategies',
'csrf_token_verifier' => 'CSRFTokenVerifier',
'html' => 'HTML',
'json' => 'JSON',
'ssrf_detector' => 'SSRFDetector',
'http' => 'HTTP',
"canonical_url" => "CanonicalURL",
"clean_up_unmatched_ips" => "CleanUpUnmatchedIPs",
"homepage_constraint" => "HomePageConstraint",
"ip_addr" => "IPAddr",
"onpdiff" => "ONPDiff",
"pop3_polling_enabled_setting_validator" => "POP3PollingEnabledSettingValidator",
"version" => "Discourse",
"onceoff" => "Jobs",
"regular" => "Jobs",
"scheduled" => "Jobs",
"google_oauth2_authenticator" => "GoogleOAuth2Authenticator",
"omniauth_strategies" => "OmniAuthStrategies",
"csrf_token_verifier" => "CSRFTokenVerifier",
"html" => "HTML",
"json" => "JSON",
"ssrf_detector" => "SSRFDetector",
"http" => "HTTP",
)
end
Rails.autoloaders.main.ignore("lib/tasks",
"lib/generators",
"lib/freedom_patches",
"lib/i18n/backend",
"lib/unicorn_logstash_patch.rb")
Rails.autoloaders.main.ignore(
"lib/tasks",
"lib/generators",
"lib/freedom_patches",
"lib/i18n/backend",
"lib/unicorn_logstash_patch.rb",
)

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true
if Rails.env.development? && ENV['DISCOURSE_FLUSH_REDIS']
if Rails.env.development? && ENV["DISCOURSE_FLUSH_REDIS"]
puts "Flushing redis (development mode)"
Discourse.redis.flushdb
end
begin
if Gem::Version.new(Discourse.redis.info['redis_version']) < Gem::Version.new("6.2.0")
if Gem::Version.new(Discourse.redis.info["redis_version"]) < Gem::Version.new("6.2.0")
STDERR.puts "Discourse requires Redis 6.2.0 or up"
exit 1
end

View File

@ -14,16 +14,12 @@ if defined?(RailsFailover::Redis)
Discourse.request_refresh!
MessageBus.keepalive_interval = message_bus_keepalive_interval
ObjectSpace.each_object(DistributedCache) do |cache|
cache.clear
end
ObjectSpace.each_object(DistributedCache) { |cache| cache.clear }
SiteSetting.refresh!
end
if Rails.logger.respond_to? :chained
RailsFailover::Redis.logger = Rails.logger.chained.first
end
RailsFailover::Redis.logger = Rails.logger.chained.first if Rails.logger.respond_to? :chained
end
if defined?(RailsFailover::ActiveRecord)
@ -73,10 +69,7 @@ if defined?(RailsFailover::ActiveRecord)
end
RailsFailover::ActiveRecord.register_force_reading_role_callback do
Discourse.redis.exists?(
Discourse::PG_READONLY_MODE_KEY,
Discourse::PG_FORCE_READONLY_MODE_KEY
)
Discourse.redis.exists?(Discourse::PG_READONLY_MODE_KEY, Discourse::PG_FORCE_READONLY_MODE_KEY)
rescue => e
if !e.is_a?(Redis::CannotConnectError)
Rails.logger.warn "#{e.class} #{e.message}: #{e.backtrace.join("\n")}"

View File

@ -30,7 +30,8 @@ def setup_message_bus_env(env)
extra_headers = {
"Access-Control-Allow-Origin" => Discourse.base_url_no_prefix,
"Access-Control-Allow-Methods" => "GET, POST",
"Access-Control-Allow-Headers" => "X-SILENCE-LOGGER, X-Shared-Session-Key, Dont-Chunk, Discourse-Present",
"Access-Control-Allow-Headers" =>
"X-SILENCE-LOGGER, X-Shared-Session-Key, Dont-Chunk, Discourse-Present",
"Access-Control-Max-Age" => "7200",
}
@ -40,7 +41,7 @@ def setup_message_bus_env(env)
rescue Discourse::InvalidAccess => e
# this is bad we need to remove the cookie
if e.opts[:delete_cookie].present?
extra_headers['Set-Cookie'] = '_t=del; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
extra_headers["Set-Cookie"] = "_t=del; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT"
end
rescue => e
Discourse.warn_exception(e, message: "Unexpected error in Message Bus", env: env)
@ -51,23 +52,22 @@ def setup_message_bus_env(env)
raise Discourse::InvalidAccess if !user_id && SiteSetting.login_required
is_admin = !!(user && user.admin?)
group_ids = if is_admin
# special rule, admin is allowed access to all groups
Group.pluck(:id)
elsif user
user.groups.pluck('groups.id')
end
group_ids =
if is_admin
# special rule, admin is allowed access to all groups
Group.pluck(:id)
elsif user
user.groups.pluck("groups.id")
end
if env[Auth::DefaultCurrentUserProvider::BAD_TOKEN]
extra_headers['Discourse-Logged-Out'] = '1'
end
extra_headers["Discourse-Logged-Out"] = "1" if env[Auth::DefaultCurrentUserProvider::BAD_TOKEN]
hash = {
extra_headers: extra_headers,
user_id: user_id,
group_ids: group_ids,
is_admin: is_admin,
site_id: RailsMultisite::ConnectionManagement.current_db
site_id: RailsMultisite::ConnectionManagement.current_db,
}
env["__mb"] = hash
end
@ -99,7 +99,7 @@ MessageBus.on_middleware_error do |env, e|
if Discourse::InvalidAccess === e
[403, {}, ["Invalid Access"]]
elsif RateLimiter::LimitExceeded === e
[429, { 'Retry-After' => e.available_in.to_s }, [e.description]]
[429, { "Retry-After" => e.available_in.to_s }, [e.description]]
end
end
@ -119,8 +119,9 @@ end
MessageBus.backend_instance.max_backlog_size = GlobalSetting.message_bus_max_backlog_size
MessageBus.backend_instance.clear_every = GlobalSetting.message_bus_clear_every
MessageBus.long_polling_enabled = GlobalSetting.enable_long_polling.nil? ? true : GlobalSetting.enable_long_polling
MessageBus.long_polling_interval = GlobalSetting.long_polling_interval || 25000
MessageBus.long_polling_enabled =
GlobalSetting.enable_long_polling.nil? ? true : GlobalSetting.enable_long_polling
MessageBus.long_polling_interval = GlobalSetting.long_polling_interval || 25_000
if Rails.env == "test" || $0 =~ /rake$/
# disable keepalive in testing

View File

@ -6,7 +6,7 @@
Discourse.git_version
if GlobalSetting.skip_redis?
require 'site_settings/local_process_provider'
require "site_settings/local_process_provider"
Rails.cache = Discourse.cache
Rails.application.config.to_prepare do
SiteSetting.provider = SiteSettings::LocalProcessProvider.new
@ -19,7 +19,8 @@ Rails.application.config.to_prepare do
begin
SiteSetting.refresh!
unless String === SiteSetting.push_api_secret_key && SiteSetting.push_api_secret_key.length == 32
unless String === SiteSetting.push_api_secret_key &&
SiteSetting.push_api_secret_key.length == 32
SiteSetting.push_api_secret_key = SecureRandom.hex
end
rescue ActiveRecord::StatementInvalid

View File

@ -5,17 +5,15 @@ return if GlobalSetting.skip_db?
Rails.application.config.to_prepare do
# Some sanity checking so we don't count on an unindexed column on boot
begin
if ActiveRecord::Base.connection.table_exists?(:users) &&
User.limit(20).count < 20 &&
User.where(admin: true).human_users.count == 0
if ActiveRecord::Base.connection.table_exists?(:users) && User.limit(20).count < 20 &&
User.where(admin: true).human_users.count == 0
notice =
if GlobalSetting.developer_emails.blank?
"Congratulations, you installed Discourse! Unfortunately, no administrator emails were defined during setup, so finalizing the configuration <a href='https://meta.discourse.org/t/create-admin-account-from-console/17274'>may be difficult</a>."
else
emails = GlobalSetting.developer_emails.split(",")
if emails.length > 1
emails = emails[0..-2].join(', ') << " or #{emails[-1]} "
emails = emails[0..-2].join(", ") << " or #{emails[-1]} "
else
emails = emails[0]
end

View File

@ -1,12 +1,13 @@
# frozen_string_literal: true
# If Mini Profiler is included via gem
if Rails.configuration.respond_to?(:load_mini_profiler) && Rails.configuration.load_mini_profiler && RUBY_ENGINE == "ruby"
require 'rack-mini-profiler'
require 'stackprof'
if Rails.configuration.respond_to?(:load_mini_profiler) && Rails.configuration.load_mini_profiler &&
RUBY_ENGINE == "ruby"
require "rack-mini-profiler"
require "stackprof"
begin
require 'memory_profiler'
require "memory_profiler"
rescue => e
STDERR.put "#{e} failed to require mini profiler"
end
@ -20,55 +21,56 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config)
# raw_connection means results are not namespaced
#
# namespacing gets complex, cause mini profiler is in the rack chain way before multisite
Rack::MiniProfiler.config.storage_instance = Rack::MiniProfiler::RedisStore.new(
connection: DiscourseRedis.new(nil, namespace: false)
)
Rack::MiniProfiler.config.storage_instance =
Rack::MiniProfiler::RedisStore.new(connection: DiscourseRedis.new(nil, namespace: false))
Rack::MiniProfiler.config.snapshot_every_n_requests = GlobalSetting.mini_profiler_snapshots_period
Rack::MiniProfiler.config.snapshots_transport_destination_url = GlobalSetting.mini_profiler_snapshots_transport_url
Rack::MiniProfiler.config.snapshots_transport_auth_key = GlobalSetting.mini_profiler_snapshots_transport_auth_key
Rack::MiniProfiler.config.snapshots_transport_destination_url =
GlobalSetting.mini_profiler_snapshots_transport_url
Rack::MiniProfiler.config.snapshots_transport_auth_key =
GlobalSetting.mini_profiler_snapshots_transport_auth_key
Rack::MiniProfiler.config.skip_paths = [
/^\/message-bus/,
/^\/extra-locales/,
/topics\/timings/,
%r{^/message-bus},
%r{^/extra-locales},
%r{topics/timings},
/assets/,
/\/user_avatar\//,
/\/letter_avatar\//,
/\/letter_avatar_proxy\//,
/\/highlight-js\//,
/\/svg-sprite\//,
%r{/user_avatar/},
%r{/letter_avatar/},
%r{/letter_avatar_proxy/},
%r{/highlight-js/},
%r{/svg-sprite/},
/qunit/,
/srv\/status/,
%r{srv/status},
/commits-widget/,
/^\/cdn_asset/,
/^\/logs/,
/^\/site_customizations/,
/^\/uploads/,
/^\/secure-media-uploads/,
/^\/secure-uploads/,
/^\/javascripts\//,
/^\/images\//,
/^\/stylesheets\//,
/^\/favicon\/proxied/,
/^\/theme-javascripts/
%r{^/cdn_asset},
%r{^/logs},
%r{^/site_customizations},
%r{^/uploads},
%r{^/secure-media-uploads},
%r{^/secure-uploads},
%r{^/javascripts/},
%r{^/images/},
%r{^/stylesheets/},
%r{^/favicon/proxied},
%r{^/theme-javascripts},
]
# we DO NOT WANT mini-profiler loading on anything but real desktops and laptops
# so let's rule out all handheld, tablet, and mobile devices
Rack::MiniProfiler.config.pre_authorize_cb = lambda do |env|
env['HTTP_USER_AGENT'] !~ /iPad|iPhone|Android/
end
Rack::MiniProfiler.config.pre_authorize_cb =
lambda { |env| env["HTTP_USER_AGENT"] !~ /iPad|iPhone|Android/ }
# without a user provider our results will use the ip address for namespacing
# with a load balancer in front this becomes really bad as some results can
# be stored associated with ip1 as the user and retrieved using ip2 causing 404s
Rack::MiniProfiler.config.user_provider = lambda do |env|
request = Rack::Request.new(env)
id = request.cookies["_t"] || request.ip || "unknown"
id = id.to_s
# some security, lets not have these tokens floating about
Digest::MD5.hexdigest(id)
end
Rack::MiniProfiler.config.user_provider =
lambda do |env|
request = Rack::Request.new(env)
id = request.cookies["_t"] || request.ip || "unknown"
id = id.to_s
# some security, lets not have these tokens floating about
Digest::MD5.hexdigest(id)
end
# Cookie path should be set to the base path so Discourse's session cookie path
# does not get clobbered.
@ -77,15 +79,15 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config)
Rack::MiniProfiler.config.position = "right"
Rack::MiniProfiler.config.backtrace_ignores ||= []
Rack::MiniProfiler.config.backtrace_ignores << /lib\/rack\/message_bus.rb/
Rack::MiniProfiler.config.backtrace_ignores << /config\/initializers\/silence_logger/
Rack::MiniProfiler.config.backtrace_ignores << /config\/initializers\/quiet_logger/
Rack::MiniProfiler.config.backtrace_ignores << %r{lib/rack/message_bus.rb}
Rack::MiniProfiler.config.backtrace_ignores << %r{config/initializers/silence_logger}
Rack::MiniProfiler.config.backtrace_ignores << %r{config/initializers/quiet_logger}
Rack::MiniProfiler.config.backtrace_includes = [/^\/?(app|config|lib|test|plugins)/]
Rack::MiniProfiler.config.backtrace_includes = [%r{^/?(app|config|lib|test|plugins)}]
Rack::MiniProfiler.config.max_traces_to_show = 100 if Rails.env.development?
Rack::MiniProfiler.counter_method(Redis::Client, :call) { 'redis' }
Rack::MiniProfiler.counter_method(Redis::Client, :call) { "redis" }
# Rack::MiniProfiler.counter_method(ActiveRecord::QueryMethods, 'build_arel')
# Rack::MiniProfiler.counter_method(Array, 'uniq')
# require "#{Rails.root}/vendor/backports/notification"
@ -115,10 +117,11 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config)
end
if ENV["PRINT_EXCEPTIONS"]
trace = TracePoint.new(:raise) do |tp|
puts tp.raised_exception
puts tp.raised_exception.backtrace.join("\n")
puts
end
trace =
TracePoint.new(:raise) do |tp|
puts tp.raised_exception
puts tp.raised_exception.backtrace.join("\n")
puts
end
trace.enable
end

View File

@ -6,18 +6,17 @@ class Discourse::Cors
def initialize(app, options = nil)
@app = app
if GlobalSetting.enable_cors && GlobalSetting.cors_origin.present?
@global_origins = GlobalSetting.cors_origin.split(',').map { |x| x.strip.chomp('/') }
@global_origins = GlobalSetting.cors_origin.split(",").map { |x| x.strip.chomp("/") }
end
end
def call(env)
cors_origins = @global_origins || []
cors_origins += SiteSetting.cors_origins.split('|') if SiteSetting.cors_origins.present?
cors_origins += SiteSetting.cors_origins.split("|") if SiteSetting.cors_origins.present?
cors_origins = cors_origins.presence
if env['REQUEST_METHOD'] == ('OPTIONS') && env['HTTP_ACCESS_CONTROL_REQUEST_METHOD']
return [200, Discourse::Cors.apply_headers(cors_origins, env, {}), []]
if env["REQUEST_METHOD"] == ("OPTIONS") && env["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]
return 200, Discourse::Cors.apply_headers(cors_origins, env, {}), []
end
env[Discourse::Cors::ORIGINS_ENV] = cors_origins if cors_origins
@ -31,21 +30,24 @@ class Discourse::Cors
end
def self.apply_headers(cors_origins, env, headers)
request_method = env['REQUEST_METHOD']
request_method = env["REQUEST_METHOD"]
if env['REQUEST_PATH'] =~ /\/(javascripts|assets)\// && Discourse.is_cdn_request?(env, request_method)
if env["REQUEST_PATH"] =~ %r{/(javascripts|assets)/} &&
Discourse.is_cdn_request?(env, request_method)
Discourse.apply_cdn_headers(headers)
elsif cors_origins
origin = nil
if origin = env['HTTP_ORIGIN']
if origin = env["HTTP_ORIGIN"]
origin = nil unless cors_origins.include?(origin)
end
headers['Access-Control-Allow-Origin'] = origin || cors_origins[0]
headers['Access-Control-Allow-Headers'] = 'Content-Type, Cache-Control, X-Requested-With, X-CSRF-Token, Discourse-Present, User-Api-Key, User-Api-Client-Id, Authorization'
headers['Access-Control-Allow-Credentials'] = 'true'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS, DELETE'
headers['Access-Control-Max-Age'] = '7200'
headers["Access-Control-Allow-Origin"] = origin || cors_origins[0]
headers[
"Access-Control-Allow-Headers"
] = "Content-Type, Cache-Control, X-Requested-With, X-CSRF-Token, Discourse-Present, User-Api-Key, User-Api-Client-Id, Authorization"
headers["Access-Control-Allow-Credentials"] = "true"
headers["Access-Control-Allow-Methods"] = "POST, PUT, GET, OPTIONS, DELETE"
headers["Access-Control-Max-Age"] = "7200"
end
headers

View File

@ -1,11 +1,7 @@
# frozen_string_literal: true
%i(
topic_recovered
).each do |event|
DiscourseEvent.on(event) do |topic, _|
WebHook.enqueue_topic_hooks(event, topic)
end
%i[topic_recovered].each do |event|
DiscourseEvent.on(event) { |topic, _| WebHook.enqueue_topic_hooks(event, topic) }
end
DiscourseEvent.on(:topic_status_updated) do |topic, status|
@ -16,18 +12,12 @@ DiscourseEvent.on(:topic_created) do |topic, _, _|
WebHook.enqueue_topic_hooks(:topic_created, topic)
end
%i(
post_created
post_recovered
).each do |event|
DiscourseEvent.on(event) do |post, _, _|
WebHook.enqueue_post_hooks(event, post)
end
%i[post_created post_recovered].each do |event|
DiscourseEvent.on(event) { |post, _, _| WebHook.enqueue_post_hooks(event, post) }
end
DiscourseEvent.on(:post_edited) do |post, topic_changed|
unless post.topic&.trashed?
# if we are editing the OP and the topic is changed, do not send
# the post_edited event -- this event is sent separately because
# when we update the OP in the UI we send two API calls in this order:
@ -42,49 +32,30 @@ DiscourseEvent.on(:post_edited) do |post, topic_changed|
end
end
%i(
%i[
user_logged_out
user_created
user_logged_in
user_approved
user_updated
user_confirmed_email
).each do |event|
DiscourseEvent.on(event) do |user|
WebHook.enqueue_object_hooks(:user, user, event)
end
].each do |event|
DiscourseEvent.on(event) { |user| WebHook.enqueue_object_hooks(:user, user, event) }
end
%i(
group_created
group_updated
).each do |event|
DiscourseEvent.on(event) do |group|
WebHook.enqueue_object_hooks(:group, group, event)
end
%i[group_created group_updated].each do |event|
DiscourseEvent.on(event) { |group| WebHook.enqueue_object_hooks(:group, group, event) }
end
%i(
category_created
category_updated
).each do |event|
DiscourseEvent.on(event) do |category|
WebHook.enqueue_object_hooks(:category, category, event)
end
%i[category_created category_updated].each do |event|
DiscourseEvent.on(event) { |category| WebHook.enqueue_object_hooks(:category, category, event) }
end
%i(
tag_created
tag_updated
).each do |event|
DiscourseEvent.on(event) do |tag|
WebHook.enqueue_object_hooks(:tag, tag, event, TagSerializer)
end
%i[tag_created tag_updated].each do |event|
DiscourseEvent.on(event) { |tag| WebHook.enqueue_object_hooks(:tag, tag, event, TagSerializer) }
end
%i(
user_badge_granted
).each do |event|
%i[user_badge_granted].each do |event|
# user_badge_revoked
DiscourseEvent.on(event) do |badge, user_id|
ub = UserBadge.find_by(badge: badge, user_id: user_id)
@ -92,30 +63,43 @@ end
end
end
%i(
reviewable_created
reviewable_score_updated
).each do |event|
%i[reviewable_created reviewable_score_updated].each do |event|
DiscourseEvent.on(event) do |reviewable|
WebHook.enqueue_object_hooks(:reviewable, reviewable, event, reviewable.serializer)
end
end
DiscourseEvent.on(:reviewable_transitioned_to) do |status, reviewable|
WebHook.enqueue_object_hooks(:reviewable, reviewable, :reviewable_transitioned_to, reviewable.serializer)
WebHook.enqueue_object_hooks(
:reviewable,
reviewable,
:reviewable_transitioned_to,
reviewable.serializer,
)
end
DiscourseEvent.on(:notification_created) do |notification|
WebHook.enqueue_object_hooks(:notification, notification, :notification_created, NotificationSerializer)
WebHook.enqueue_object_hooks(
:notification,
notification,
:notification_created,
NotificationSerializer,
)
end
DiscourseEvent.on(:user_added_to_group) do |user, group, options|
group_user = GroupUser.find_by(user: user, group: group)
WebHook.enqueue_object_hooks(:group_user, group_user, :user_added_to_group, WebHookGroupUserSerializer)
WebHook.enqueue_object_hooks(
:group_user,
group_user,
:user_added_to_group,
WebHookGroupUserSerializer,
)
end
DiscourseEvent.on(:user_promoted) do |payload|
user_id, new_trust_level, old_trust_level = payload.values_at(:user_id, :new_trust_level, :old_trust_level)
user_id, new_trust_level, old_trust_level =
payload.values_at(:user_id, :new_trust_level, :old_trust_level)
next if new_trust_level < old_trust_level
@ -130,8 +114,13 @@ DiscourseEvent.on(:like_created) do |post_action|
category_id = topic&.category_id
tag_ids = topic&.tag_ids
WebHook.enqueue_object_hooks(:like,
post_action, :post_liked, WebHookLikeSerializer,
group_ids: group_ids, category_id: category_id, tag_ids: tag_ids
WebHook.enqueue_object_hooks(
:like,
post_action,
:post_liked,
WebHookLikeSerializer,
group_ids: group_ids,
category_id: category_id,
tag_ids: tag_ids,
)
end

View File

@ -1,4 +1,4 @@
# frozen_string_literal: true
require 'excon'
require "excon"
Excon::DEFAULTS[:omit_default_port] = true

View File

@ -6,10 +6,11 @@ DiscourseEvent.on(:site_setting_changed) do |name, old_value, new_value|
# Enabling `must_approve_users` on an existing site is odd, so we assume that the
# existing users are approved.
if name == :must_approve_users && new_value == true
User.where(approved: false)
User
.where(approved: false)
.joins("LEFT JOIN reviewables r ON r.target_id = users.id")
.where(r: { id: nil }).update_all(approved: true)
.where(r: { id: nil })
.update_all(approved: true)
end
if name == :emoji_set
@ -19,31 +20,28 @@ DiscourseEvent.on(:site_setting_changed) do |name, old_value, new_value|
after = "/images/emoji/#{new_value}/"
Scheduler::Defer.later("Fix Emoji Links") do
DB.exec("UPDATE posts SET cooked = REPLACE(cooked, :before, :after) WHERE cooked LIKE :like",
DB.exec(
"UPDATE posts SET cooked = REPLACE(cooked, :before, :after) WHERE cooked LIKE :like",
before: before,
after: after,
like: "%#{before}%"
like: "%#{before}%",
)
end
end
Stylesheet::Manager.clear_color_scheme_cache! if [:base_font, :heading_font].include?(name)
Stylesheet::Manager.clear_color_scheme_cache! if %i[base_font heading_font].include?(name)
Report.clear_cache(:storage_stats) if [:backup_location, :s3_backup_bucket].include?(name)
Report.clear_cache(:storage_stats) if %i[backup_location s3_backup_bucket].include?(name)
if name == :slug_generation_method
Scheduler::Defer.later("Null topic slug") do
Topic.update_all(slug: nil)
end
Scheduler::Defer.later("Null topic slug") { Topic.update_all(slug: nil) }
end
Jobs.enqueue(:update_s3_inventory) if [:enable_s3_inventory, :s3_upload_bucket].include?(name)
Jobs.enqueue(:update_s3_inventory) if %i[enable_s3_inventory s3_upload_bucket].include?(name)
SvgSprite.expire_cache if name.to_s.include?("_icon")
if SiteIconManager::WATCHED_SETTINGS.include?(name)
SiteIconManager.ensure_optimized!
end
SiteIconManager.ensure_optimized! if SiteIconManager::WATCHED_SETTINGS.include?(name)
# Make sure medium and high priority thresholds were calculated.
if name == :reviewable_low_priority_threshold && Reviewable.min_score_for_priority(:medium) > 0

View File

@ -9,7 +9,7 @@ enabled =
Rails.env.production?
end
if !ENV['DISCOURSE_DISABLE_ANON_CACHE'] && enabled
if !ENV["DISCOURSE_DISABLE_ANON_CACHE"] && enabled
# in an ideal world this is position 0, but mobile detection uses ... session and request and params
Rails.configuration.middleware.insert_after ActionDispatch::Flash, Middleware::AnonymousCache
end

View File

@ -0,0 +1 @@

View File

@ -2,8 +2,8 @@
# order: after 02-freedom_patches.rb
require 'i18n/backend/discourse_i18n'
require 'i18n/backend/fallback_locale_list'
require "i18n/backend/discourse_i18n"
require "i18n/backend/fallback_locale_list"
# Requires the `translate_accelerator.rb` freedom patch to be loaded
Rails.application.reloader.to_prepare do
@ -11,7 +11,7 @@ Rails.application.reloader.to_prepare do
I18n.fallbacks = I18n::Backend::FallbackLocaleList.new
I18n.config.missing_interpolation_argument_handler = proc { throw(:exception) }
I18n.reload!
I18n.init_accelerator!(overrides_enabled: ENV['DISABLE_TRANSLATION_OVERRIDES'] != '1')
I18n.init_accelerator!(overrides_enabled: ENV["DISABLE_TRANSLATION_OVERRIDES"] != "1")
unless Rails.env.test?
MessageBus.subscribe("/i18n-flush") do

View File

@ -2,9 +2,7 @@
if GlobalSetting.skip_redis?
Rails.application.reloader.to_prepare do
if Rails.logger.respond_to? :chained
Rails.logger = Rails.logger.chained.first
end
Rails.logger = Rails.logger.chained.first if Rails.logger.respond_to? :chained
end
return
end
@ -39,9 +37,7 @@ if Rails.env.production?
# https://github.com/rails/rails/blob/f2caed1e/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb#L39-L42
/^ActionController::RoutingError \(No route matches/,
/^ActionDispatch::Http::MimeNegotiation::InvalidType/,
/^PG::Error: ERROR:\s+duplicate key/,
/^ActionController::UnknownFormat/,
/^ActionController::UnknownHttpMethod/,
/^AbstractController::ActionNotFound/,
@ -51,29 +47,21 @@ if Rails.env.production?
# Column:
#
/(?m).*?Line: (?:\D|0).*?Column: (?:\D|0)/,
# suppress empty JS errors (covers MSIE 9, etc)
/^(Syntax|Script) error.*Line: (0|1)\b/m,
# CSRF errors are not providing enough data
# suppress unconditionally for now
/^Can't verify CSRF token authenticity.$/,
# Yandex bot triggers this JS error a lot
/^Uncaught ReferenceError: I18n is not defined/,
# related to browser plugins somehow, we don't care
/Error calling method on NPObject/,
# 404s can be dealt with elsewhere
/^ActiveRecord::RecordNotFound/,
# bad asset requested, no need to log
/^ActionController::BadRequest/,
# we can't do anything about invalid parameters
/Rack::QueryParser::InvalidParameterError/,
# we handle this cleanly in the message bus middleware
# no point logging to logster
/RateLimiter::LimitExceeded.*/m,
@ -98,33 +86,37 @@ store.redis_raw_connection = redis.without_namespace
severities = [Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN]
RailsMultisite::ConnectionManagement.each_connection do
error_rate_per_minute = SiteSetting.alert_admins_if_errors_per_minute rescue 0
error_rate_per_minute =
begin
SiteSetting.alert_admins_if_errors_per_minute
rescue StandardError
0
end
if (error_rate_per_minute || 0) > 0
store.register_rate_limit_per_minute(severities, error_rate_per_minute) do |rate|
MessageBus.publish("/logs_error_rate_exceeded",
{
rate: rate,
duration: 'minute',
publish_at: Time.current.to_i
},
group_ids: [Group::AUTO_GROUPS[:admins]]
)
MessageBus.publish(
"/logs_error_rate_exceeded",
{ rate: rate, duration: "minute", publish_at: Time.current.to_i },
group_ids: [Group::AUTO_GROUPS[:admins]],
)
end
end
error_rate_per_hour = SiteSetting.alert_admins_if_errors_per_hour rescue 0
error_rate_per_hour =
begin
SiteSetting.alert_admins_if_errors_per_hour
rescue StandardError
0
end
if (error_rate_per_hour || 0) > 0
store.register_rate_limit_per_hour(severities, error_rate_per_hour) do |rate|
MessageBus.publish("/logs_error_rate_exceeded",
{
rate: rate,
duration: 'hour',
publish_at: Time.current.to_i,
},
group_ids: [Group::AUTO_GROUPS[:admins]]
)
MessageBus.publish(
"/logs_error_rate_exceeded",
{ rate: rate, duration: "hour", publish_at: Time.current.to_i },
group_ids: [Group::AUTO_GROUPS[:admins]],
)
end
end
end
@ -137,13 +129,13 @@ if Rails.configuration.multisite
end
Logster.config.project_directories = [
{ path: Rails.root.to_s, url: "https://github.com/discourse/discourse", main_app: true }
{ path: Rails.root.to_s, url: "https://github.com/discourse/discourse", main_app: true },
]
Discourse.plugins.each do |plugin|
next if !plugin.metadata.url
Logster.config.project_directories << {
path: "#{Rails.root.to_s}/plugins/#{plugin.directory_name}",
url: plugin.metadata.url
url: plugin.metadata.url,
}
end

View File

@ -6,13 +6,13 @@ Rails.application.config.to_prepare do
twitter_client: TwitterApi,
redirect_limit: 3,
user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}",
allowed_ports: [80, 443, SiteSetting.port.to_i]
allowed_ports: [80, 443, SiteSetting.port.to_i],
}
else
Onebox.options = {
twitter_client: TwitterApi,
redirect_limit: 3,
user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}"
user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}",
}
end
end

View File

@ -3,13 +3,11 @@
return if GlobalSetting.skip_db?
Rails.application.config.to_prepare do
require 'web-push'
require "web-push"
def generate_vapid_key?
SiteSetting.vapid_public_key.blank? ||
SiteSetting.vapid_private_key.blank? ||
SiteSetting.vapid_public_key_bytes.blank? ||
SiteSetting.vapid_base_url != Discourse.base_url
SiteSetting.vapid_public_key.blank? || SiteSetting.vapid_private_key.blank? ||
SiteSetting.vapid_public_key_bytes.blank? || SiteSetting.vapid_base_url != Discourse.base_url
end
SiteSetting.vapid_base_url = Discourse.base_url if SiteSetting.vapid_base_url.blank?
@ -19,15 +17,12 @@ Rails.application.config.to_prepare do
SiteSetting.vapid_public_key = vapid_key.public_key
SiteSetting.vapid_private_key = vapid_key.private_key
SiteSetting.vapid_public_key_bytes = Base64.urlsafe_decode64(SiteSetting.vapid_public_key).bytes.join("|")
SiteSetting.vapid_public_key_bytes =
Base64.urlsafe_decode64(SiteSetting.vapid_public_key).bytes.join("|")
SiteSetting.vapid_base_url = Discourse.base_url
if ActiveRecord::Base.connection.table_exists?(:push_subscriptions)
PushSubscription.delete_all
end
PushSubscription.delete_all if ActiveRecord::Base.connection.table_exists?(:push_subscriptions)
end
DiscourseEvent.on(:user_logged_out) do |user|
PushNotificationPusher.clear_subscriptions(user)
end
DiscourseEvent.on(:user_logged_out) { |user| PushNotificationPusher.clear_subscriptions(user) }
end

View File

@ -1,30 +1,23 @@
# frozen_string_literal: true
Rails.application.config.assets.configure do |env|
env.logger = Logger.new('/dev/null')
end
Rails.application.config.assets.configure { |env| env.logger = Logger.new("/dev/null") }
module DiscourseRackQuietAssetsLogger
def call(env)
override = false
if (env['PATH_INFO'].index("/assets/") == 0) ||
(env['PATH_INFO'].index("/stylesheets") == 0) ||
(env['PATH_INFO'].index("/svg-sprite") == 0) ||
(env['PATH_INFO'].index("/manifest") == 0) ||
(env['PATH_INFO'].index("/service-worker") == 0) ||
(env['PATH_INFO'].index("mini-profiler-resources") == 0) ||
(env['PATH_INFO'].index("/srv/status") == 0)
if (env["PATH_INFO"].index("/assets/") == 0) || (env["PATH_INFO"].index("/stylesheets") == 0) ||
(env["PATH_INFO"].index("/svg-sprite") == 0) ||
(env["PATH_INFO"].index("/manifest") == 0) ||
(env["PATH_INFO"].index("/service-worker") == 0) ||
(env["PATH_INFO"].index("mini-profiler-resources") == 0) ||
(env["PATH_INFO"].index("/srv/status") == 0)
if ::Logster::Logger === Rails.logger
override = true
Rails.logger.override_level = Logger::ERROR
end
end
super(env).tap do
if override
Rails.logger.override_level = nil
end
end
super(env).tap { Rails.logger.override_level = nil if override }
end
end

View File

@ -4,8 +4,15 @@
Rails.application.config.session_store(
:discourse_cookie_store,
key: '_forum_session',
path: (Rails.application.config.relative_url_root.nil?) ? '/' : Rails.application.config.relative_url_root
key: "_forum_session",
path:
(
if (Rails.application.config.relative_url_root.nil?)
"/"
else
Rails.application.config.relative_url_root
end
),
)
Rails.application.config.to_prepare do

View File

@ -1,22 +1,17 @@
# frozen_string_literal: true
require "sidekiq/pausable"
require 'sidekiq_logster_reporter'
require "sidekiq_logster_reporter"
Sidekiq.configure_client do |config|
config.redis = Discourse.sidekiq_redis_config
end
Sidekiq.configure_client { |config| config.redis = Discourse.sidekiq_redis_config }
Sidekiq.configure_server do |config|
config.redis = Discourse.sidekiq_redis_config
config.server_middleware do |chain|
chain.add Sidekiq::Pausable
end
config.server_middleware { |chain| chain.add Sidekiq::Pausable }
end
if Sidekiq.server?
module Sidekiq
class CLI
private
@ -34,13 +29,17 @@ if Sidekiq.server?
# warm up AR
RailsMultisite::ConnectionManagement.safe_each_connection do
(ActiveRecord::Base.connection.tables - %w[schema_migrations versions]).each do |table|
table.classify.constantize.first rescue nil
begin
table.classify.constantize.first
rescue StandardError
nil
end
end
end
scheduler_hostname = ENV["UNICORN_SCHEDULER_HOSTNAME"]
if !scheduler_hostname || scheduler_hostname.split(',').include?(Discourse.os_hostname)
if !scheduler_hostname || scheduler_hostname.split(",").include?(Discourse.os_hostname)
begin
MiniScheduler.start(workers: GlobalSetting.mini_scheduler_workers)
rescue MiniScheduler::DistributedMutex::Timeout
@ -57,9 +56,11 @@ else
# Instead, this patch adds a dedicated logger instance and patches
# the #add method to forward messages to Rails.logger.
Sidekiq.logger = Logger.new(nil)
Sidekiq.logger.define_singleton_method(:add) do |severity, message = nil, progname = nil, &blk|
Rails.logger.add(severity, message, progname, &blk)
end
Sidekiq
.logger
.define_singleton_method(:add) do |severity, message = nil, progname = nil, &blk|
Rails.logger.add(severity, message, progname, &blk)
end
end
Sidekiq.error_handlers.clear
@ -69,28 +70,20 @@ Sidekiq.strict_args!
Rails.application.config.to_prepare do
# Ensure that scheduled jobs are loaded before mini_scheduler is configured.
if Rails.env.development?
Dir.glob("#{Rails.root}/app/jobs/scheduled/*.rb") do |f|
require(f)
end
end
Dir.glob("#{Rails.root}/app/jobs/scheduled/*.rb") { |f| require(f) } if Rails.env.development?
MiniScheduler.configure do |config|
config.redis = Discourse.redis
config.job_exception_handler do |ex, context|
Discourse.handle_job_exception(ex, context)
end
config.job_exception_handler { |ex, context| Discourse.handle_job_exception(ex, context) }
config.job_ran do |stat|
DiscourseEvent.trigger(:scheduled_job_ran, stat)
end
config.job_ran { |stat| DiscourseEvent.trigger(:scheduled_job_ran, stat) }
config.skip_schedule { Sidekiq.paused? }
config.before_sidekiq_web_request do
RailsMultisite::ConnectionManagement.establish_connection(
db: RailsMultisite::ConnectionManagement::DEFAULT
db: RailsMultisite::ConnectionManagement::DEFAULT,
)
end
end

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true
class SilenceLogger < Rails::Rack::Logger
PATH_INFO = 'PATH_INFO'
HTTP_X_SILENCE_LOGGER = 'HTTP_X_SILENCE_LOGGER'
PATH_INFO = "PATH_INFO"
HTTP_X_SILENCE_LOGGER = "HTTP_X_SILENCE_LOGGER"
def initialize(app, opts = {})
@app = app
@ -17,11 +17,9 @@ class SilenceLogger < Rails::Rack::Logger
path_info = env[PATH_INFO]
override = false
if env[HTTP_X_SILENCE_LOGGER] ||
@opts[:silenced].include?(path_info) ||
path_info.start_with?('/logs') ||
path_info.start_with?('/user_avatar') ||
path_info.start_with?('/letter_avatar')
if env[HTTP_X_SILENCE_LOGGER] || @opts[:silenced].include?(path_info) ||
path_info.start_with?("/logs") || path_info.start_with?("/user_avatar") ||
path_info.start_with?("/letter_avatar")
if ::Logster::Logger === Rails.logger
override = true
Rails.logger.override_level = Logger::WARN
@ -35,10 +33,10 @@ class SilenceLogger < Rails::Rack::Logger
end
end
silenced = [
"/mini-profiler-resources/results",
"/mini-profiler-resources/includes.js",
"/mini-profiler-resources/includes.css",
"/mini-profiler-resources/jquery.tmpl.js"
silenced = %w[
/mini-profiler-resources/results
/mini-profiler-resources/includes.js
/mini-profiler-resources/includes.css
/mini-profiler-resources/jquery.tmpl.js
]
Rails.configuration.middleware.swap Rails::Rack::Logger, SilenceLogger, silenced: silenced

View File

@ -3,8 +3,7 @@
# Check that the app is configured correctly. Raise some helpful errors if something is wrong.
if defined?(Rails::Server) && Rails.env.production? # Only run these checks when starting up a production server
if ['localhost', 'production.localhost'].include?(Discourse.current_hostname)
if %w[localhost production.localhost].include?(Discourse.current_hostname)
puts <<~TEXT
Discourse.current_hostname = '#{Discourse.current_hostname}'
@ -18,7 +17,7 @@ if defined?(Rails::Server) && Rails.env.production? # Only run these checks when
raise "Invalid host_names in database.yml"
end
if !Dir.glob(File.join(Rails.root, 'public', 'assets', 'application*.js')).present?
if !Dir.glob(File.join(Rails.root, "public", "assets", "application*.js")).present?
puts <<~TEXT
Assets have not been precompiled. Please run the following command

View File

@ -6,11 +6,7 @@
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json]
end
ActiveSupport.on_load(:action_controller) { wrap_parameters format: [:json] }
# Disable root element in JSON by default.
ActiveSupport.on_load(:active_record) do
self.include_root_in_json = false
end
ActiveSupport.on_load(:active_record) { self.include_root_in_json = false }

View File

@ -1,8 +1,9 @@
# frozen_string_literal: true
Rails.application.config.to_prepare do
if (Rails.env.production? && SiteSetting.logging_provider == 'lograge') || (ENV["ENABLE_LOGRAGE"] == "1")
require 'lograge'
if (Rails.env.production? && SiteSetting.logging_provider == "lograge") ||
(ENV["ENABLE_LOGRAGE"] == "1")
require "lograge"
if Rails.configuration.multisite
Rails.logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
@ -11,20 +12,20 @@ Rails.application.config.to_prepare do
Rails.application.configure do
config.lograge.enabled = true
Lograge.ignore(lambda do |event|
# this is our hijack magic status,
# no point logging this cause we log again
# direct from hijack
event.payload[:status] == 418
end)
Lograge.ignore(
lambda do |event|
# this is our hijack magic status,
# no point logging this cause we log again
# direct from hijack
event.payload[:status] == 418
end,
)
config.lograge.custom_payload do |controller|
begin
username =
begin
if controller.respond_to?(:current_user)
controller.current_user&.username
end
controller.current_user&.username if controller.respond_to?(:current_user)
rescue Discourse::InvalidAccess, Discourse::ReadOnly, ActiveRecord::ReadOnlyError
nil
end
@ -36,78 +37,77 @@ Rails.application.config.to_prepare do
nil
end
{
ip: ip,
username: username
}
{ ip: ip, username: username }
rescue => e
Rails.logger.warn("Failed to append custom payload: #{e.message}\n#{e.backtrace.join("\n")}")
Rails.logger.warn(
"Failed to append custom payload: #{e.message}\n#{e.backtrace.join("\n")}",
)
{}
end
end
config.lograge.custom_options = lambda do |event|
begin
exceptions = %w(controller action format id)
config.lograge.custom_options =
lambda do |event|
begin
exceptions = %w[controller action format id]
params = event.payload[:params].except(*exceptions)
params = event.payload[:params].except(*exceptions)
if (file = params[:file]) && file.respond_to?(:headers)
params[:file] = file.headers
if (file = params[:file]) && file.respond_to?(:headers)
params[:file] = file.headers
end
if (files = params[:files]) && files.respond_to?(:map)
params[:files] = files.map { |f| f.respond_to?(:headers) ? f.headers : f }
end
output = {
params: params.to_query,
database: RailsMultisite::ConnectionManagement.current_db,
}
if data = (Thread.current[:_method_profiler] || event.payload[:timings])
sql = data[:sql]
if sql
output[:db] = sql[:duration] * 1000
output[:db_calls] = sql[:calls]
end
redis = data[:redis]
if redis
output[:redis] = redis[:duration] * 1000
output[:redis_calls] = redis[:calls]
end
net = data[:net]
if net
output[:net] = net[:duration] * 1000
output[:net_calls] = net[:calls]
end
end
output
rescue RateLimiter::LimitExceeded
# no idea who this is, but they are limited
{}
rescue => e
Rails.logger.warn(
"Failed to append custom options: #{e.message}\n#{e.backtrace.join("\n")}",
)
{}
end
if (files = params[:files]) && files.respond_to?(:map)
params[:files] = files.map do |f|
f.respond_to?(:headers) ? f.headers : f
end
end
output = {
params: params.to_query,
database: RailsMultisite::ConnectionManagement.current_db,
}
if data = (Thread.current[:_method_profiler] || event.payload[:timings])
sql = data[:sql]
if sql
output[:db] = sql[:duration] * 1000
output[:db_calls] = sql[:calls]
end
redis = data[:redis]
if redis
output[:redis] = redis[:duration] * 1000
output[:redis_calls] = redis[:calls]
end
net = data[:net]
if net
output[:net] = net[:duration] * 1000
output[:net_calls] = net[:calls]
end
end
output
rescue RateLimiter::LimitExceeded
# no idea who this is, but they are limited
{}
rescue => e
Rails.logger.warn("Failed to append custom options: #{e.message}\n#{e.backtrace.join("\n")}")
{}
end
end
if ENV["LOGSTASH_URI"]
config.lograge.formatter = Lograge::Formatters::Logstash.new
require 'discourse_logstash_logger'
require "discourse_logstash_logger"
config.lograge.logger = DiscourseLogstashLogger.logger(
uri: ENV['LOGSTASH_URI'], type: :rails
)
config.lograge.logger =
DiscourseLogstashLogger.logger(uri: ENV["LOGSTASH_URI"], type: :rails)
# Remove ActiveSupport::Logger from the chain and replace with Lograge's
# logger

View File

@ -11,13 +11,11 @@ Rails.configuration.middleware.unshift(MessageBus::Rack::Middleware)
# no reason to track this in development, that is 300+ redis calls saved per
# page view (we serve all assets out of thin in development)
if Rails.env != 'development' || ENV['TRACK_REQUESTS']
require 'middleware/request_tracker'
if Rails.env != "development" || ENV["TRACK_REQUESTS"]
require "middleware/request_tracker"
Rails.configuration.middleware.unshift Middleware::RequestTracker
if GlobalSetting.enable_performance_http_headers
MethodProfiler.ensure_discourse_instrumentation!
end
MethodProfiler.ensure_discourse_instrumentation! if GlobalSetting.enable_performance_http_headers
end
if Rails.env.test?
@ -30,23 +28,27 @@ if Rails.env.test?
super(env)
end
end
Rails.configuration.middleware.unshift TestMultisiteMiddleware, RailsMultisite::DiscoursePatches.config
Rails.configuration.middleware.unshift TestMultisiteMiddleware,
RailsMultisite::DiscoursePatches.config
elsif Rails.configuration.multisite
assets_hostnames = GlobalSetting.cdn_hostnames
if assets_hostnames.empty?
assets_hostnames =
Discourse::Application.config.database_configuration[Rails.env]["host_names"]
assets_hostnames = Discourse::Application.config.database_configuration[Rails.env]["host_names"]
end
RailsMultisite::ConnectionManagement.asset_hostnames = assets_hostnames
# Multisite needs to be first, because the request tracker and message bus rely on it
Rails.configuration.middleware.unshift RailsMultisite::Middleware, RailsMultisite::DiscoursePatches.config
Rails.configuration.middleware.unshift RailsMultisite::Middleware,
RailsMultisite::DiscoursePatches.config
Rails.configuration.middleware.delete ActionDispatch::Executor
if defined?(RailsFailover::ActiveRecord) && Rails.configuration.active_record_rails_failover
Rails.configuration.middleware.insert_after(RailsMultisite::Middleware, RailsFailover::ActiveRecord::Middleware)
Rails.configuration.middleware.insert_after(
RailsMultisite::Middleware,
RailsFailover::ActiveRecord::Middleware,
)
end
if Rails.env.development?
@ -57,5 +59,8 @@ elsif Rails.configuration.multisite
end
end
elsif defined?(RailsFailover::ActiveRecord) && Rails.configuration.active_record_rails_failover
Rails.configuration.middleware.insert_before(MessageBus::Rack::Middleware, RailsFailover::ActiveRecord::Middleware)
Rails.configuration.middleware.insert_before(
MessageBus::Rack::Middleware,
RailsFailover::ActiveRecord::Middleware,
)
end

View File

@ -2,18 +2,32 @@
if !GlobalSetting.skip_redis?
if GlobalSetting.respond_to?(:redis_slave_host) && GlobalSetting.redis_slave_host.present?
Discourse.deprecate("redis_slave_host is deprecated, use redis_replica_host instead", drop_from: "2.8")
Discourse.deprecate(
"redis_slave_host is deprecated, use redis_replica_host instead",
drop_from: "2.8",
)
end
if GlobalSetting.respond_to?(:redis_slave_port) && GlobalSetting.redis_slave_port.present?
Discourse.deprecate("redis_slave_port is deprecated, use redis_replica_port instead", drop_from: "2.8")
Discourse.deprecate(
"redis_slave_port is deprecated, use redis_replica_port instead",
drop_from: "2.8",
)
end
if GlobalSetting.respond_to?(:message_bus_redis_slave_host) && GlobalSetting.message_bus_redis_slave_host.present?
Discourse.deprecate("message_bus_redis_slave_host is deprecated, use message_bus_redis_replica_host", drop_from: "2.8")
if GlobalSetting.respond_to?(:message_bus_redis_slave_host) &&
GlobalSetting.message_bus_redis_slave_host.present?
Discourse.deprecate(
"message_bus_redis_slave_host is deprecated, use message_bus_redis_replica_host",
drop_from: "2.8",
)
end
if GlobalSetting.respond_to?(:message_bus_redis_slave_port) && GlobalSetting.message_bus_redis_slave_port.present?
Discourse.deprecate("message_bus_redis_slave_port is deprecated, use message_bus_redis_replica_port", drop_from: "2.8")
if GlobalSetting.respond_to?(:message_bus_redis_slave_port) &&
GlobalSetting.message_bus_redis_slave_port.present?
Discourse.deprecate(
"message_bus_redis_slave_port is deprecated, use message_bus_redis_replica_port",
drop_from: "2.8",
)
end
end

View File

@ -17,11 +17,13 @@ Rails.application.config.assets.paths << "#{Rails.root}/public/javascripts"
# folder are already added.
# explicitly precompile any images in plugins ( /assets/images ) path
Rails.application.config.assets.precompile += [lambda do |filename, path|
path =~ /assets\/images/ && !%w(.js .css).include?(File.extname(filename))
end]
Rails.application.config.assets.precompile += [
lambda do |filename, path|
path =~ %r{assets/images} && !%w[.js .css].include?(File.extname(filename))
end,
]
Rails.application.config.assets.precompile += %w{
Rails.application.config.assets.precompile += %w[
discourse.js
vendor.js
admin.js
@ -49,15 +51,21 @@ Rails.application.config.assets.precompile += %w{
embed-application.js
scripts/discourse-test-listen-boot
scripts/discourse-boot
}
]
Rails.application.config.assets.precompile += EmberCli.assets.map { |name| name.sub('.js', '.map') }
Rails.application.config.assets.precompile += EmberCli.assets.map { |name| name.sub(".js", ".map") }
# Precompile all available locales
unless GlobalSetting.try(:omit_base_locales)
Dir.glob("#{Rails.root}/app/assets/javascripts/locales/*.js.erb").each do |file|
Rails.application.config.assets.precompile << "locales/#{file.match(/([a-z_A-Z]+\.js)\.erb$/)[1]}"
end
Dir
.glob("#{Rails.root}/app/assets/javascripts/locales/*.js.erb")
.each do |file|
Rails
.application
.config
.assets
.precompile << "locales/#{file.match(/([a-z_A-Z]+\.js)\.erb$/)[1]}"
end
end
# out of the box sprockets 3 grabs loose files that are hanging in assets,
@ -65,18 +73,16 @@ end
Rails.application.config.assets.precompile.delete(Sprockets::Railtie::LOOSE_APP_ASSETS)
# We don't want application from node_modules, only from the root
Rails.application.config.assets.precompile.delete(/(?:\/|\\|\A)application\.(css|js)$/)
Rails.application.config.assets.precompile += ['application.js']
Rails.application.config.assets.precompile.delete(%r{(?:/|\\|\A)application\.(css|js)$})
Rails.application.config.assets.precompile += ["application.js"]
start_path = ::Rails.root.join("app/assets").to_s
exclude = ['.es6', '.hbs', '.hbr', '.js', '.css', '.lock', '.json', '.log', '.html', '']
exclude = [".es6", ".hbs", ".hbr", ".js", ".css", ".lock", ".json", ".log", ".html", ""]
Rails.application.config.assets.precompile << lambda do |logical_path, filename|
filename.start_with?(start_path) &&
!filename.include?("/node_modules/") &&
!filename.include?("/dist/") &&
!exclude.include?(File.extname(logical_path))
filename.start_with?(start_path) && !filename.include?("/node_modules/") &&
!filename.include?("/dist/") && !exclude.include?(File.extname(logical_path))
end
Discourse.find_plugin_js_assets(include_disabled: true).each do |file|
Rails.application.config.assets.precompile << "#{file}.js"
end
Discourse
.find_plugin_js_assets(include_disabled: true)
.each { |file| Rails.application.config.assets.precompile << "#{file}.js" }

View File

@ -3,13 +3,13 @@
# Be sure to restart your server when you modify this file.
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [
:password,
:pop3_polling_password,
:api_key,
:s3_secret_access_key,
:twitter_consumer_secret,
:facebook_app_secret,
:github_client_secret,
:second_factor_token,
Rails.application.config.filter_parameters += %i[
password
pop3_polling_password
api_key
s3_secret_access_key
twitter_consumer_secret
facebook_app_secret
github_client_secret
second_factor_token
]

View File

@ -102,5 +102,5 @@ Rails.application.config.action_dispatch.default_headers = {
"X-Content-Type-Options" => "nosniff",
"X-Download-Options" => "noopen",
"X-Permitted-Cross-Domain-Policies" => "none",
"Referrer-Policy" => "strict-origin-when-cross-origin"
"Referrer-Policy" => "strict-origin-when-cross-origin",
}

View File

@ -3,6 +3,7 @@
# source: https://github.com/svenfuchs/i18n/blob/master/test/test_data/locales/plurals.rb
# stree-ignore
{
af: { i18n: { plural: { keys: [:one, :other], rule: lambda { |n| n == 1 ? :one : :other } } } },
am: { i18n: { plural: { keys: [:one, :other], rule: lambda { |n| [0, 1].include?(n) ? :one : :other } } } },

View File

@ -1,9 +1,8 @@
# frozen_string_literal: true
if ENV['RAILS_ENV'] == 'production'
if ENV["RAILS_ENV"] == "production"
# First, you need to change these below to your situation.
APP_ROOT = ENV["APP_ROOT"] || '/home/discourse/discourse'
APP_ROOT = ENV["APP_ROOT"] || "/home/discourse/discourse"
num_workers = ENV["NUM_WEBS"].to_i > 0 ? ENV["NUM_WEBS"].to_i : 4
# Second, you can choose how many threads that you are going to run at same time.
@ -16,5 +15,4 @@ if ENV['RAILS_ENV'] == 'production'
pidfile "#{APP_ROOT}/tmp/pids/puma.pid"
state_path "#{APP_ROOT}/tmp/pids/puma.state"
preload_app!
end

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,5 @@
# spring binstub rails
# spring binstub rake
# spring binstub rspec
Spring.after_fork do
Discourse.after_fork
end
Spring.after_fork { Discourse.after_fork }
Spring::Commands::Rake.environment_matchers["spec"] = "test"

View File

@ -3,9 +3,9 @@
# See http://unicorn.bogomips.org/Unicorn/Configurator.html
if (ENV["LOGSTASH_UNICORN_URI"] || "").length > 0
require_relative '../lib/discourse_logstash_logger'
require_relative '../lib/unicorn_logstash_patch'
logger DiscourseLogstashLogger.logger(uri: ENV['LOGSTASH_UNICORN_URI'], type: :unicorn)
require_relative "../lib/discourse_logstash_logger"
require_relative "../lib/unicorn_logstash_patch"
logger DiscourseLogstashLogger.logger(uri: ENV["LOGSTASH_UNICORN_URI"], type: :unicorn)
end
discourse_path = File.expand_path(File.expand_path(File.dirname(__FILE__)) + "/../")
@ -16,11 +16,10 @@ worker_processes (ENV["UNICORN_WORKERS"] || 3).to_i
working_directory discourse_path
# listen "#{discourse_path}/tmp/sockets/unicorn.sock"
listen ENV["UNICORN_LISTENER"] || "#{(ENV["UNICORN_BIND_ALL"] ? "" : "127.0.0.1:")}#{(ENV["UNICORN_PORT"] || 3000).to_i}"
listen ENV["UNICORN_LISTENER"] ||
"#{(ENV["UNICORN_BIND_ALL"] ? "" : "127.0.0.1:")}#{(ENV["UNICORN_PORT"] || 3000).to_i}"
if !File.exist?("#{discourse_path}/tmp/pids")
FileUtils.mkdir_p("#{discourse_path}/tmp/pids")
end
FileUtils.mkdir_p("#{discourse_path}/tmp/pids") if !File.exist?("#{discourse_path}/tmp/pids")
# feel free to point this anywhere accessible on the filesystem
pid (ENV["UNICORN_PID_PATH"] || "#{discourse_path}/tmp/pids/unicorn.pid")
@ -52,7 +51,6 @@ check_client_connection false
initialized = false
before_fork do |server, worker|
unless initialized
Discourse.preload_rails!
@ -67,7 +65,7 @@ before_fork do |server, worker|
initialized = true
supervisor = ENV['UNICORN_SUPERVISOR_PID'].to_i
supervisor = ENV["UNICORN_SUPERVISOR_PID"].to_i
if supervisor > 0
Thread.new do
while true
@ -80,14 +78,12 @@ before_fork do |server, worker|
end
end
sidekiqs = ENV['UNICORN_SIDEKIQS'].to_i
sidekiqs = ENV["UNICORN_SIDEKIQS"].to_i
if sidekiqs > 0
server.logger.info "starting #{sidekiqs} supervised sidekiqs"
require 'demon/sidekiq'
Demon::Sidekiq.after_fork do
DiscourseEvent.trigger(:sidekiq_fork_started)
end
require "demon/sidekiq"
Demon::Sidekiq.after_fork { DiscourseEvent.trigger(:sidekiq_fork_started) }
Demon::Sidekiq.start(sidekiqs)
@ -98,13 +94,14 @@ before_fork do |server, worker|
# Trap USR1, so we can re-issue to sidekiq workers
# but chain the default unicorn implementation as well
old_handler = Signal.trap("USR1") do
Demon::Sidekiq.kill("USR1")
old_handler.call
end
old_handler =
Signal.trap("USR1") do
Demon::Sidekiq.kill("USR1")
old_handler.call
end
end
if ENV['DISCOURSE_ENABLE_EMAIL_SYNC_DEMON'] == 'true'
if ENV["DISCOURSE_ENABLE_EMAIL_SYNC_DEMON"] == "true"
server.logger.info "starting up EmailSync demon"
Demon::EmailSync.start
Signal.trap("SIGTSTP") do
@ -119,13 +116,13 @@ before_fork do |server, worker|
end
class ::Unicorn::HttpServer
alias :master_sleep_orig :master_sleep
alias master_sleep_orig master_sleep
def max_sidekiq_rss
rss = `ps -eo rss,args | grep sidekiq | grep -v grep | awk '{print $1}'`
.split("\n")
.map(&:to_i)
.max
rss =
`ps -eo rss,args | grep sidekiq | grep -v grep | awk '{print $1}'`.split("\n")
.map(&:to_i)
.max
rss ||= 0
@ -133,18 +130,24 @@ before_fork do |server, worker|
end
def max_allowed_sidekiq_rss
[ENV['UNICORN_SIDEKIQ_MAX_RSS'].to_i, 500].max.megabytes
[ENV["UNICORN_SIDEKIQ_MAX_RSS"].to_i, 500].max.megabytes
end
def force_kill_rogue_sidekiq
info = `ps -eo pid,rss,args | grep sidekiq | grep -v grep | awk '{print $1,$2}'`
info.split("\n").each do |row|
pid, mem = row.split(" ").map(&:to_i)
if pid > 0 && (mem * 1024) > max_allowed_sidekiq_rss
Rails.logger.warn "Detected rogue Sidekiq pid #{pid} mem #{mem * 1024}, killing"
Process.kill("KILL", pid) rescue nil
info
.split("\n")
.each do |row|
pid, mem = row.split(" ").map(&:to_i)
if pid > 0 && (mem * 1024) > max_allowed_sidekiq_rss
Rails.logger.warn "Detected rogue Sidekiq pid #{pid} mem #{mem * 1024}, killing"
begin
Process.kill("KILL", pid)
rescue StandardError
nil
end
end
end
end
end
def check_sidekiq_heartbeat
@ -152,13 +155,15 @@ before_fork do |server, worker|
@sidekiq_next_heartbeat_check ||= Time.now.to_i + @sidekiq_heartbeat_interval
if @sidekiq_next_heartbeat_check < Time.now.to_i
last_heartbeat = Jobs::RunHeartbeat.last_heartbeat
restart = false
sidekiq_rss = max_sidekiq_rss
if sidekiq_rss > max_allowed_sidekiq_rss
Rails.logger.warn("Sidekiq is consuming too much memory (using: %0.2fM) for '%s', restarting" % [(sidekiq_rss.to_f / 1.megabyte), ENV["DISCOURSE_HOSTNAME"]])
Rails.logger.warn(
"Sidekiq is consuming too much memory (using: %0.2fM) for '%s', restarting" %
[(sidekiq_rss.to_f / 1.megabyte), ENV["DISCOURSE_HOSTNAME"]],
)
restart = true
end
@ -185,16 +190,18 @@ before_fork do |server, worker|
email_sync_pids = Demon::EmailSync.demons.map { |uid, demon| demon.pid }
return 0 if email_sync_pids.empty?
rss = `ps -eo pid,rss,args | grep '#{email_sync_pids.join('|')}' | grep -v grep | awk '{print $2}'`
.split("\n")
.map(&:to_i)
.max
rss =
`ps -eo pid,rss,args | grep '#{email_sync_pids.join("|")}' | grep -v grep | awk '{print $2}'`.split(
"\n",
)
.map(&:to_i)
.max
(rss || 0) * 1024
end
def max_allowed_email_sync_rss
[ENV['UNICORN_EMAIL_SYNC_MAX_RSS'].to_i, 500].max.megabytes
[ENV["UNICORN_EMAIL_SYNC_MAX_RSS"].to_i, 500].max.megabytes
end
def check_email_sync_heartbeat
@ -207,16 +214,22 @@ before_fork do |server, worker|
restart = false
# Restart process if it does not respond anymore
last_heartbeat_ago = Time.now.to_i - Discourse.redis.get(Demon::EmailSync::HEARTBEAT_KEY).to_i
last_heartbeat_ago =
Time.now.to_i - Discourse.redis.get(Demon::EmailSync::HEARTBEAT_KEY).to_i
if last_heartbeat_ago > Demon::EmailSync::HEARTBEAT_INTERVAL.to_i
STDERR.puts("EmailSync heartbeat test failed (last heartbeat was #{last_heartbeat_ago}s ago), restarting")
STDERR.puts(
"EmailSync heartbeat test failed (last heartbeat was #{last_heartbeat_ago}s ago), restarting",
)
restart = true
end
# Restart process if memory usage is too high
email_sync_rss = max_email_sync_rss
if email_sync_rss > max_allowed_email_sync_rss
STDERR.puts("EmailSync is consuming too much memory (using: %0.2fM) for '%s', restarting" % [(email_sync_rss.to_f / 1.megabyte), ENV["DISCOURSE_HOSTNAME"]])
STDERR.puts(
"EmailSync is consuming too much memory (using: %0.2fM) for '%s', restarting" %
[(email_sync_rss.to_f / 1.megabyte), ENV["DISCOURSE_HOSTNAME"]],
)
restart = true
end
@ -224,25 +237,22 @@ before_fork do |server, worker|
end
def master_sleep(sec)
sidekiqs = ENV['UNICORN_SIDEKIQS'].to_i
sidekiqs = ENV["UNICORN_SIDEKIQS"].to_i
if sidekiqs > 0
Demon::Sidekiq.ensure_running
check_sidekiq_heartbeat
end
if ENV['DISCOURSE_ENABLE_EMAIL_SYNC_DEMON'] == 'true'
if ENV["DISCOURSE_ENABLE_EMAIL_SYNC_DEMON"] == "true"
Demon::EmailSync.ensure_running
check_email_sync_heartbeat
end
DiscoursePluginRegistry.demon_processes.each do |demon_class|
demon_class.ensure_running
end
DiscoursePluginRegistry.demon_processes.each { |demon_class| demon_class.ensure_running }
master_sleep_orig(sec)
end
end
end
Discourse.redis.close