DEV: Apply syntax_tree formatting to `config/*`
This commit is contained in:
parent
436b3b392b
commit
7c77cc6a58
1
.streerc
1
.streerc
|
@ -2,7 +2,6 @@
|
||||||
--plugins=plugin/trailing_comma,disable_ternary
|
--plugins=plugin/trailing_comma,disable_ternary
|
||||||
--ignore-files=Gemfile
|
--ignore-files=Gemfile
|
||||||
--ignore-files=app/*
|
--ignore-files=app/*
|
||||||
--ignore-files=config/*
|
|
||||||
--ignore-files=db/*
|
--ignore-files=db/*
|
||||||
--ignore-files=lib/*
|
--ignore-files=lib/*
|
||||||
--ignore-files=spec/*
|
--ignore-files=spec/*
|
||||||
|
|
|
@ -5,12 +5,12 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7.0")
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
require File.expand_path('../boot', __FILE__)
|
require File.expand_path("../boot", __FILE__)
|
||||||
require 'active_record/railtie'
|
require "active_record/railtie"
|
||||||
require 'action_controller/railtie'
|
require "action_controller/railtie"
|
||||||
require 'action_view/railtie'
|
require "action_view/railtie"
|
||||||
require 'action_mailer/railtie'
|
require "action_mailer/railtie"
|
||||||
require 'sprockets/railtie'
|
require "sprockets/railtie"
|
||||||
|
|
||||||
if !Rails.env.production?
|
if !Rails.env.production?
|
||||||
recommended = File.read(".ruby-version.sample").strip
|
recommended = File.read(".ruby-version.sample").strip
|
||||||
|
@ -20,66 +20,59 @@ if !Rails.env.production?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Plugin related stuff
|
# Plugin related stuff
|
||||||
require_relative '../lib/plugin'
|
require_relative "../lib/plugin"
|
||||||
require_relative '../lib/discourse_event'
|
require_relative "../lib/discourse_event"
|
||||||
require_relative '../lib/discourse_plugin_registry'
|
require_relative "../lib/discourse_plugin_registry"
|
||||||
|
|
||||||
require_relative '../lib/plugin_gem'
|
require_relative "../lib/plugin_gem"
|
||||||
|
|
||||||
# Global config
|
# Global config
|
||||||
require_relative '../app/models/global_setting'
|
require_relative "../app/models/global_setting"
|
||||||
GlobalSetting.configure!
|
GlobalSetting.configure!
|
||||||
if GlobalSetting.load_plugins?
|
if GlobalSetting.load_plugins?
|
||||||
# Support for plugins to register custom setting providers. They can do this
|
# 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
|
# by having a file, `register_provider.rb` in their root that will be run
|
||||||
# at this point.
|
# 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
|
require p
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
GlobalSetting.load_defaults
|
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"
|
STDERR.puts "WARNING: Your CDN URL does not begin with a protocol like `https://` - this is probably not going to work"
|
||||||
end
|
end
|
||||||
|
|
||||||
if ENV['SKIP_DB_AND_REDIS'] == '1'
|
if ENV["SKIP_DB_AND_REDIS"] == "1"
|
||||||
GlobalSetting.skip_db = true
|
GlobalSetting.skip_db = true
|
||||||
GlobalSetting.skip_redis = true
|
GlobalSetting.skip_redis = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if !GlobalSetting.skip_db?
|
require "rails_failover/active_record" if !GlobalSetting.skip_db?
|
||||||
require 'rails_failover/active_record'
|
|
||||||
end
|
|
||||||
|
|
||||||
if !GlobalSetting.skip_redis?
|
require "rails_failover/redis" if !GlobalSetting.skip_redis?
|
||||||
require 'rails_failover/redis'
|
|
||||||
end
|
|
||||||
|
|
||||||
require 'pry-rails' if Rails.env.development?
|
require "pry-rails" if Rails.env.development?
|
||||||
require 'pry-byebug' 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)
|
if defined?(Bundler)
|
||||||
bundler_groups = [:default]
|
bundler_groups = [:default]
|
||||||
|
|
||||||
if !Rails.env.production?
|
if !Rails.env.production?
|
||||||
bundler_groups = bundler_groups.concat(Rails.groups(
|
bundler_groups = bundler_groups.concat(Rails.groups(assets: %w[development test profile]))
|
||||||
assets: %w(development test profile)
|
|
||||||
))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Bundler.require(*bundler_groups)
|
Bundler.require(*bundler_groups)
|
||||||
end
|
end
|
||||||
|
|
||||||
require_relative '../lib/require_dependency_backward_compatibility'
|
require_relative "../lib/require_dependency_backward_compatibility"
|
||||||
|
|
||||||
module Discourse
|
module Discourse
|
||||||
class Application < Rails::Application
|
class Application < Rails::Application
|
||||||
|
|
||||||
def config.database_configuration
|
def config.database_configuration
|
||||||
if Rails.env.production?
|
if Rails.env.production?
|
||||||
GlobalSetting.database_config
|
GlobalSetting.database_config
|
||||||
|
@ -91,18 +84,23 @@ module Discourse
|
||||||
# Application configuration should go into files in config/initializers
|
# Application configuration should go into files in config/initializers
|
||||||
# -- all .rb files in that directory are automatically loaded.
|
# -- all .rb files in that directory are automatically loaded.
|
||||||
|
|
||||||
require 'discourse'
|
require "discourse"
|
||||||
require 'js_locale_helper'
|
require "js_locale_helper"
|
||||||
|
|
||||||
# tiny file needed by site settings
|
# tiny file needed by site settings
|
||||||
require 'highlight_js'
|
require "highlight_js"
|
||||||
|
|
||||||
config.load_defaults 6.1
|
config.load_defaults 6.1
|
||||||
config.active_record.cache_versioning = false # our custom cache class doesn’t support this
|
config.active_record.cache_versioning = false # our custom cache class doesn’t support this
|
||||||
config.action_controller.forgery_protection_origin_check = false
|
config.action_controller.forgery_protection_origin_check = false
|
||||||
config.active_record.belongs_to_required_by_default = false
|
config.active_record.belongs_to_required_by_default = false
|
||||||
config.active_record.legacy_connection_handling = true
|
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
|
# we skip it cause we configure it in the initializer
|
||||||
# the railtie for message_bus would insert it in the
|
# the railtie for message_bus would insert it in the
|
||||||
|
@ -111,7 +109,8 @@ module Discourse
|
||||||
config.skip_multisite_middleware = true
|
config.skip_multisite_middleware = true
|
||||||
config.skip_rails_failover_active_record_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)
|
config.multisite_config_path = File.absolute_path(multisite_config_path, Rails.root)
|
||||||
|
|
||||||
# Custom directories with classes and modules you want to be autoloadable.
|
# 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.
|
# 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.
|
# 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
|
# auto-load locales in plugins
|
||||||
# NOTE: we load both client & server locales since some might be used by PrettyText
|
# 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"]
|
config.i18n.load_path += Dir["#{Rails.root}/plugins/*/config/locales/*.yml"]
|
||||||
|
|
||||||
# Configure the default encoding used in templates for Ruby 1.9.
|
# 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
|
# see: http://stackoverflow.com/questions/11894180/how-does-one-correctly-add-custom-sql-dml-in-migrations/11894420#11894420
|
||||||
config.active_record.schema_format = :sql
|
config.active_record.schema_format = :sql
|
||||||
|
@ -145,7 +144,7 @@ module Discourse
|
||||||
config.active_record.use_schema_cache_dump = false
|
config.active_record.use_schema_cache_dump = false
|
||||||
|
|
||||||
# per https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
|
# per https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
|
||||||
config.pbkdf2_iterations = 64000
|
config.pbkdf2_iterations = 64_000
|
||||||
config.pbkdf2_algorithm = "sha256"
|
config.pbkdf2_algorithm = "sha256"
|
||||||
|
|
||||||
# rack lock is nothing but trouble, get rid of it
|
# rack lock is nothing but trouble, get rid of it
|
||||||
|
@ -160,32 +159,39 @@ module Discourse
|
||||||
# supports etags (post 1.7)
|
# supports etags (post 1.7)
|
||||||
config.middleware.delete Rack::ETag
|
config.middleware.delete Rack::ETag
|
||||||
|
|
||||||
if !(Rails.env.development? || ENV['SKIP_ENFORCE_HOSTNAME'] == "1")
|
if !(Rails.env.development? || ENV["SKIP_ENFORCE_HOSTNAME"] == "1")
|
||||||
require 'middleware/enforce_hostname'
|
require "middleware/enforce_hostname"
|
||||||
config.middleware.insert_after Rack::MethodOverride, Middleware::EnforceHostname
|
config.middleware.insert_after Rack::MethodOverride, Middleware::EnforceHostname
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'content_security_policy/middleware'
|
require "content_security_policy/middleware"
|
||||||
config.middleware.swap ActionDispatch::ContentSecurityPolicy::Middleware, ContentSecurityPolicy::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)
|
config.exceptions_app = Middleware::DiscoursePublicExceptions.new(Rails.public_path)
|
||||||
|
|
||||||
require 'discourse_js_processor'
|
require "discourse_js_processor"
|
||||||
require 'discourse_sourcemapping_url_processor'
|
require "discourse_sourcemapping_url_processor"
|
||||||
|
|
||||||
Sprockets.register_mime_type 'application/javascript', extensions: ['.js', '.es6', '.js.es6'], charset: :unicode
|
Sprockets.register_mime_type "application/javascript",
|
||||||
Sprockets.register_postprocessor 'application/javascript', DiscourseJsProcessor
|
extensions: %w[.js .es6 .js.es6],
|
||||||
|
charset: :unicode
|
||||||
|
Sprockets.register_postprocessor "application/javascript", DiscourseJsProcessor
|
||||||
|
|
||||||
Discourse::Application.initializer :prepend_ember_assets do |app|
|
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
|
# 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"
|
app
|
||||||
Sprockets.unregister_postprocessor 'application/javascript', Sprockets::Rails::SourcemappingUrlProcessor
|
.config
|
||||||
Sprockets.register_postprocessor 'application/javascript', DiscourseSourcemappingUrlProcessor
|
.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
|
end
|
||||||
|
|
||||||
require 'discourse_redis'
|
require "discourse_redis"
|
||||||
require 'logster/redis_store'
|
require "logster/redis_store"
|
||||||
# Use redis for our cache
|
# Use redis for our cache
|
||||||
config.cache_store = DiscourseRedis.new_redis_store
|
config.cache_store = DiscourseRedis.new_redis_store
|
||||||
Discourse.redis = DiscourseRedis.new
|
Discourse.redis = DiscourseRedis.new
|
||||||
|
@ -198,7 +204,7 @@ module Discourse
|
||||||
# our setup does not use rack cache and instead defers to nginx
|
# our setup does not use rack cache and instead defers to nginx
|
||||||
config.action_dispatch.rack_cache = nil
|
config.action_dispatch.rack_cache = nil
|
||||||
|
|
||||||
require 'auth'
|
require "auth"
|
||||||
|
|
||||||
if GlobalSetting.relative_url_root.present?
|
if GlobalSetting.relative_url_root.present?
|
||||||
config.relative_url_root = GlobalSetting.relative_url_root
|
config.relative_url_root = GlobalSetting.relative_url_root
|
||||||
|
@ -207,38 +213,28 @@ module Discourse
|
||||||
if Rails.env.test? && GlobalSetting.load_plugins?
|
if Rails.env.test? && GlobalSetting.load_plugins?
|
||||||
Discourse.activate_plugins!
|
Discourse.activate_plugins!
|
||||||
elsif GlobalSetting.load_plugins?
|
elsif GlobalSetting.load_plugins?
|
||||||
Plugin.initialization_guard do
|
Plugin.initialization_guard { Discourse.activate_plugins! }
|
||||||
Discourse.activate_plugins!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use discourse-fonts gem to symlink fonts and generate .scss file
|
# 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)
|
Discourse::Utils.atomic_ln_s(DiscourseFonts.path_for_fonts, fonts_path)
|
||||||
|
|
||||||
require 'stylesheet/manager'
|
require "stylesheet/manager"
|
||||||
require 'svg_sprite'
|
require "svg_sprite"
|
||||||
|
|
||||||
config.after_initialize do
|
config.after_initialize do
|
||||||
# Load plugins
|
# Load plugins
|
||||||
Plugin.initialization_guard do
|
Plugin.initialization_guard { Discourse.plugins.each(&:notify_after_initialize) }
|
||||||
Discourse.plugins.each(&:notify_after_initialize)
|
|
||||||
end
|
|
||||||
|
|
||||||
# we got to clear the pool in case plugins connect
|
# we got to clear the pool in case plugins connect
|
||||||
ActiveRecord::Base.connection_handler.clear_active_connections!
|
ActiveRecord::Base.connection_handler.clear_active_connections!
|
||||||
end
|
end
|
||||||
|
|
||||||
if ENV['RBTRACE'] == "1"
|
require "rbtrace" if ENV["RBTRACE"] == "1"
|
||||||
require 'rbtrace'
|
|
||||||
end
|
|
||||||
|
|
||||||
if ENV['RAILS_QUERY_LOG_TAGS'] == "1"
|
config.active_record.query_log_tags_enabled = true if ENV["RAILS_QUERY_LOG_TAGS"] == "1"
|
||||||
config.active_record.query_log_tags_enabled = true
|
|
||||||
end
|
|
||||||
|
|
||||||
config.generators do |g|
|
config.generators { |g| g.test_framework :rspec, fixture: false }
|
||||||
g.test_framework :rspec, fixture: false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,48 +1,49 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
if ENV['DISCOURSE_DUMP_HEAP'] == "1"
|
if ENV["DISCOURSE_DUMP_HEAP"] == "1"
|
||||||
require 'objspace'
|
require "objspace"
|
||||||
ObjectSpace.trace_object_allocations_start
|
ObjectSpace.trace_object_allocations_start
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'rubygems'
|
require "rubygems"
|
||||||
|
|
||||||
# Set up gems listed in the Gemfile.
|
# 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
|
begin
|
||||||
require 'bootsnap'
|
require "bootsnap"
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
# not a strong requirement
|
# not a strong requirement
|
||||||
end
|
end
|
||||||
|
|
||||||
if defined? Bootsnap
|
if defined?(Bootsnap)
|
||||||
Bootsnap.setup(
|
Bootsnap.setup(
|
||||||
cache_dir: 'tmp/cache', # Path to your cache
|
cache_dir: "tmp/cache", # Path to your cache
|
||||||
load_path_cache: true, # Should we optimize the LOAD_PATH with a 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_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
|
compile_cache_yaml: false, # Skip YAML cache for now, cause we were seeing issues with it
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parallel spec system
|
# Parallel spec system
|
||||||
if ENV['RAILS_ENV'] == "test" && ENV['TEST_ENV_NUMBER']
|
if ENV["RAILS_ENV"] == "test" && ENV["TEST_ENV_NUMBER"]
|
||||||
if ENV['TEST_ENV_NUMBER'] == ''
|
if ENV["TEST_ENV_NUMBER"] == ""
|
||||||
n = 1
|
n = 1
|
||||||
else
|
else
|
||||||
n = ENV['TEST_ENV_NUMBER'].to_i
|
n = ENV["TEST_ENV_NUMBER"].to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
port = 10000 + n
|
port = 10_000 + n
|
||||||
|
|
||||||
STDERR.puts "Setting up parallel test mode - starting Redis #{n} on port #{port}"
|
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`
|
`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["DISCOURSE_REDIS_PORT"] = port.to_s
|
||||||
ENV["RAILS_DB"] = "discourse_test_#{n}"
|
ENV["RAILS_DB"] = "discourse_test_#{n}"
|
||||||
|
|
|
@ -7,7 +7,7 @@ Discourse::Application.configure do
|
||||||
config.cache_classes = true
|
config.cache_classes = true
|
||||||
|
|
||||||
# Full error reports are disabled and caching is turned on
|
# 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
|
config.action_controller.perform_caching = true
|
||||||
|
|
||||||
# Disable Rails's static asset server (Apache or nginx will already do this)
|
# 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
|
config.assets.digest = true
|
||||||
|
|
||||||
# Specifies the header that your server uses for sending files
|
# 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
|
# you may use other configuration here for mail eg: sendgrid
|
||||||
|
|
||||||
config.action_mailer.delivery_method = :smtp
|
config.action_mailer.delivery_method = :smtp
|
||||||
config.action_mailer.smtp_settings = {
|
config.action_mailer.smtp_settings = {
|
||||||
address: ENV['SMTP_ADDRESS'],
|
address: ENV["SMTP_ADDRESS"],
|
||||||
port: ENV['SMTP_PORT'],
|
port: ENV["SMTP_PORT"],
|
||||||
domain: ENV['SMTP_DOMAIN'],
|
domain: ENV["SMTP_DOMAIN"],
|
||||||
user_name: ENV['SMTP_USERNAME'],
|
user_name: ENV["SMTP_USERNAME"],
|
||||||
password: ENV['SMTP_PASSWORD'],
|
password: ENV["SMTP_PASSWORD"],
|
||||||
authentication: 'plain',
|
authentication: "plain",
|
||||||
enable_starttls_auto: true }
|
enable_starttls_auto: true,
|
||||||
|
}
|
||||||
|
|
||||||
#config.action_mailer.delivery_method = :sendmail
|
#config.action_mailer.delivery_method = :sendmail
|
||||||
#config.action_mailer.sendmail_settings = {arguments: '-i'}
|
#config.action_mailer.sendmail_settings = {arguments: '-i'}
|
||||||
|
@ -59,5 +60,4 @@ Discourse::Application.configure do
|
||||||
# Discourse strongly recommend you use a CDN.
|
# Discourse strongly recommend you use a CDN.
|
||||||
# For origin pull cdns all you need to do is register an account and configure
|
# For origin pull cdns all you need to do is register an account and configure
|
||||||
# config.action_controller.asset_host = "http://YOUR_CDN_HERE"
|
# config.action_controller.asset_host = "http://YOUR_CDN_HERE"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ require_relative "application"
|
||||||
Rails.application.initialize!
|
Rails.application.initialize!
|
||||||
|
|
||||||
# When in "dev" mode, ensure we won't be sending any emails
|
# 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"
|
fail "In development mode, you should be using mailhog otherwise you might end up sending thousands of digest emails"
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ Discourse::Application.configure do
|
||||||
config.active_record.use_schema_cache_dump = true
|
config.active_record.use_schema_cache_dump = true
|
||||||
|
|
||||||
# Show full error reports and disable caching
|
# 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.perform_caching = false
|
||||||
|
|
||||||
config.action_controller.asset_host = GlobalSetting.cdn_url
|
config.action_controller.asset_host = GlobalSetting.cdn_url
|
||||||
|
@ -32,27 +32,23 @@ Discourse::Application.configure do
|
||||||
|
|
||||||
config.assets.debug = false
|
config.assets.debug = false
|
||||||
|
|
||||||
config.public_file_server.headers = {
|
config.public_file_server.headers = { "Access-Control-Allow-Origin" => "*" }
|
||||||
'Access-Control-Allow-Origin' => '*'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Raise an error on page load if there are pending migrations
|
# Raise an error on page load if there are pending migrations
|
||||||
config.active_record.migration_error = :page_load
|
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
|
# we recommend you use mailhog https://github.com/mailhog/MailHog
|
||||||
config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
|
config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
|
||||||
|
|
||||||
config.action_mailer.raise_delivery_errors = true
|
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 if ENV["RAILS_VERBOSE_QUERY_LOGS"] == "1"
|
||||||
config.active_record.verbose_query_logs = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if defined?(BetterErrors)
|
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
|
if defined?(Unicorn) && ENV["UNICORN_WORKERS"].to_i != 1
|
||||||
# BetterErrors doesn't work with multiple unicorn workers. Disable it to avoid confusion
|
# BetterErrors doesn't work with multiple unicorn workers. Disable it to avoid confusion
|
||||||
|
@ -60,51 +56,44 @@ Discourse::Application.configure do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if !ENV["DISABLE_MINI_PROFILER"]
|
config.load_mini_profiler = true if !ENV["DISABLE_MINI_PROFILER"]
|
||||||
config.load_mini_profiler = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if hosts = ENV['DISCOURSE_DEV_HOSTS']
|
if hosts = ENV["DISCOURSE_DEV_HOSTS"]
|
||||||
Discourse.deprecate("DISCOURSE_DEV_HOSTS is deprecated. Use RAILS_DEVELOPMENT_HOSTS instead.")
|
Discourse.deprecate("DISCOURSE_DEV_HOSTS is deprecated. Use RAILS_DEVELOPMENT_HOSTS instead.")
|
||||||
config.hosts.concat(hosts.split(","))
|
config.hosts.concat(hosts.split(","))
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'middleware/turbo_dev'
|
require "middleware/turbo_dev"
|
||||||
config.middleware.insert 0, Middleware::TurboDev
|
config.middleware.insert 0, Middleware::TurboDev
|
||||||
require 'middleware/missing_avatars'
|
require "middleware/missing_avatars"
|
||||||
config.middleware.insert 1, Middleware::MissingAvatars
|
config.middleware.insert 1, Middleware::MissingAvatars
|
||||||
|
|
||||||
config.enable_anon_caching = false
|
config.enable_anon_caching = false
|
||||||
if RUBY_ENGINE == "ruby"
|
require "rbtrace" if RUBY_ENGINE == "ruby"
|
||||||
require 'rbtrace'
|
|
||||||
end
|
|
||||||
|
|
||||||
if emails = GlobalSetting.developer_emails
|
if emails = GlobalSetting.developer_emails
|
||||||
config.developer_emails = emails.split(",").map(&:downcase).map(&:strip)
|
config.developer_emails = emails.split(",").map(&:downcase).map(&:strip)
|
||||||
end
|
end
|
||||||
|
|
||||||
if ENV["DISCOURSE_SKIP_CSS_WATCHER"] != "1" && (defined?(Rails::Server) || defined?(Puma) || defined?(Unicorn))
|
if ENV["DISCOURSE_SKIP_CSS_WATCHER"] != "1" &&
|
||||||
require 'stylesheet/watcher'
|
(defined?(Rails::Server) || defined?(Puma) || defined?(Unicorn))
|
||||||
|
require "stylesheet/watcher"
|
||||||
STDERR.puts "Starting CSS change watcher"
|
STDERR.puts "Starting CSS change watcher"
|
||||||
@watcher = Stylesheet::Watcher.watch
|
@watcher = Stylesheet::Watcher.watch
|
||||||
end
|
end
|
||||||
|
|
||||||
config.after_initialize do
|
config.after_initialize do
|
||||||
if ENV["RAILS_COLORIZE_LOGGING"] == "1"
|
config.colorize_logging = true if ENV["RAILS_COLORIZE_LOGGING"] == "1"
|
||||||
config.colorize_logging = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if ENV["RAILS_VERBOSE_QUERY_LOGS"] == "1"
|
if ENV["RAILS_VERBOSE_QUERY_LOGS"] == "1"
|
||||||
ActiveRecord::LogSubscriber.backtrace_cleaner.add_silencer do |line|
|
ActiveRecord::LogSubscriber.backtrace_cleaner.add_silencer do |line|
|
||||||
line =~ /lib\/freedom_patches/
|
line =~ %r{lib/freedom_patches}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ENV["RAILS_DISABLE_ACTIVERECORD_LOGS"] == "1"
|
ActiveRecord::Base.logger = nil if ENV["RAILS_DISABLE_ACTIVERECORD_LOGS"] == "1"
|
||||||
ActiveRecord::Base.logger = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if ENV['BULLET']
|
if ENV["BULLET"]
|
||||||
Bullet.enable = true
|
Bullet.enable = true
|
||||||
Bullet.rails_logger = true
|
Bullet.rails_logger = true
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ Discourse::Application.configure do
|
||||||
config.eager_load = true
|
config.eager_load = true
|
||||||
|
|
||||||
# Full error reports are disabled and caching is turned on
|
# 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
|
config.action_controller.perform_caching = true
|
||||||
|
|
||||||
# Disable Rails's static asset server (Apache or nginx will already do this)
|
# 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,
|
authentication: GlobalSetting.smtp_authentication,
|
||||||
enable_starttls_auto: GlobalSetting.smtp_enable_start_tls,
|
enable_starttls_auto: GlobalSetting.smtp_enable_start_tls,
|
||||||
open_timeout: GlobalSetting.smtp_open_timeout,
|
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 if GlobalSetting.smtp_force_tls
|
||||||
settings[:tls] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
config.action_mailer.smtp_settings = settings.compact
|
config.action_mailer.smtp_settings = settings.compact
|
||||||
else
|
else
|
||||||
config.action_mailer.delivery_method = :sendmail
|
config.action_mailer.delivery_method = :sendmail
|
||||||
config.action_mailer.sendmail_settings = { arguments: '-i' }
|
config.action_mailer.sendmail_settings = { arguments: "-i" }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Send deprecation notices to registered listeners
|
# Send deprecation notices to registered listeners
|
||||||
|
|
|
@ -11,7 +11,7 @@ Discourse::Application.configure do
|
||||||
config.log_level = :info
|
config.log_level = :info
|
||||||
|
|
||||||
# Full error reports are disabled and caching is turned on
|
# 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
|
config.action_controller.perform_caching = true
|
||||||
|
|
||||||
# in profile mode we serve static assets
|
# in profile mode we serve static assets
|
||||||
|
@ -27,7 +27,7 @@ Discourse::Application.configure do
|
||||||
config.assets.digest = true
|
config.assets.digest = true
|
||||||
|
|
||||||
# Specifies the header that your server uses for sending files
|
# 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
|
# we recommend you use mailhog https://github.com/mailhog/MailHog
|
||||||
config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
|
config.action_mailer.smtp_settings = { address: "localhost", port: 1025 }
|
||||||
|
@ -39,9 +39,7 @@ Discourse::Application.configure do
|
||||||
config.load_mini_profiler = false
|
config.load_mini_profiler = false
|
||||||
|
|
||||||
# we don't need full logster support, but need to keep it working
|
# we don't need full logster support, but need to keep it working
|
||||||
config.after_initialize do
|
config.after_initialize { Logster.logger = Rails.logger }
|
||||||
Logster.logger = Rails.logger
|
|
||||||
end
|
|
||||||
|
|
||||||
# for profiling with perftools
|
# for profiling with perftools
|
||||||
# config.middleware.use ::Rack::PerftoolsProfiler, default_printer: 'gif'
|
# config.middleware.use ::Rack::PerftoolsProfiler, default_printer: 'gif'
|
||||||
|
|
|
@ -46,21 +46,22 @@ Discourse::Application.configure do
|
||||||
|
|
||||||
config.eager_load = false
|
config.eager_load = false
|
||||||
|
|
||||||
if ENV['RAILS_ENABLE_TEST_LOG']
|
if ENV["RAILS_ENABLE_TEST_LOG"]
|
||||||
config.logger = Logger.new(STDOUT)
|
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
|
else
|
||||||
config.logger = Logger.new(nil)
|
config.logger = Logger.new(nil)
|
||||||
config.log_level = :fatal
|
config.log_level = :fatal
|
||||||
end
|
end
|
||||||
|
|
||||||
if defined? RspecErrorTracker
|
if defined?(RspecErrorTracker)
|
||||||
config.middleware.insert_after ActionDispatch::Flash, RspecErrorTracker
|
config.middleware.insert_after ActionDispatch::Flash, RspecErrorTracker
|
||||||
end
|
end
|
||||||
|
|
||||||
config.after_initialize do
|
config.after_initialize do
|
||||||
SiteSetting.defaults.tap do |s|
|
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_post_length, 5)
|
||||||
s.set_regardless_of_locale(:min_first_post_length, 5)
|
s.set_regardless_of_locale(:min_first_post_length, 5)
|
||||||
s.set_regardless_of_locale(:min_personal_message_post_length, 10)
|
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)
|
s.set_regardless_of_locale(:allow_uncategorized_topics, true)
|
||||||
|
|
||||||
# disable plugins
|
# disable plugins
|
||||||
if ENV['LOAD_PLUGINS'] == '1'
|
if ENV["LOAD_PLUGINS"] == "1"
|
||||||
s.set_regardless_of_locale(:discourse_narrative_bot_enabled, false)
|
s.set_regardless_of_locale(:discourse_narrative_bot_enabled, false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,25 +8,35 @@ if Rails.env.development? && !Rails.configuration.cache_classes && Discourse.run
|
||||||
*Dir["#{Rails.root}/app/*"].reject { |path| path.end_with? "/assets" },
|
*Dir["#{Rails.root}/app/*"].reject { |path| path.end_with? "/assets" },
|
||||||
"#{Rails.root}/config",
|
"#{Rails.root}/config",
|
||||||
"#{Rails.root}/lib",
|
"#{Rails.root}/lib",
|
||||||
"#{Rails.root}/plugins"
|
"#{Rails.root}/plugins",
|
||||||
]
|
]
|
||||||
|
|
||||||
Listen.to(*paths, only: /\.rb$/) do |modified, added, removed|
|
Listen
|
||||||
supervisor_pid = UNICORN_DEV_SUPERVISOR_PID
|
.to(*paths, only: /\.rb$/) do |modified, added, removed|
|
||||||
auto_restart = supervisor_pid && ENV["AUTO_RESTART"] != "0"
|
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|
|
not_autoloaded =
|
||||||
autoloaded = Rails.autoloaders.main.autoloads.key? file
|
files.filter_map do |file|
|
||||||
Pathname.new(file).relative_path_from(Rails.root) if !autoloaded
|
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
|
end
|
||||||
|
.start
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'mini_sql_multisite_connection'
|
require "mini_sql_multisite_connection"
|
||||||
::DB = MiniSqlMultisiteConnection.instance
|
::DB = MiniSqlMultisiteConnection.instance
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
unless Discourse.skip_post_deployment_migrations?
|
unless Discourse.skip_post_deployment_migrations?
|
||||||
ActiveRecord::Tasks::DatabaseTasks.migrations_paths << Rails.root.join(
|
ActiveRecord::Tasks::DatabaseTasks.migrations_paths << Rails
|
||||||
Discourse::DB_POST_MIGRATE_PATH
|
.root
|
||||||
).to_s
|
.join(Discourse::DB_POST_MIGRATE_PATH)
|
||||||
|
.to_s
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,31 +15,32 @@
|
||||||
# Warning: this could create some very large files!
|
# Warning: this could create some very large files!
|
||||||
|
|
||||||
if ENV["TRACE_PG_CONNECTIONS"]
|
if ENV["TRACE_PG_CONNECTIONS"]
|
||||||
PG::Connection.prepend(Module.new do
|
PG::Connection.prepend(
|
||||||
TRACE_DIR = "tmp/pgtrace"
|
Module.new do
|
||||||
|
TRACE_DIR = "tmp/pgtrace"
|
||||||
|
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
super(*args).tap do
|
super(*args).tap do
|
||||||
next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
|
next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
|
||||||
FileUtils.mkdir_p(TRACE_DIR)
|
FileUtils.mkdir_p(TRACE_DIR)
|
||||||
@trace_filename = "#{TRACE_DIR}/#{Process.pid}_#{self.object_id}.txt"
|
@trace_filename = "#{TRACE_DIR}/#{Process.pid}_#{self.object_id}.txt"
|
||||||
trace File.new(@trace_filename, "w")
|
trace File.new(@trace_filename, "w")
|
||||||
|
end
|
||||||
|
@access_log_mutex = Mutex.new
|
||||||
|
@accessor_thread = nil
|
||||||
end
|
end
|
||||||
@access_log_mutex = Mutex.new
|
|
||||||
@accessor_thread = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def close
|
def close
|
||||||
super.tap do
|
super.tap do
|
||||||
next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
|
next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server?
|
||||||
File.delete(@trace_filename)
|
File.delete(@trace_filename)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def log_access(&blk)
|
def log_access(&blk)
|
||||||
@access_log_mutex.synchronize do
|
@access_log_mutex.synchronize do
|
||||||
if !@accessor_thread.nil?
|
if !@accessor_thread.nil?
|
||||||
Rails.logger.error <<~TEXT
|
Rails.logger.error <<~TEXT
|
||||||
PG Clash: A connection is being accessed from two locations
|
PG Clash: A connection is being accessed from two locations
|
||||||
|
|
||||||
#{@accessor_thread} was using the connection. Backtrace:
|
#{@accessor_thread} was using the connection. Backtrace:
|
||||||
|
@ -51,37 +52,38 @@ if ENV["TRACE_PG_CONNECTIONS"]
|
||||||
#{Thread.current&.backtrace&.join("\n")}
|
#{Thread.current&.backtrace&.join("\n")}
|
||||||
TEXT
|
TEXT
|
||||||
|
|
||||||
if ENV["ON_PG_CLASH"] == "byebug"
|
if ENV["ON_PG_CLASH"] == "byebug"
|
||||||
require "byebug"
|
require "byebug"
|
||||||
byebug # rubocop:disable Lint/Debugger
|
byebug # rubocop:disable Lint/Debugger
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@accessor_thread = Thread.current
|
||||||
end
|
end
|
||||||
@accessor_thread = Thread.current
|
yield
|
||||||
|
ensure
|
||||||
|
@access_log_mutex.synchronize { @accessor_thread = nil }
|
||||||
end
|
end
|
||||||
yield
|
end,
|
||||||
ensure
|
)
|
||||||
@access_log_mutex.synchronize do
|
|
||||||
@accessor_thread = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end)
|
|
||||||
|
|
||||||
class PG::Connection
|
class PG::Connection
|
||||||
LOG_ACCESS_METHODS = [:exec, :sync_exec, :async_exec,
|
LOG_ACCESS_METHODS = %i[
|
||||||
:sync_exec_params, :async_exec_params,
|
exec
|
||||||
:sync_prepare, :async_prepare,
|
sync_exec
|
||||||
:sync_exec_prepared, :async_exec_prepared,
|
async_exec
|
||||||
]
|
sync_exec_params
|
||||||
|
async_exec_params
|
||||||
|
sync_prepare
|
||||||
|
async_prepare
|
||||||
|
sync_exec_prepared
|
||||||
|
async_exec_prepared
|
||||||
|
]
|
||||||
|
|
||||||
LOG_ACCESS_METHODS.each do |method|
|
LOG_ACCESS_METHODS.each do |method|
|
||||||
new_method = "#{method}_without_logging".to_sym
|
new_method = "#{method}_without_logging".to_sym
|
||||||
alias_method new_method, method
|
alias_method new_method, method
|
||||||
|
|
||||||
define_method(method) do |*args, &blk|
|
define_method(method) { |*args, &blk| log_access { send(new_method, *args, &blk) } }
|
||||||
log_access { send(new_method, *args, &blk) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ module DiscourseInflector
|
||||||
|
|
||||||
def self.camelize(basename, abspath)
|
def self.camelize(basename, abspath)
|
||||||
return basename.camelize if abspath.ends_with?("onceoff.rb")
|
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
|
@overrides[basename] || basename.camelize
|
||||||
end
|
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
|
# 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.
|
# for now until we decide to fix them one day.
|
||||||
autoloader.inflector.inflect(
|
autoloader.inflector.inflect(
|
||||||
'canonical_url' => 'CanonicalURL',
|
"canonical_url" => "CanonicalURL",
|
||||||
'clean_up_unmatched_ips' => 'CleanUpUnmatchedIPs',
|
"clean_up_unmatched_ips" => "CleanUpUnmatchedIPs",
|
||||||
'homepage_constraint' => 'HomePageConstraint',
|
"homepage_constraint" => "HomePageConstraint",
|
||||||
'ip_addr' => 'IPAddr',
|
"ip_addr" => "IPAddr",
|
||||||
'onpdiff' => 'ONPDiff',
|
"onpdiff" => "ONPDiff",
|
||||||
'pop3_polling_enabled_setting_validator' => 'POP3PollingEnabledSettingValidator',
|
"pop3_polling_enabled_setting_validator" => "POP3PollingEnabledSettingValidator",
|
||||||
'version' => 'Discourse',
|
"version" => "Discourse",
|
||||||
'onceoff' => 'Jobs',
|
"onceoff" => "Jobs",
|
||||||
'regular' => 'Jobs',
|
"regular" => "Jobs",
|
||||||
'scheduled' => 'Jobs',
|
"scheduled" => "Jobs",
|
||||||
'google_oauth2_authenticator' => 'GoogleOAuth2Authenticator',
|
"google_oauth2_authenticator" => "GoogleOAuth2Authenticator",
|
||||||
'omniauth_strategies' => 'OmniAuthStrategies',
|
"omniauth_strategies" => "OmniAuthStrategies",
|
||||||
'csrf_token_verifier' => 'CSRFTokenVerifier',
|
"csrf_token_verifier" => "CSRFTokenVerifier",
|
||||||
'html' => 'HTML',
|
"html" => "HTML",
|
||||||
'json' => 'JSON',
|
"json" => "JSON",
|
||||||
'ssrf_detector' => 'SSRFDetector',
|
"ssrf_detector" => "SSRFDetector",
|
||||||
'http' => 'HTTP',
|
"http" => "HTTP",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
Rails.autoloaders.main.ignore("lib/tasks",
|
Rails.autoloaders.main.ignore(
|
||||||
"lib/generators",
|
"lib/tasks",
|
||||||
"lib/freedom_patches",
|
"lib/generators",
|
||||||
"lib/i18n/backend",
|
"lib/freedom_patches",
|
||||||
"lib/unicorn_logstash_patch.rb")
|
"lib/i18n/backend",
|
||||||
|
"lib/unicorn_logstash_patch.rb",
|
||||||
|
)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
# frozen_string_literal: true
|
# 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)"
|
puts "Flushing redis (development mode)"
|
||||||
Discourse.redis.flushdb
|
Discourse.redis.flushdb
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
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"
|
STDERR.puts "Discourse requires Redis 6.2.0 or up"
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,16 +14,12 @@ if defined?(RailsFailover::Redis)
|
||||||
Discourse.request_refresh!
|
Discourse.request_refresh!
|
||||||
MessageBus.keepalive_interval = message_bus_keepalive_interval
|
MessageBus.keepalive_interval = message_bus_keepalive_interval
|
||||||
|
|
||||||
ObjectSpace.each_object(DistributedCache) do |cache|
|
ObjectSpace.each_object(DistributedCache) { |cache| cache.clear }
|
||||||
cache.clear
|
|
||||||
end
|
|
||||||
|
|
||||||
SiteSetting.refresh!
|
SiteSetting.refresh!
|
||||||
end
|
end
|
||||||
|
|
||||||
if Rails.logger.respond_to? :chained
|
RailsFailover::Redis.logger = Rails.logger.chained.first if Rails.logger.respond_to? :chained
|
||||||
RailsFailover::Redis.logger = Rails.logger.chained.first
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if defined?(RailsFailover::ActiveRecord)
|
if defined?(RailsFailover::ActiveRecord)
|
||||||
|
@ -73,10 +69,7 @@ if defined?(RailsFailover::ActiveRecord)
|
||||||
end
|
end
|
||||||
|
|
||||||
RailsFailover::ActiveRecord.register_force_reading_role_callback do
|
RailsFailover::ActiveRecord.register_force_reading_role_callback do
|
||||||
Discourse.redis.exists?(
|
Discourse.redis.exists?(Discourse::PG_READONLY_MODE_KEY, Discourse::PG_FORCE_READONLY_MODE_KEY)
|
||||||
Discourse::PG_READONLY_MODE_KEY,
|
|
||||||
Discourse::PG_FORCE_READONLY_MODE_KEY
|
|
||||||
)
|
|
||||||
rescue => e
|
rescue => e
|
||||||
if !e.is_a?(Redis::CannotConnectError)
|
if !e.is_a?(Redis::CannotConnectError)
|
||||||
Rails.logger.warn "#{e.class} #{e.message}: #{e.backtrace.join("\n")}"
|
Rails.logger.warn "#{e.class} #{e.message}: #{e.backtrace.join("\n")}"
|
||||||
|
|
|
@ -30,7 +30,8 @@ def setup_message_bus_env(env)
|
||||||
extra_headers = {
|
extra_headers = {
|
||||||
"Access-Control-Allow-Origin" => Discourse.base_url_no_prefix,
|
"Access-Control-Allow-Origin" => Discourse.base_url_no_prefix,
|
||||||
"Access-Control-Allow-Methods" => "GET, POST",
|
"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",
|
"Access-Control-Max-Age" => "7200",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ def setup_message_bus_env(env)
|
||||||
rescue Discourse::InvalidAccess => e
|
rescue Discourse::InvalidAccess => e
|
||||||
# this is bad we need to remove the cookie
|
# this is bad we need to remove the cookie
|
||||||
if e.opts[:delete_cookie].present?
|
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
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
Discourse.warn_exception(e, message: "Unexpected error in Message Bus", env: env)
|
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
|
raise Discourse::InvalidAccess if !user_id && SiteSetting.login_required
|
||||||
|
|
||||||
is_admin = !!(user && user.admin?)
|
is_admin = !!(user && user.admin?)
|
||||||
group_ids = if is_admin
|
group_ids =
|
||||||
# special rule, admin is allowed access to all groups
|
if is_admin
|
||||||
Group.pluck(:id)
|
# special rule, admin is allowed access to all groups
|
||||||
elsif user
|
Group.pluck(:id)
|
||||||
user.groups.pluck('groups.id')
|
elsif user
|
||||||
end
|
user.groups.pluck("groups.id")
|
||||||
|
end
|
||||||
|
|
||||||
if env[Auth::DefaultCurrentUserProvider::BAD_TOKEN]
|
extra_headers["Discourse-Logged-Out"] = "1" if env[Auth::DefaultCurrentUserProvider::BAD_TOKEN]
|
||||||
extra_headers['Discourse-Logged-Out'] = '1'
|
|
||||||
end
|
|
||||||
|
|
||||||
hash = {
|
hash = {
|
||||||
extra_headers: extra_headers,
|
extra_headers: extra_headers,
|
||||||
user_id: user_id,
|
user_id: user_id,
|
||||||
group_ids: group_ids,
|
group_ids: group_ids,
|
||||||
is_admin: is_admin,
|
is_admin: is_admin,
|
||||||
site_id: RailsMultisite::ConnectionManagement.current_db
|
site_id: RailsMultisite::ConnectionManagement.current_db,
|
||||||
}
|
}
|
||||||
env["__mb"] = hash
|
env["__mb"] = hash
|
||||||
end
|
end
|
||||||
|
@ -99,7 +99,7 @@ MessageBus.on_middleware_error do |env, e|
|
||||||
if Discourse::InvalidAccess === e
|
if Discourse::InvalidAccess === e
|
||||||
[403, {}, ["Invalid Access"]]
|
[403, {}, ["Invalid Access"]]
|
||||||
elsif RateLimiter::LimitExceeded === e
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -119,8 +119,9 @@ end
|
||||||
|
|
||||||
MessageBus.backend_instance.max_backlog_size = GlobalSetting.message_bus_max_backlog_size
|
MessageBus.backend_instance.max_backlog_size = GlobalSetting.message_bus_max_backlog_size
|
||||||
MessageBus.backend_instance.clear_every = GlobalSetting.message_bus_clear_every
|
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_enabled =
|
||||||
MessageBus.long_polling_interval = GlobalSetting.long_polling_interval || 25000
|
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$/
|
if Rails.env == "test" || $0 =~ /rake$/
|
||||||
# disable keepalive in testing
|
# disable keepalive in testing
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
Discourse.git_version
|
Discourse.git_version
|
||||||
|
|
||||||
if GlobalSetting.skip_redis?
|
if GlobalSetting.skip_redis?
|
||||||
require 'site_settings/local_process_provider'
|
require "site_settings/local_process_provider"
|
||||||
Rails.cache = Discourse.cache
|
Rails.cache = Discourse.cache
|
||||||
Rails.application.config.to_prepare do
|
Rails.application.config.to_prepare do
|
||||||
SiteSetting.provider = SiteSettings::LocalProcessProvider.new
|
SiteSetting.provider = SiteSettings::LocalProcessProvider.new
|
||||||
|
@ -19,7 +19,8 @@ Rails.application.config.to_prepare do
|
||||||
begin
|
begin
|
||||||
SiteSetting.refresh!
|
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
|
SiteSetting.push_api_secret_key = SecureRandom.hex
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::StatementInvalid
|
rescue ActiveRecord::StatementInvalid
|
||||||
|
|
|
@ -5,17 +5,15 @@ return if GlobalSetting.skip_db?
|
||||||
Rails.application.config.to_prepare do
|
Rails.application.config.to_prepare do
|
||||||
# Some sanity checking so we don't count on an unindexed column on boot
|
# Some sanity checking so we don't count on an unindexed column on boot
|
||||||
begin
|
begin
|
||||||
if ActiveRecord::Base.connection.table_exists?(:users) &&
|
if ActiveRecord::Base.connection.table_exists?(:users) && User.limit(20).count < 20 &&
|
||||||
User.limit(20).count < 20 &&
|
User.where(admin: true).human_users.count == 0
|
||||||
User.where(admin: true).human_users.count == 0
|
|
||||||
|
|
||||||
notice =
|
notice =
|
||||||
if GlobalSetting.developer_emails.blank?
|
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>."
|
"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
|
else
|
||||||
emails = GlobalSetting.developer_emails.split(",")
|
emails = GlobalSetting.developer_emails.split(",")
|
||||||
if emails.length > 1
|
if emails.length > 1
|
||||||
emails = emails[0..-2].join(', ') << " or #{emails[-1]} "
|
emails = emails[0..-2].join(", ") << " or #{emails[-1]} "
|
||||||
else
|
else
|
||||||
emails = emails[0]
|
emails = emails[0]
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# If Mini Profiler is included via gem
|
# If Mini Profiler is included via gem
|
||||||
if Rails.configuration.respond_to?(:load_mini_profiler) && Rails.configuration.load_mini_profiler && RUBY_ENGINE == "ruby"
|
if Rails.configuration.respond_to?(:load_mini_profiler) && Rails.configuration.load_mini_profiler &&
|
||||||
require 'rack-mini-profiler'
|
RUBY_ENGINE == "ruby"
|
||||||
require 'stackprof'
|
require "rack-mini-profiler"
|
||||||
|
require "stackprof"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
require 'memory_profiler'
|
require "memory_profiler"
|
||||||
rescue => e
|
rescue => e
|
||||||
STDERR.put "#{e} failed to require mini profiler"
|
STDERR.put "#{e} failed to require mini profiler"
|
||||||
end
|
end
|
||||||
|
@ -20,55 +21,56 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config)
|
||||||
# raw_connection means results are not namespaced
|
# raw_connection means results are not namespaced
|
||||||
#
|
#
|
||||||
# namespacing gets complex, cause mini profiler is in the rack chain way before multisite
|
# namespacing gets complex, cause mini profiler is in the rack chain way before multisite
|
||||||
Rack::MiniProfiler.config.storage_instance = Rack::MiniProfiler::RedisStore.new(
|
Rack::MiniProfiler.config.storage_instance =
|
||||||
connection: DiscourseRedis.new(nil, namespace: false)
|
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.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_destination_url =
|
||||||
Rack::MiniProfiler.config.snapshots_transport_auth_key = GlobalSetting.mini_profiler_snapshots_transport_auth_key
|
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 = [
|
Rack::MiniProfiler.config.skip_paths = [
|
||||||
/^\/message-bus/,
|
%r{^/message-bus},
|
||||||
/^\/extra-locales/,
|
%r{^/extra-locales},
|
||||||
/topics\/timings/,
|
%r{topics/timings},
|
||||||
/assets/,
|
/assets/,
|
||||||
/\/user_avatar\//,
|
%r{/user_avatar/},
|
||||||
/\/letter_avatar\//,
|
%r{/letter_avatar/},
|
||||||
/\/letter_avatar_proxy\//,
|
%r{/letter_avatar_proxy/},
|
||||||
/\/highlight-js\//,
|
%r{/highlight-js/},
|
||||||
/\/svg-sprite\//,
|
%r{/svg-sprite/},
|
||||||
/qunit/,
|
/qunit/,
|
||||||
/srv\/status/,
|
%r{srv/status},
|
||||||
/commits-widget/,
|
/commits-widget/,
|
||||||
/^\/cdn_asset/,
|
%r{^/cdn_asset},
|
||||||
/^\/logs/,
|
%r{^/logs},
|
||||||
/^\/site_customizations/,
|
%r{^/site_customizations},
|
||||||
/^\/uploads/,
|
%r{^/uploads},
|
||||||
/^\/secure-media-uploads/,
|
%r{^/secure-media-uploads},
|
||||||
/^\/secure-uploads/,
|
%r{^/secure-uploads},
|
||||||
/^\/javascripts\//,
|
%r{^/javascripts/},
|
||||||
/^\/images\//,
|
%r{^/images/},
|
||||||
/^\/stylesheets\//,
|
%r{^/stylesheets/},
|
||||||
/^\/favicon\/proxied/,
|
%r{^/favicon/proxied},
|
||||||
/^\/theme-javascripts/
|
%r{^/theme-javascripts},
|
||||||
]
|
]
|
||||||
|
|
||||||
# we DO NOT WANT mini-profiler loading on anything but real desktops and laptops
|
# 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
|
# so let's rule out all handheld, tablet, and mobile devices
|
||||||
Rack::MiniProfiler.config.pre_authorize_cb = lambda do |env|
|
Rack::MiniProfiler.config.pre_authorize_cb =
|
||||||
env['HTTP_USER_AGENT'] !~ /iPad|iPhone|Android/
|
lambda { |env| env["HTTP_USER_AGENT"] !~ /iPad|iPhone|Android/ }
|
||||||
end
|
|
||||||
|
|
||||||
# without a user provider our results will use the ip address for namespacing
|
# 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
|
# 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
|
# be stored associated with ip1 as the user and retrieved using ip2 causing 404s
|
||||||
Rack::MiniProfiler.config.user_provider = lambda do |env|
|
Rack::MiniProfiler.config.user_provider =
|
||||||
request = Rack::Request.new(env)
|
lambda do |env|
|
||||||
id = request.cookies["_t"] || request.ip || "unknown"
|
request = Rack::Request.new(env)
|
||||||
id = id.to_s
|
id = request.cookies["_t"] || request.ip || "unknown"
|
||||||
# some security, lets not have these tokens floating about
|
id = id.to_s
|
||||||
Digest::MD5.hexdigest(id)
|
# some security, lets not have these tokens floating about
|
||||||
end
|
Digest::MD5.hexdigest(id)
|
||||||
|
end
|
||||||
|
|
||||||
# Cookie path should be set to the base path so Discourse's session cookie path
|
# Cookie path should be set to the base path so Discourse's session cookie path
|
||||||
# does not get clobbered.
|
# does not get clobbered.
|
||||||
|
@ -77,15 +79,15 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config)
|
||||||
Rack::MiniProfiler.config.position = "right"
|
Rack::MiniProfiler.config.position = "right"
|
||||||
|
|
||||||
Rack::MiniProfiler.config.backtrace_ignores ||= []
|
Rack::MiniProfiler.config.backtrace_ignores ||= []
|
||||||
Rack::MiniProfiler.config.backtrace_ignores << /lib\/rack\/message_bus.rb/
|
Rack::MiniProfiler.config.backtrace_ignores << %r{lib/rack/message_bus.rb}
|
||||||
Rack::MiniProfiler.config.backtrace_ignores << /config\/initializers\/silence_logger/
|
Rack::MiniProfiler.config.backtrace_ignores << %r{config/initializers/silence_logger}
|
||||||
Rack::MiniProfiler.config.backtrace_ignores << /config\/initializers\/quiet_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.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(ActiveRecord::QueryMethods, 'build_arel')
|
||||||
# Rack::MiniProfiler.counter_method(Array, 'uniq')
|
# Rack::MiniProfiler.counter_method(Array, 'uniq')
|
||||||
# require "#{Rails.root}/vendor/backports/notification"
|
# require "#{Rails.root}/vendor/backports/notification"
|
||||||
|
@ -115,10 +117,11 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config)
|
||||||
end
|
end
|
||||||
|
|
||||||
if ENV["PRINT_EXCEPTIONS"]
|
if ENV["PRINT_EXCEPTIONS"]
|
||||||
trace = TracePoint.new(:raise) do |tp|
|
trace =
|
||||||
puts tp.raised_exception
|
TracePoint.new(:raise) do |tp|
|
||||||
puts tp.raised_exception.backtrace.join("\n")
|
puts tp.raised_exception
|
||||||
puts
|
puts tp.raised_exception.backtrace.join("\n")
|
||||||
end
|
puts
|
||||||
|
end
|
||||||
trace.enable
|
trace.enable
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,18 +6,17 @@ class Discourse::Cors
|
||||||
def initialize(app, options = nil)
|
def initialize(app, options = nil)
|
||||||
@app = app
|
@app = app
|
||||||
if GlobalSetting.enable_cors && GlobalSetting.cors_origin.present?
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
|
|
||||||
cors_origins = @global_origins || []
|
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
|
cors_origins = cors_origins.presence
|
||||||
|
|
||||||
if env['REQUEST_METHOD'] == ('OPTIONS') && env['HTTP_ACCESS_CONTROL_REQUEST_METHOD']
|
if env["REQUEST_METHOD"] == ("OPTIONS") && env["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]
|
||||||
return [200, Discourse::Cors.apply_headers(cors_origins, env, {}), []]
|
return 200, Discourse::Cors.apply_headers(cors_origins, env, {}), []
|
||||||
end
|
end
|
||||||
|
|
||||||
env[Discourse::Cors::ORIGINS_ENV] = cors_origins if cors_origins
|
env[Discourse::Cors::ORIGINS_ENV] = cors_origins if cors_origins
|
||||||
|
@ -31,21 +30,24 @@ class Discourse::Cors
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.apply_headers(cors_origins, env, headers)
|
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)
|
Discourse.apply_cdn_headers(headers)
|
||||||
elsif cors_origins
|
elsif cors_origins
|
||||||
origin = nil
|
origin = nil
|
||||||
if origin = env['HTTP_ORIGIN']
|
if origin = env["HTTP_ORIGIN"]
|
||||||
origin = nil unless cors_origins.include?(origin)
|
origin = nil unless cors_origins.include?(origin)
|
||||||
end
|
end
|
||||||
|
|
||||||
headers['Access-Control-Allow-Origin'] = origin || cors_origins[0]
|
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[
|
||||||
headers['Access-Control-Allow-Credentials'] = 'true'
|
"Access-Control-Allow-Headers"
|
||||||
headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS, DELETE'
|
] = "Content-Type, Cache-Control, X-Requested-With, X-CSRF-Token, Discourse-Present, User-Api-Key, User-Api-Client-Id, Authorization"
|
||||||
headers['Access-Control-Max-Age'] = '7200'
|
headers["Access-Control-Allow-Credentials"] = "true"
|
||||||
|
headers["Access-Control-Allow-Methods"] = "POST, PUT, GET, OPTIONS, DELETE"
|
||||||
|
headers["Access-Control-Max-Age"] = "7200"
|
||||||
end
|
end
|
||||||
|
|
||||||
headers
|
headers
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
%i(
|
%i[topic_recovered].each do |event|
|
||||||
topic_recovered
|
DiscourseEvent.on(event) { |topic, _| WebHook.enqueue_topic_hooks(event, topic) }
|
||||||
).each do |event|
|
|
||||||
DiscourseEvent.on(event) do |topic, _|
|
|
||||||
WebHook.enqueue_topic_hooks(event, topic)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
DiscourseEvent.on(:topic_status_updated) do |topic, status|
|
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)
|
WebHook.enqueue_topic_hooks(:topic_created, topic)
|
||||||
end
|
end
|
||||||
|
|
||||||
%i(
|
%i[post_created post_recovered].each do |event|
|
||||||
post_created
|
DiscourseEvent.on(event) { |post, _, _| WebHook.enqueue_post_hooks(event, post) }
|
||||||
post_recovered
|
|
||||||
).each do |event|
|
|
||||||
DiscourseEvent.on(event) do |post, _, _|
|
|
||||||
WebHook.enqueue_post_hooks(event, post)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
DiscourseEvent.on(:post_edited) do |post, topic_changed|
|
DiscourseEvent.on(:post_edited) do |post, topic_changed|
|
||||||
unless post.topic&.trashed?
|
unless post.topic&.trashed?
|
||||||
|
|
||||||
# if we are editing the OP and the topic is changed, do not send
|
# if we are editing the OP and the topic is changed, do not send
|
||||||
# the post_edited event -- this event is sent separately because
|
# 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:
|
# 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
|
||||||
end
|
end
|
||||||
|
|
||||||
%i(
|
%i[
|
||||||
user_logged_out
|
user_logged_out
|
||||||
user_created
|
user_created
|
||||||
user_logged_in
|
user_logged_in
|
||||||
user_approved
|
user_approved
|
||||||
user_updated
|
user_updated
|
||||||
user_confirmed_email
|
user_confirmed_email
|
||||||
).each do |event|
|
].each do |event|
|
||||||
DiscourseEvent.on(event) do |user|
|
DiscourseEvent.on(event) { |user| WebHook.enqueue_object_hooks(:user, user, event) }
|
||||||
WebHook.enqueue_object_hooks(:user, user, event)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%i(
|
%i[group_created group_updated].each do |event|
|
||||||
group_created
|
DiscourseEvent.on(event) { |group| WebHook.enqueue_object_hooks(:group, group, event) }
|
||||||
group_updated
|
|
||||||
).each do |event|
|
|
||||||
DiscourseEvent.on(event) do |group|
|
|
||||||
WebHook.enqueue_object_hooks(:group, group, event)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%i(
|
%i[category_created category_updated].each do |event|
|
||||||
category_created
|
DiscourseEvent.on(event) { |category| WebHook.enqueue_object_hooks(:category, category, event) }
|
||||||
category_updated
|
|
||||||
).each do |event|
|
|
||||||
DiscourseEvent.on(event) do |category|
|
|
||||||
WebHook.enqueue_object_hooks(:category, category, event)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%i(
|
%i[tag_created tag_updated].each do |event|
|
||||||
tag_created
|
DiscourseEvent.on(event) { |tag| WebHook.enqueue_object_hooks(:tag, tag, event, TagSerializer) }
|
||||||
tag_updated
|
|
||||||
).each do |event|
|
|
||||||
DiscourseEvent.on(event) do |tag|
|
|
||||||
WebHook.enqueue_object_hooks(:tag, tag, event, TagSerializer)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%i(
|
%i[user_badge_granted].each do |event|
|
||||||
user_badge_granted
|
|
||||||
).each do |event|
|
|
||||||
# user_badge_revoked
|
# user_badge_revoked
|
||||||
DiscourseEvent.on(event) do |badge, user_id|
|
DiscourseEvent.on(event) do |badge, user_id|
|
||||||
ub = UserBadge.find_by(badge: badge, user_id: user_id)
|
ub = UserBadge.find_by(badge: badge, user_id: user_id)
|
||||||
|
@ -92,30 +63,43 @@ end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
%i(
|
%i[reviewable_created reviewable_score_updated].each do |event|
|
||||||
reviewable_created
|
|
||||||
reviewable_score_updated
|
|
||||||
).each do |event|
|
|
||||||
DiscourseEvent.on(event) do |reviewable|
|
DiscourseEvent.on(event) do |reviewable|
|
||||||
WebHook.enqueue_object_hooks(:reviewable, reviewable, event, reviewable.serializer)
|
WebHook.enqueue_object_hooks(:reviewable, reviewable, event, reviewable.serializer)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
DiscourseEvent.on(:reviewable_transitioned_to) do |status, reviewable|
|
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
|
end
|
||||||
|
|
||||||
DiscourseEvent.on(:notification_created) do |notification|
|
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
|
end
|
||||||
|
|
||||||
DiscourseEvent.on(:user_added_to_group) do |user, group, options|
|
DiscourseEvent.on(:user_added_to_group) do |user, group, options|
|
||||||
group_user = GroupUser.find_by(user: user, group: group)
|
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
|
end
|
||||||
|
|
||||||
DiscourseEvent.on(:user_promoted) do |payload|
|
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
|
next if new_trust_level < old_trust_level
|
||||||
|
|
||||||
|
@ -130,8 +114,13 @@ DiscourseEvent.on(:like_created) do |post_action|
|
||||||
category_id = topic&.category_id
|
category_id = topic&.category_id
|
||||||
tag_ids = topic&.tag_ids
|
tag_ids = topic&.tag_ids
|
||||||
|
|
||||||
WebHook.enqueue_object_hooks(:like,
|
WebHook.enqueue_object_hooks(
|
||||||
post_action, :post_liked, WebHookLikeSerializer,
|
:like,
|
||||||
group_ids: group_ids, category_id: category_id, tag_ids: tag_ids
|
post_action,
|
||||||
|
:post_liked,
|
||||||
|
WebHookLikeSerializer,
|
||||||
|
group_ids: group_ids,
|
||||||
|
category_id: category_id,
|
||||||
|
tag_ids: tag_ids,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'excon'
|
require "excon"
|
||||||
Excon::DEFAULTS[:omit_default_port] = true
|
Excon::DEFAULTS[:omit_default_port] = true
|
||||||
|
|
|
@ -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
|
# Enabling `must_approve_users` on an existing site is odd, so we assume that the
|
||||||
# existing users are approved.
|
# existing users are approved.
|
||||||
if name == :must_approve_users && new_value == true
|
if name == :must_approve_users && new_value == true
|
||||||
|
User
|
||||||
User.where(approved: false)
|
.where(approved: false)
|
||||||
.joins("LEFT JOIN reviewables r ON r.target_id = users.id")
|
.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
|
end
|
||||||
|
|
||||||
if name == :emoji_set
|
if name == :emoji_set
|
||||||
|
@ -19,31 +20,28 @@ DiscourseEvent.on(:site_setting_changed) do |name, old_value, new_value|
|
||||||
after = "/images/emoji/#{new_value}/"
|
after = "/images/emoji/#{new_value}/"
|
||||||
|
|
||||||
Scheduler::Defer.later("Fix Emoji Links") do
|
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,
|
before: before,
|
||||||
after: after,
|
after: after,
|
||||||
like: "%#{before}%"
|
like: "%#{before}%",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
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
|
if name == :slug_generation_method
|
||||||
Scheduler::Defer.later("Null topic slug") do
|
Scheduler::Defer.later("Null topic slug") { Topic.update_all(slug: nil) }
|
||||||
Topic.update_all(slug: nil)
|
|
||||||
end
|
|
||||||
end
|
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")
|
SvgSprite.expire_cache if name.to_s.include?("_icon")
|
||||||
|
|
||||||
if SiteIconManager::WATCHED_SETTINGS.include?(name)
|
SiteIconManager.ensure_optimized! if SiteIconManager::WATCHED_SETTINGS.include?(name)
|
||||||
SiteIconManager.ensure_optimized!
|
|
||||||
end
|
|
||||||
|
|
||||||
# Make sure medium and high priority thresholds were calculated.
|
# Make sure medium and high priority thresholds were calculated.
|
||||||
if name == :reviewable_low_priority_threshold && Reviewable.min_score_for_priority(:medium) > 0
|
if name == :reviewable_low_priority_threshold && Reviewable.min_score_for_priority(:medium) > 0
|
||||||
|
|
|
@ -9,7 +9,7 @@ enabled =
|
||||||
Rails.env.production?
|
Rails.env.production?
|
||||||
end
|
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
|
# 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
|
Rails.configuration.middleware.insert_after ActionDispatch::Flash, Middleware::AnonymousCache
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
# order: after 02-freedom_patches.rb
|
# order: after 02-freedom_patches.rb
|
||||||
|
|
||||||
require 'i18n/backend/discourse_i18n'
|
require "i18n/backend/discourse_i18n"
|
||||||
require 'i18n/backend/fallback_locale_list'
|
require "i18n/backend/fallback_locale_list"
|
||||||
|
|
||||||
# Requires the `translate_accelerator.rb` freedom patch to be loaded
|
# Requires the `translate_accelerator.rb` freedom patch to be loaded
|
||||||
Rails.application.reloader.to_prepare do
|
Rails.application.reloader.to_prepare do
|
||||||
|
@ -11,7 +11,7 @@ Rails.application.reloader.to_prepare do
|
||||||
I18n.fallbacks = I18n::Backend::FallbackLocaleList.new
|
I18n.fallbacks = I18n::Backend::FallbackLocaleList.new
|
||||||
I18n.config.missing_interpolation_argument_handler = proc { throw(:exception) }
|
I18n.config.missing_interpolation_argument_handler = proc { throw(:exception) }
|
||||||
I18n.reload!
|
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?
|
unless Rails.env.test?
|
||||||
MessageBus.subscribe("/i18n-flush") do
|
MessageBus.subscribe("/i18n-flush") do
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
if GlobalSetting.skip_redis?
|
if GlobalSetting.skip_redis?
|
||||||
Rails.application.reloader.to_prepare do
|
Rails.application.reloader.to_prepare do
|
||||||
if Rails.logger.respond_to? :chained
|
Rails.logger = Rails.logger.chained.first if Rails.logger.respond_to? :chained
|
||||||
Rails.logger = Rails.logger.chained.first
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
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
|
# https://github.com/rails/rails/blob/f2caed1e/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb#L39-L42
|
||||||
/^ActionController::RoutingError \(No route matches/,
|
/^ActionController::RoutingError \(No route matches/,
|
||||||
/^ActionDispatch::Http::MimeNegotiation::InvalidType/,
|
/^ActionDispatch::Http::MimeNegotiation::InvalidType/,
|
||||||
|
|
||||||
/^PG::Error: ERROR:\s+duplicate key/,
|
/^PG::Error: ERROR:\s+duplicate key/,
|
||||||
|
|
||||||
/^ActionController::UnknownFormat/,
|
/^ActionController::UnknownFormat/,
|
||||||
/^ActionController::UnknownHttpMethod/,
|
/^ActionController::UnknownHttpMethod/,
|
||||||
/^AbstractController::ActionNotFound/,
|
/^AbstractController::ActionNotFound/,
|
||||||
|
@ -51,29 +47,21 @@ if Rails.env.production?
|
||||||
# Column:
|
# Column:
|
||||||
#
|
#
|
||||||
/(?m).*?Line: (?:\D|0).*?Column: (?:\D|0)/,
|
/(?m).*?Line: (?:\D|0).*?Column: (?:\D|0)/,
|
||||||
|
|
||||||
# suppress empty JS errors (covers MSIE 9, etc)
|
# suppress empty JS errors (covers MSIE 9, etc)
|
||||||
/^(Syntax|Script) error.*Line: (0|1)\b/m,
|
/^(Syntax|Script) error.*Line: (0|1)\b/m,
|
||||||
|
|
||||||
# CSRF errors are not providing enough data
|
# CSRF errors are not providing enough data
|
||||||
# suppress unconditionally for now
|
# suppress unconditionally for now
|
||||||
/^Can't verify CSRF token authenticity.$/,
|
/^Can't verify CSRF token authenticity.$/,
|
||||||
|
|
||||||
# Yandex bot triggers this JS error a lot
|
# Yandex bot triggers this JS error a lot
|
||||||
/^Uncaught ReferenceError: I18n is not defined/,
|
/^Uncaught ReferenceError: I18n is not defined/,
|
||||||
|
|
||||||
# related to browser plugins somehow, we don't care
|
# related to browser plugins somehow, we don't care
|
||||||
/Error calling method on NPObject/,
|
/Error calling method on NPObject/,
|
||||||
|
|
||||||
# 404s can be dealt with elsewhere
|
# 404s can be dealt with elsewhere
|
||||||
/^ActiveRecord::RecordNotFound/,
|
/^ActiveRecord::RecordNotFound/,
|
||||||
|
|
||||||
# bad asset requested, no need to log
|
# bad asset requested, no need to log
|
||||||
/^ActionController::BadRequest/,
|
/^ActionController::BadRequest/,
|
||||||
|
|
||||||
# we can't do anything about invalid parameters
|
# we can't do anything about invalid parameters
|
||||||
/Rack::QueryParser::InvalidParameterError/,
|
/Rack::QueryParser::InvalidParameterError/,
|
||||||
|
|
||||||
# we handle this cleanly in the message bus middleware
|
# we handle this cleanly in the message bus middleware
|
||||||
# no point logging to logster
|
# no point logging to logster
|
||||||
/RateLimiter::LimitExceeded.*/m,
|
/RateLimiter::LimitExceeded.*/m,
|
||||||
|
@ -98,33 +86,37 @@ store.redis_raw_connection = redis.without_namespace
|
||||||
severities = [Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN]
|
severities = [Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN]
|
||||||
|
|
||||||
RailsMultisite::ConnectionManagement.each_connection do
|
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
|
if (error_rate_per_minute || 0) > 0
|
||||||
store.register_rate_limit_per_minute(severities, error_rate_per_minute) do |rate|
|
store.register_rate_limit_per_minute(severities, error_rate_per_minute) do |rate|
|
||||||
MessageBus.publish("/logs_error_rate_exceeded",
|
MessageBus.publish(
|
||||||
{
|
"/logs_error_rate_exceeded",
|
||||||
rate: rate,
|
{ rate: rate, duration: "minute", publish_at: Time.current.to_i },
|
||||||
duration: 'minute',
|
group_ids: [Group::AUTO_GROUPS[:admins]],
|
||||||
publish_at: Time.current.to_i
|
)
|
||||||
},
|
|
||||||
group_ids: [Group::AUTO_GROUPS[:admins]]
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
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
|
if (error_rate_per_hour || 0) > 0
|
||||||
store.register_rate_limit_per_hour(severities, error_rate_per_hour) do |rate|
|
store.register_rate_limit_per_hour(severities, error_rate_per_hour) do |rate|
|
||||||
MessageBus.publish("/logs_error_rate_exceeded",
|
MessageBus.publish(
|
||||||
{
|
"/logs_error_rate_exceeded",
|
||||||
rate: rate,
|
{ rate: rate, duration: "hour", publish_at: Time.current.to_i },
|
||||||
duration: 'hour',
|
group_ids: [Group::AUTO_GROUPS[:admins]],
|
||||||
publish_at: Time.current.to_i,
|
)
|
||||||
},
|
|
||||||
group_ids: [Group::AUTO_GROUPS[:admins]]
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -137,13 +129,13 @@ if Rails.configuration.multisite
|
||||||
end
|
end
|
||||||
|
|
||||||
Logster.config.project_directories = [
|
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|
|
Discourse.plugins.each do |plugin|
|
||||||
next if !plugin.metadata.url
|
next if !plugin.metadata.url
|
||||||
|
|
||||||
Logster.config.project_directories << {
|
Logster.config.project_directories << {
|
||||||
path: "#{Rails.root.to_s}/plugins/#{plugin.directory_name}",
|
path: "#{Rails.root.to_s}/plugins/#{plugin.directory_name}",
|
||||||
url: plugin.metadata.url
|
url: plugin.metadata.url,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,13 +6,13 @@ Rails.application.config.to_prepare do
|
||||||
twitter_client: TwitterApi,
|
twitter_client: TwitterApi,
|
||||||
redirect_limit: 3,
|
redirect_limit: 3,
|
||||||
user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}",
|
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
|
else
|
||||||
Onebox.options = {
|
Onebox.options = {
|
||||||
twitter_client: TwitterApi,
|
twitter_client: TwitterApi,
|
||||||
redirect_limit: 3,
|
redirect_limit: 3,
|
||||||
user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}"
|
user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,13 +3,11 @@
|
||||||
return if GlobalSetting.skip_db?
|
return if GlobalSetting.skip_db?
|
||||||
|
|
||||||
Rails.application.config.to_prepare do
|
Rails.application.config.to_prepare do
|
||||||
require 'web-push'
|
require "web-push"
|
||||||
|
|
||||||
def generate_vapid_key?
|
def generate_vapid_key?
|
||||||
SiteSetting.vapid_public_key.blank? ||
|
SiteSetting.vapid_public_key.blank? || SiteSetting.vapid_private_key.blank? ||
|
||||||
SiteSetting.vapid_private_key.blank? ||
|
SiteSetting.vapid_public_key_bytes.blank? || SiteSetting.vapid_base_url != Discourse.base_url
|
||||||
SiteSetting.vapid_public_key_bytes.blank? ||
|
|
||||||
SiteSetting.vapid_base_url != Discourse.base_url
|
|
||||||
end
|
end
|
||||||
|
|
||||||
SiteSetting.vapid_base_url = Discourse.base_url if SiteSetting.vapid_base_url.blank?
|
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_public_key = vapid_key.public_key
|
||||||
SiteSetting.vapid_private_key = vapid_key.private_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
|
SiteSetting.vapid_base_url = Discourse.base_url
|
||||||
|
|
||||||
if ActiveRecord::Base.connection.table_exists?(:push_subscriptions)
|
PushSubscription.delete_all if ActiveRecord::Base.connection.table_exists?(:push_subscriptions)
|
||||||
PushSubscription.delete_all
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
DiscourseEvent.on(:user_logged_out) do |user|
|
DiscourseEvent.on(:user_logged_out) { |user| PushNotificationPusher.clear_subscriptions(user) }
|
||||||
PushNotificationPusher.clear_subscriptions(user)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,30 +1,23 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Rails.application.config.assets.configure do |env|
|
Rails.application.config.assets.configure { |env| env.logger = Logger.new("/dev/null") }
|
||||||
env.logger = Logger.new('/dev/null')
|
|
||||||
end
|
|
||||||
|
|
||||||
module DiscourseRackQuietAssetsLogger
|
module DiscourseRackQuietAssetsLogger
|
||||||
def call(env)
|
def call(env)
|
||||||
override = false
|
override = false
|
||||||
if (env['PATH_INFO'].index("/assets/") == 0) ||
|
if (env["PATH_INFO"].index("/assets/") == 0) || (env["PATH_INFO"].index("/stylesheets") == 0) ||
|
||||||
(env['PATH_INFO'].index("/stylesheets") == 0) ||
|
(env["PATH_INFO"].index("/svg-sprite") == 0) ||
|
||||||
(env['PATH_INFO'].index("/svg-sprite") == 0) ||
|
(env["PATH_INFO"].index("/manifest") == 0) ||
|
||||||
(env['PATH_INFO'].index("/manifest") == 0) ||
|
(env["PATH_INFO"].index("/service-worker") == 0) ||
|
||||||
(env['PATH_INFO'].index("/service-worker") == 0) ||
|
(env["PATH_INFO"].index("mini-profiler-resources") == 0) ||
|
||||||
(env['PATH_INFO'].index("mini-profiler-resources") == 0) ||
|
(env["PATH_INFO"].index("/srv/status") == 0)
|
||||||
(env['PATH_INFO'].index("/srv/status") == 0)
|
|
||||||
if ::Logster::Logger === Rails.logger
|
if ::Logster::Logger === Rails.logger
|
||||||
override = true
|
override = true
|
||||||
Rails.logger.override_level = Logger::ERROR
|
Rails.logger.override_level = Logger::ERROR
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
super(env).tap do
|
super(env).tap { Rails.logger.override_level = nil if override }
|
||||||
if override
|
|
||||||
Rails.logger.override_level = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,15 @@
|
||||||
|
|
||||||
Rails.application.config.session_store(
|
Rails.application.config.session_store(
|
||||||
:discourse_cookie_store,
|
:discourse_cookie_store,
|
||||||
key: '_forum_session',
|
key: "_forum_session",
|
||||||
path: (Rails.application.config.relative_url_root.nil?) ? '/' : Rails.application.config.relative_url_root
|
path:
|
||||||
|
(
|
||||||
|
if (Rails.application.config.relative_url_root.nil?)
|
||||||
|
"/"
|
||||||
|
else
|
||||||
|
Rails.application.config.relative_url_root
|
||||||
|
end
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
Rails.application.config.to_prepare do
|
Rails.application.config.to_prepare do
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "sidekiq/pausable"
|
require "sidekiq/pausable"
|
||||||
require 'sidekiq_logster_reporter'
|
require "sidekiq_logster_reporter"
|
||||||
|
|
||||||
Sidekiq.configure_client do |config|
|
Sidekiq.configure_client { |config| config.redis = Discourse.sidekiq_redis_config }
|
||||||
config.redis = Discourse.sidekiq_redis_config
|
|
||||||
end
|
|
||||||
|
|
||||||
Sidekiq.configure_server do |config|
|
Sidekiq.configure_server do |config|
|
||||||
config.redis = Discourse.sidekiq_redis_config
|
config.redis = Discourse.sidekiq_redis_config
|
||||||
|
|
||||||
config.server_middleware do |chain|
|
config.server_middleware { |chain| chain.add Sidekiq::Pausable }
|
||||||
chain.add Sidekiq::Pausable
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if Sidekiq.server?
|
if Sidekiq.server?
|
||||||
|
|
||||||
module Sidekiq
|
module Sidekiq
|
||||||
class CLI
|
class CLI
|
||||||
private
|
private
|
||||||
|
@ -34,13 +29,17 @@ if Sidekiq.server?
|
||||||
# warm up AR
|
# warm up AR
|
||||||
RailsMultisite::ConnectionManagement.safe_each_connection do
|
RailsMultisite::ConnectionManagement.safe_each_connection do
|
||||||
(ActiveRecord::Base.connection.tables - %w[schema_migrations versions]).each do |table|
|
(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
|
||||||
end
|
end
|
||||||
|
|
||||||
scheduler_hostname = ENV["UNICORN_SCHEDULER_HOSTNAME"]
|
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
|
begin
|
||||||
MiniScheduler.start(workers: GlobalSetting.mini_scheduler_workers)
|
MiniScheduler.start(workers: GlobalSetting.mini_scheduler_workers)
|
||||||
rescue MiniScheduler::DistributedMutex::Timeout
|
rescue MiniScheduler::DistributedMutex::Timeout
|
||||||
|
@ -57,9 +56,11 @@ else
|
||||||
# Instead, this patch adds a dedicated logger instance and patches
|
# Instead, this patch adds a dedicated logger instance and patches
|
||||||
# the #add method to forward messages to Rails.logger.
|
# the #add method to forward messages to Rails.logger.
|
||||||
Sidekiq.logger = Logger.new(nil)
|
Sidekiq.logger = Logger.new(nil)
|
||||||
Sidekiq.logger.define_singleton_method(:add) do |severity, message = nil, progname = nil, &blk|
|
Sidekiq
|
||||||
Rails.logger.add(severity, message, progname, &blk)
|
.logger
|
||||||
end
|
.define_singleton_method(:add) do |severity, message = nil, progname = nil, &blk|
|
||||||
|
Rails.logger.add(severity, message, progname, &blk)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Sidekiq.error_handlers.clear
|
Sidekiq.error_handlers.clear
|
||||||
|
@ -69,28 +70,20 @@ Sidekiq.strict_args!
|
||||||
|
|
||||||
Rails.application.config.to_prepare do
|
Rails.application.config.to_prepare do
|
||||||
# Ensure that scheduled jobs are loaded before mini_scheduler is configured.
|
# Ensure that scheduled jobs are loaded before mini_scheduler is configured.
|
||||||
if Rails.env.development?
|
Dir.glob("#{Rails.root}/app/jobs/scheduled/*.rb") { |f| require(f) } if Rails.env.development?
|
||||||
Dir.glob("#{Rails.root}/app/jobs/scheduled/*.rb") do |f|
|
|
||||||
require(f)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
MiniScheduler.configure do |config|
|
MiniScheduler.configure do |config|
|
||||||
config.redis = Discourse.redis
|
config.redis = Discourse.redis
|
||||||
|
|
||||||
config.job_exception_handler do |ex, context|
|
config.job_exception_handler { |ex, context| Discourse.handle_job_exception(ex, context) }
|
||||||
Discourse.handle_job_exception(ex, context)
|
|
||||||
end
|
|
||||||
|
|
||||||
config.job_ran do |stat|
|
config.job_ran { |stat| DiscourseEvent.trigger(:scheduled_job_ran, stat) }
|
||||||
DiscourseEvent.trigger(:scheduled_job_ran, stat)
|
|
||||||
end
|
|
||||||
|
|
||||||
config.skip_schedule { Sidekiq.paused? }
|
config.skip_schedule { Sidekiq.paused? }
|
||||||
|
|
||||||
config.before_sidekiq_web_request do
|
config.before_sidekiq_web_request do
|
||||||
RailsMultisite::ConnectionManagement.establish_connection(
|
RailsMultisite::ConnectionManagement.establish_connection(
|
||||||
db: RailsMultisite::ConnectionManagement::DEFAULT
|
db: RailsMultisite::ConnectionManagement::DEFAULT,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class SilenceLogger < Rails::Rack::Logger
|
class SilenceLogger < Rails::Rack::Logger
|
||||||
PATH_INFO = 'PATH_INFO'
|
PATH_INFO = "PATH_INFO"
|
||||||
HTTP_X_SILENCE_LOGGER = 'HTTP_X_SILENCE_LOGGER'
|
HTTP_X_SILENCE_LOGGER = "HTTP_X_SILENCE_LOGGER"
|
||||||
|
|
||||||
def initialize(app, opts = {})
|
def initialize(app, opts = {})
|
||||||
@app = app
|
@app = app
|
||||||
|
@ -17,11 +17,9 @@ class SilenceLogger < Rails::Rack::Logger
|
||||||
path_info = env[PATH_INFO]
|
path_info = env[PATH_INFO]
|
||||||
override = false
|
override = false
|
||||||
|
|
||||||
if env[HTTP_X_SILENCE_LOGGER] ||
|
if env[HTTP_X_SILENCE_LOGGER] || @opts[:silenced].include?(path_info) ||
|
||||||
@opts[:silenced].include?(path_info) ||
|
path_info.start_with?("/logs") || path_info.start_with?("/user_avatar") ||
|
||||||
path_info.start_with?('/logs') ||
|
path_info.start_with?("/letter_avatar")
|
||||||
path_info.start_with?('/user_avatar') ||
|
|
||||||
path_info.start_with?('/letter_avatar')
|
|
||||||
if ::Logster::Logger === Rails.logger
|
if ::Logster::Logger === Rails.logger
|
||||||
override = true
|
override = true
|
||||||
Rails.logger.override_level = Logger::WARN
|
Rails.logger.override_level = Logger::WARN
|
||||||
|
@ -35,10 +33,10 @@ class SilenceLogger < Rails::Rack::Logger
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
silenced = [
|
silenced = %w[
|
||||||
"/mini-profiler-resources/results",
|
/mini-profiler-resources/results
|
||||||
"/mini-profiler-resources/includes.js",
|
/mini-profiler-resources/includes.js
|
||||||
"/mini-profiler-resources/includes.css",
|
/mini-profiler-resources/includes.css
|
||||||
"/mini-profiler-resources/jquery.tmpl.js"
|
/mini-profiler-resources/jquery.tmpl.js
|
||||||
]
|
]
|
||||||
Rails.configuration.middleware.swap Rails::Rack::Logger, SilenceLogger, silenced: silenced
|
Rails.configuration.middleware.swap Rails::Rack::Logger, SilenceLogger, silenced: silenced
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
# Check that the app is configured correctly. Raise some helpful errors if something is wrong.
|
# 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 defined?(Rails::Server) && Rails.env.production? # Only run these checks when starting up a production server
|
||||||
|
if %w[localhost production.localhost].include?(Discourse.current_hostname)
|
||||||
if ['localhost', 'production.localhost'].include?(Discourse.current_hostname)
|
|
||||||
puts <<~TEXT
|
puts <<~TEXT
|
||||||
|
|
||||||
Discourse.current_hostname = '#{Discourse.current_hostname}'
|
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"
|
raise "Invalid host_names in database.yml"
|
||||||
end
|
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
|
puts <<~TEXT
|
||||||
|
|
||||||
Assets have not been precompiled. Please run the following command
|
Assets have not been precompiled. Please run the following command
|
||||||
|
|
|
@ -6,11 +6,7 @@
|
||||||
# is enabled by default.
|
# is enabled by default.
|
||||||
|
|
||||||
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
||||||
ActiveSupport.on_load(:action_controller) do
|
ActiveSupport.on_load(:action_controller) { wrap_parameters format: [:json] }
|
||||||
wrap_parameters format: [:json]
|
|
||||||
end
|
|
||||||
|
|
||||||
# Disable root element in JSON by default.
|
# Disable root element in JSON by default.
|
||||||
ActiveSupport.on_load(:active_record) do
|
ActiveSupport.on_load(:active_record) { self.include_root_in_json = false }
|
||||||
self.include_root_in_json = false
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Rails.application.config.to_prepare do
|
Rails.application.config.to_prepare do
|
||||||
if (Rails.env.production? && SiteSetting.logging_provider == 'lograge') || (ENV["ENABLE_LOGRAGE"] == "1")
|
if (Rails.env.production? && SiteSetting.logging_provider == "lograge") ||
|
||||||
require 'lograge'
|
(ENV["ENABLE_LOGRAGE"] == "1")
|
||||||
|
require "lograge"
|
||||||
|
|
||||||
if Rails.configuration.multisite
|
if Rails.configuration.multisite
|
||||||
Rails.logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
|
Rails.logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
|
||||||
|
@ -11,20 +12,20 @@ Rails.application.config.to_prepare do
|
||||||
Rails.application.configure do
|
Rails.application.configure do
|
||||||
config.lograge.enabled = true
|
config.lograge.enabled = true
|
||||||
|
|
||||||
Lograge.ignore(lambda do |event|
|
Lograge.ignore(
|
||||||
# this is our hijack magic status,
|
lambda do |event|
|
||||||
# no point logging this cause we log again
|
# this is our hijack magic status,
|
||||||
# direct from hijack
|
# no point logging this cause we log again
|
||||||
event.payload[:status] == 418
|
# direct from hijack
|
||||||
end)
|
event.payload[:status] == 418
|
||||||
|
end,
|
||||||
|
)
|
||||||
|
|
||||||
config.lograge.custom_payload do |controller|
|
config.lograge.custom_payload do |controller|
|
||||||
begin
|
begin
|
||||||
username =
|
username =
|
||||||
begin
|
begin
|
||||||
if controller.respond_to?(:current_user)
|
controller.current_user&.username if controller.respond_to?(:current_user)
|
||||||
controller.current_user&.username
|
|
||||||
end
|
|
||||||
rescue Discourse::InvalidAccess, Discourse::ReadOnly, ActiveRecord::ReadOnlyError
|
rescue Discourse::InvalidAccess, Discourse::ReadOnly, ActiveRecord::ReadOnlyError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
@ -36,78 +37,77 @@ Rails.application.config.to_prepare do
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
{
|
{ ip: ip, username: username }
|
||||||
ip: ip,
|
|
||||||
username: username
|
|
||||||
}
|
|
||||||
rescue => e
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
config.lograge.custom_options = lambda do |event|
|
config.lograge.custom_options =
|
||||||
begin
|
lambda do |event|
|
||||||
exceptions = %w(controller action format id)
|
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)
|
if (file = params[:file]) && file.respond_to?(:headers)
|
||||||
params[:file] = file.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
|
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
|
||||||
end
|
|
||||||
|
|
||||||
if ENV["LOGSTASH_URI"]
|
if ENV["LOGSTASH_URI"]
|
||||||
config.lograge.formatter = Lograge::Formatters::Logstash.new
|
config.lograge.formatter = Lograge::Formatters::Logstash.new
|
||||||
|
|
||||||
require 'discourse_logstash_logger'
|
require "discourse_logstash_logger"
|
||||||
|
|
||||||
config.lograge.logger = DiscourseLogstashLogger.logger(
|
config.lograge.logger =
|
||||||
uri: ENV['LOGSTASH_URI'], type: :rails
|
DiscourseLogstashLogger.logger(uri: ENV["LOGSTASH_URI"], type: :rails)
|
||||||
)
|
|
||||||
|
|
||||||
# Remove ActiveSupport::Logger from the chain and replace with Lograge's
|
# Remove ActiveSupport::Logger from the chain and replace with Lograge's
|
||||||
# logger
|
# logger
|
||||||
|
|
|
@ -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
|
# 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)
|
# page view (we serve all assets out of thin in development)
|
||||||
if Rails.env != 'development' || ENV['TRACK_REQUESTS']
|
if Rails.env != "development" || ENV["TRACK_REQUESTS"]
|
||||||
require 'middleware/request_tracker'
|
require "middleware/request_tracker"
|
||||||
Rails.configuration.middleware.unshift Middleware::RequestTracker
|
Rails.configuration.middleware.unshift Middleware::RequestTracker
|
||||||
|
|
||||||
if GlobalSetting.enable_performance_http_headers
|
MethodProfiler.ensure_discourse_instrumentation! if GlobalSetting.enable_performance_http_headers
|
||||||
MethodProfiler.ensure_discourse_instrumentation!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if Rails.env.test?
|
if Rails.env.test?
|
||||||
|
@ -30,23 +28,27 @@ if Rails.env.test?
|
||||||
super(env)
|
super(env)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Rails.configuration.middleware.unshift TestMultisiteMiddleware, RailsMultisite::DiscoursePatches.config
|
Rails.configuration.middleware.unshift TestMultisiteMiddleware,
|
||||||
|
RailsMultisite::DiscoursePatches.config
|
||||||
elsif Rails.configuration.multisite
|
elsif Rails.configuration.multisite
|
||||||
assets_hostnames = GlobalSetting.cdn_hostnames
|
assets_hostnames = GlobalSetting.cdn_hostnames
|
||||||
|
|
||||||
if assets_hostnames.empty?
|
if assets_hostnames.empty?
|
||||||
assets_hostnames =
|
assets_hostnames = Discourse::Application.config.database_configuration[Rails.env]["host_names"]
|
||||||
Discourse::Application.config.database_configuration[Rails.env]["host_names"]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
RailsMultisite::ConnectionManagement.asset_hostnames = assets_hostnames
|
RailsMultisite::ConnectionManagement.asset_hostnames = assets_hostnames
|
||||||
|
|
||||||
# Multisite needs to be first, because the request tracker and message bus rely on it
|
# 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
|
Rails.configuration.middleware.delete ActionDispatch::Executor
|
||||||
|
|
||||||
if defined?(RailsFailover::ActiveRecord) && Rails.configuration.active_record_rails_failover
|
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
|
end
|
||||||
|
|
||||||
if Rails.env.development?
|
if Rails.env.development?
|
||||||
|
@ -57,5 +59,8 @@ elsif Rails.configuration.multisite
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif defined?(RailsFailover::ActiveRecord) && Rails.configuration.active_record_rails_failover
|
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
|
end
|
||||||
|
|
|
@ -2,18 +2,32 @@
|
||||||
|
|
||||||
if !GlobalSetting.skip_redis?
|
if !GlobalSetting.skip_redis?
|
||||||
if GlobalSetting.respond_to?(:redis_slave_host) && GlobalSetting.redis_slave_host.present?
|
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
|
end
|
||||||
|
|
||||||
if GlobalSetting.respond_to?(:redis_slave_port) && GlobalSetting.redis_slave_port.present?
|
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
|
end
|
||||||
|
|
||||||
if GlobalSetting.respond_to?(:message_bus_redis_slave_host) && GlobalSetting.message_bus_redis_slave_host.present?
|
if GlobalSetting.respond_to?(:message_bus_redis_slave_host) &&
|
||||||
Discourse.deprecate("message_bus_redis_slave_host is deprecated, use message_bus_redis_replica_host", drop_from: "2.8")
|
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
|
end
|
||||||
|
|
||||||
if GlobalSetting.respond_to?(:message_bus_redis_slave_port) && GlobalSetting.message_bus_redis_slave_port.present?
|
if GlobalSetting.respond_to?(:message_bus_redis_slave_port) &&
|
||||||
Discourse.deprecate("message_bus_redis_slave_port is deprecated, use message_bus_redis_replica_port", drop_from: "2.8")
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,11 +17,13 @@ Rails.application.config.assets.paths << "#{Rails.root}/public/javascripts"
|
||||||
# folder are already added.
|
# folder are already added.
|
||||||
|
|
||||||
# explicitly precompile any images in plugins ( /assets/images ) path
|
# explicitly precompile any images in plugins ( /assets/images ) path
|
||||||
Rails.application.config.assets.precompile += [lambda do |filename, path|
|
Rails.application.config.assets.precompile += [
|
||||||
path =~ /assets\/images/ && !%w(.js .css).include?(File.extname(filename))
|
lambda do |filename, path|
|
||||||
end]
|
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
|
discourse.js
|
||||||
vendor.js
|
vendor.js
|
||||||
admin.js
|
admin.js
|
||||||
|
@ -49,15 +51,21 @@ Rails.application.config.assets.precompile += %w{
|
||||||
embed-application.js
|
embed-application.js
|
||||||
scripts/discourse-test-listen-boot
|
scripts/discourse-test-listen-boot
|
||||||
scripts/discourse-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
|
# Precompile all available locales
|
||||||
unless GlobalSetting.try(:omit_base_locales)
|
unless GlobalSetting.try(:omit_base_locales)
|
||||||
Dir.glob("#{Rails.root}/app/assets/javascripts/locales/*.js.erb").each do |file|
|
Dir
|
||||||
Rails.application.config.assets.precompile << "locales/#{file.match(/([a-z_A-Z]+\.js)\.erb$/)[1]}"
|
.glob("#{Rails.root}/app/assets/javascripts/locales/*.js.erb")
|
||||||
end
|
.each do |file|
|
||||||
|
Rails
|
||||||
|
.application
|
||||||
|
.config
|
||||||
|
.assets
|
||||||
|
.precompile << "locales/#{file.match(/([a-z_A-Z]+\.js)\.erb$/)[1]}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# out of the box sprockets 3 grabs loose files that are hanging in assets,
|
# 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)
|
Rails.application.config.assets.precompile.delete(Sprockets::Railtie::LOOSE_APP_ASSETS)
|
||||||
|
|
||||||
# We don't want application from node_modules, only from the root
|
# 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.delete(%r{(?:/|\\|\A)application\.(css|js)$})
|
||||||
Rails.application.config.assets.precompile += ['application.js']
|
Rails.application.config.assets.precompile += ["application.js"]
|
||||||
|
|
||||||
start_path = ::Rails.root.join("app/assets").to_s
|
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|
|
Rails.application.config.assets.precompile << lambda do |logical_path, filename|
|
||||||
filename.start_with?(start_path) &&
|
filename.start_with?(start_path) && !filename.include?("/node_modules/") &&
|
||||||
!filename.include?("/node_modules/") &&
|
!filename.include?("/dist/") && !exclude.include?(File.extname(logical_path))
|
||||||
!filename.include?("/dist/") &&
|
|
||||||
!exclude.include?(File.extname(logical_path))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Discourse.find_plugin_js_assets(include_disabled: true).each do |file|
|
Discourse
|
||||||
Rails.application.config.assets.precompile << "#{file}.js"
|
.find_plugin_js_assets(include_disabled: true)
|
||||||
end
|
.each { |file| Rails.application.config.assets.precompile << "#{file}.js" }
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
# Configure sensitive parameters which will be filtered from the log file.
|
# Configure sensitive parameters which will be filtered from the log file.
|
||||||
Rails.application.config.filter_parameters += [
|
Rails.application.config.filter_parameters += %i[
|
||||||
:password,
|
password
|
||||||
:pop3_polling_password,
|
pop3_polling_password
|
||||||
:api_key,
|
api_key
|
||||||
:s3_secret_access_key,
|
s3_secret_access_key
|
||||||
:twitter_consumer_secret,
|
twitter_consumer_secret
|
||||||
:facebook_app_secret,
|
facebook_app_secret
|
||||||
:github_client_secret,
|
github_client_secret
|
||||||
:second_factor_token,
|
second_factor_token
|
||||||
]
|
]
|
||||||
|
|
|
@ -102,5 +102,5 @@ Rails.application.config.action_dispatch.default_headers = {
|
||||||
"X-Content-Type-Options" => "nosniff",
|
"X-Content-Type-Options" => "nosniff",
|
||||||
"X-Download-Options" => "noopen",
|
"X-Download-Options" => "noopen",
|
||||||
"X-Permitted-Cross-Domain-Policies" => "none",
|
"X-Permitted-Cross-Domain-Policies" => "none",
|
||||||
"Referrer-Policy" => "strict-origin-when-cross-origin"
|
"Referrer-Policy" => "strict-origin-when-cross-origin",
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
# source: https://github.com/svenfuchs/i18n/blob/master/test/test_data/locales/plurals.rb
|
# 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 } } } },
|
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 } } } },
|
am: { i18n: { plural: { keys: [:one, :other], rule: lambda { |n| [0, 1].include?(n) ? :one : :other } } } },
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
if ENV['RAILS_ENV'] == 'production'
|
if ENV["RAILS_ENV"] == "production"
|
||||||
|
|
||||||
# First, you need to change these below to your situation.
|
# 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
|
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.
|
# 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"
|
pidfile "#{APP_ROOT}/tmp/pids/puma.pid"
|
||||||
state_path "#{APP_ROOT}/tmp/pids/puma.state"
|
state_path "#{APP_ROOT}/tmp/pids/puma.state"
|
||||||
preload_app!
|
preload_app!
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
1373
config/routes.rb
1373
config/routes.rb
File diff suppressed because it is too large
Load Diff
|
@ -7,7 +7,5 @@
|
||||||
# spring binstub rails
|
# spring binstub rails
|
||||||
# spring binstub rake
|
# spring binstub rake
|
||||||
# spring binstub rspec
|
# spring binstub rspec
|
||||||
Spring.after_fork do
|
Spring.after_fork { Discourse.after_fork }
|
||||||
Discourse.after_fork
|
|
||||||
end
|
|
||||||
Spring::Commands::Rake.environment_matchers["spec"] = "test"
|
Spring::Commands::Rake.environment_matchers["spec"] = "test"
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
# See http://unicorn.bogomips.org/Unicorn/Configurator.html
|
# See http://unicorn.bogomips.org/Unicorn/Configurator.html
|
||||||
|
|
||||||
if (ENV["LOGSTASH_UNICORN_URI"] || "").length > 0
|
if (ENV["LOGSTASH_UNICORN_URI"] || "").length > 0
|
||||||
require_relative '../lib/discourse_logstash_logger'
|
require_relative "../lib/discourse_logstash_logger"
|
||||||
require_relative '../lib/unicorn_logstash_patch'
|
require_relative "../lib/unicorn_logstash_patch"
|
||||||
logger DiscourseLogstashLogger.logger(uri: ENV['LOGSTASH_UNICORN_URI'], type: :unicorn)
|
logger DiscourseLogstashLogger.logger(uri: ENV["LOGSTASH_UNICORN_URI"], type: :unicorn)
|
||||||
end
|
end
|
||||||
|
|
||||||
discourse_path = File.expand_path(File.expand_path(File.dirname(__FILE__)) + "/../")
|
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
|
working_directory discourse_path
|
||||||
|
|
||||||
# listen "#{discourse_path}/tmp/sockets/unicorn.sock"
|
# 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") if !File.exist?("#{discourse_path}/tmp/pids")
|
||||||
FileUtils.mkdir_p("#{discourse_path}/tmp/pids")
|
|
||||||
end
|
|
||||||
|
|
||||||
# feel free to point this anywhere accessible on the filesystem
|
# feel free to point this anywhere accessible on the filesystem
|
||||||
pid (ENV["UNICORN_PID_PATH"] || "#{discourse_path}/tmp/pids/unicorn.pid")
|
pid (ENV["UNICORN_PID_PATH"] || "#{discourse_path}/tmp/pids/unicorn.pid")
|
||||||
|
@ -52,7 +51,6 @@ check_client_connection false
|
||||||
|
|
||||||
initialized = false
|
initialized = false
|
||||||
before_fork do |server, worker|
|
before_fork do |server, worker|
|
||||||
|
|
||||||
unless initialized
|
unless initialized
|
||||||
Discourse.preload_rails!
|
Discourse.preload_rails!
|
||||||
|
|
||||||
|
@ -67,7 +65,7 @@ before_fork do |server, worker|
|
||||||
|
|
||||||
initialized = true
|
initialized = true
|
||||||
|
|
||||||
supervisor = ENV['UNICORN_SUPERVISOR_PID'].to_i
|
supervisor = ENV["UNICORN_SUPERVISOR_PID"].to_i
|
||||||
if supervisor > 0
|
if supervisor > 0
|
||||||
Thread.new do
|
Thread.new do
|
||||||
while true
|
while true
|
||||||
|
@ -80,14 +78,12 @@ before_fork do |server, worker|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sidekiqs = ENV['UNICORN_SIDEKIQS'].to_i
|
sidekiqs = ENV["UNICORN_SIDEKIQS"].to_i
|
||||||
if sidekiqs > 0
|
if sidekiqs > 0
|
||||||
server.logger.info "starting #{sidekiqs} supervised sidekiqs"
|
server.logger.info "starting #{sidekiqs} supervised sidekiqs"
|
||||||
|
|
||||||
require 'demon/sidekiq'
|
require "demon/sidekiq"
|
||||||
Demon::Sidekiq.after_fork do
|
Demon::Sidekiq.after_fork { DiscourseEvent.trigger(:sidekiq_fork_started) }
|
||||||
DiscourseEvent.trigger(:sidekiq_fork_started)
|
|
||||||
end
|
|
||||||
|
|
||||||
Demon::Sidekiq.start(sidekiqs)
|
Demon::Sidekiq.start(sidekiqs)
|
||||||
|
|
||||||
|
@ -98,13 +94,14 @@ before_fork do |server, worker|
|
||||||
|
|
||||||
# Trap USR1, so we can re-issue to sidekiq workers
|
# Trap USR1, so we can re-issue to sidekiq workers
|
||||||
# but chain the default unicorn implementation as well
|
# but chain the default unicorn implementation as well
|
||||||
old_handler = Signal.trap("USR1") do
|
old_handler =
|
||||||
Demon::Sidekiq.kill("USR1")
|
Signal.trap("USR1") do
|
||||||
old_handler.call
|
Demon::Sidekiq.kill("USR1")
|
||||||
end
|
old_handler.call
|
||||||
|
end
|
||||||
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"
|
server.logger.info "starting up EmailSync demon"
|
||||||
Demon::EmailSync.start
|
Demon::EmailSync.start
|
||||||
Signal.trap("SIGTSTP") do
|
Signal.trap("SIGTSTP") do
|
||||||
|
@ -119,13 +116,13 @@ before_fork do |server, worker|
|
||||||
end
|
end
|
||||||
|
|
||||||
class ::Unicorn::HttpServer
|
class ::Unicorn::HttpServer
|
||||||
alias :master_sleep_orig :master_sleep
|
alias master_sleep_orig master_sleep
|
||||||
|
|
||||||
def max_sidekiq_rss
|
def max_sidekiq_rss
|
||||||
rss = `ps -eo rss,args | grep sidekiq | grep -v grep | awk '{print $1}'`
|
rss =
|
||||||
.split("\n")
|
`ps -eo rss,args | grep sidekiq | grep -v grep | awk '{print $1}'`.split("\n")
|
||||||
.map(&:to_i)
|
.map(&:to_i)
|
||||||
.max
|
.max
|
||||||
|
|
||||||
rss ||= 0
|
rss ||= 0
|
||||||
|
|
||||||
|
@ -133,18 +130,24 @@ before_fork do |server, worker|
|
||||||
end
|
end
|
||||||
|
|
||||||
def max_allowed_sidekiq_rss
|
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
|
end
|
||||||
|
|
||||||
def force_kill_rogue_sidekiq
|
def force_kill_rogue_sidekiq
|
||||||
info = `ps -eo pid,rss,args | grep sidekiq | grep -v grep | awk '{print $1,$2}'`
|
info = `ps -eo pid,rss,args | grep sidekiq | grep -v grep | awk '{print $1,$2}'`
|
||||||
info.split("\n").each do |row|
|
info
|
||||||
pid, mem = row.split(" ").map(&:to_i)
|
.split("\n")
|
||||||
if pid > 0 && (mem * 1024) > max_allowed_sidekiq_rss
|
.each do |row|
|
||||||
Rails.logger.warn "Detected rogue Sidekiq pid #{pid} mem #{mem * 1024}, killing"
|
pid, mem = row.split(" ").map(&:to_i)
|
||||||
Process.kill("KILL", pid) rescue nil
|
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_sidekiq_heartbeat
|
def check_sidekiq_heartbeat
|
||||||
|
@ -152,13 +155,15 @@ before_fork do |server, worker|
|
||||||
@sidekiq_next_heartbeat_check ||= Time.now.to_i + @sidekiq_heartbeat_interval
|
@sidekiq_next_heartbeat_check ||= Time.now.to_i + @sidekiq_heartbeat_interval
|
||||||
|
|
||||||
if @sidekiq_next_heartbeat_check < Time.now.to_i
|
if @sidekiq_next_heartbeat_check < Time.now.to_i
|
||||||
|
|
||||||
last_heartbeat = Jobs::RunHeartbeat.last_heartbeat
|
last_heartbeat = Jobs::RunHeartbeat.last_heartbeat
|
||||||
restart = false
|
restart = false
|
||||||
|
|
||||||
sidekiq_rss = max_sidekiq_rss
|
sidekiq_rss = max_sidekiq_rss
|
||||||
if sidekiq_rss > max_allowed_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
|
restart = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -185,16 +190,18 @@ before_fork do |server, worker|
|
||||||
email_sync_pids = Demon::EmailSync.demons.map { |uid, demon| demon.pid }
|
email_sync_pids = Demon::EmailSync.demons.map { |uid, demon| demon.pid }
|
||||||
return 0 if email_sync_pids.empty?
|
return 0 if email_sync_pids.empty?
|
||||||
|
|
||||||
rss = `ps -eo pid,rss,args | grep '#{email_sync_pids.join('|')}' | grep -v grep | awk '{print $2}'`
|
rss =
|
||||||
.split("\n")
|
`ps -eo pid,rss,args | grep '#{email_sync_pids.join("|")}' | grep -v grep | awk '{print $2}'`.split(
|
||||||
.map(&:to_i)
|
"\n",
|
||||||
.max
|
)
|
||||||
|
.map(&:to_i)
|
||||||
|
.max
|
||||||
|
|
||||||
(rss || 0) * 1024
|
(rss || 0) * 1024
|
||||||
end
|
end
|
||||||
|
|
||||||
def max_allowed_email_sync_rss
|
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
|
end
|
||||||
|
|
||||||
def check_email_sync_heartbeat
|
def check_email_sync_heartbeat
|
||||||
|
@ -207,16 +214,22 @@ before_fork do |server, worker|
|
||||||
restart = false
|
restart = false
|
||||||
|
|
||||||
# Restart process if it does not respond anymore
|
# 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
|
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
|
restart = true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Restart process if memory usage is too high
|
# Restart process if memory usage is too high
|
||||||
email_sync_rss = max_email_sync_rss
|
email_sync_rss = max_email_sync_rss
|
||||||
if email_sync_rss > max_allowed_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
|
restart = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -224,25 +237,22 @@ before_fork do |server, worker|
|
||||||
end
|
end
|
||||||
|
|
||||||
def master_sleep(sec)
|
def master_sleep(sec)
|
||||||
sidekiqs = ENV['UNICORN_SIDEKIQS'].to_i
|
sidekiqs = ENV["UNICORN_SIDEKIQS"].to_i
|
||||||
if sidekiqs > 0
|
if sidekiqs > 0
|
||||||
Demon::Sidekiq.ensure_running
|
Demon::Sidekiq.ensure_running
|
||||||
check_sidekiq_heartbeat
|
check_sidekiq_heartbeat
|
||||||
end
|
end
|
||||||
|
|
||||||
if ENV['DISCOURSE_ENABLE_EMAIL_SYNC_DEMON'] == 'true'
|
if ENV["DISCOURSE_ENABLE_EMAIL_SYNC_DEMON"] == "true"
|
||||||
Demon::EmailSync.ensure_running
|
Demon::EmailSync.ensure_running
|
||||||
check_email_sync_heartbeat
|
check_email_sync_heartbeat
|
||||||
end
|
end
|
||||||
|
|
||||||
DiscoursePluginRegistry.demon_processes.each do |demon_class|
|
DiscoursePluginRegistry.demon_processes.each { |demon_class| demon_class.ensure_running }
|
||||||
demon_class.ensure_running
|
|
||||||
end
|
|
||||||
|
|
||||||
master_sleep_orig(sec)
|
master_sleep_orig(sec)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Discourse.redis.close
|
Discourse.redis.close
|
||||||
|
|
Loading…
Reference in New Issue