diff --git a/.streerc b/.streerc index 612e4b246dc..c385bd0b7c7 100644 --- a/.streerc +++ b/.streerc @@ -2,7 +2,6 @@ --plugins=plugin/trailing_comma,disable_ternary --ignore-files=Gemfile --ignore-files=app/* ---ignore-files=config/* --ignore-files=db/* --ignore-files=lib/* --ignore-files=spec/* diff --git a/config/application.rb b/config/application.rb index 1c69f3d99ca..0c31d3a327c 100644 --- a/config/application.rb +++ b/config/application.rb @@ -5,12 +5,12 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7.0") exit 1 end -require File.expand_path('../boot', __FILE__) -require 'active_record/railtie' -require 'action_controller/railtie' -require 'action_view/railtie' -require 'action_mailer/railtie' -require 'sprockets/railtie' +require File.expand_path("../boot", __FILE__) +require "active_record/railtie" +require "action_controller/railtie" +require "action_view/railtie" +require "action_mailer/railtie" +require "sprockets/railtie" if !Rails.env.production? recommended = File.read(".ruby-version.sample").strip @@ -20,66 +20,59 @@ if !Rails.env.production? end # Plugin related stuff -require_relative '../lib/plugin' -require_relative '../lib/discourse_event' -require_relative '../lib/discourse_plugin_registry' +require_relative "../lib/plugin" +require_relative "../lib/discourse_event" +require_relative "../lib/discourse_plugin_registry" -require_relative '../lib/plugin_gem' +require_relative "../lib/plugin_gem" # Global config -require_relative '../app/models/global_setting' +require_relative "../app/models/global_setting" GlobalSetting.configure! if GlobalSetting.load_plugins? # Support for plugins to register custom setting providers. They can do this # by having a file, `register_provider.rb` in their root that will be run # at this point. - Dir.glob(File.join(File.dirname(__FILE__), '../plugins', '*', "register_provider.rb")) do |p| + Dir.glob(File.join(File.dirname(__FILE__), "../plugins", "*", "register_provider.rb")) do |p| require p end end GlobalSetting.load_defaults -if GlobalSetting.try(:cdn_url).present? && GlobalSetting.cdn_url !~ /^https?:\/\// +if GlobalSetting.try(:cdn_url).present? && GlobalSetting.cdn_url !~ %r{^https?://} STDERR.puts "WARNING: Your CDN URL does not begin with a protocol like `https://` - this is probably not going to work" end -if ENV['SKIP_DB_AND_REDIS'] == '1' +if ENV["SKIP_DB_AND_REDIS"] == "1" GlobalSetting.skip_db = true GlobalSetting.skip_redis = true end -if !GlobalSetting.skip_db? - require 'rails_failover/active_record' -end +require "rails_failover/active_record" if !GlobalSetting.skip_db? -if !GlobalSetting.skip_redis? - require 'rails_failover/redis' -end +require "rails_failover/redis" if !GlobalSetting.skip_redis? -require 'pry-rails' if Rails.env.development? -require 'pry-byebug' if Rails.env.development? +require "pry-rails" if Rails.env.development? +require "pry-byebug" if Rails.env.development? -require 'discourse_fonts' +require "discourse_fonts" -require_relative '../lib/ember_cli' +require_relative "../lib/ember_cli" if defined?(Bundler) bundler_groups = [:default] if !Rails.env.production? - bundler_groups = bundler_groups.concat(Rails.groups( - assets: %w(development test profile) - )) + bundler_groups = bundler_groups.concat(Rails.groups(assets: %w[development test profile])) end Bundler.require(*bundler_groups) end -require_relative '../lib/require_dependency_backward_compatibility' +require_relative "../lib/require_dependency_backward_compatibility" module Discourse class Application < Rails::Application - def config.database_configuration if Rails.env.production? GlobalSetting.database_config @@ -91,18 +84,23 @@ module Discourse # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. - require 'discourse' - require 'js_locale_helper' + require "discourse" + require "js_locale_helper" # tiny file needed by site settings - require 'highlight_js' + require "highlight_js" config.load_defaults 6.1 config.active_record.cache_versioning = false # our custom cache class doesn’t support this config.action_controller.forgery_protection_origin_check = false config.active_record.belongs_to_required_by_default = false config.active_record.legacy_connection_handling = true - config.active_record.yaml_column_permitted_classes = [Hash, HashWithIndifferentAccess, Time, Symbol] + config.active_record.yaml_column_permitted_classes = [ + Hash, + HashWithIndifferentAccess, + Time, + Symbol, + ] # we skip it cause we configure it in the initializer # the railtie for message_bus would insert it in the @@ -111,7 +109,8 @@ module Discourse config.skip_multisite_middleware = true config.skip_rails_failover_active_record_middleware = true - multisite_config_path = ENV['DISCOURSE_MULTISITE_CONFIG_PATH'] || GlobalSetting.multisite_config_path + multisite_config_path = + ENV["DISCOURSE_MULTISITE_CONFIG_PATH"] || GlobalSetting.multisite_config_path config.multisite_config_path = File.absolute_path(multisite_config_path, Rails.root) # Custom directories with classes and modules you want to be autoloadable. @@ -129,14 +128,14 @@ module Discourse # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - config.time_zone = 'UTC' + config.time_zone = "UTC" # auto-load locales in plugins # NOTE: we load both client & server locales since some might be used by PrettyText config.i18n.load_path += Dir["#{Rails.root}/plugins/*/config/locales/*.yml"] # Configure the default encoding used in templates for Ruby 1.9. - config.encoding = 'utf-8' + config.encoding = "utf-8" # see: http://stackoverflow.com/questions/11894180/how-does-one-correctly-add-custom-sql-dml-in-migrations/11894420#11894420 config.active_record.schema_format = :sql @@ -145,7 +144,7 @@ module Discourse config.active_record.use_schema_cache_dump = false # per https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet - config.pbkdf2_iterations = 64000 + config.pbkdf2_iterations = 64_000 config.pbkdf2_algorithm = "sha256" # rack lock is nothing but trouble, get rid of it @@ -160,32 +159,39 @@ module Discourse # supports etags (post 1.7) config.middleware.delete Rack::ETag - if !(Rails.env.development? || ENV['SKIP_ENFORCE_HOSTNAME'] == "1") - require 'middleware/enforce_hostname' + if !(Rails.env.development? || ENV["SKIP_ENFORCE_HOSTNAME"] == "1") + require "middleware/enforce_hostname" config.middleware.insert_after Rack::MethodOverride, Middleware::EnforceHostname end - require 'content_security_policy/middleware' - config.middleware.swap ActionDispatch::ContentSecurityPolicy::Middleware, ContentSecurityPolicy::Middleware + require "content_security_policy/middleware" + config.middleware.swap ActionDispatch::ContentSecurityPolicy::Middleware, + ContentSecurityPolicy::Middleware - require 'middleware/discourse_public_exceptions' + require "middleware/discourse_public_exceptions" config.exceptions_app = Middleware::DiscoursePublicExceptions.new(Rails.public_path) - require 'discourse_js_processor' - require 'discourse_sourcemapping_url_processor' + require "discourse_js_processor" + require "discourse_sourcemapping_url_processor" - Sprockets.register_mime_type 'application/javascript', extensions: ['.js', '.es6', '.js.es6'], charset: :unicode - Sprockets.register_postprocessor 'application/javascript', DiscourseJsProcessor + Sprockets.register_mime_type "application/javascript", + extensions: %w[.js .es6 .js.es6], + charset: :unicode + Sprockets.register_postprocessor "application/javascript", DiscourseJsProcessor Discourse::Application.initializer :prepend_ember_assets do |app| # Needs to be in its own initializer so it runs after the append_assets_path initializer defined by Sprockets - app.config.assets.paths.unshift "#{app.config.root}/app/assets/javascripts/discourse/dist/assets" - Sprockets.unregister_postprocessor 'application/javascript', Sprockets::Rails::SourcemappingUrlProcessor - Sprockets.register_postprocessor 'application/javascript', DiscourseSourcemappingUrlProcessor + app + .config + .assets + .paths.unshift "#{app.config.root}/app/assets/javascripts/discourse/dist/assets" + Sprockets.unregister_postprocessor "application/javascript", + Sprockets::Rails::SourcemappingUrlProcessor + Sprockets.register_postprocessor "application/javascript", DiscourseSourcemappingUrlProcessor end - require 'discourse_redis' - require 'logster/redis_store' + require "discourse_redis" + require "logster/redis_store" # Use redis for our cache config.cache_store = DiscourseRedis.new_redis_store Discourse.redis = DiscourseRedis.new @@ -198,7 +204,7 @@ module Discourse # our setup does not use rack cache and instead defers to nginx config.action_dispatch.rack_cache = nil - require 'auth' + require "auth" if GlobalSetting.relative_url_root.present? config.relative_url_root = GlobalSetting.relative_url_root @@ -207,38 +213,28 @@ module Discourse if Rails.env.test? && GlobalSetting.load_plugins? Discourse.activate_plugins! elsif GlobalSetting.load_plugins? - Plugin.initialization_guard do - Discourse.activate_plugins! - end + Plugin.initialization_guard { Discourse.activate_plugins! } end # Use discourse-fonts gem to symlink fonts and generate .scss file - fonts_path = File.join(config.root, 'public/fonts') + fonts_path = File.join(config.root, "public/fonts") Discourse::Utils.atomic_ln_s(DiscourseFonts.path_for_fonts, fonts_path) - require 'stylesheet/manager' - require 'svg_sprite' + require "stylesheet/manager" + require "svg_sprite" config.after_initialize do # Load plugins - Plugin.initialization_guard do - Discourse.plugins.each(&:notify_after_initialize) - end + Plugin.initialization_guard { Discourse.plugins.each(&:notify_after_initialize) } # we got to clear the pool in case plugins connect ActiveRecord::Base.connection_handler.clear_active_connections! end - if ENV['RBTRACE'] == "1" - require 'rbtrace' - end + require "rbtrace" if ENV["RBTRACE"] == "1" - if ENV['RAILS_QUERY_LOG_TAGS'] == "1" - config.active_record.query_log_tags_enabled = true - end + config.active_record.query_log_tags_enabled = true if ENV["RAILS_QUERY_LOG_TAGS"] == "1" - config.generators do |g| - g.test_framework :rspec, fixture: false - end + config.generators { |g| g.test_framework :rspec, fixture: false } end end diff --git a/config/boot.rb b/config/boot.rb index 6866506f24b..bf5d61d56d6 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,48 +1,49 @@ # frozen_string_literal: true -if ENV['DISCOURSE_DUMP_HEAP'] == "1" - require 'objspace' +if ENV["DISCOURSE_DUMP_HEAP"] == "1" + require "objspace" ObjectSpace.trace_object_allocations_start end -require 'rubygems' +require "rubygems" # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__) -require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) -if (ENV['DISABLE_BOOTSNAP'] != '1') +if (ENV["DISABLE_BOOTSNAP"] != "1") begin - require 'bootsnap' + require "bootsnap" rescue LoadError # not a strong requirement end - if defined? Bootsnap + if defined?(Bootsnap) Bootsnap.setup( - cache_dir: 'tmp/cache', # Path to your cache - load_path_cache: true, # Should we optimize the LOAD_PATH with a cache? - compile_cache_iseq: true, # Should compile Ruby code into ISeq cache? - compile_cache_yaml: false # Skip YAML cache for now, cause we were seeing issues with it + cache_dir: "tmp/cache", # Path to your cache + load_path_cache: true, # Should we optimize the LOAD_PATH with a cache? + compile_cache_iseq: true, # Should compile Ruby code into ISeq cache? + compile_cache_yaml: false, # Skip YAML cache for now, cause we were seeing issues with it ) end end # Parallel spec system -if ENV['RAILS_ENV'] == "test" && ENV['TEST_ENV_NUMBER'] - if ENV['TEST_ENV_NUMBER'] == '' +if ENV["RAILS_ENV"] == "test" && ENV["TEST_ENV_NUMBER"] + if ENV["TEST_ENV_NUMBER"] == "" n = 1 else - n = ENV['TEST_ENV_NUMBER'].to_i + n = ENV["TEST_ENV_NUMBER"].to_i end - port = 10000 + n + port = 10_000 + n STDERR.puts "Setting up parallel test mode - starting Redis #{n} on port #{port}" `rm -rf tmp/test_data_#{n} && mkdir -p tmp/test_data_#{n}/redis` - pid = Process.spawn("redis-server --dir tmp/test_data_#{n}/redis --port #{port}", out: "/dev/null") + pid = + Process.spawn("redis-server --dir tmp/test_data_#{n}/redis --port #{port}", out: "/dev/null") ENV["DISCOURSE_REDIS_PORT"] = port.to_s ENV["RAILS_DB"] = "discourse_test_#{n}" diff --git a/config/cloud/cloud66/files/production.rb b/config/cloud/cloud66/files/production.rb index f527db5d6a9..2814996b68b 100644 --- a/config/cloud/cloud66/files/production.rb +++ b/config/cloud/cloud66/files/production.rb @@ -7,7 +7,7 @@ Discourse::Application.configure do config.cache_classes = true # Full error reports are disabled and caching is turned on - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) @@ -23,19 +23,20 @@ Discourse::Application.configure do config.assets.digest = true # Specifies the header that your server uses for sending files - config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for nginx # you may use other configuration here for mail eg: sendgrid config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { - address: ENV['SMTP_ADDRESS'], - port: ENV['SMTP_PORT'], - domain: ENV['SMTP_DOMAIN'], - user_name: ENV['SMTP_USERNAME'], - password: ENV['SMTP_PASSWORD'], - authentication: 'plain', - enable_starttls_auto: true } + address: ENV["SMTP_ADDRESS"], + port: ENV["SMTP_PORT"], + domain: ENV["SMTP_DOMAIN"], + user_name: ENV["SMTP_USERNAME"], + password: ENV["SMTP_PASSWORD"], + authentication: "plain", + enable_starttls_auto: true, + } #config.action_mailer.delivery_method = :sendmail #config.action_mailer.sendmail_settings = {arguments: '-i'} @@ -59,5 +60,4 @@ Discourse::Application.configure do # Discourse strongly recommend you use a CDN. # For origin pull cdns all you need to do is register an account and configure # config.action_controller.asset_host = "http://YOUR_CDN_HERE" - end diff --git a/config/environment.rb b/config/environment.rb index 7bb5d95ae90..90ea3b4fa98 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -7,6 +7,7 @@ require_relative "application" Rails.application.initialize! # When in "dev" mode, ensure we won't be sending any emails -if Rails.env.development? && ActionMailer::Base.smtp_settings.slice(:address, :port) != { address: "localhost", port: 1025 } +if Rails.env.development? && + ActionMailer::Base.smtp_settings.slice(:address, :port) != { address: "localhost", port: 1025 } fail "In development mode, you should be using mailhog otherwise you might end up sending thousands of digest emails" end diff --git a/config/environments/development.rb b/config/environments/development.rb index 3e6496f1a92..62b3dd28438 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -16,7 +16,7 @@ Discourse::Application.configure do config.active_record.use_schema_cache_dump = true # Show full error reports and disable caching - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false config.action_controller.asset_host = GlobalSetting.cdn_url @@ -32,27 +32,23 @@ Discourse::Application.configure do config.assets.debug = false - config.public_file_server.headers = { - 'Access-Control-Allow-Origin' => '*' - } + config.public_file_server.headers = { "Access-Control-Allow-Origin" => "*" } # Raise an error on page load if there are pending migrations config.active_record.migration_error = :page_load - config.watchable_dirs['lib'] = [:rb] + config.watchable_dirs["lib"] = [:rb] # we recommend you use mailhog https://github.com/mailhog/MailHog config.action_mailer.smtp_settings = { address: "localhost", port: 1025 } config.action_mailer.raise_delivery_errors = true - config.log_level = ENV['DISCOURSE_DEV_LOG_LEVEL'] if ENV['DISCOURSE_DEV_LOG_LEVEL'] + config.log_level = ENV["DISCOURSE_DEV_LOG_LEVEL"] if ENV["DISCOURSE_DEV_LOG_LEVEL"] - if ENV['RAILS_VERBOSE_QUERY_LOGS'] == "1" - config.active_record.verbose_query_logs = true - end + config.active_record.verbose_query_logs = true if ENV["RAILS_VERBOSE_QUERY_LOGS"] == "1" if defined?(BetterErrors) - BetterErrors::Middleware.allow_ip! ENV['TRUSTED_IP'] if ENV['TRUSTED_IP'] + BetterErrors::Middleware.allow_ip! ENV["TRUSTED_IP"] if ENV["TRUSTED_IP"] if defined?(Unicorn) && ENV["UNICORN_WORKERS"].to_i != 1 # BetterErrors doesn't work with multiple unicorn workers. Disable it to avoid confusion @@ -60,51 +56,44 @@ Discourse::Application.configure do end end - if !ENV["DISABLE_MINI_PROFILER"] - config.load_mini_profiler = true - end + config.load_mini_profiler = true if !ENV["DISABLE_MINI_PROFILER"] - if hosts = ENV['DISCOURSE_DEV_HOSTS'] + if hosts = ENV["DISCOURSE_DEV_HOSTS"] Discourse.deprecate("DISCOURSE_DEV_HOSTS is deprecated. Use RAILS_DEVELOPMENT_HOSTS instead.") config.hosts.concat(hosts.split(",")) end - require 'middleware/turbo_dev' + require "middleware/turbo_dev" config.middleware.insert 0, Middleware::TurboDev - require 'middleware/missing_avatars' + require "middleware/missing_avatars" config.middleware.insert 1, Middleware::MissingAvatars config.enable_anon_caching = false - if RUBY_ENGINE == "ruby" - require 'rbtrace' - end + require "rbtrace" if RUBY_ENGINE == "ruby" if emails = GlobalSetting.developer_emails config.developer_emails = emails.split(",").map(&:downcase).map(&:strip) end - if ENV["DISCOURSE_SKIP_CSS_WATCHER"] != "1" && (defined?(Rails::Server) || defined?(Puma) || defined?(Unicorn)) - require 'stylesheet/watcher' + if ENV["DISCOURSE_SKIP_CSS_WATCHER"] != "1" && + (defined?(Rails::Server) || defined?(Puma) || defined?(Unicorn)) + require "stylesheet/watcher" STDERR.puts "Starting CSS change watcher" @watcher = Stylesheet::Watcher.watch end config.after_initialize do - if ENV["RAILS_COLORIZE_LOGGING"] == "1" - config.colorize_logging = true - end + config.colorize_logging = true if ENV["RAILS_COLORIZE_LOGGING"] == "1" if ENV["RAILS_VERBOSE_QUERY_LOGS"] == "1" ActiveRecord::LogSubscriber.backtrace_cleaner.add_silencer do |line| - line =~ /lib\/freedom_patches/ + line =~ %r{lib/freedom_patches} end end - if ENV["RAILS_DISABLE_ACTIVERECORD_LOGS"] == "1" - ActiveRecord::Base.logger = nil - end + ActiveRecord::Base.logger = nil if ENV["RAILS_DISABLE_ACTIVERECORD_LOGS"] == "1" - if ENV['BULLET'] + if ENV["BULLET"] Bullet.enable = true Bullet.rails_logger = true end diff --git a/config/environments/production.rb b/config/environments/production.rb index f5a5df8ff50..5b6cd924561 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -8,7 +8,7 @@ Discourse::Application.configure do config.eager_load = true # Full error reports are disabled and caching is turned on - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) @@ -34,19 +34,19 @@ Discourse::Application.configure do authentication: GlobalSetting.smtp_authentication, enable_starttls_auto: GlobalSetting.smtp_enable_start_tls, open_timeout: GlobalSetting.smtp_open_timeout, - read_timeout: GlobalSetting.smtp_read_timeout + read_timeout: GlobalSetting.smtp_read_timeout, } - settings[:openssl_verify_mode] = GlobalSetting.smtp_openssl_verify_mode if GlobalSetting.smtp_openssl_verify_mode + settings[ + :openssl_verify_mode + ] = GlobalSetting.smtp_openssl_verify_mode if GlobalSetting.smtp_openssl_verify_mode - if GlobalSetting.smtp_force_tls - settings[:tls] = true - end + settings[:tls] = true if GlobalSetting.smtp_force_tls config.action_mailer.smtp_settings = settings.compact else config.action_mailer.delivery_method = :sendmail - config.action_mailer.sendmail_settings = { arguments: '-i' } + config.action_mailer.sendmail_settings = { arguments: "-i" } end # Send deprecation notices to registered listeners diff --git a/config/environments/profile.rb b/config/environments/profile.rb index d8f55a44f5b..05e526c5730 100644 --- a/config/environments/profile.rb +++ b/config/environments/profile.rb @@ -11,7 +11,7 @@ Discourse::Application.configure do config.log_level = :info # Full error reports are disabled and caching is turned on - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true # in profile mode we serve static assets @@ -27,7 +27,7 @@ Discourse::Application.configure do config.assets.digest = true # Specifies the header that your server uses for sending files - config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for nginx # we recommend you use mailhog https://github.com/mailhog/MailHog config.action_mailer.smtp_settings = { address: "localhost", port: 1025 } @@ -39,9 +39,7 @@ Discourse::Application.configure do config.load_mini_profiler = false # we don't need full logster support, but need to keep it working - config.after_initialize do - Logster.logger = Rails.logger - end + config.after_initialize { Logster.logger = Rails.logger } # for profiling with perftools # config.middleware.use ::Rack::PerftoolsProfiler, default_printer: 'gif' diff --git a/config/environments/test.rb b/config/environments/test.rb index 85b20535d53..e80e4f7a648 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -46,21 +46,22 @@ Discourse::Application.configure do config.eager_load = false - if ENV['RAILS_ENABLE_TEST_LOG'] + if ENV["RAILS_ENABLE_TEST_LOG"] config.logger = Logger.new(STDOUT) - config.log_level = ENV['RAILS_TEST_LOG_LEVEL'].present? ? ENV['RAILS_TEST_LOG_LEVEL'].to_sym : :info + config.log_level = + ENV["RAILS_TEST_LOG_LEVEL"].present? ? ENV["RAILS_TEST_LOG_LEVEL"].to_sym : :info else config.logger = Logger.new(nil) config.log_level = :fatal end - if defined? RspecErrorTracker + if defined?(RspecErrorTracker) config.middleware.insert_after ActionDispatch::Flash, RspecErrorTracker end config.after_initialize do SiteSetting.defaults.tap do |s| - s.set_regardless_of_locale(:s3_upload_bucket, 'bucket') + s.set_regardless_of_locale(:s3_upload_bucket, "bucket") s.set_regardless_of_locale(:min_post_length, 5) s.set_regardless_of_locale(:min_first_post_length, 5) s.set_regardless_of_locale(:min_personal_message_post_length, 10) @@ -73,7 +74,7 @@ Discourse::Application.configure do s.set_regardless_of_locale(:allow_uncategorized_topics, true) # disable plugins - if ENV['LOAD_PLUGINS'] == '1' + if ENV["LOAD_PLUGINS"] == "1" s.set_regardless_of_locale(:discourse_narrative_bot_enabled, false) end end diff --git a/config/initializers/000-development_reload_warnings.rb b/config/initializers/000-development_reload_warnings.rb index ce0260a8ee5..bc1f74718f8 100644 --- a/config/initializers/000-development_reload_warnings.rb +++ b/config/initializers/000-development_reload_warnings.rb @@ -8,25 +8,35 @@ if Rails.env.development? && !Rails.configuration.cache_classes && Discourse.run *Dir["#{Rails.root}/app/*"].reject { |path| path.end_with? "/assets" }, "#{Rails.root}/config", "#{Rails.root}/lib", - "#{Rails.root}/plugins" + "#{Rails.root}/plugins", ] - Listen.to(*paths, only: /\.rb$/) do |modified, added, removed| - supervisor_pid = UNICORN_DEV_SUPERVISOR_PID - auto_restart = supervisor_pid && ENV["AUTO_RESTART"] != "0" + Listen + .to(*paths, only: /\.rb$/) do |modified, added, removed| + supervisor_pid = UNICORN_DEV_SUPERVISOR_PID + auto_restart = supervisor_pid && ENV["AUTO_RESTART"] != "0" - files = modified + added + removed + files = modified + added + removed - not_autoloaded = files.filter_map do |file| - autoloaded = Rails.autoloaders.main.autoloads.key? file - Pathname.new(file).relative_path_from(Rails.root) if !autoloaded + not_autoloaded = + files.filter_map do |file| + autoloaded = Rails.autoloaders.main.autoloads.key? file + Pathname.new(file).relative_path_from(Rails.root) if !autoloaded + end + + if not_autoloaded.length > 0 + message = + ( + if auto_restart + "Restarting server..." + else + "Server restart required. Automate this by setting AUTO_RESTART=1." + end + ) + STDERR.puts "[DEV]: Edited files which are not autoloaded. #{message}" + STDERR.puts not_autoloaded.map { |path| "- #{path}".indent(7) }.join("\n") + Process.kill("USR2", supervisor_pid) if auto_restart + end end - - if not_autoloaded.length > 0 - message = auto_restart ? "Restarting server..." : "Server restart required. Automate this by setting AUTO_RESTART=1." - STDERR.puts "[DEV]: Edited files which are not autoloaded. #{message}" - STDERR.puts not_autoloaded.map { |path| "- #{path}".indent(7) }.join("\n") - Process.kill("USR2", supervisor_pid) if auto_restart - end - end.start + .start end diff --git a/config/initializers/000-mini_sql.rb b/config/initializers/000-mini_sql.rb index 15bbb7de068..53a9b7aa94b 100644 --- a/config/initializers/000-mini_sql.rb +++ b/config/initializers/000-mini_sql.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true -require 'mini_sql_multisite_connection' +require "mini_sql_multisite_connection" ::DB = MiniSqlMultisiteConnection.instance diff --git a/config/initializers/000-post_migration.rb b/config/initializers/000-post_migration.rb index 31d5370e97b..2029d9a9cd8 100644 --- a/config/initializers/000-post_migration.rb +++ b/config/initializers/000-post_migration.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true unless Discourse.skip_post_deployment_migrations? - ActiveRecord::Tasks::DatabaseTasks.migrations_paths << Rails.root.join( - Discourse::DB_POST_MIGRATE_PATH - ).to_s + ActiveRecord::Tasks::DatabaseTasks.migrations_paths << Rails + .root + .join(Discourse::DB_POST_MIGRATE_PATH) + .to_s end diff --git a/config/initializers/000-trace_pg_connections.rb b/config/initializers/000-trace_pg_connections.rb index ccfa7600080..6a04daf399c 100644 --- a/config/initializers/000-trace_pg_connections.rb +++ b/config/initializers/000-trace_pg_connections.rb @@ -15,31 +15,32 @@ # Warning: this could create some very large files! if ENV["TRACE_PG_CONNECTIONS"] - PG::Connection.prepend(Module.new do - TRACE_DIR = "tmp/pgtrace" + PG::Connection.prepend( + Module.new do + TRACE_DIR = "tmp/pgtrace" - def initialize(*args) - super(*args).tap do - next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server? - FileUtils.mkdir_p(TRACE_DIR) - @trace_filename = "#{TRACE_DIR}/#{Process.pid}_#{self.object_id}.txt" - trace File.new(@trace_filename, "w") + def initialize(*args) + super(*args).tap do + next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server? + FileUtils.mkdir_p(TRACE_DIR) + @trace_filename = "#{TRACE_DIR}/#{Process.pid}_#{self.object_id}.txt" + trace File.new(@trace_filename, "w") + end + @access_log_mutex = Mutex.new + @accessor_thread = nil end - @access_log_mutex = Mutex.new - @accessor_thread = nil - end - def close - super.tap do - next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server? - File.delete(@trace_filename) + def close + super.tap do + next if ENV["TRACE_PG_CONNECTIONS"] == "SIDEKIQ" && !Sidekiq.server? + File.delete(@trace_filename) + end end - end - def log_access(&blk) - @access_log_mutex.synchronize do - if !@accessor_thread.nil? - Rails.logger.error <<~TEXT + def log_access(&blk) + @access_log_mutex.synchronize do + if !@accessor_thread.nil? + Rails.logger.error <<~TEXT PG Clash: A connection is being accessed from two locations #{@accessor_thread} was using the connection. Backtrace: @@ -51,37 +52,38 @@ if ENV["TRACE_PG_CONNECTIONS"] #{Thread.current&.backtrace&.join("\n")} TEXT - if ENV["ON_PG_CLASH"] == "byebug" - require "byebug" - byebug # rubocop:disable Lint/Debugger + if ENV["ON_PG_CLASH"] == "byebug" + require "byebug" + byebug # rubocop:disable Lint/Debugger + end end + @accessor_thread = Thread.current end - @accessor_thread = Thread.current + yield + ensure + @access_log_mutex.synchronize { @accessor_thread = nil } end - yield - ensure - @access_log_mutex.synchronize do - @accessor_thread = nil - end - end - - end) + end, + ) class PG::Connection - LOG_ACCESS_METHODS = [:exec, :sync_exec, :async_exec, - :sync_exec_params, :async_exec_params, - :sync_prepare, :async_prepare, - :sync_exec_prepared, :async_exec_prepared, - ] + LOG_ACCESS_METHODS = %i[ + exec + sync_exec + async_exec + sync_exec_params + async_exec_params + sync_prepare + async_prepare + sync_exec_prepared + async_exec_prepared + ] LOG_ACCESS_METHODS.each do |method| new_method = "#{method}_without_logging".to_sym alias_method new_method, method - define_method(method) do |*args, &blk| - log_access { send(new_method, *args, &blk) } - end + define_method(method) { |*args, &blk| log_access { send(new_method, *args, &blk) } } end end - end diff --git a/config/initializers/000-zeitwerk.rb b/config/initializers/000-zeitwerk.rb index 130ba2d5c70..13131cbb016 100644 --- a/config/initializers/000-zeitwerk.rb +++ b/config/initializers/000-zeitwerk.rb @@ -11,7 +11,7 @@ module DiscourseInflector def self.camelize(basename, abspath) return basename.camelize if abspath.ends_with?("onceoff.rb") - return 'Jobs' if abspath.ends_with?("jobs/base.rb") + return "Jobs" if abspath.ends_with?("jobs/base.rb") @overrides[basename] || basename.camelize end @@ -26,27 +26,29 @@ Rails.autoloaders.each do |autoloader| # We have filenames that do not follow Zeitwerk's camelization convention. Maintain an inflections for these files # for now until we decide to fix them one day. autoloader.inflector.inflect( - 'canonical_url' => 'CanonicalURL', - 'clean_up_unmatched_ips' => 'CleanUpUnmatchedIPs', - 'homepage_constraint' => 'HomePageConstraint', - 'ip_addr' => 'IPAddr', - 'onpdiff' => 'ONPDiff', - 'pop3_polling_enabled_setting_validator' => 'POP3PollingEnabledSettingValidator', - 'version' => 'Discourse', - 'onceoff' => 'Jobs', - 'regular' => 'Jobs', - 'scheduled' => 'Jobs', - 'google_oauth2_authenticator' => 'GoogleOAuth2Authenticator', - 'omniauth_strategies' => 'OmniAuthStrategies', - 'csrf_token_verifier' => 'CSRFTokenVerifier', - 'html' => 'HTML', - 'json' => 'JSON', - 'ssrf_detector' => 'SSRFDetector', - 'http' => 'HTTP', + "canonical_url" => "CanonicalURL", + "clean_up_unmatched_ips" => "CleanUpUnmatchedIPs", + "homepage_constraint" => "HomePageConstraint", + "ip_addr" => "IPAddr", + "onpdiff" => "ONPDiff", + "pop3_polling_enabled_setting_validator" => "POP3PollingEnabledSettingValidator", + "version" => "Discourse", + "onceoff" => "Jobs", + "regular" => "Jobs", + "scheduled" => "Jobs", + "google_oauth2_authenticator" => "GoogleOAuth2Authenticator", + "omniauth_strategies" => "OmniAuthStrategies", + "csrf_token_verifier" => "CSRFTokenVerifier", + "html" => "HTML", + "json" => "JSON", + "ssrf_detector" => "SSRFDetector", + "http" => "HTTP", ) end -Rails.autoloaders.main.ignore("lib/tasks", - "lib/generators", - "lib/freedom_patches", - "lib/i18n/backend", - "lib/unicorn_logstash_patch.rb") +Rails.autoloaders.main.ignore( + "lib/tasks", + "lib/generators", + "lib/freedom_patches", + "lib/i18n/backend", + "lib/unicorn_logstash_patch.rb", +) diff --git a/config/initializers/001-redis.rb b/config/initializers/001-redis.rb index d61f467b289..1384e444672 100644 --- a/config/initializers/001-redis.rb +++ b/config/initializers/001-redis.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -if Rails.env.development? && ENV['DISCOURSE_FLUSH_REDIS'] +if Rails.env.development? && ENV["DISCOURSE_FLUSH_REDIS"] puts "Flushing redis (development mode)" Discourse.redis.flushdb end begin - if Gem::Version.new(Discourse.redis.info['redis_version']) < Gem::Version.new("6.2.0") + if Gem::Version.new(Discourse.redis.info["redis_version"]) < Gem::Version.new("6.2.0") STDERR.puts "Discourse requires Redis 6.2.0 or up" exit 1 end diff --git a/config/initializers/002-rails_failover.rb b/config/initializers/002-rails_failover.rb index 3f1463fdd87..276e6d951bb 100644 --- a/config/initializers/002-rails_failover.rb +++ b/config/initializers/002-rails_failover.rb @@ -14,16 +14,12 @@ if defined?(RailsFailover::Redis) Discourse.request_refresh! MessageBus.keepalive_interval = message_bus_keepalive_interval - ObjectSpace.each_object(DistributedCache) do |cache| - cache.clear - end + ObjectSpace.each_object(DistributedCache) { |cache| cache.clear } SiteSetting.refresh! end - if Rails.logger.respond_to? :chained - RailsFailover::Redis.logger = Rails.logger.chained.first - end + RailsFailover::Redis.logger = Rails.logger.chained.first if Rails.logger.respond_to? :chained end if defined?(RailsFailover::ActiveRecord) @@ -73,10 +69,7 @@ if defined?(RailsFailover::ActiveRecord) end RailsFailover::ActiveRecord.register_force_reading_role_callback do - Discourse.redis.exists?( - Discourse::PG_READONLY_MODE_KEY, - Discourse::PG_FORCE_READONLY_MODE_KEY - ) + Discourse.redis.exists?(Discourse::PG_READONLY_MODE_KEY, Discourse::PG_FORCE_READONLY_MODE_KEY) rescue => e if !e.is_a?(Redis::CannotConnectError) Rails.logger.warn "#{e.class} #{e.message}: #{e.backtrace.join("\n")}" diff --git a/config/initializers/004-message_bus.rb b/config/initializers/004-message_bus.rb index 46a531e3f7f..2fa74be763d 100644 --- a/config/initializers/004-message_bus.rb +++ b/config/initializers/004-message_bus.rb @@ -30,7 +30,8 @@ def setup_message_bus_env(env) extra_headers = { "Access-Control-Allow-Origin" => Discourse.base_url_no_prefix, "Access-Control-Allow-Methods" => "GET, POST", - "Access-Control-Allow-Headers" => "X-SILENCE-LOGGER, X-Shared-Session-Key, Dont-Chunk, Discourse-Present", + "Access-Control-Allow-Headers" => + "X-SILENCE-LOGGER, X-Shared-Session-Key, Dont-Chunk, Discourse-Present", "Access-Control-Max-Age" => "7200", } @@ -40,7 +41,7 @@ def setup_message_bus_env(env) rescue Discourse::InvalidAccess => e # this is bad we need to remove the cookie if e.opts[:delete_cookie].present? - extra_headers['Set-Cookie'] = '_t=del; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT' + extra_headers["Set-Cookie"] = "_t=del; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT" end rescue => e Discourse.warn_exception(e, message: "Unexpected error in Message Bus", env: env) @@ -51,23 +52,22 @@ def setup_message_bus_env(env) raise Discourse::InvalidAccess if !user_id && SiteSetting.login_required is_admin = !!(user && user.admin?) - group_ids = if is_admin - # special rule, admin is allowed access to all groups - Group.pluck(:id) - elsif user - user.groups.pluck('groups.id') - end + group_ids = + if is_admin + # special rule, admin is allowed access to all groups + Group.pluck(:id) + elsif user + user.groups.pluck("groups.id") + end - if env[Auth::DefaultCurrentUserProvider::BAD_TOKEN] - extra_headers['Discourse-Logged-Out'] = '1' - end + extra_headers["Discourse-Logged-Out"] = "1" if env[Auth::DefaultCurrentUserProvider::BAD_TOKEN] hash = { extra_headers: extra_headers, user_id: user_id, group_ids: group_ids, is_admin: is_admin, - site_id: RailsMultisite::ConnectionManagement.current_db + site_id: RailsMultisite::ConnectionManagement.current_db, } env["__mb"] = hash end @@ -99,7 +99,7 @@ MessageBus.on_middleware_error do |env, e| if Discourse::InvalidAccess === e [403, {}, ["Invalid Access"]] elsif RateLimiter::LimitExceeded === e - [429, { 'Retry-After' => e.available_in.to_s }, [e.description]] + [429, { "Retry-After" => e.available_in.to_s }, [e.description]] end end @@ -119,8 +119,9 @@ end MessageBus.backend_instance.max_backlog_size = GlobalSetting.message_bus_max_backlog_size MessageBus.backend_instance.clear_every = GlobalSetting.message_bus_clear_every -MessageBus.long_polling_enabled = GlobalSetting.enable_long_polling.nil? ? true : GlobalSetting.enable_long_polling -MessageBus.long_polling_interval = GlobalSetting.long_polling_interval || 25000 +MessageBus.long_polling_enabled = + GlobalSetting.enable_long_polling.nil? ? true : GlobalSetting.enable_long_polling +MessageBus.long_polling_interval = GlobalSetting.long_polling_interval || 25_000 if Rails.env == "test" || $0 =~ /rake$/ # disable keepalive in testing diff --git a/config/initializers/005-site_settings.rb b/config/initializers/005-site_settings.rb index 9286affcbf0..c05c4709f72 100644 --- a/config/initializers/005-site_settings.rb +++ b/config/initializers/005-site_settings.rb @@ -6,7 +6,7 @@ Discourse.git_version if GlobalSetting.skip_redis? - require 'site_settings/local_process_provider' + require "site_settings/local_process_provider" Rails.cache = Discourse.cache Rails.application.config.to_prepare do SiteSetting.provider = SiteSettings::LocalProcessProvider.new @@ -19,7 +19,8 @@ Rails.application.config.to_prepare do begin SiteSetting.refresh! - unless String === SiteSetting.push_api_secret_key && SiteSetting.push_api_secret_key.length == 32 + unless String === SiteSetting.push_api_secret_key && + SiteSetting.push_api_secret_key.length == 32 SiteSetting.push_api_secret_key = SecureRandom.hex end rescue ActiveRecord::StatementInvalid diff --git a/config/initializers/006-ensure_login_hint.rb b/config/initializers/006-ensure_login_hint.rb index 06debac7564..830ed10d7f4 100644 --- a/config/initializers/006-ensure_login_hint.rb +++ b/config/initializers/006-ensure_login_hint.rb @@ -5,17 +5,15 @@ return if GlobalSetting.skip_db? Rails.application.config.to_prepare do # Some sanity checking so we don't count on an unindexed column on boot begin - if ActiveRecord::Base.connection.table_exists?(:users) && - User.limit(20).count < 20 && - User.where(admin: true).human_users.count == 0 - + if ActiveRecord::Base.connection.table_exists?(:users) && User.limit(20).count < 20 && + User.where(admin: true).human_users.count == 0 notice = if GlobalSetting.developer_emails.blank? "Congratulations, you installed Discourse! Unfortunately, no administrator emails were defined during setup, so finalizing the configuration may be difficult." else emails = GlobalSetting.developer_emails.split(",") if emails.length > 1 - emails = emails[0..-2].join(', ') << " or #{emails[-1]} " + emails = emails[0..-2].join(", ") << " or #{emails[-1]} " else emails = emails[0] end diff --git a/config/initializers/006-mini_profiler.rb b/config/initializers/006-mini_profiler.rb index 96428943525..2972a981106 100644 --- a/config/initializers/006-mini_profiler.rb +++ b/config/initializers/006-mini_profiler.rb @@ -1,12 +1,13 @@ # frozen_string_literal: true # If Mini Profiler is included via gem -if Rails.configuration.respond_to?(:load_mini_profiler) && Rails.configuration.load_mini_profiler && RUBY_ENGINE == "ruby" - require 'rack-mini-profiler' - require 'stackprof' +if Rails.configuration.respond_to?(:load_mini_profiler) && Rails.configuration.load_mini_profiler && + RUBY_ENGINE == "ruby" + require "rack-mini-profiler" + require "stackprof" begin - require 'memory_profiler' + require "memory_profiler" rescue => e STDERR.put "#{e} failed to require mini profiler" end @@ -20,55 +21,56 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config) # raw_connection means results are not namespaced # # namespacing gets complex, cause mini profiler is in the rack chain way before multisite - Rack::MiniProfiler.config.storage_instance = Rack::MiniProfiler::RedisStore.new( - connection: DiscourseRedis.new(nil, namespace: false) - ) + Rack::MiniProfiler.config.storage_instance = + Rack::MiniProfiler::RedisStore.new(connection: DiscourseRedis.new(nil, namespace: false)) Rack::MiniProfiler.config.snapshot_every_n_requests = GlobalSetting.mini_profiler_snapshots_period - Rack::MiniProfiler.config.snapshots_transport_destination_url = GlobalSetting.mini_profiler_snapshots_transport_url - Rack::MiniProfiler.config.snapshots_transport_auth_key = GlobalSetting.mini_profiler_snapshots_transport_auth_key + Rack::MiniProfiler.config.snapshots_transport_destination_url = + GlobalSetting.mini_profiler_snapshots_transport_url + Rack::MiniProfiler.config.snapshots_transport_auth_key = + GlobalSetting.mini_profiler_snapshots_transport_auth_key Rack::MiniProfiler.config.skip_paths = [ - /^\/message-bus/, - /^\/extra-locales/, - /topics\/timings/, + %r{^/message-bus}, + %r{^/extra-locales}, + %r{topics/timings}, /assets/, - /\/user_avatar\//, - /\/letter_avatar\//, - /\/letter_avatar_proxy\//, - /\/highlight-js\//, - /\/svg-sprite\//, + %r{/user_avatar/}, + %r{/letter_avatar/}, + %r{/letter_avatar_proxy/}, + %r{/highlight-js/}, + %r{/svg-sprite/}, /qunit/, - /srv\/status/, + %r{srv/status}, /commits-widget/, - /^\/cdn_asset/, - /^\/logs/, - /^\/site_customizations/, - /^\/uploads/, - /^\/secure-media-uploads/, - /^\/secure-uploads/, - /^\/javascripts\//, - /^\/images\//, - /^\/stylesheets\//, - /^\/favicon\/proxied/, - /^\/theme-javascripts/ + %r{^/cdn_asset}, + %r{^/logs}, + %r{^/site_customizations}, + %r{^/uploads}, + %r{^/secure-media-uploads}, + %r{^/secure-uploads}, + %r{^/javascripts/}, + %r{^/images/}, + %r{^/stylesheets/}, + %r{^/favicon/proxied}, + %r{^/theme-javascripts}, ] # we DO NOT WANT mini-profiler loading on anything but real desktops and laptops # so let's rule out all handheld, tablet, and mobile devices - Rack::MiniProfiler.config.pre_authorize_cb = lambda do |env| - env['HTTP_USER_AGENT'] !~ /iPad|iPhone|Android/ - end + Rack::MiniProfiler.config.pre_authorize_cb = + lambda { |env| env["HTTP_USER_AGENT"] !~ /iPad|iPhone|Android/ } # without a user provider our results will use the ip address for namespacing # with a load balancer in front this becomes really bad as some results can # be stored associated with ip1 as the user and retrieved using ip2 causing 404s - Rack::MiniProfiler.config.user_provider = lambda do |env| - request = Rack::Request.new(env) - id = request.cookies["_t"] || request.ip || "unknown" - id = id.to_s - # some security, lets not have these tokens floating about - Digest::MD5.hexdigest(id) - end + Rack::MiniProfiler.config.user_provider = + lambda do |env| + request = Rack::Request.new(env) + id = request.cookies["_t"] || request.ip || "unknown" + id = id.to_s + # some security, lets not have these tokens floating about + Digest::MD5.hexdigest(id) + end # Cookie path should be set to the base path so Discourse's session cookie path # does not get clobbered. @@ -77,15 +79,15 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config) Rack::MiniProfiler.config.position = "right" Rack::MiniProfiler.config.backtrace_ignores ||= [] - Rack::MiniProfiler.config.backtrace_ignores << /lib\/rack\/message_bus.rb/ - Rack::MiniProfiler.config.backtrace_ignores << /config\/initializers\/silence_logger/ - Rack::MiniProfiler.config.backtrace_ignores << /config\/initializers\/quiet_logger/ + Rack::MiniProfiler.config.backtrace_ignores << %r{lib/rack/message_bus.rb} + Rack::MiniProfiler.config.backtrace_ignores << %r{config/initializers/silence_logger} + Rack::MiniProfiler.config.backtrace_ignores << %r{config/initializers/quiet_logger} - Rack::MiniProfiler.config.backtrace_includes = [/^\/?(app|config|lib|test|plugins)/] + Rack::MiniProfiler.config.backtrace_includes = [%r{^/?(app|config|lib|test|plugins)}] Rack::MiniProfiler.config.max_traces_to_show = 100 if Rails.env.development? - Rack::MiniProfiler.counter_method(Redis::Client, :call) { 'redis' } + Rack::MiniProfiler.counter_method(Redis::Client, :call) { "redis" } # Rack::MiniProfiler.counter_method(ActiveRecord::QueryMethods, 'build_arel') # Rack::MiniProfiler.counter_method(Array, 'uniq') # require "#{Rails.root}/vendor/backports/notification" @@ -115,10 +117,11 @@ if defined?(Rack::MiniProfiler) && defined?(Rack::MiniProfiler::Config) end if ENV["PRINT_EXCEPTIONS"] - trace = TracePoint.new(:raise) do |tp| - puts tp.raised_exception - puts tp.raised_exception.backtrace.join("\n") - puts - end + trace = + TracePoint.new(:raise) do |tp| + puts tp.raised_exception + puts tp.raised_exception.backtrace.join("\n") + puts + end trace.enable end diff --git a/config/initializers/008-rack-cors.rb b/config/initializers/008-rack-cors.rb index b03fb2568fb..d499a38cc8d 100644 --- a/config/initializers/008-rack-cors.rb +++ b/config/initializers/008-rack-cors.rb @@ -6,18 +6,17 @@ class Discourse::Cors def initialize(app, options = nil) @app = app if GlobalSetting.enable_cors && GlobalSetting.cors_origin.present? - @global_origins = GlobalSetting.cors_origin.split(',').map { |x| x.strip.chomp('/') } + @global_origins = GlobalSetting.cors_origin.split(",").map { |x| x.strip.chomp("/") } end end def call(env) - cors_origins = @global_origins || [] - cors_origins += SiteSetting.cors_origins.split('|') if SiteSetting.cors_origins.present? + cors_origins += SiteSetting.cors_origins.split("|") if SiteSetting.cors_origins.present? cors_origins = cors_origins.presence - if env['REQUEST_METHOD'] == ('OPTIONS') && env['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] - return [200, Discourse::Cors.apply_headers(cors_origins, env, {}), []] + if env["REQUEST_METHOD"] == ("OPTIONS") && env["HTTP_ACCESS_CONTROL_REQUEST_METHOD"] + return 200, Discourse::Cors.apply_headers(cors_origins, env, {}), [] end env[Discourse::Cors::ORIGINS_ENV] = cors_origins if cors_origins @@ -31,21 +30,24 @@ class Discourse::Cors end def self.apply_headers(cors_origins, env, headers) - request_method = env['REQUEST_METHOD'] + request_method = env["REQUEST_METHOD"] - if env['REQUEST_PATH'] =~ /\/(javascripts|assets)\// && Discourse.is_cdn_request?(env, request_method) + if env["REQUEST_PATH"] =~ %r{/(javascripts|assets)/} && + Discourse.is_cdn_request?(env, request_method) Discourse.apply_cdn_headers(headers) elsif cors_origins origin = nil - if origin = env['HTTP_ORIGIN'] + if origin = env["HTTP_ORIGIN"] origin = nil unless cors_origins.include?(origin) end - headers['Access-Control-Allow-Origin'] = origin || cors_origins[0] - headers['Access-Control-Allow-Headers'] = 'Content-Type, Cache-Control, X-Requested-With, X-CSRF-Token, Discourse-Present, User-Api-Key, User-Api-Client-Id, Authorization' - headers['Access-Control-Allow-Credentials'] = 'true' - headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS, DELETE' - headers['Access-Control-Max-Age'] = '7200' + headers["Access-Control-Allow-Origin"] = origin || cors_origins[0] + headers[ + "Access-Control-Allow-Headers" + ] = "Content-Type, Cache-Control, X-Requested-With, X-CSRF-Token, Discourse-Present, User-Api-Key, User-Api-Client-Id, Authorization" + headers["Access-Control-Allow-Credentials"] = "true" + headers["Access-Control-Allow-Methods"] = "POST, PUT, GET, OPTIONS, DELETE" + headers["Access-Control-Max-Age"] = "7200" end headers diff --git a/config/initializers/012-web_hook_events.rb b/config/initializers/012-web_hook_events.rb index fa08cd3aea0..520f4ecd6fc 100644 --- a/config/initializers/012-web_hook_events.rb +++ b/config/initializers/012-web_hook_events.rb @@ -1,11 +1,7 @@ # frozen_string_literal: true -%i( - topic_recovered -).each do |event| - DiscourseEvent.on(event) do |topic, _| - WebHook.enqueue_topic_hooks(event, topic) - end +%i[topic_recovered].each do |event| + DiscourseEvent.on(event) { |topic, _| WebHook.enqueue_topic_hooks(event, topic) } end DiscourseEvent.on(:topic_status_updated) do |topic, status| @@ -16,18 +12,12 @@ DiscourseEvent.on(:topic_created) do |topic, _, _| WebHook.enqueue_topic_hooks(:topic_created, topic) end -%i( - post_created - post_recovered -).each do |event| - DiscourseEvent.on(event) do |post, _, _| - WebHook.enqueue_post_hooks(event, post) - end +%i[post_created post_recovered].each do |event| + DiscourseEvent.on(event) { |post, _, _| WebHook.enqueue_post_hooks(event, post) } end DiscourseEvent.on(:post_edited) do |post, topic_changed| unless post.topic&.trashed? - # if we are editing the OP and the topic is changed, do not send # the post_edited event -- this event is sent separately because # when we update the OP in the UI we send two API calls in this order: @@ -42,49 +32,30 @@ DiscourseEvent.on(:post_edited) do |post, topic_changed| end end -%i( +%i[ user_logged_out user_created user_logged_in user_approved user_updated user_confirmed_email -).each do |event| - DiscourseEvent.on(event) do |user| - WebHook.enqueue_object_hooks(:user, user, event) - end +].each do |event| + DiscourseEvent.on(event) { |user| WebHook.enqueue_object_hooks(:user, user, event) } end -%i( - group_created - group_updated -).each do |event| - DiscourseEvent.on(event) do |group| - WebHook.enqueue_object_hooks(:group, group, event) - end +%i[group_created group_updated].each do |event| + DiscourseEvent.on(event) { |group| WebHook.enqueue_object_hooks(:group, group, event) } end -%i( - category_created - category_updated -).each do |event| - DiscourseEvent.on(event) do |category| - WebHook.enqueue_object_hooks(:category, category, event) - end +%i[category_created category_updated].each do |event| + DiscourseEvent.on(event) { |category| WebHook.enqueue_object_hooks(:category, category, event) } end -%i( - tag_created - tag_updated -).each do |event| - DiscourseEvent.on(event) do |tag| - WebHook.enqueue_object_hooks(:tag, tag, event, TagSerializer) - end +%i[tag_created tag_updated].each do |event| + DiscourseEvent.on(event) { |tag| WebHook.enqueue_object_hooks(:tag, tag, event, TagSerializer) } end -%i( - user_badge_granted -).each do |event| +%i[user_badge_granted].each do |event| # user_badge_revoked DiscourseEvent.on(event) do |badge, user_id| ub = UserBadge.find_by(badge: badge, user_id: user_id) @@ -92,30 +63,43 @@ end end end -%i( - reviewable_created - reviewable_score_updated -).each do |event| +%i[reviewable_created reviewable_score_updated].each do |event| DiscourseEvent.on(event) do |reviewable| WebHook.enqueue_object_hooks(:reviewable, reviewable, event, reviewable.serializer) end end DiscourseEvent.on(:reviewable_transitioned_to) do |status, reviewable| - WebHook.enqueue_object_hooks(:reviewable, reviewable, :reviewable_transitioned_to, reviewable.serializer) + WebHook.enqueue_object_hooks( + :reviewable, + reviewable, + :reviewable_transitioned_to, + reviewable.serializer, + ) end DiscourseEvent.on(:notification_created) do |notification| - WebHook.enqueue_object_hooks(:notification, notification, :notification_created, NotificationSerializer) + WebHook.enqueue_object_hooks( + :notification, + notification, + :notification_created, + NotificationSerializer, + ) end DiscourseEvent.on(:user_added_to_group) do |user, group, options| group_user = GroupUser.find_by(user: user, group: group) - WebHook.enqueue_object_hooks(:group_user, group_user, :user_added_to_group, WebHookGroupUserSerializer) + WebHook.enqueue_object_hooks( + :group_user, + group_user, + :user_added_to_group, + WebHookGroupUserSerializer, + ) end DiscourseEvent.on(:user_promoted) do |payload| - user_id, new_trust_level, old_trust_level = payload.values_at(:user_id, :new_trust_level, :old_trust_level) + user_id, new_trust_level, old_trust_level = + payload.values_at(:user_id, :new_trust_level, :old_trust_level) next if new_trust_level < old_trust_level @@ -130,8 +114,13 @@ DiscourseEvent.on(:like_created) do |post_action| category_id = topic&.category_id tag_ids = topic&.tag_ids - WebHook.enqueue_object_hooks(:like, - post_action, :post_liked, WebHookLikeSerializer, - group_ids: group_ids, category_id: category_id, tag_ids: tag_ids + WebHook.enqueue_object_hooks( + :like, + post_action, + :post_liked, + WebHookLikeSerializer, + group_ids: group_ids, + category_id: category_id, + tag_ids: tag_ids, ) end diff --git a/config/initializers/013-excon_defaults.rb b/config/initializers/013-excon_defaults.rb index 40389051db3..302dbda4995 100644 --- a/config/initializers/013-excon_defaults.rb +++ b/config/initializers/013-excon_defaults.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true -require 'excon' +require "excon" Excon::DEFAULTS[:omit_default_port] = true diff --git a/config/initializers/014-track-setting-changes.rb b/config/initializers/014-track-setting-changes.rb index ae4705bb21c..410b8091d70 100644 --- a/config/initializers/014-track-setting-changes.rb +++ b/config/initializers/014-track-setting-changes.rb @@ -6,10 +6,11 @@ DiscourseEvent.on(:site_setting_changed) do |name, old_value, new_value| # Enabling `must_approve_users` on an existing site is odd, so we assume that the # existing users are approved. if name == :must_approve_users && new_value == true - - User.where(approved: false) + User + .where(approved: false) .joins("LEFT JOIN reviewables r ON r.target_id = users.id") - .where(r: { id: nil }).update_all(approved: true) + .where(r: { id: nil }) + .update_all(approved: true) end if name == :emoji_set @@ -19,31 +20,28 @@ DiscourseEvent.on(:site_setting_changed) do |name, old_value, new_value| after = "/images/emoji/#{new_value}/" Scheduler::Defer.later("Fix Emoji Links") do - DB.exec("UPDATE posts SET cooked = REPLACE(cooked, :before, :after) WHERE cooked LIKE :like", + DB.exec( + "UPDATE posts SET cooked = REPLACE(cooked, :before, :after) WHERE cooked LIKE :like", before: before, after: after, - like: "%#{before}%" + like: "%#{before}%", ) end end - Stylesheet::Manager.clear_color_scheme_cache! if [:base_font, :heading_font].include?(name) + Stylesheet::Manager.clear_color_scheme_cache! if %i[base_font heading_font].include?(name) - Report.clear_cache(:storage_stats) if [:backup_location, :s3_backup_bucket].include?(name) + Report.clear_cache(:storage_stats) if %i[backup_location s3_backup_bucket].include?(name) if name == :slug_generation_method - Scheduler::Defer.later("Null topic slug") do - Topic.update_all(slug: nil) - end + Scheduler::Defer.later("Null topic slug") { Topic.update_all(slug: nil) } end - Jobs.enqueue(:update_s3_inventory) if [:enable_s3_inventory, :s3_upload_bucket].include?(name) + Jobs.enqueue(:update_s3_inventory) if %i[enable_s3_inventory s3_upload_bucket].include?(name) SvgSprite.expire_cache if name.to_s.include?("_icon") - if SiteIconManager::WATCHED_SETTINGS.include?(name) - SiteIconManager.ensure_optimized! - end + SiteIconManager.ensure_optimized! if SiteIconManager::WATCHED_SETTINGS.include?(name) # Make sure medium and high priority thresholds were calculated. if name == :reviewable_low_priority_threshold && Reviewable.min_score_for_priority(:medium) > 0 diff --git a/config/initializers/099-anon-cache.rb b/config/initializers/099-anon-cache.rb index 32bca432060..ee5e240d93a 100644 --- a/config/initializers/099-anon-cache.rb +++ b/config/initializers/099-anon-cache.rb @@ -9,7 +9,7 @@ enabled = Rails.env.production? end -if !ENV['DISCOURSE_DISABLE_ANON_CACHE'] && enabled +if !ENV["DISCOURSE_DISABLE_ANON_CACHE"] && enabled # in an ideal world this is position 0, but mobile detection uses ... session and request and params Rails.configuration.middleware.insert_after ActionDispatch::Flash, Middleware::AnonymousCache end diff --git a/config/initializers/099-drain_pool.rb b/config/initializers/099-drain_pool.rb index e69de29bb2d..8b137891791 100644 --- a/config/initializers/099-drain_pool.rb +++ b/config/initializers/099-drain_pool.rb @@ -0,0 +1 @@ + diff --git a/config/initializers/100-i18n.rb b/config/initializers/100-i18n.rb index 4165bd75b60..473e2f49331 100644 --- a/config/initializers/100-i18n.rb +++ b/config/initializers/100-i18n.rb @@ -2,8 +2,8 @@ # order: after 02-freedom_patches.rb -require 'i18n/backend/discourse_i18n' -require 'i18n/backend/fallback_locale_list' +require "i18n/backend/discourse_i18n" +require "i18n/backend/fallback_locale_list" # Requires the `translate_accelerator.rb` freedom patch to be loaded Rails.application.reloader.to_prepare do @@ -11,7 +11,7 @@ Rails.application.reloader.to_prepare do I18n.fallbacks = I18n::Backend::FallbackLocaleList.new I18n.config.missing_interpolation_argument_handler = proc { throw(:exception) } I18n.reload! - I18n.init_accelerator!(overrides_enabled: ENV['DISABLE_TRANSLATION_OVERRIDES'] != '1') + I18n.init_accelerator!(overrides_enabled: ENV["DISABLE_TRANSLATION_OVERRIDES"] != "1") unless Rails.env.test? MessageBus.subscribe("/i18n-flush") do diff --git a/config/initializers/100-logster.rb b/config/initializers/100-logster.rb index 5047a01a638..8bbbc2a7a1c 100644 --- a/config/initializers/100-logster.rb +++ b/config/initializers/100-logster.rb @@ -2,9 +2,7 @@ if GlobalSetting.skip_redis? Rails.application.reloader.to_prepare do - if Rails.logger.respond_to? :chained - Rails.logger = Rails.logger.chained.first - end + Rails.logger = Rails.logger.chained.first if Rails.logger.respond_to? :chained end return end @@ -39,9 +37,7 @@ if Rails.env.production? # https://github.com/rails/rails/blob/f2caed1e/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb#L39-L42 /^ActionController::RoutingError \(No route matches/, /^ActionDispatch::Http::MimeNegotiation::InvalidType/, - /^PG::Error: ERROR:\s+duplicate key/, - /^ActionController::UnknownFormat/, /^ActionController::UnknownHttpMethod/, /^AbstractController::ActionNotFound/, @@ -51,29 +47,21 @@ if Rails.env.production? # Column: # /(?m).*?Line: (?:\D|0).*?Column: (?:\D|0)/, - # suppress empty JS errors (covers MSIE 9, etc) /^(Syntax|Script) error.*Line: (0|1)\b/m, - # CSRF errors are not providing enough data # suppress unconditionally for now /^Can't verify CSRF token authenticity.$/, - # Yandex bot triggers this JS error a lot /^Uncaught ReferenceError: I18n is not defined/, - # related to browser plugins somehow, we don't care /Error calling method on NPObject/, - # 404s can be dealt with elsewhere /^ActiveRecord::RecordNotFound/, - # bad asset requested, no need to log /^ActionController::BadRequest/, - # we can't do anything about invalid parameters /Rack::QueryParser::InvalidParameterError/, - # we handle this cleanly in the message bus middleware # no point logging to logster /RateLimiter::LimitExceeded.*/m, @@ -98,33 +86,37 @@ store.redis_raw_connection = redis.without_namespace severities = [Logger::WARN, Logger::ERROR, Logger::FATAL, Logger::UNKNOWN] RailsMultisite::ConnectionManagement.each_connection do - error_rate_per_minute = SiteSetting.alert_admins_if_errors_per_minute rescue 0 + error_rate_per_minute = + begin + SiteSetting.alert_admins_if_errors_per_minute + rescue StandardError + 0 + end if (error_rate_per_minute || 0) > 0 store.register_rate_limit_per_minute(severities, error_rate_per_minute) do |rate| - MessageBus.publish("/logs_error_rate_exceeded", - { - rate: rate, - duration: 'minute', - publish_at: Time.current.to_i - }, - group_ids: [Group::AUTO_GROUPS[:admins]] - ) + MessageBus.publish( + "/logs_error_rate_exceeded", + { rate: rate, duration: "minute", publish_at: Time.current.to_i }, + group_ids: [Group::AUTO_GROUPS[:admins]], + ) end end - error_rate_per_hour = SiteSetting.alert_admins_if_errors_per_hour rescue 0 + error_rate_per_hour = + begin + SiteSetting.alert_admins_if_errors_per_hour + rescue StandardError + 0 + end if (error_rate_per_hour || 0) > 0 store.register_rate_limit_per_hour(severities, error_rate_per_hour) do |rate| - MessageBus.publish("/logs_error_rate_exceeded", - { - rate: rate, - duration: 'hour', - publish_at: Time.current.to_i, - }, - group_ids: [Group::AUTO_GROUPS[:admins]] - ) + MessageBus.publish( + "/logs_error_rate_exceeded", + { rate: rate, duration: "hour", publish_at: Time.current.to_i }, + group_ids: [Group::AUTO_GROUPS[:admins]], + ) end end end @@ -137,13 +129,13 @@ if Rails.configuration.multisite end Logster.config.project_directories = [ - { path: Rails.root.to_s, url: "https://github.com/discourse/discourse", main_app: true } + { path: Rails.root.to_s, url: "https://github.com/discourse/discourse", main_app: true }, ] Discourse.plugins.each do |plugin| next if !plugin.metadata.url Logster.config.project_directories << { path: "#{Rails.root.to_s}/plugins/#{plugin.directory_name}", - url: plugin.metadata.url + url: plugin.metadata.url, } end diff --git a/config/initializers/100-onebox_options.rb b/config/initializers/100-onebox_options.rb index 3d2e4a2f055..70f0a468e8f 100644 --- a/config/initializers/100-onebox_options.rb +++ b/config/initializers/100-onebox_options.rb @@ -6,13 +6,13 @@ Rails.application.config.to_prepare do twitter_client: TwitterApi, redirect_limit: 3, user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}", - allowed_ports: [80, 443, SiteSetting.port.to_i] + allowed_ports: [80, 443, SiteSetting.port.to_i], } else Onebox.options = { twitter_client: TwitterApi, redirect_limit: 3, - user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}" + user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}", } end end diff --git a/config/initializers/100-push-notifications.rb b/config/initializers/100-push-notifications.rb index 056e4bb56e7..1261c465c6a 100644 --- a/config/initializers/100-push-notifications.rb +++ b/config/initializers/100-push-notifications.rb @@ -3,13 +3,11 @@ return if GlobalSetting.skip_db? Rails.application.config.to_prepare do - require 'web-push' + require "web-push" def generate_vapid_key? - SiteSetting.vapid_public_key.blank? || - SiteSetting.vapid_private_key.blank? || - SiteSetting.vapid_public_key_bytes.blank? || - SiteSetting.vapid_base_url != Discourse.base_url + SiteSetting.vapid_public_key.blank? || SiteSetting.vapid_private_key.blank? || + SiteSetting.vapid_public_key_bytes.blank? || SiteSetting.vapid_base_url != Discourse.base_url end SiteSetting.vapid_base_url = Discourse.base_url if SiteSetting.vapid_base_url.blank? @@ -19,15 +17,12 @@ Rails.application.config.to_prepare do SiteSetting.vapid_public_key = vapid_key.public_key SiteSetting.vapid_private_key = vapid_key.private_key - SiteSetting.vapid_public_key_bytes = Base64.urlsafe_decode64(SiteSetting.vapid_public_key).bytes.join("|") + SiteSetting.vapid_public_key_bytes = + Base64.urlsafe_decode64(SiteSetting.vapid_public_key).bytes.join("|") SiteSetting.vapid_base_url = Discourse.base_url - if ActiveRecord::Base.connection.table_exists?(:push_subscriptions) - PushSubscription.delete_all - end + PushSubscription.delete_all if ActiveRecord::Base.connection.table_exists?(:push_subscriptions) end - DiscourseEvent.on(:user_logged_out) do |user| - PushNotificationPusher.clear_subscriptions(user) - end + DiscourseEvent.on(:user_logged_out) { |user| PushNotificationPusher.clear_subscriptions(user) } end diff --git a/config/initializers/100-quiet_logger.rb b/config/initializers/100-quiet_logger.rb index f73826f108f..ef156499861 100644 --- a/config/initializers/100-quiet_logger.rb +++ b/config/initializers/100-quiet_logger.rb @@ -1,30 +1,23 @@ # frozen_string_literal: true -Rails.application.config.assets.configure do |env| - env.logger = Logger.new('/dev/null') -end +Rails.application.config.assets.configure { |env| env.logger = Logger.new("/dev/null") } module DiscourseRackQuietAssetsLogger def call(env) override = false - if (env['PATH_INFO'].index("/assets/") == 0) || - (env['PATH_INFO'].index("/stylesheets") == 0) || - (env['PATH_INFO'].index("/svg-sprite") == 0) || - (env['PATH_INFO'].index("/manifest") == 0) || - (env['PATH_INFO'].index("/service-worker") == 0) || - (env['PATH_INFO'].index("mini-profiler-resources") == 0) || - (env['PATH_INFO'].index("/srv/status") == 0) + if (env["PATH_INFO"].index("/assets/") == 0) || (env["PATH_INFO"].index("/stylesheets") == 0) || + (env["PATH_INFO"].index("/svg-sprite") == 0) || + (env["PATH_INFO"].index("/manifest") == 0) || + (env["PATH_INFO"].index("/service-worker") == 0) || + (env["PATH_INFO"].index("mini-profiler-resources") == 0) || + (env["PATH_INFO"].index("/srv/status") == 0) if ::Logster::Logger === Rails.logger override = true Rails.logger.override_level = Logger::ERROR end end - super(env).tap do - if override - Rails.logger.override_level = nil - end - end + super(env).tap { Rails.logger.override_level = nil if override } end end diff --git a/config/initializers/100-session_store.rb b/config/initializers/100-session_store.rb index b2ce5d47b46..b06e28dd63d 100644 --- a/config/initializers/100-session_store.rb +++ b/config/initializers/100-session_store.rb @@ -4,8 +4,15 @@ Rails.application.config.session_store( :discourse_cookie_store, - key: '_forum_session', - path: (Rails.application.config.relative_url_root.nil?) ? '/' : Rails.application.config.relative_url_root + key: "_forum_session", + path: + ( + if (Rails.application.config.relative_url_root.nil?) + "/" + else + Rails.application.config.relative_url_root + end + ), ) Rails.application.config.to_prepare do diff --git a/config/initializers/100-sidekiq.rb b/config/initializers/100-sidekiq.rb index 79422e0b79e..3ce1927722f 100644 --- a/config/initializers/100-sidekiq.rb +++ b/config/initializers/100-sidekiq.rb @@ -1,22 +1,17 @@ # frozen_string_literal: true require "sidekiq/pausable" -require 'sidekiq_logster_reporter' +require "sidekiq_logster_reporter" -Sidekiq.configure_client do |config| - config.redis = Discourse.sidekiq_redis_config -end +Sidekiq.configure_client { |config| config.redis = Discourse.sidekiq_redis_config } Sidekiq.configure_server do |config| config.redis = Discourse.sidekiq_redis_config - config.server_middleware do |chain| - chain.add Sidekiq::Pausable - end + config.server_middleware { |chain| chain.add Sidekiq::Pausable } end if Sidekiq.server? - module Sidekiq class CLI private @@ -34,13 +29,17 @@ if Sidekiq.server? # warm up AR RailsMultisite::ConnectionManagement.safe_each_connection do (ActiveRecord::Base.connection.tables - %w[schema_migrations versions]).each do |table| - table.classify.constantize.first rescue nil + begin + table.classify.constantize.first + rescue StandardError + nil + end end end scheduler_hostname = ENV["UNICORN_SCHEDULER_HOSTNAME"] - if !scheduler_hostname || scheduler_hostname.split(',').include?(Discourse.os_hostname) + if !scheduler_hostname || scheduler_hostname.split(",").include?(Discourse.os_hostname) begin MiniScheduler.start(workers: GlobalSetting.mini_scheduler_workers) rescue MiniScheduler::DistributedMutex::Timeout @@ -57,9 +56,11 @@ else # Instead, this patch adds a dedicated logger instance and patches # the #add method to forward messages to Rails.logger. Sidekiq.logger = Logger.new(nil) - Sidekiq.logger.define_singleton_method(:add) do |severity, message = nil, progname = nil, &blk| - Rails.logger.add(severity, message, progname, &blk) - end + Sidekiq + .logger + .define_singleton_method(:add) do |severity, message = nil, progname = nil, &blk| + Rails.logger.add(severity, message, progname, &blk) + end end Sidekiq.error_handlers.clear @@ -69,28 +70,20 @@ Sidekiq.strict_args! Rails.application.config.to_prepare do # Ensure that scheduled jobs are loaded before mini_scheduler is configured. - if Rails.env.development? - Dir.glob("#{Rails.root}/app/jobs/scheduled/*.rb") do |f| - require(f) - end - end + Dir.glob("#{Rails.root}/app/jobs/scheduled/*.rb") { |f| require(f) } if Rails.env.development? MiniScheduler.configure do |config| config.redis = Discourse.redis - config.job_exception_handler do |ex, context| - Discourse.handle_job_exception(ex, context) - end + config.job_exception_handler { |ex, context| Discourse.handle_job_exception(ex, context) } - config.job_ran do |stat| - DiscourseEvent.trigger(:scheduled_job_ran, stat) - end + config.job_ran { |stat| DiscourseEvent.trigger(:scheduled_job_ran, stat) } config.skip_schedule { Sidekiq.paused? } config.before_sidekiq_web_request do RailsMultisite::ConnectionManagement.establish_connection( - db: RailsMultisite::ConnectionManagement::DEFAULT + db: RailsMultisite::ConnectionManagement::DEFAULT, ) end end diff --git a/config/initializers/100-silence_logger.rb b/config/initializers/100-silence_logger.rb index 3a900d24e37..e01b29816f7 100644 --- a/config/initializers/100-silence_logger.rb +++ b/config/initializers/100-silence_logger.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true class SilenceLogger < Rails::Rack::Logger - PATH_INFO = 'PATH_INFO' - HTTP_X_SILENCE_LOGGER = 'HTTP_X_SILENCE_LOGGER' + PATH_INFO = "PATH_INFO" + HTTP_X_SILENCE_LOGGER = "HTTP_X_SILENCE_LOGGER" def initialize(app, opts = {}) @app = app @@ -17,11 +17,9 @@ class SilenceLogger < Rails::Rack::Logger path_info = env[PATH_INFO] override = false - if env[HTTP_X_SILENCE_LOGGER] || - @opts[:silenced].include?(path_info) || - path_info.start_with?('/logs') || - path_info.start_with?('/user_avatar') || - path_info.start_with?('/letter_avatar') + if env[HTTP_X_SILENCE_LOGGER] || @opts[:silenced].include?(path_info) || + path_info.start_with?("/logs") || path_info.start_with?("/user_avatar") || + path_info.start_with?("/letter_avatar") if ::Logster::Logger === Rails.logger override = true Rails.logger.override_level = Logger::WARN @@ -35,10 +33,10 @@ class SilenceLogger < Rails::Rack::Logger end end -silenced = [ - "/mini-profiler-resources/results", - "/mini-profiler-resources/includes.js", - "/mini-profiler-resources/includes.css", - "/mini-profiler-resources/jquery.tmpl.js" +silenced = %w[ + /mini-profiler-resources/results + /mini-profiler-resources/includes.js + /mini-profiler-resources/includes.css + /mini-profiler-resources/jquery.tmpl.js ] Rails.configuration.middleware.swap Rails::Rack::Logger, SilenceLogger, silenced: silenced diff --git a/config/initializers/100-verify_config.rb b/config/initializers/100-verify_config.rb index c2e7c63e669..5d779b6aac6 100644 --- a/config/initializers/100-verify_config.rb +++ b/config/initializers/100-verify_config.rb @@ -3,8 +3,7 @@ # Check that the app is configured correctly. Raise some helpful errors if something is wrong. if defined?(Rails::Server) && Rails.env.production? # Only run these checks when starting up a production server - - if ['localhost', 'production.localhost'].include?(Discourse.current_hostname) + if %w[localhost production.localhost].include?(Discourse.current_hostname) puts <<~TEXT Discourse.current_hostname = '#{Discourse.current_hostname}' @@ -18,7 +17,7 @@ if defined?(Rails::Server) && Rails.env.production? # Only run these checks when raise "Invalid host_names in database.yml" end - if !Dir.glob(File.join(Rails.root, 'public', 'assets', 'application*.js')).present? + if !Dir.glob(File.join(Rails.root, "public", "assets", "application*.js")).present? puts <<~TEXT Assets have not been precompiled. Please run the following command diff --git a/config/initializers/100-wrap_parameters.rb b/config/initializers/100-wrap_parameters.rb index 85b2d840618..26c901dedec 100644 --- a/config/initializers/100-wrap_parameters.rb +++ b/config/initializers/100-wrap_parameters.rb @@ -6,11 +6,7 @@ # is enabled by default. # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. -ActiveSupport.on_load(:action_controller) do - wrap_parameters format: [:json] -end +ActiveSupport.on_load(:action_controller) { wrap_parameters format: [:json] } # Disable root element in JSON by default. -ActiveSupport.on_load(:active_record) do - self.include_root_in_json = false -end +ActiveSupport.on_load(:active_record) { self.include_root_in_json = false } diff --git a/config/initializers/101-lograge.rb b/config/initializers/101-lograge.rb index 311c64c7533..3baac8b4b46 100644 --- a/config/initializers/101-lograge.rb +++ b/config/initializers/101-lograge.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true Rails.application.config.to_prepare do - if (Rails.env.production? && SiteSetting.logging_provider == 'lograge') || (ENV["ENABLE_LOGRAGE"] == "1") - require 'lograge' + if (Rails.env.production? && SiteSetting.logging_provider == "lograge") || + (ENV["ENABLE_LOGRAGE"] == "1") + require "lograge" if Rails.configuration.multisite Rails.logger.formatter = ActiveSupport::Logger::SimpleFormatter.new @@ -11,20 +12,20 @@ Rails.application.config.to_prepare do Rails.application.configure do config.lograge.enabled = true - Lograge.ignore(lambda do |event| - # this is our hijack magic status, - # no point logging this cause we log again - # direct from hijack - event.payload[:status] == 418 - end) + Lograge.ignore( + lambda do |event| + # this is our hijack magic status, + # no point logging this cause we log again + # direct from hijack + event.payload[:status] == 418 + end, + ) config.lograge.custom_payload do |controller| begin username = begin - if controller.respond_to?(:current_user) - controller.current_user&.username - end + controller.current_user&.username if controller.respond_to?(:current_user) rescue Discourse::InvalidAccess, Discourse::ReadOnly, ActiveRecord::ReadOnlyError nil end @@ -36,78 +37,77 @@ Rails.application.config.to_prepare do nil end - { - ip: ip, - username: username - } + { ip: ip, username: username } rescue => e - Rails.logger.warn("Failed to append custom payload: #{e.message}\n#{e.backtrace.join("\n")}") + Rails.logger.warn( + "Failed to append custom payload: #{e.message}\n#{e.backtrace.join("\n")}", + ) {} end end - config.lograge.custom_options = lambda do |event| - begin - exceptions = %w(controller action format id) + config.lograge.custom_options = + lambda do |event| + begin + exceptions = %w[controller action format id] - params = event.payload[:params].except(*exceptions) + params = event.payload[:params].except(*exceptions) - if (file = params[:file]) && file.respond_to?(:headers) - params[:file] = file.headers + if (file = params[:file]) && file.respond_to?(:headers) + params[:file] = file.headers + end + + if (files = params[:files]) && files.respond_to?(:map) + params[:files] = files.map { |f| f.respond_to?(:headers) ? f.headers : f } + end + + output = { + params: params.to_query, + database: RailsMultisite::ConnectionManagement.current_db, + } + + if data = (Thread.current[:_method_profiler] || event.payload[:timings]) + sql = data[:sql] + + if sql + output[:db] = sql[:duration] * 1000 + output[:db_calls] = sql[:calls] + end + + redis = data[:redis] + + if redis + output[:redis] = redis[:duration] * 1000 + output[:redis_calls] = redis[:calls] + end + + net = data[:net] + + if net + output[:net] = net[:duration] * 1000 + output[:net_calls] = net[:calls] + end + end + + output + rescue RateLimiter::LimitExceeded + # no idea who this is, but they are limited + {} + rescue => e + Rails.logger.warn( + "Failed to append custom options: #{e.message}\n#{e.backtrace.join("\n")}", + ) + {} end - - if (files = params[:files]) && files.respond_to?(:map) - params[:files] = files.map do |f| - f.respond_to?(:headers) ? f.headers : f - end - end - - output = { - params: params.to_query, - database: RailsMultisite::ConnectionManagement.current_db, - } - - if data = (Thread.current[:_method_profiler] || event.payload[:timings]) - sql = data[:sql] - - if sql - output[:db] = sql[:duration] * 1000 - output[:db_calls] = sql[:calls] - end - - redis = data[:redis] - - if redis - output[:redis] = redis[:duration] * 1000 - output[:redis_calls] = redis[:calls] - end - - net = data[:net] - - if net - output[:net] = net[:duration] * 1000 - output[:net_calls] = net[:calls] - end - end - - output - rescue RateLimiter::LimitExceeded - # no idea who this is, but they are limited - {} - rescue => e - Rails.logger.warn("Failed to append custom options: #{e.message}\n#{e.backtrace.join("\n")}") - {} end - end if ENV["LOGSTASH_URI"] config.lograge.formatter = Lograge::Formatters::Logstash.new - require 'discourse_logstash_logger' + require "discourse_logstash_logger" - config.lograge.logger = DiscourseLogstashLogger.logger( - uri: ENV['LOGSTASH_URI'], type: :rails - ) + config.lograge.logger = + DiscourseLogstashLogger.logger(uri: ENV["LOGSTASH_URI"], type: :rails) # Remove ActiveSupport::Logger from the chain and replace with Lograge's # logger diff --git a/config/initializers/200-first_middlewares.rb b/config/initializers/200-first_middlewares.rb index 4617bd519d9..ea011a6f8af 100644 --- a/config/initializers/200-first_middlewares.rb +++ b/config/initializers/200-first_middlewares.rb @@ -11,13 +11,11 @@ Rails.configuration.middleware.unshift(MessageBus::Rack::Middleware) # no reason to track this in development, that is 300+ redis calls saved per # page view (we serve all assets out of thin in development) -if Rails.env != 'development' || ENV['TRACK_REQUESTS'] - require 'middleware/request_tracker' +if Rails.env != "development" || ENV["TRACK_REQUESTS"] + require "middleware/request_tracker" Rails.configuration.middleware.unshift Middleware::RequestTracker - if GlobalSetting.enable_performance_http_headers - MethodProfiler.ensure_discourse_instrumentation! - end + MethodProfiler.ensure_discourse_instrumentation! if GlobalSetting.enable_performance_http_headers end if Rails.env.test? @@ -30,23 +28,27 @@ if Rails.env.test? super(env) end end - Rails.configuration.middleware.unshift TestMultisiteMiddleware, RailsMultisite::DiscoursePatches.config + Rails.configuration.middleware.unshift TestMultisiteMiddleware, + RailsMultisite::DiscoursePatches.config elsif Rails.configuration.multisite assets_hostnames = GlobalSetting.cdn_hostnames if assets_hostnames.empty? - assets_hostnames = - Discourse::Application.config.database_configuration[Rails.env]["host_names"] + assets_hostnames = Discourse::Application.config.database_configuration[Rails.env]["host_names"] end RailsMultisite::ConnectionManagement.asset_hostnames = assets_hostnames # Multisite needs to be first, because the request tracker and message bus rely on it - Rails.configuration.middleware.unshift RailsMultisite::Middleware, RailsMultisite::DiscoursePatches.config + Rails.configuration.middleware.unshift RailsMultisite::Middleware, + RailsMultisite::DiscoursePatches.config Rails.configuration.middleware.delete ActionDispatch::Executor if defined?(RailsFailover::ActiveRecord) && Rails.configuration.active_record_rails_failover - Rails.configuration.middleware.insert_after(RailsMultisite::Middleware, RailsFailover::ActiveRecord::Middleware) + Rails.configuration.middleware.insert_after( + RailsMultisite::Middleware, + RailsFailover::ActiveRecord::Middleware, + ) end if Rails.env.development? @@ -57,5 +59,8 @@ elsif Rails.configuration.multisite end end elsif defined?(RailsFailover::ActiveRecord) && Rails.configuration.active_record_rails_failover - Rails.configuration.middleware.insert_before(MessageBus::Rack::Middleware, RailsFailover::ActiveRecord::Middleware) + Rails.configuration.middleware.insert_before( + MessageBus::Rack::Middleware, + RailsFailover::ActiveRecord::Middleware, + ) end diff --git a/config/initializers/400-deprecations.rb b/config/initializers/400-deprecations.rb index 39373182d16..29d636f584c 100644 --- a/config/initializers/400-deprecations.rb +++ b/config/initializers/400-deprecations.rb @@ -2,18 +2,32 @@ if !GlobalSetting.skip_redis? if GlobalSetting.respond_to?(:redis_slave_host) && GlobalSetting.redis_slave_host.present? - Discourse.deprecate("redis_slave_host is deprecated, use redis_replica_host instead", drop_from: "2.8") + Discourse.deprecate( + "redis_slave_host is deprecated, use redis_replica_host instead", + drop_from: "2.8", + ) end if GlobalSetting.respond_to?(:redis_slave_port) && GlobalSetting.redis_slave_port.present? - Discourse.deprecate("redis_slave_port is deprecated, use redis_replica_port instead", drop_from: "2.8") + Discourse.deprecate( + "redis_slave_port is deprecated, use redis_replica_port instead", + drop_from: "2.8", + ) end - if GlobalSetting.respond_to?(:message_bus_redis_slave_host) && GlobalSetting.message_bus_redis_slave_host.present? - Discourse.deprecate("message_bus_redis_slave_host is deprecated, use message_bus_redis_replica_host", drop_from: "2.8") + if GlobalSetting.respond_to?(:message_bus_redis_slave_host) && + GlobalSetting.message_bus_redis_slave_host.present? + Discourse.deprecate( + "message_bus_redis_slave_host is deprecated, use message_bus_redis_replica_host", + drop_from: "2.8", + ) end - if GlobalSetting.respond_to?(:message_bus_redis_slave_port) && GlobalSetting.message_bus_redis_slave_port.present? - Discourse.deprecate("message_bus_redis_slave_port is deprecated, use message_bus_redis_replica_port", drop_from: "2.8") + if GlobalSetting.respond_to?(:message_bus_redis_slave_port) && + GlobalSetting.message_bus_redis_slave_port.present? + Discourse.deprecate( + "message_bus_redis_slave_port is deprecated, use message_bus_redis_replica_port", + drop_from: "2.8", + ) end end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 98564a17cfe..191f6acc288 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -17,11 +17,13 @@ Rails.application.config.assets.paths << "#{Rails.root}/public/javascripts" # folder are already added. # explicitly precompile any images in plugins ( /assets/images ) path -Rails.application.config.assets.precompile += [lambda do |filename, path| - path =~ /assets\/images/ && !%w(.js .css).include?(File.extname(filename)) -end] +Rails.application.config.assets.precompile += [ + lambda do |filename, path| + path =~ %r{assets/images} && !%w[.js .css].include?(File.extname(filename)) + end, +] -Rails.application.config.assets.precompile += %w{ +Rails.application.config.assets.precompile += %w[ discourse.js vendor.js admin.js @@ -49,15 +51,21 @@ Rails.application.config.assets.precompile += %w{ embed-application.js scripts/discourse-test-listen-boot scripts/discourse-boot -} +] -Rails.application.config.assets.precompile += EmberCli.assets.map { |name| name.sub('.js', '.map') } +Rails.application.config.assets.precompile += EmberCli.assets.map { |name| name.sub(".js", ".map") } # Precompile all available locales unless GlobalSetting.try(:omit_base_locales) - Dir.glob("#{Rails.root}/app/assets/javascripts/locales/*.js.erb").each do |file| - Rails.application.config.assets.precompile << "locales/#{file.match(/([a-z_A-Z]+\.js)\.erb$/)[1]}" - end + Dir + .glob("#{Rails.root}/app/assets/javascripts/locales/*.js.erb") + .each do |file| + Rails + .application + .config + .assets + .precompile << "locales/#{file.match(/([a-z_A-Z]+\.js)\.erb$/)[1]}" + end end # out of the box sprockets 3 grabs loose files that are hanging in assets, @@ -65,18 +73,16 @@ end Rails.application.config.assets.precompile.delete(Sprockets::Railtie::LOOSE_APP_ASSETS) # We don't want application from node_modules, only from the root -Rails.application.config.assets.precompile.delete(/(?:\/|\\|\A)application\.(css|js)$/) -Rails.application.config.assets.precompile += ['application.js'] +Rails.application.config.assets.precompile.delete(%r{(?:/|\\|\A)application\.(css|js)$}) +Rails.application.config.assets.precompile += ["application.js"] start_path = ::Rails.root.join("app/assets").to_s -exclude = ['.es6', '.hbs', '.hbr', '.js', '.css', '.lock', '.json', '.log', '.html', ''] +exclude = [".es6", ".hbs", ".hbr", ".js", ".css", ".lock", ".json", ".log", ".html", ""] Rails.application.config.assets.precompile << lambda do |logical_path, filename| - filename.start_with?(start_path) && - !filename.include?("/node_modules/") && - !filename.include?("/dist/") && - !exclude.include?(File.extname(logical_path)) + filename.start_with?(start_path) && !filename.include?("/node_modules/") && + !filename.include?("/dist/") && !exclude.include?(File.extname(logical_path)) end -Discourse.find_plugin_js_assets(include_disabled: true).each do |file| - Rails.application.config.assets.precompile << "#{file}.js" -end +Discourse + .find_plugin_js_assets(include_disabled: true) + .each { |file| Rails.application.config.assets.precompile << "#{file}.js" } diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index af4c108bf6e..44f7fffd745 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -3,13 +3,13 @@ # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [ - :password, - :pop3_polling_password, - :api_key, - :s3_secret_access_key, - :twitter_consumer_secret, - :facebook_app_secret, - :github_client_secret, - :second_factor_token, +Rails.application.config.filter_parameters += %i[ + password + pop3_polling_password + api_key + s3_secret_access_key + twitter_consumer_secret + facebook_app_secret + github_client_secret + second_factor_token ] diff --git a/config/initializers/new_framework_defaults_7_0.rb b/config/initializers/new_framework_defaults_7_0.rb index 7ee8ffa85fe..fdbf91e62fc 100644 --- a/config/initializers/new_framework_defaults_7_0.rb +++ b/config/initializers/new_framework_defaults_7_0.rb @@ -102,5 +102,5 @@ Rails.application.config.action_dispatch.default_headers = { "X-Content-Type-Options" => "nosniff", "X-Download-Options" => "noopen", "X-Permitted-Cross-Domain-Policies" => "none", - "Referrer-Policy" => "strict-origin-when-cross-origin" + "Referrer-Policy" => "strict-origin-when-cross-origin", } diff --git a/config/locales/plurals.rb b/config/locales/plurals.rb index 4ffacf44088..babf8cf131a 100644 --- a/config/locales/plurals.rb +++ b/config/locales/plurals.rb @@ -3,6 +3,7 @@ # source: https://github.com/svenfuchs/i18n/blob/master/test/test_data/locales/plurals.rb +# stree-ignore { af: { i18n: { plural: { keys: [:one, :other], rule: lambda { |n| n == 1 ? :one : :other } } } }, am: { i18n: { plural: { keys: [:one, :other], rule: lambda { |n| [0, 1].include?(n) ? :one : :other } } } }, diff --git a/config/puma.rb b/config/puma.rb index 0fea9a24873..c349148f57b 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true -if ENV['RAILS_ENV'] == 'production' - +if ENV["RAILS_ENV"] == "production" # First, you need to change these below to your situation. - APP_ROOT = ENV["APP_ROOT"] || '/home/discourse/discourse' + APP_ROOT = ENV["APP_ROOT"] || "/home/discourse/discourse" num_workers = ENV["NUM_WEBS"].to_i > 0 ? ENV["NUM_WEBS"].to_i : 4 # Second, you can choose how many threads that you are going to run at same time. @@ -16,5 +15,4 @@ if ENV['RAILS_ENV'] == 'production' pidfile "#{APP_ROOT}/tmp/pids/puma.pid" state_path "#{APP_ROOT}/tmp/pids/puma.state" preload_app! - end diff --git a/config/routes.rb b/config/routes.rb index baf501a6f98..abdf514ef8d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,16 +4,27 @@ require "sidekiq/web" require "mini_scheduler/web" # The following constants have been replaced with `RouteFormat` and are deprecated. -USERNAME_ROUTE_FORMAT = /[%\w.\-]+?/ unless defined? USERNAME_ROUTE_FORMAT -BACKUP_ROUTE_FORMAT = /.+\.(sql\.gz|tar\.gz|tgz)/i unless defined? BACKUP_ROUTE_FORMAT +USERNAME_ROUTE_FORMAT = /[%\w.\-]+?/ unless defined?(USERNAME_ROUTE_FORMAT) +BACKUP_ROUTE_FORMAT = /.+\.(sql\.gz|tar\.gz|tgz)/i unless defined?(BACKUP_ROUTE_FORMAT) Discourse::Application.routes.draw do - def patch(*) end # Disable PATCH requests + def patch(*) + end # Disable PATCH requests - scope path: nil, constraints: { format: /(json|html|\*\/\*)/ } do - relative_url_root = (defined?(Rails.configuration.relative_url_root) && Rails.configuration.relative_url_root) ? Rails.configuration.relative_url_root + '/' : '/' + scope path: nil, constraints: { format: %r{(json|html|\*/\*)} } do + relative_url_root = + ( + if ( + defined?(Rails.configuration.relative_url_root) && + Rails.configuration.relative_url_root + ) + Rails.configuration.relative_url_root + "/" + else + "/" + end + ) - match "/404", to: "exceptions#not_found", via: [:get, :post] + match "/404", to: "exceptions#not_found", via: %i[get post] get "/404-body" => "exceptions#not_found_body" get "/bootstrap" => "bootstrap#index" @@ -22,8 +33,8 @@ Discourse::Application.routes.draw do end post "webhooks/aws" => "webhooks#aws" - post "webhooks/mailgun" => "webhooks#mailgun" - post "webhooks/mailjet" => "webhooks#mailjet" + post "webhooks/mailgun" => "webhooks#mailgun" + post "webhooks/mailjet" => "webhooks#mailjet" post "webhooks/mandrill" => "webhooks#mandrill" get "webhooks/mandrill" => "webhooks#mandrill_head" post "webhooks/postmark" => "webhooks#postmark" @@ -32,7 +43,7 @@ Discourse::Application.routes.draw do scope path: nil, format: true, constraints: { format: :xml } do resources :sitemap, only: [:index] - get "/sitemap_:page" => "sitemap#page", page: /[1-9][0-9]*/ + get "/sitemap_:page" => "sitemap#page", :page => /[1-9][0-9]*/ get "/sitemap_recent" => "sitemap#recent" get "/news" => "sitemap#news" end @@ -43,15 +54,13 @@ Discourse::Application.routes.draw do mount Logster::Web => "/logs" else # only allow sidekiq in master site - mount Sidekiq::Web => "/sidekiq", constraints: AdminConstraint.new(require_master: true) - mount Logster::Web => "/logs", constraints: AdminConstraint.new + mount Sidekiq::Web => "/sidekiq", :constraints => AdminConstraint.new(require_master: true) + mount Logster::Web => "/logs", :constraints => AdminConstraint.new end end resources :about do - collection do - get "live_post_counts" - end + collection { get "live_post_counts" } end get "finish-installation" => "finish_installation#index" @@ -76,25 +85,23 @@ Discourse::Application.routes.draw do get "emoji" end - get "site/basic-info" => 'site#basic_info' - get "site/statistics" => 'site#statistics' + get "site/basic-info" => "site#basic_info" + get "site/statistics" => "site#statistics" get "srv/status" => "forums#status" get "wizard" => "wizard#index" - get 'wizard/steps' => 'steps#index' - get 'wizard/steps/:id' => "wizard#index" - put 'wizard/steps/:id' => "steps#update" + get "wizard/steps" => "steps#index" + get "wizard/steps/:id" => "wizard#index" + put "wizard/steps/:id" => "steps#update" namespace :admin, constraints: StaffConstraint.new do get "" => "admin#index" - get 'plugins' => 'plugins#index' + get "plugins" => "plugins#index" resources :site_settings, constraints: AdminConstraint.new do - collection do - get "category/:id" => "site_settings#index" - end + collection { get "category/:id" => "site_settings#index" } put "user_count" => "site_settings#user_count" end @@ -111,13 +118,11 @@ Discourse::Application.routes.draw do end end resources :groups, except: [:create], constraints: AdminConstraint.new do - collection do - put "automatic_membership_count" => "groups#automatic_membership_count" - end + collection { put "automatic_membership_count" => "groups#automatic_membership_count" } end - get "groups/:type" => "groups#show", constraints: AdminConstraint.new - get "groups/:type/:id" => "groups#show", constraints: AdminConstraint.new + get "groups/:type" => "groups#show", :constraints => AdminConstraint.new + get "groups/:type/:id" => "groups#show", :constraints => AdminConstraint.new resources :users, id: RouteFormat.username, except: [:show] do collection do @@ -145,8 +150,8 @@ Discourse::Application.routes.draw do put "trust_level" put "trust_level_lock" put "primary_group" - post "groups" => "users#add_group", constraints: AdminConstraint.new - delete "groups/:group_id" => "users#remove_group", constraints: AdminConstraint.new + post "groups" => "users#add_group", :constraints => AdminConstraint.new + delete "groups/:group_id" => "users#remove_group", :constraints => AdminConstraint.new get "badges" get "leader_requirements" => "users#tl3_requirements" get "tl3_requirements" @@ -156,12 +161,16 @@ Discourse::Application.routes.draw do put "disable_second_factor" delete "sso_record" end - get "users/:id.json" => 'users#show', defaults: { format: 'json' } - get 'users/:id/:username' => 'users#show', constraints: { username: RouteFormat.username }, as: :user_show - get 'users/:id/:username/badges' => 'users#show' - get 'users/:id/:username/tl3_requirements' => 'users#show' + get "users/:id.json" => "users#show", :defaults => { format: "json" } + get "users/:id/:username" => "users#show", + :constraints => { + username: RouteFormat.username, + }, + :as => :user_show + get "users/:id/:username/badges" => "users#show" + get "users/:id/:username/tl3_requirements" => "users#show" - post "users/sync_sso" => "users#sync_sso", constraints: AdminConstraint.new + post "users/sync_sso" => "users#sync_sso", :constraints => AdminConstraint.new resources :impersonate, constraints: AdminConstraint.new @@ -186,28 +195,29 @@ Discourse::Application.routes.draw do end scope "/logs" do - resources :staff_action_logs, only: [:index] - get 'staff_action_logs/:id/diff' => 'staff_action_logs#diff' - resources :screened_emails, only: [:index, :destroy] - resources :screened_ip_addresses, only: [:index, :create, :update, :destroy] - resources :screened_urls, only: [:index] - resources :search_logs, only: [:index] - get 'search_logs/term/' => 'search_logs#term' + resources :staff_action_logs, only: [:index] + get "staff_action_logs/:id/diff" => "staff_action_logs#diff" + resources :screened_emails, only: %i[index destroy] + resources :screened_ip_addresses, only: %i[index create update destroy] + resources :screened_urls, only: [:index] + resources :search_logs, only: [:index] + get "search_logs/term/" => "search_logs#term" end get "/logs" => "staff_action_logs#index" # alias - get '/logs/watched_words', to: redirect(relative_url_root + 'admin/customize/watched_words') - get '/logs/watched_words/*path', to: redirect(relative_url_root + 'admin/customize/watched_words/%{path}') + get "/logs/watched_words", to: redirect(relative_url_root + "admin/customize/watched_words") + get "/logs/watched_words/*path", + to: redirect(relative_url_root + "admin/customize/watched_words/%{path}") - get "customize" => "color_schemes#index", constraints: AdminConstraint.new - get "customize/themes" => "themes#index", constraints: AdminConstraint.new - get "customize/colors" => "color_schemes#index", constraints: AdminConstraint.new - get "customize/colors/:id" => "color_schemes#index", constraints: AdminConstraint.new - get "customize/permalinks" => "permalinks#index", constraints: AdminConstraint.new - get "customize/embedding" => "embedding#show", constraints: AdminConstraint.new - put "customize/embedding" => "embedding#update", constraints: AdminConstraint.new + get "customize" => "color_schemes#index", :constraints => AdminConstraint.new + get "customize/themes" => "themes#index", :constraints => AdminConstraint.new + get "customize/colors" => "color_schemes#index", :constraints => AdminConstraint.new + get "customize/colors/:id" => "color_schemes#index", :constraints => AdminConstraint.new + get "customize/permalinks" => "permalinks#index", :constraints => AdminConstraint.new + get "customize/embedding" => "embedding#show", :constraints => AdminConstraint.new + put "customize/embedding" => "embedding#update", :constraints => AdminConstraint.new resources :themes, constraints: AdminConstraint.new do member do @@ -225,33 +235,42 @@ Discourse::Application.routes.draw do resources :user_fields, constraints: AdminConstraint.new resources :emojis, constraints: AdminConstraint.new - get 'themes/:id/:target/:field_name/edit' => 'themes#index' - get 'themes/:id' => 'themes#index' + get "themes/:id/:target/:field_name/edit" => "themes#index" + get "themes/:id" => "themes#index" get "themes/:id/export" => "themes#export" # They have periods in their URLs often: - get 'site_texts' => 'site_texts#index' - get 'site_texts/:id.json' => 'site_texts#show', constraints: { id: /[\w.\-\+\%\&]+/i } - get 'site_texts/:id' => 'site_texts#show', constraints: { id: /[\w.\-\+\%\&]+/i } - put 'site_texts/:id.json' => 'site_texts#update', constraints: { id: /[\w.\-\+\%\&]+/i } - put 'site_texts/:id' => 'site_texts#update', constraints: { id: /[\w.\-\+\%\&]+/i } - delete 'site_texts/:id.json' => 'site_texts#revert', constraints: { id: /[\w.\-\+\%\&]+/i } - delete 'site_texts/:id' => 'site_texts#revert', constraints: { id: /[\w.\-\+\%\&]+/i } + get "site_texts" => "site_texts#index" + get "site_texts/:id.json" => "site_texts#show", :constraints => { id: /[\w.\-\+\%\&]+/i } + get "site_texts/:id" => "site_texts#show", :constraints => { id: /[\w.\-\+\%\&]+/i } + put "site_texts/:id.json" => "site_texts#update", :constraints => { id: /[\w.\-\+\%\&]+/i } + put "site_texts/:id" => "site_texts#update", :constraints => { id: /[\w.\-\+\%\&]+/i } + delete "site_texts/:id.json" => "site_texts#revert", + :constraints => { + id: /[\w.\-\+\%\&]+/i, + } + delete "site_texts/:id" => "site_texts#revert", :constraints => { id: /[\w.\-\+\%\&]+/i } - get 'reseed' => 'site_texts#get_reseed_options' - post 'reseed' => 'site_texts#reseed' + get "reseed" => "site_texts#get_reseed_options" + post "reseed" => "site_texts#reseed" - get 'email_templates' => 'email_templates#index' - get 'email_templates/(:id)' => 'email_templates#show', constraints: { id: /[0-9a-z_.]+/ } - put 'email_templates/(:id)' => 'email_templates#update', constraints: { id: /[0-9a-z_.]+/ } - delete 'email_templates/(:id)' => 'email_templates#revert', constraints: { id: /[0-9a-z_.]+/ } + get "email_templates" => "email_templates#index" + get "email_templates/(:id)" => "email_templates#show", :constraints => { id: /[0-9a-z_.]+/ } + put "email_templates/(:id)" => "email_templates#update", + :constraints => { + id: /[0-9a-z_.]+/, + } + delete "email_templates/(:id)" => "email_templates#revert", + :constraints => { + id: /[0-9a-z_.]+/, + } - get 'robots' => 'robots_txt#show' - put 'robots.json' => 'robots_txt#update' - delete 'robots.json' => 'robots_txt#reset' + get "robots" => "robots_txt#show" + put "robots.json" => "robots_txt#update" + delete "robots.json" => "robots_txt#reset" - resource :email_style, only: [:show, :update] - get 'email_style/:field' => 'email_styles#show', constraints: { field: /html|css/ } + resource :email_style, only: %i[show update] + get "email_style/:field" => "email_styles#show", :constraints => { field: /html|css/ } end resources :embeddable_hosts, constraints: AdminConstraint.new @@ -259,7 +278,7 @@ Discourse::Application.routes.draw do resources :permalinks, constraints: AdminConstraint.new scope "/customize" do - resources :watched_words, only: [:index, :create, :update, :destroy] do + resources :watched_words, only: %i[index create update destroy] do collection do get "action/:id" => "watched_words#index" get "action/:id/download" => "watched_words#download" @@ -280,17 +299,13 @@ Discourse::Application.routes.draw do put "dashboard/mark-new-features-as-seen" => "dashboard#mark_new_features_as_seen" resources :dashboard, only: [:index] do - collection do - get "problems" - end + collection { get "problems" } end resources :api, only: [:index], constraints: AdminConstraint.new do collection do - resources :keys, controller: 'api', only: [:index, :show, :update, :create, :destroy] do - collection do - get 'scopes' => 'api#scopes' - end + resources :keys, controller: "api", only: %i[index show update create destroy] do + collection { get "scopes" => "api#scopes" } member do post "revoke" => "api#revoke_key" @@ -299,26 +314,27 @@ Discourse::Application.routes.draw do end resources :web_hooks - get 'web_hook_events/:id' => 'web_hooks#list_events', as: :web_hook_events - get 'web_hooks/:id/events/bulk' => 'web_hooks#bulk_events' - post 'web_hooks/:web_hook_id/events/:event_id/redeliver' => 'web_hooks#redeliver_event' - post 'web_hooks/:id/ping' => 'web_hooks#ping' + get "web_hook_events/:id" => "web_hooks#list_events", :as => :web_hook_events + get "web_hooks/:id/events/bulk" => "web_hooks#bulk_events" + post "web_hooks/:web_hook_id/events/:event_id/redeliver" => "web_hooks#redeliver_event" + post "web_hooks/:id/ping" => "web_hooks#ping" end end - resources :backups, only: [:index, :create], constraints: AdminConstraint.new do + resources :backups, only: %i[index create], constraints: AdminConstraint.new do member do - get "" => "backups#show", constraints: { id: RouteFormat.backup } - put "" => "backups#email", constraints: { id: RouteFormat.backup } - delete "" => "backups#destroy", constraints: { id: RouteFormat.backup } - post "restore" => "backups#restore", constraints: { id: RouteFormat.backup } + get "" => "backups#show", :constraints => { id: RouteFormat.backup } + put "" => "backups#email", :constraints => { id: RouteFormat.backup } + delete "" => "backups#destroy", :constraints => { id: RouteFormat.backup } + post "restore" => "backups#restore", :constraints => { id: RouteFormat.backup } end collection do # multipart uploads - post "create-multipart" => "backups#create_multipart", format: :json - post "complete-multipart" => "backups#complete_multipart", format: :json - post "abort-multipart" => "backups#abort_multipart", format: :json - post "batch-presign-multipart-parts" => "backups#batch_presign_multipart_parts", format: :json + post "create-multipart" => "backups#create_multipart", :format => :json + post "complete-multipart" => "backups#complete_multipart", :format => :json + post "abort-multipart" => "backups#abort_multipart", :format => :json + post "batch-presign-multipart-parts" => "backups#batch_presign_multipart_parts", + :format => :json get "logs" => "backups#logs" get "status" => "backups#status" @@ -340,39 +356,41 @@ Discourse::Application.routes.draw do post "preview" => "badges#preview" end end - end # admin namespace - get "email/unsubscribe/:key" => "email#unsubscribe", as: "email_unsubscribe" - get "email/unsubscribed" => "email#unsubscribed", as: "email_unsubscribed" - post "email/unsubscribe/:key" => "email#perform_unsubscribe", as: "email_perform_unsubscribe" + get "email/unsubscribe/:key" => "email#unsubscribe", :as => "email_unsubscribe" + get "email/unsubscribed" => "email#unsubscribed", :as => "email_unsubscribed" + post "email/unsubscribe/:key" => "email#perform_unsubscribe", :as => "email_perform_unsubscribe" get "extra-locales/:bundle" => "extra_locales#show" - resources :session, id: RouteFormat.username, only: [:create, :destroy, :become] do - if !Rails.env.production? - get 'become' - end + resources :session, id: RouteFormat.username, only: %i[create destroy become] do + get "become" if !Rails.env.production? - collection do - post "forgot_password" - end + collection { post "forgot_password" } end get "review" => "reviewables#index" # For ember app - get "review/:reviewable_id" => "reviewables#show", constraints: { reviewable_id: /\d+/ } - get "review/:reviewable_id/explain" => "reviewables#explain", constraints: { reviewable_id: /\d+/ } + get "review/:reviewable_id" => "reviewables#show", :constraints => { reviewable_id: /\d+/ } + get "review/:reviewable_id/explain" => "reviewables#explain", + :constraints => { + reviewable_id: /\d+/, + } get "review/count" => "reviewables#count" get "review/topics" => "reviewables#topics" get "review/settings" => "reviewables#settings" - get "review/user-menu-list" => "reviewables#user_menu_list", format: :json + get "review/user-menu-list" => "reviewables#user_menu_list", :format => :json put "review/settings" => "reviewables#settings" - put "review/:reviewable_id/perform/:action_id" => "reviewables#perform", constraints: { - reviewable_id: /\d+/, - action_id: /[a-z\_]+/ - } - put "review/:reviewable_id" => "reviewables#update", constraints: { reviewable_id: /\d+/ } - delete "review/:reviewable_id" => "reviewables#destroy", constraints: { reviewable_id: /\d+/ } + put "review/:reviewable_id/perform/:action_id" => "reviewables#perform", + :constraints => { + reviewable_id: /\d+/, + action_id: /[a-z\_]+/, + } + put "review/:reviewable_id" => "reviewables#update", :constraints => { reviewable_id: /\d+/ } + delete "review/:reviewable_id" => "reviewables#destroy", + :constraints => { + reviewable_id: /\d+/, + } resources :reviewable_claimed_topics @@ -384,8 +402,8 @@ Discourse::Application.routes.draw do get "session/hp" => "session#get_honeypot_value" get "session/email-login/:token" => "session#email_login_info" post "session/email-login/:token" => "session#email_login" - get "session/otp/:token" => "session#one_time_password", constraints: { token: /[0-9a-f]+/ } - post "session/otp/:token" => "session#one_time_password", constraints: { token: /[0-9a-f]+/ } + get "session/otp/:token" => "session#one_time_password", :constraints => { token: /[0-9a-f]+/ } + post "session/otp/:token" => "session#one_time_password", :constraints => { token: /[0-9a-f]+/ } get "session/2fa" => "session#second_factor_auth_show" post "session/2fa" => "session#second_factor_auth_perform" if Rails.env.test? @@ -398,30 +416,31 @@ Discourse::Application.routes.draw do resources :static post "login" => "static#enter" - get "login" => "static#show", id: "login" - get "password-reset" => "static#show", id: "password_reset" - get "faq" => "static#show", id: "faq" - get "tos" => "static#show", id: "tos", as: 'tos' - get "privacy" => "static#show", id: "privacy", as: 'privacy' - get "signup" => "static#show", id: "signup" - get "login-preferences" => "static#show", id: "login" + get "login" => "static#show", :id => "login" + get "password-reset" => "static#show", :id => "password_reset" + get "faq" => "static#show", :id => "faq" + get "tos" => "static#show", :id => "tos", :as => "tos" + get "privacy" => "static#show", :id => "privacy", :as => "privacy" + get "signup" => "static#show", :id => "signup" + get "login-preferences" => "static#show", :id => "login" - %w{guidelines rules conduct}.each do |faq_alias| - get faq_alias => "static#show", id: "guidelines", as: faq_alias + %w[guidelines rules conduct].each do |faq_alias| + get faq_alias => "static#show", :id => "guidelines", :as => faq_alias end - get "my/*path", to: 'users#my_redirect' - get ".well-known/change-password", to: redirect(relative_url_root + 'my/preferences/security', status: 302) + get "my/*path", to: "users#my_redirect" + get ".well-known/change-password", + to: redirect(relative_url_root + "my/preferences/security", status: 302) - get "user-cards" => "users#cards", format: :json - get "directory-columns" => "directory_columns#index", format: :json - get "edit-directory-columns" => "edit_directory_columns#index", format: :json - put "edit-directory-columns" => "edit_directory_columns#update", format: :json + get "user-cards" => "users#cards", :format => :json + get "directory-columns" => "directory_columns#index", :format => :json + get "edit-directory-columns" => "edit_directory_columns#index", :format => :json + put "edit-directory-columns" => "edit_directory_columns#update", :format => :json - %w{users u}.each_with_index do |root_path, index| - get "#{root_path}" => "users#index", constraints: { format: 'html' } + %w[users u].each_with_index do |root_path, index| + get "#{root_path}" => "users#index", :constraints => { format: "html" } - resources :users, except: [:index, :new, :show, :update, :destroy], path: root_path do + resources :users, except: %i[index new show update destroy], path: root_path do collection do get "check_username" get "check_email" @@ -431,8 +450,10 @@ Discourse::Application.routes.draw do post "#{root_path}/second_factors" => "users#list_second_factors" put "#{root_path}/second_factor" => "users#update_second_factor" - post "#{root_path}/create_second_factor_security_key" => "users#create_second_factor_security_key" - post "#{root_path}/register_second_factor_security_key" => "users#register_second_factor_security_key" + post "#{root_path}/create_second_factor_security_key" => + "users#create_second_factor_security_key" + post "#{root_path}/register_second_factor_security_key" => + "users#register_second_factor_security_key" put "#{root_path}/security_key" => "users#update_security_key" post "#{root_path}/create_second_factor_totp" => "users#create_second_factor_totp" post "#{root_path}/enable_second_factor_totp" => "users#enable_second_factor_totp" @@ -446,19 +467,40 @@ Discourse::Application.routes.draw do put "#{root_path}/admin-login" => "users#admin_login" post "#{root_path}/toggle-anon" => "users#toggle_anon" post "#{root_path}/read-faq" => "users#read_faq" - get "#{root_path}/recent-searches" => "users#recent_searches", constraints: { format: 'json' } - delete "#{root_path}/recent-searches" => "users#reset_recent_searches", constraints: { format: 'json' } + get "#{root_path}/recent-searches" => "users#recent_searches", + :constraints => { + format: "json", + } + delete "#{root_path}/recent-searches" => "users#reset_recent_searches", + :constraints => { + format: "json", + } get "#{root_path}/search/users" => "users#search_users" - get({ "#{root_path}/account-created/" => "users#account_created" }.merge(index == 1 ? { as: :users_account_created } : { as: :old_account_created })) + get( + { "#{root_path}/account-created/" => "users#account_created" }.merge( + index == 1 ? { as: :users_account_created } : { as: :old_account_created }, + ), + ) get "#{root_path}/account-created/resent" => "users#account_created" get "#{root_path}/account-created/edit-email" => "users#account_created" - get({ "#{root_path}/password-reset/:token" => "users#password_reset_show" }.merge(index == 1 ? { as: :password_reset_token } : {})) - get "#{root_path}/confirm-email-token/:token" => "users#confirm_email_token", constraints: { format: 'json' } + get( + { "#{root_path}/password-reset/:token" => "users#password_reset_show" }.merge( + index == 1 ? { as: :password_reset_token } : {}, + ), + ) + get "#{root_path}/confirm-email-token/:token" => "users#confirm_email_token", + :constraints => { + format: "json", + } put "#{root_path}/password-reset/:token" => "users#password_reset_update" get "#{root_path}/activate-account/:token" => "users#activate_account" - put({ "#{root_path}/activate-account/:token" => "users#perform_account_activation" }.merge(index == 1 ? { as: 'perform_activate_account' } : {})) + put( + { "#{root_path}/activate-account/:token" => "users#perform_account_activation" }.merge( + index == 1 ? { as: "perform_activate_account" } : {}, + ), + ) get "#{root_path}/confirm-old-email/:token" => "users_email#show_confirm_old_email" put "#{root_path}/confirm-old-email" => "users_email#confirm_old_email" @@ -466,105 +508,415 @@ Discourse::Application.routes.draw do get "#{root_path}/confirm-new-email/:token" => "users_email#show_confirm_new_email" put "#{root_path}/confirm-new-email" => "users_email#confirm_new_email" - get({ - "#{root_path}/confirm-admin/:token" => "users#confirm_admin", - constraints: { token: /[0-9a-f]+/ } - }.merge(index == 1 ? { as: 'confirm_admin' } : {})) - post "#{root_path}/confirm-admin/:token" => "users#confirm_admin", constraints: { token: /[0-9a-f]+/ } - get "#{root_path}/:username/private-messages" => "user_actions#private_messages", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/private-messages/:filter" => "user_actions#private_messages", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/messages" => "user_actions#private_messages", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/messages/:filter" => "user_actions#private_messages", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/messages/group/:group_name" => "user_actions#private_messages", constraints: { username: RouteFormat.username, group_name: RouteFormat.username } - get "#{root_path}/:username/messages/group/:group_name/:filter" => "user_actions#private_messages", constraints: { username: RouteFormat.username, group_name: RouteFormat.username } - get "#{root_path}/:username/messages/tags/:tag_id" => "list#private_messages_tag", constraints: { username: RouteFormat.username } - get "#{root_path}/:username.json" => "users#show", constraints: { username: RouteFormat.username }, defaults: { format: :json } - get({ "#{root_path}/:username" => "users#show", constraints: { username: RouteFormat.username } }.merge(index == 1 ? { as: 'user' } : {})) - put "#{root_path}/:username" => "users#update", constraints: { username: RouteFormat.username }, defaults: { format: :json } - get "#{root_path}/:username/emails" => "users#check_emails", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/sso-email" => "users#check_sso_email", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/sso-payload" => "users#check_sso_payload", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/email" => "users_email#index", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/account" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/security" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/profile" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/emails" => "users#preferences", constraints: { username: RouteFormat.username } - put "#{root_path}/:username/preferences/primary-email" => "users#update_primary_email", format: :json, constraints: { username: RouteFormat.username } - delete "#{root_path}/:username/preferences/email" => "users#destroy_email", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/notifications" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/tracking" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/categories" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/users" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/tags" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/interface" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/sidebar" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/apps" => "users#preferences", constraints: { username: RouteFormat.username } - post "#{root_path}/:username/preferences/email" => "users_email#create", constraints: { username: RouteFormat.username } - put "#{root_path}/:username/preferences/email" => "users_email#update", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/badge_title" => "users#preferences", constraints: { username: RouteFormat.username } - put "#{root_path}/:username/preferences/badge_title" => "users#badge_title", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/username" => "users#preferences", constraints: { username: RouteFormat.username } - put "#{root_path}/:username/preferences/username" => "users#username", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/second-factor" => "users#preferences", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/preferences/second-factor-backup" => "users#preferences", constraints: { username: RouteFormat.username } - delete "#{root_path}/:username/preferences/user_image" => "users#destroy_user_image", constraints: { username: RouteFormat.username } - put "#{root_path}/:username/preferences/avatar/pick" => "users#pick_avatar", constraints: { username: RouteFormat.username } - put "#{root_path}/:username/preferences/avatar/select" => "users#select_avatar", constraints: { username: RouteFormat.username } - post "#{root_path}/:username/preferences/revoke-account" => "users#revoke_account", constraints: { username: RouteFormat.username } - post "#{root_path}/:username/preferences/revoke-auth-token" => "users#revoke_auth_token", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/staff-info" => "users#staff_info", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/summary" => "users#summary", constraints: { username: RouteFormat.username } - put "#{root_path}/:username/notification_level" => "users#notification_level", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/invited" => "users#invited", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/invited/:filter" => "users#invited", constraints: { username: RouteFormat.username } + get( + { + "#{root_path}/confirm-admin/:token" => "users#confirm_admin", + :constraints => { + token: /[0-9a-f]+/, + }, + }.merge(index == 1 ? { as: "confirm_admin" } : {}), + ) + post "#{root_path}/confirm-admin/:token" => "users#confirm_admin", + :constraints => { + token: /[0-9a-f]+/, + } + get "#{root_path}/:username/private-messages" => "user_actions#private_messages", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/private-messages/:filter" => "user_actions#private_messages", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/messages" => "user_actions#private_messages", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/messages/:filter" => "user_actions#private_messages", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/messages/group/:group_name" => "user_actions#private_messages", + :constraints => { + username: RouteFormat.username, + group_name: RouteFormat.username, + } + get "#{root_path}/:username/messages/group/:group_name/:filter" => + "user_actions#private_messages", + :constraints => { + username: RouteFormat.username, + group_name: RouteFormat.username, + } + get "#{root_path}/:username/messages/tags/:tag_id" => "list#private_messages_tag", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username.json" => "users#show", + :constraints => { + username: RouteFormat.username, + }, + :defaults => { + format: :json, + } + get( + { + "#{root_path}/:username" => "users#show", + :constraints => { + username: RouteFormat.username, + }, + }.merge(index == 1 ? { as: "user" } : {}), + ) + put "#{root_path}/:username" => "users#update", + :constraints => { + username: RouteFormat.username, + }, + :defaults => { + format: :json, + } + get "#{root_path}/:username/emails" => "users#check_emails", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/sso-email" => "users#check_sso_email", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/sso-payload" => "users#check_sso_payload", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/email" => "users_email#index", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/account" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/security" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/profile" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/emails" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + put "#{root_path}/:username/preferences/primary-email" => "users#update_primary_email", + :format => :json, + :constraints => { + username: RouteFormat.username, + } + delete "#{root_path}/:username/preferences/email" => "users#destroy_email", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/notifications" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/tracking" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/categories" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/users" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/tags" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/interface" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/sidebar" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/apps" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + post "#{root_path}/:username/preferences/email" => "users_email#create", + :constraints => { + username: RouteFormat.username, + } + put "#{root_path}/:username/preferences/email" => "users_email#update", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/badge_title" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + put "#{root_path}/:username/preferences/badge_title" => "users#badge_title", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/username" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + put "#{root_path}/:username/preferences/username" => "users#username", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/second-factor" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/preferences/second-factor-backup" => "users#preferences", + :constraints => { + username: RouteFormat.username, + } + delete "#{root_path}/:username/preferences/user_image" => "users#destroy_user_image", + :constraints => { + username: RouteFormat.username, + } + put "#{root_path}/:username/preferences/avatar/pick" => "users#pick_avatar", + :constraints => { + username: RouteFormat.username, + } + put "#{root_path}/:username/preferences/avatar/select" => "users#select_avatar", + :constraints => { + username: RouteFormat.username, + } + post "#{root_path}/:username/preferences/revoke-account" => "users#revoke_account", + :constraints => { + username: RouteFormat.username, + } + post "#{root_path}/:username/preferences/revoke-auth-token" => "users#revoke_auth_token", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/staff-info" => "users#staff_info", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/summary" => "users#summary", + :constraints => { + username: RouteFormat.username, + } + put "#{root_path}/:username/notification_level" => "users#notification_level", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/invited" => "users#invited", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/invited/:filter" => "users#invited", + :constraints => { + username: RouteFormat.username, + } post "#{root_path}/action/send_activation_email" => "users#send_activation_email" - get "#{root_path}/:username/summary" => "users#show", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/activity/topics.rss" => "list#user_topics_feed", format: :rss, constraints: { username: RouteFormat.username } - get "#{root_path}/:username/activity.rss" => "posts#user_posts_feed", format: :rss, constraints: { username: RouteFormat.username } - get "#{root_path}/:username/activity.json" => "posts#user_posts_feed", format: :json, constraints: { username: RouteFormat.username } - get "#{root_path}/:username/activity" => "users#show", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/activity/:filter" => "users#show", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/badges" => "users#badges", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/bookmarks" => "users#bookmarks", constraints: { username: RouteFormat.username, format: /(json|ics)/ } - get "#{root_path}/:username/user-menu-bookmarks" => "users#user_menu_bookmarks", constraints: { username: RouteFormat.username, format: :json } - get "#{root_path}/:username/user-menu-private-messages" => "users#user_menu_messages", constraints: { username: RouteFormat.username, format: :json } - get "#{root_path}/:username/notifications" => "users#show", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/notifications/:filter" => "users#show", constraints: { username: RouteFormat.username } - delete "#{root_path}/:username" => "users#destroy", constraints: { username: RouteFormat.username } - get "#{root_path}/by-external/:external_id" => "users#show", constraints: { external_id: /[^\/]+/ } - get "#{root_path}/by-external/:external_provider/:external_id" => "users#show", constraints: { external_id: /[^\/]+/ } - get "#{root_path}/:username/flagged-posts" => "users#show", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/deleted-posts" => "users#show", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/topic-tracking-state" => "users#topic_tracking_state", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/private-message-topic-tracking-state" => "users#private_message_topic_tracking_state", constraints: { username: RouteFormat.username } + get "#{root_path}/:username/summary" => "users#show", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/activity/topics.rss" => "list#user_topics_feed", + :format => :rss, + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/activity.rss" => "posts#user_posts_feed", + :format => :rss, + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/activity.json" => "posts#user_posts_feed", + :format => :json, + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/activity" => "users#show", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/activity/:filter" => "users#show", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/badges" => "users#badges", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/bookmarks" => "users#bookmarks", + :constraints => { + username: RouteFormat.username, + format: /(json|ics)/, + } + get "#{root_path}/:username/user-menu-bookmarks" => "users#user_menu_bookmarks", + :constraints => { + username: RouteFormat.username, + format: :json, + } + get "#{root_path}/:username/user-menu-private-messages" => "users#user_menu_messages", + :constraints => { + username: RouteFormat.username, + format: :json, + } + get "#{root_path}/:username/notifications" => "users#show", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/notifications/:filter" => "users#show", + :constraints => { + username: RouteFormat.username, + } + delete "#{root_path}/:username" => "users#destroy", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/by-external/:external_id" => "users#show", + :constraints => { + external_id: %r{[^/]+}, + } + get "#{root_path}/by-external/:external_provider/:external_id" => "users#show", + :constraints => { + external_id: %r{[^/]+}, + } + get "#{root_path}/:username/flagged-posts" => "users#show", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/deleted-posts" => "users#show", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/topic-tracking-state" => "users#topic_tracking_state", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/private-message-topic-tracking-state" => + "users#private_message_topic_tracking_state", + :constraints => { + username: RouteFormat.username, + } get "#{root_path}/:username/profile-hidden" => "users#profile_hidden" - put "#{root_path}/:username/feature-topic" => "users#feature_topic", constraints: { username: RouteFormat.username } - put "#{root_path}/:username/clear-featured-topic" => "users#clear_featured_topic", constraints: { username: RouteFormat.username } - get "#{root_path}/:username/card.json" => "users#show_card", format: :json, constraints: { username: RouteFormat.username } + put "#{root_path}/:username/feature-topic" => "users#feature_topic", + :constraints => { + username: RouteFormat.username, + } + put "#{root_path}/:username/clear-featured-topic" => "users#clear_featured_topic", + :constraints => { + username: RouteFormat.username, + } + get "#{root_path}/:username/card.json" => "users#show_card", + :format => :json, + :constraints => { + username: RouteFormat.username, + } end - get "user-badges/:username.json" => "user_badges#username", constraints: { username: RouteFormat.username }, defaults: { format: :json } - get "user-badges/:username" => "user_badges#username", constraints: { username: RouteFormat.username } + get "user-badges/:username.json" => "user_badges#username", + :constraints => { + username: RouteFormat.username, + }, + :defaults => { + format: :json, + } + get "user-badges/:username" => "user_badges#username", + :constraints => { + username: RouteFormat.username, + } - post "user_avatar/:username/refresh_gravatar" => "user_avatars#refresh_gravatar", constraints: { username: RouteFormat.username } - get "letter_avatar/:username/:size/:version.png" => "user_avatars#show_letter", constraints: { hostname: /[\w\.-]+/, size: /\d+/, username: RouteFormat.username, format: :png } - get "user_avatar/:hostname/:username/:size/:version.png" => "user_avatars#show", constraints: { hostname: /[\w\.-]+/, size: /\d+/, username: RouteFormat.username, format: :png } + post "user_avatar/:username/refresh_gravatar" => "user_avatars#refresh_gravatar", + :constraints => { + username: RouteFormat.username, + } + get "letter_avatar/:username/:size/:version.png" => "user_avatars#show_letter", + :constraints => { + hostname: /[\w\.-]+/, + size: /\d+/, + username: RouteFormat.username, + format: :png, + } + get "user_avatar/:hostname/:username/:size/:version.png" => "user_avatars#show", + :constraints => { + hostname: /[\w\.-]+/, + size: /\d+/, + username: RouteFormat.username, + format: :png, + } - get "letter_avatar_proxy/:version/letter/:letter/:color/:size.png" => "user_avatars#show_proxy_letter", constraints: { format: :png } + get "letter_avatar_proxy/:version/letter/:letter/:color/:size.png" => + "user_avatars#show_proxy_letter", + :constraints => { + format: :png, + } - get "svg-sprite/:hostname/svg-:theme_id-:version.js" => "svg_sprite#show", constraints: { hostname: /[\w\.-]+/, version: /\h{40}/, theme_id: /([0-9]+)?/, format: :js } - get "svg-sprite/search/:keyword" => "svg_sprite#search", format: false, constraints: { keyword: /[-a-z0-9\s\%]+/ } - get "svg-sprite/picker-search" => "svg_sprite#icon_picker_search", defaults: { format: :json } - get "svg-sprite/:hostname/icon(/:color)/:name.svg" => "svg_sprite#svg_icon", constraints: { hostname: /[\w\.-]+/, name: /[-a-z0-9\s\%]+/, color: /(\h{3}{1,2})/, format: :svg } + get "svg-sprite/:hostname/svg-:theme_id-:version.js" => "svg_sprite#show", + :constraints => { + hostname: /[\w\.-]+/, + version: /\h{40}/, + theme_id: /([0-9]+)?/, + format: :js, + } + get "svg-sprite/search/:keyword" => "svg_sprite#search", + :format => false, + :constraints => { + keyword: /[-a-z0-9\s\%]+/, + } + get "svg-sprite/picker-search" => "svg_sprite#icon_picker_search", + :defaults => { + format: :json, + } + get "svg-sprite/:hostname/icon(/:color)/:name.svg" => "svg_sprite#svg_icon", + :constraints => { + hostname: /[\w\.-]+/, + name: /[-a-z0-9\s\%]+/, + color: /(\h{3}{1,2})/, + format: :svg, + } - get "highlight-js/:hostname/:version.js" => "highlight_js#show", constraints: { hostname: /[\w\.-]+/, format: :js } + get "highlight-js/:hostname/:version.js" => "highlight_js#show", + :constraints => { + hostname: /[\w\.-]+/, + format: :js, + } - get "stylesheets/:name" => "stylesheets#show_source_map", constraints: { name: /[-a-z0-9_]+/, format: /css\.map/ }, format: true - get "stylesheets/:name" => "stylesheets#show", constraints: { name: /[-a-z0-9_]+/, format: "css" }, format: true - get "color-scheme-stylesheet/:id(/:theme_id)" => "stylesheets#color_scheme", constraints: { format: :json } - get "theme-javascripts/:digest" => "theme_javascripts#show", constraints: { digest: /\h{40}/, format: :js }, format: true - get "theme-javascripts/:digest" => "theme_javascripts#show_map", constraints: { digest: /\h{40}/, format: :map }, format: true + get "stylesheets/:name" => "stylesheets#show_source_map", + :constraints => { + name: /[-a-z0-9_]+/, + format: /css\.map/, + }, + :format => true + get "stylesheets/:name" => "stylesheets#show", + :constraints => { + name: /[-a-z0-9_]+/, + format: "css", + }, + :format => true + get "color-scheme-stylesheet/:id(/:theme_id)" => "stylesheets#color_scheme", + :constraints => { + format: :json, + } + get "theme-javascripts/:digest" => "theme_javascripts#show", + :constraints => { + digest: /\h{40}/, + format: :js, + }, + :format => true + get "theme-javascripts/:digest" => "theme_javascripts#show_map", + :constraints => { + digest: /\h{40}/, + format: :map, + }, + :format => true get "theme-javascripts/tests/:theme_id-:digest.js" => "theme_javascripts#show_tests" post "uploads/lookup-metadata" => "uploads#metadata" @@ -572,65 +924,115 @@ Discourse::Application.routes.draw do post "uploads/lookup-urls" => "uploads#lookup_urls" # direct to s3 uploads - post "uploads/generate-presigned-put" => "uploads#generate_presigned_put", format: :json - post "uploads/complete-external-upload" => "uploads#complete_external_upload", format: :json + post "uploads/generate-presigned-put" => "uploads#generate_presigned_put", :format => :json + post "uploads/complete-external-upload" => "uploads#complete_external_upload", :format => :json # multipart uploads - post "uploads/create-multipart" => "uploads#create_multipart", format: :json - post "uploads/complete-multipart" => "uploads#complete_multipart", format: :json - post "uploads/abort-multipart" => "uploads#abort_multipart", format: :json - post "uploads/batch-presign-multipart-parts" => "uploads#batch_presign_multipart_parts", format: :json + post "uploads/create-multipart" => "uploads#create_multipart", :format => :json + post "uploads/complete-multipart" => "uploads#complete_multipart", :format => :json + post "uploads/abort-multipart" => "uploads#abort_multipart", :format => :json + post "uploads/batch-presign-multipart-parts" => "uploads#batch_presign_multipart_parts", + :format => :json # used to download original images - get "uploads/:site/:sha(.:extension)" => "uploads#show", constraints: { site: /\w+/, sha: /\h{40}/, extension: /[a-z0-9\._]+/i } - get "uploads/short-url/:base62(.:extension)" => "uploads#show_short", constraints: { site: /\w+/, base62: /[a-zA-Z0-9]+/, extension: /[a-zA-Z0-9\._-]+/i }, as: :upload_short + get "uploads/:site/:sha(.:extension)" => "uploads#show", + :constraints => { + site: /\w+/, + sha: /\h{40}/, + extension: /[a-z0-9\._]+/i, + } + get "uploads/short-url/:base62(.:extension)" => "uploads#show_short", + :constraints => { + site: /\w+/, + base62: /[a-zA-Z0-9]+/, + extension: /[a-zA-Z0-9\._-]+/i, + }, + :as => :upload_short # used to download attachments - get "uploads/:site/original/:tree:sha(.:extension)" => "uploads#show", constraints: { site: /\w+/, tree: /([a-z0-9]+\/)+/i, sha: /\h{40}/, extension: /[a-z0-9\._]+/i } + get "uploads/:site/original/:tree:sha(.:extension)" => "uploads#show", + :constraints => { + site: /\w+/, + tree: %r{([a-z0-9]+/)+}i, + sha: /\h{40}/, + extension: /[a-z0-9\._]+/i, + } if Rails.env.test? - get "uploads/:site/test_:index/original/:tree:sha(.:extension)" => "uploads#show", constraints: { site: /\w+/, index: /\d+/, tree: /([a-z0-9]+\/)+/i, sha: /\h{40}/, extension: /[a-z0-9\._]+/i } + get "uploads/:site/test_:index/original/:tree:sha(.:extension)" => "uploads#show", + :constraints => { + site: /\w+/, + index: /\d+/, + tree: %r{([a-z0-9]+/)+}i, + sha: /\h{40}/, + extension: /[a-z0-9\._]+/i, + } end # used to download attachments (old route) - get "uploads/:site/:id/:sha" => "uploads#show", constraints: { site: /\w+/, id: /\d+/, sha: /\h{16}/, format: /.*/ } + get "uploads/:site/:id/:sha" => "uploads#show", + :constraints => { + site: /\w+/, + id: /\d+/, + sha: /\h{16}/, + format: /.*/, + } # NOTE: secure-media-uploads is the old form, all new URLs generated for # secure uploads will be secure-uploads, this is left in for backwards # compat without needing to rebake all posts for each site. - get "secure-media-uploads/*path(.:extension)" => "uploads#_show_secure_deprecated", constraints: { extension: /[a-z0-9\._]+/i } - get "secure-uploads/*path(.:extension)" => "uploads#show_secure", constraints: { extension: /[a-z0-9\._]+/i } + get "secure-media-uploads/*path(.:extension)" => "uploads#_show_secure_deprecated", + :constraints => { + extension: /[a-z0-9\._]+/i, + } + get "secure-uploads/*path(.:extension)" => "uploads#show_secure", + :constraints => { + extension: /[a-z0-9\._]+/i, + } - get "posts" => "posts#latest", id: "latest_posts", constraints: { format: /(json|rss)/ } - get "private-posts" => "posts#latest", id: "private_posts", constraints: { format: /(json|rss)/ } + get "posts" => "posts#latest", :id => "latest_posts", :constraints => { format: /(json|rss)/ } + get "private-posts" => "posts#latest", + :id => "private_posts", + :constraints => { + format: /(json|rss)/, + } get "posts/by_number/:topic_id/:post_number" => "posts#by_number" get "posts/by-date/:topic_id/:date" => "posts#by_date" get "posts/:id/reply-history" => "posts#reply_history" - get "posts/:id/reply-ids" => "posts#reply_ids" + get "posts/:id/reply-ids" => "posts#reply_ids" get "posts/:id/reply-ids/all" => "posts#all_reply_ids" - get "posts/:username/deleted" => "posts#deleted_posts", constraints: { username: RouteFormat.username } - get "posts/:username/flagged" => "posts#flagged_posts", constraints: { username: RouteFormat.username } - get "posts/:username/pending" => "posts#pending", constraints: { username: RouteFormat.username } + get "posts/:username/deleted" => "posts#deleted_posts", + :constraints => { + username: RouteFormat.username, + } + get "posts/:username/flagged" => "posts#flagged_posts", + :constraints => { + username: RouteFormat.username, + } + get "posts/:username/pending" => "posts#pending", + :constraints => { + username: RouteFormat.username, + } - %w{groups g}.each do |root_path| + %w[groups g].each do |root_path| resources :groups, id: RouteFormat.username, path: root_path do - get "posts.rss" => "groups#posts_feed", format: :rss - get "mentions.rss" => "groups#mentions_feed", format: :rss + get "posts.rss" => "groups#posts_feed", :format => :rss + get "mentions.rss" => "groups#mentions_feed", :format => :rss - get 'members' - get 'posts' - get 'mentions' - get 'counts' - get 'mentionable' - get 'messageable' - get 'logs' => 'groups#histories' - post 'test_email_settings' + get "members" + get "posts" + get "mentions" + get "counts" + get "mentionable" + get "messageable" + get "logs" => "groups#histories" + post "test_email_settings" collection do - get "check-name" => 'groups#check_name' - get 'custom/new' => 'groups#new', constraints: StaffConstraint.new + get "check-name" => "groups#check_name" + get "custom/new" => "groups#new", :constraints => StaffConstraint.new get "search" => "groups#search" end member do - %w{ + %w[ activity activity/:filter requests @@ -646,9 +1048,7 @@ Discourse::Application.routes.draw do manage/categories manage/tags manage/logs - }.each do |path| - get path => 'groups#show' - end + ].each { |path| get path => "groups#show" } get "permissions" => "groups#permissions" put "members" => "groups#add_members" @@ -665,8 +1065,8 @@ Discourse::Application.routes.draw do resources :associated_groups, only: %i[index], constraints: AdminConstraint.new # aliases so old API code works - delete "admin/groups/:id/members" => "groups#remove_member", constraints: AdminConstraint.new - put "admin/groups/:id/members" => "groups#add_members", constraints: AdminConstraint.new + delete "admin/groups/:id/members" => "groups#remove_member", :constraints => AdminConstraint.new + put "admin/groups/:id/members" => "groups#add_members", :constraints => AdminConstraint.new resources :posts do delete "bookmark", to: "posts#destroy_bookmark" @@ -678,10 +1078,10 @@ Discourse::Application.routes.draw do put "notice" get "replies" get "revisions/latest" => "posts#latest_revision" - get "revisions/:revision" => "posts#revisions", constraints: { revision: /\d+/ } - put "revisions/:revision/hide" => "posts#hide_revision", constraints: { revision: /\d+/ } - put "revisions/:revision/show" => "posts#show_revision", constraints: { revision: /\d+/ } - put "revisions/:revision/revert" => "posts#revert", constraints: { revision: /\d+/ } + get "revisions/:revision" => "posts#revisions", :constraints => { revision: /\d+/ } + put "revisions/:revision/hide" => "posts#hide_revision", :constraints => { revision: /\d+/ } + put "revisions/:revision/show" => "posts#show_revision", :constraints => { revision: /\d+/ } + put "revisions/:revision/revert" => "posts#revert", :constraints => { revision: /\d+/ } put "recover" collection do delete "destroy_many" @@ -695,23 +1095,29 @@ Discourse::Application.routes.draw do resources :notifications, except: :show do collection do - put 'mark-read' => 'notifications#mark_read' + put "mark-read" => "notifications#mark_read" # creating an alias cause the api was extended to mark a single notification # this allows us to cleanly target it - put 'read' => 'notifications#mark_read' + put "read" => "notifications#mark_read" end end - match "/auth/failure", to: "users/omniauth_callbacks#failure", via: [:get, :post] + match "/auth/failure", to: "users/omniauth_callbacks#failure", via: %i[get post] get "/auth/:provider", to: "users/omniauth_callbacks#confirm_request" - match "/auth/:provider/callback", to: "users/omniauth_callbacks#complete", via: [:get, :post] - get "/associate/:token", to: "users/associate_accounts#connect_info", constraints: { token: /\h{32}/ } - post "/associate/:token", to: "users/associate_accounts#connect", constraints: { token: /\h{32}/ } + match "/auth/:provider/callback", to: "users/omniauth_callbacks#complete", via: %i[get post] + get "/associate/:token", + to: "users/associate_accounts#connect_info", + constraints: { + token: /\h{32}/, + } + post "/associate/:token", + to: "users/associate_accounts#connect", + constraints: { + token: /\h{32}/, + } resources :clicks do - collection do - post "track" - end + collection { post "track" } end get "excerpt" => "excerpt#show" @@ -727,17 +1133,17 @@ Discourse::Application.routes.draw do resources :user_actions resources :badges, only: [:index] - get "/badges/:id(/:slug)" => "badges#show", constraints: { format: /(json|html|rss)/ } - resources :user_badges, only: [:index, :create, :destroy] do - put "toggle_favorite" => "user_badges#toggle_favorite", constraints: { format: :json } + get "/badges/:id(/:slug)" => "badges#show", :constraints => { format: /(json|html|rss)/ } + resources :user_badges, only: %i[index create destroy] do + put "toggle_favorite" => "user_badges#toggle_favorite", :constraints => { format: :json } end - get '/c', to: redirect(relative_url_root + 'categories') + get "/c", to: redirect(relative_url_root + "categories") - resources :categories, except: [:show, :new, :edit] + resources :categories, except: %i[show new edit] post "categories/reorder" => "categories#reorder" - scope path: 'category/:category_id' do + scope path: "category/:category_id" do post "/move" => "categories#move" post "/notifications" => "categories#set_notifications" put "/slug" => "categories#update_slug" @@ -752,11 +1158,14 @@ Discourse::Application.routes.draw do get "c/:id/visible_groups" => "categories#visible_groups" get "c/*category_slug/find_by_slug" => "categories#find_by_slug" - get "c/*category_slug/edit(/:tab)" => "categories#find_by_slug", constraints: { format: 'html' } - get "/new-category" => "categories#show", constraints: { format: 'html' } + get "c/*category_slug/edit(/:tab)" => "categories#find_by_slug", + :constraints => { + format: "html", + } + get "/new-category" => "categories#show", :constraints => { format: "html" } - get "c/*category_slug_path_with_id.rss" => "list#category_feed", format: :rss - scope path: 'c/*category_slug_path_with_id' do + get "c/*category_slug_path_with_id.rss" => "list#category_feed", :format => :rss + scope path: "c/*category_slug_path_with_id" do get "/none" => "list#category_none_latest" TopTopic.periods.each do |period| @@ -765,12 +1174,16 @@ Discourse::Application.routes.draw do end Discourse.filters.each do |filter| - get "/none/l/#{filter}" => "list#category_none_#{filter}", as: "category_none_#{filter}" - get "/l/#{filter}" => "list#category_#{filter}", as: "category_#{filter}" + get "/none/l/#{filter}" => "list#category_none_#{filter}", :as => "category_none_#{filter}" + get "/l/#{filter}" => "list#category_#{filter}", :as => "category_#{filter}" end - get "/all" => "list#category_default", as: "category_all", constraints: { format: 'html' } - get "/" => "list#category_default", as: "category_default" + get "/all" => "list#category_default", + :as => "category_all", + :constraints => { + format: "html", + } + get "/" => "list#category_default", :as => "category_default" end get "hashtags" => "hashtags#lookup" @@ -783,12 +1196,10 @@ Discourse::Application.routes.draw do end Discourse.anonymous_filters.each do |filter| - get "#{filter}.rss" => "list##{filter}_feed", format: :rss + get "#{filter}.rss" => "list##{filter}_feed", :format => :rss end - Discourse.filters.each do |filter| - get "#{filter}" => "list##{filter}" - end + Discourse.filters.each { |filter| get "#{filter}" => "list##{filter}" } get "search/query" => "search#query" get "search" => "search#show" @@ -796,7 +1207,7 @@ Discourse::Application.routes.draw do # Topics resource get "t/:id" => "topics#show" - put "t/:topic_id" => "topics#update", constraints: { topic_id: /\d+/ } + put "t/:topic_id" => "topics#update", :constraints => { topic_id: /\d+/ } delete "t/:id" => "topics#destroy" put "t/:id/archive-message" => "topics#archive_message" put "t/:id/move-to-inbox" => "topics#move_to_inbox" @@ -805,89 +1216,191 @@ Discourse::Application.routes.draw do put "t/:id/shared-draft" => "topics#update_shared_draft" put "t/:id/reset-bump-date" => "topics#reset_bump_date" put "topics/bulk" - put "topics/reset-new" => 'topics#reset_new' - put "topics/pm-reset-new" => 'topics#private_message_reset_new' + put "topics/reset-new" => "topics#reset_new" + put "topics/pm-reset-new" => "topics#private_message_reset_new" post "topics/timings" - get 'topics/similar_to' => 'similar_topics#index' + get "topics/similar_to" => "similar_topics#index" resources :similar_topics get "topics/feature_stats" scope "/topics", username: RouteFormat.username do - get "created-by/:username" => "list#topics_by", as: "topics_by", defaults: { format: :json } - get "private-messages/:username" => "list#private_messages", as: "topics_private_messages", defaults: { format: :json } - get "private-messages-sent/:username" => "list#private_messages_sent", as: "topics_private_messages_sent", defaults: { format: :json } - get "private-messages-archive/:username" => "list#private_messages_archive", as: "topics_private_messages_archive", defaults: { format: :json } - get "private-messages-unread/:username" => "list#private_messages_unread", as: "topics_private_messages_unread", defaults: { format: :json } - get "private-messages-tags/:username/:tag_id.json" => "list#private_messages_tag", as: "topics_private_messages_tag", defaults: { format: :json } - get "private-messages-new/:username" => "list#private_messages_new", as: "topics_private_messages_new", defaults: { format: :json } - get "private-messages-warnings/:username" => "list#private_messages_warnings", as: "topics_private_messages_warnings", defaults: { format: :json } - get "groups/:group_name" => "list#group_topics", as: "group_topics", group_name: RouteFormat.username + get "created-by/:username" => "list#topics_by", + :as => "topics_by", + :defaults => { + format: :json, + } + get "private-messages/:username" => "list#private_messages", + :as => "topics_private_messages", + :defaults => { + format: :json, + } + get "private-messages-sent/:username" => "list#private_messages_sent", + :as => "topics_private_messages_sent", + :defaults => { + format: :json, + } + get "private-messages-archive/:username" => "list#private_messages_archive", + :as => "topics_private_messages_archive", + :defaults => { + format: :json, + } + get "private-messages-unread/:username" => "list#private_messages_unread", + :as => "topics_private_messages_unread", + :defaults => { + format: :json, + } + get "private-messages-tags/:username/:tag_id.json" => "list#private_messages_tag", + :as => "topics_private_messages_tag", + :defaults => { + format: :json, + } + get "private-messages-new/:username" => "list#private_messages_new", + :as => "topics_private_messages_new", + :defaults => { + format: :json, + } + get "private-messages-warnings/:username" => "list#private_messages_warnings", + :as => "topics_private_messages_warnings", + :defaults => { + format: :json, + } + get "groups/:group_name" => "list#group_topics", + :as => "group_topics", + :group_name => RouteFormat.username scope "/private-messages-group/:username", group_name: RouteFormat.username do - get ":group_name.json" => "list#private_messages_group", as: "topics_private_messages_group" - get ":group_name/archive.json" => "list#private_messages_group_archive", as: "topics_private_messages_group_archive" - get ":group_name/new.json" => "list#private_messages_group_new", as: "topics_private_messages_group_new" - get ":group_name/unread.json" => "list#private_messages_group_unread", as: "topics_private_messages_group_unread" + get ":group_name.json" => "list#private_messages_group", + :as => "topics_private_messages_group" + get ":group_name/archive.json" => "list#private_messages_group_archive", + :as => "topics_private_messages_group_archive" + get ":group_name/new.json" => "list#private_messages_group_new", + :as => "topics_private_messages_group_new" + get ":group_name/unread.json" => "list#private_messages_group_unread", + :as => "topics_private_messages_group_unread" end end - get 'embed/topics' => 'embed#topics' - get 'embed/comments' => 'embed#comments' - get 'embed/count' => 'embed#count' - get 'embed/info' => 'embed#info' + get "embed/topics" => "embed#topics" + get "embed/comments" => "embed#comments" + get "embed/count" => "embed#count" + get "embed/info" => "embed#info" get "new-topic" => "new_topic#index" get "new-message" => "new_topic#index" # Topic routes get "t/id_for/:slug" => "topics#id_for_slug" - get "t/external_id/:external_id" => "topics#show_by_external_id", format: :json, constraints: { external_id: /[\w-]+/ } - get "t/:slug/:topic_id/print" => "topics#show", format: :html, print: 'true', constraints: { topic_id: /\d+/ } - get "t/:slug/:topic_id/wordpress" => "topics#wordpress", constraints: { topic_id: /\d+/ } - get "t/:topic_id/wordpress" => "topics#wordpress", constraints: { topic_id: /\d+/ } - get "t/:slug/:topic_id/moderator-liked" => "topics#moderator_liked", constraints: { topic_id: /\d+/ } - get "t/:slug/:topic_id/summary" => "topics#show", defaults: { summary: true }, constraints: { topic_id: /\d+/ } - get "t/:topic_id/summary" => "topics#show", constraints: { topic_id: /\d+/ } - put "t/:slug/:topic_id" => "topics#update", constraints: { topic_id: /\d+/ } - put "t/:slug/:topic_id/star" => "topics#star", constraints: { topic_id: /\d+/ } - put "t/:topic_id/star" => "topics#star", constraints: { topic_id: /\d+/ } - put "t/:slug/:topic_id/status" => "topics#status", constraints: { topic_id: /\d+/ } - put "t/:topic_id/status" => "topics#status", constraints: { topic_id: /\d+/ } - put "t/:topic_id/clear-pin" => "topics#clear_pin", constraints: { topic_id: /\d+/ } - put "t/:topic_id/re-pin" => "topics#re_pin", constraints: { topic_id: /\d+/ } - put "t/:topic_id/mute" => "topics#mute", constraints: { topic_id: /\d+/ } - put "t/:topic_id/unmute" => "topics#unmute", constraints: { topic_id: /\d+/ } - post "t/:topic_id/timer" => "topics#timer", constraints: { topic_id: /\d+/ } - put "t/:topic_id/make-banner" => "topics#make_banner", constraints: { topic_id: /\d+/ } - put "t/:topic_id/remove-banner" => "topics#remove_banner", constraints: { topic_id: /\d+/ } - put "t/:topic_id/remove-allowed-user" => "topics#remove_allowed_user", constraints: { topic_id: /\d+/ } - put "t/:topic_id/remove-allowed-group" => "topics#remove_allowed_group", constraints: { topic_id: /\d+/ } - put "t/:topic_id/recover" => "topics#recover", constraints: { topic_id: /\d+/ } - get "t/:topic_id/:post_number" => "topics#show", constraints: { topic_id: /\d+/, post_number: /\d+/ } - get "t/:topic_id/last" => "topics#show", post_number: 99999999, constraints: { topic_id: /\d+/ } - get "t/:slug/:topic_id.rss" => "topics#feed", format: :rss, constraints: { topic_id: /\d+/ } - get "t/:slug/:topic_id" => "topics#show", constraints: { topic_id: /\d+/ } - get "t/:slug/:topic_id/:post_number" => "topics#show", constraints: { topic_id: /\d+/, post_number: /\d+/ } - get "t/:slug/:topic_id/last" => "topics#show", post_number: 99999999, constraints: { topic_id: /\d+/ } - get "t/:topic_id/posts" => "topics#posts", constraints: { topic_id: /\d+/ }, format: :json - get "t/:topic_id/post_ids" => "topics#post_ids", constraints: { topic_id: /\d+/ }, format: :json - get "t/:topic_id/excerpts" => "topics#excerpts", constraints: { topic_id: /\d+/ }, format: :json - post "t/:topic_id/timings" => "topics#timings", constraints: { topic_id: /\d+/ } - post "t/:topic_id/invite" => "topics#invite", constraints: { topic_id: /\d+/ } - post "t/:topic_id/invite-group" => "topics#invite_group", constraints: { topic_id: /\d+/ } - post "t/:topic_id/move-posts" => "topics#move_posts", constraints: { topic_id: /\d+/ } - post "t/:topic_id/merge-topic" => "topics#merge_topic", constraints: { topic_id: /\d+/ } - post "t/:topic_id/change-owner" => "topics#change_post_owners", constraints: { topic_id: /\d+/ } - put "t/:topic_id/change-timestamp" => "topics#change_timestamps", constraints: { topic_id: /\d+/ } - delete "t/:topic_id/timings" => "topics#destroy_timings", constraints: { topic_id: /\d+/ } - put "t/:topic_id/bookmark" => "topics#bookmark", constraints: { topic_id: /\d+/ } - put "t/:topic_id/remove_bookmarks" => "topics#remove_bookmarks", constraints: { topic_id: /\d+/ } - put "t/:topic_id/tags" => "topics#update_tags", constraints: { topic_id: /\d+/ } - put "t/:topic_id/slow_mode" => "topics#set_slow_mode", constraints: { topic_id: /\d+/ } + get "t/external_id/:external_id" => "topics#show_by_external_id", + :format => :json, + :constraints => { + external_id: /[\w-]+/, + } + get "t/:slug/:topic_id/print" => "topics#show", + :format => :html, + :print => "true", + :constraints => { + topic_id: /\d+/, + } + get "t/:slug/:topic_id/wordpress" => "topics#wordpress", :constraints => { topic_id: /\d+/ } + get "t/:topic_id/wordpress" => "topics#wordpress", :constraints => { topic_id: /\d+/ } + get "t/:slug/:topic_id/moderator-liked" => "topics#moderator_liked", + :constraints => { + topic_id: /\d+/, + } + get "t/:slug/:topic_id/summary" => "topics#show", + :defaults => { + summary: true, + }, + :constraints => { + topic_id: /\d+/, + } + get "t/:topic_id/summary" => "topics#show", :constraints => { topic_id: /\d+/ } + put "t/:slug/:topic_id" => "topics#update", :constraints => { topic_id: /\d+/ } + put "t/:slug/:topic_id/star" => "topics#star", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/star" => "topics#star", :constraints => { topic_id: /\d+/ } + put "t/:slug/:topic_id/status" => "topics#status", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/status" => "topics#status", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/clear-pin" => "topics#clear_pin", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/re-pin" => "topics#re_pin", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/mute" => "topics#mute", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/unmute" => "topics#unmute", :constraints => { topic_id: /\d+/ } + post "t/:topic_id/timer" => "topics#timer", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/make-banner" => "topics#make_banner", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/remove-banner" => "topics#remove_banner", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/remove-allowed-user" => "topics#remove_allowed_user", + :constraints => { + topic_id: /\d+/, + } + put "t/:topic_id/remove-allowed-group" => "topics#remove_allowed_group", + :constraints => { + topic_id: /\d+/, + } + put "t/:topic_id/recover" => "topics#recover", :constraints => { topic_id: /\d+/ } + get "t/:topic_id/:post_number" => "topics#show", + :constraints => { + topic_id: /\d+/, + post_number: /\d+/, + } + get "t/:topic_id/last" => "topics#show", + :post_number => 99_999_999, + :constraints => { + topic_id: /\d+/, + } + get "t/:slug/:topic_id.rss" => "topics#feed", + :format => :rss, + :constraints => { + topic_id: /\d+/, + } + get "t/:slug/:topic_id" => "topics#show", :constraints => { topic_id: /\d+/ } + get "t/:slug/:topic_id/:post_number" => "topics#show", + :constraints => { + topic_id: /\d+/, + post_number: /\d+/, + } + get "t/:slug/:topic_id/last" => "topics#show", + :post_number => 99_999_999, + :constraints => { + topic_id: /\d+/, + } + get "t/:topic_id/posts" => "topics#posts", :constraints => { topic_id: /\d+/ }, :format => :json + get "t/:topic_id/post_ids" => "topics#post_ids", + :constraints => { + topic_id: /\d+/, + }, + :format => :json + get "t/:topic_id/excerpts" => "topics#excerpts", + :constraints => { + topic_id: /\d+/, + }, + :format => :json + post "t/:topic_id/timings" => "topics#timings", :constraints => { topic_id: /\d+/ } + post "t/:topic_id/invite" => "topics#invite", :constraints => { topic_id: /\d+/ } + post "t/:topic_id/invite-group" => "topics#invite_group", :constraints => { topic_id: /\d+/ } + post "t/:topic_id/move-posts" => "topics#move_posts", :constraints => { topic_id: /\d+/ } + post "t/:topic_id/merge-topic" => "topics#merge_topic", :constraints => { topic_id: /\d+/ } + post "t/:topic_id/change-owner" => "topics#change_post_owners", + :constraints => { + topic_id: /\d+/, + } + put "t/:topic_id/change-timestamp" => "topics#change_timestamps", + :constraints => { + topic_id: /\d+/, + } + delete "t/:topic_id/timings" => "topics#destroy_timings", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/bookmark" => "topics#bookmark", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/remove_bookmarks" => "topics#remove_bookmarks", + :constraints => { + topic_id: /\d+/, + } + put "t/:topic_id/tags" => "topics#update_tags", :constraints => { topic_id: /\d+/ } + put "t/:topic_id/slow_mode" => "topics#set_slow_mode", :constraints => { topic_id: /\d+/ } - post "t/:topic_id/notifications" => "topics#set_notifications" , constraints: { topic_id: /\d+/ } + post "t/:topic_id/notifications" => "topics#set_notifications", + :constraints => { + topic_id: /\d+/, + } get "p/:post_id(/:user_id)" => "posts#short_link" get "/posts/:id/cooked" => "posts#cooked" @@ -897,7 +1410,7 @@ Discourse::Application.routes.draw do get "raw/:topic_id(/:post_number)" => "posts#markdown_num" resources :invites, except: [:show] - get "/invites/:id" => "invites#show", constraints: { format: :html } + get "/invites/:id" => "invites#show", :constraints => { format: :html } put "/invites/:id" => "invites#update" post "invites/upload_csv" => "invites#upload_csv" @@ -905,13 +1418,11 @@ Discourse::Application.routes.draw do post "invites/reinvite" => "invites#resend_invite" post "invites/reinvite-all" => "invites#resend_all_invites" delete "invites" => "invites#destroy" - put "invites/show/:id" => "invites#perform_accept_invitation", as: 'perform_accept_invite' + put "invites/show/:id" => "invites#perform_accept_invitation", :as => "perform_accept_invite" get "invites/retrieve" => "invites#retrieve" resources :export_csv do - collection do - post "export_entity" => "export_csv#export_entity" - end + collection { post "export_entity" => "export_csv#export_entity" } end get "onebox" => "onebox#show" @@ -921,95 +1432,129 @@ Discourse::Application.routes.draw do get "message-bus/poll" => "message_bus#poll" - resources :drafts, only: [:index, :create, :show, :destroy] + resources :drafts, only: %i[index create show destroy] - get "/service-worker.js" => "static#service_worker_asset", format: :js - if service_worker_asset = Rails.application.assets_manifest.assets['service-worker.js'] + get "/service-worker.js" => "static#service_worker_asset", :format => :js + if service_worker_asset = Rails.application.assets_manifest.assets["service-worker.js"] # https://developers.google.com/web/fundamentals/codelabs/debugging-service-workers/ # Normally the browser will wait until a user closes all tabs that contain the # current site before updating to a new Service Worker. # Support the old Service Worker path to avoid routing error filling up the # logs. - get service_worker_asset => "static#service_worker_asset", format: :js + get service_worker_asset => "static#service_worker_asset", :format => :js end - get "cdn_asset/:site/*path" => "static#cdn_asset", format: false, constraints: { format: /.*/ } - get "brotli_asset/*path" => "static#brotli_asset", format: false, constraints: { format: /.*/ } + get "cdn_asset/:site/*path" => "static#cdn_asset", + :format => false, + :constraints => { + format: /.*/, + } + get "brotli_asset/*path" => "static#brotli_asset", + :format => false, + :constraints => { + format: /.*/, + } - get "favicon/proxied" => "static#favicon", format: false + get "favicon/proxied" => "static#favicon", :format => false get "robots.txt" => "robots_txt#index" get "robots-builder.json" => "robots_txt#builder" get "offline.html" => "offline#index" - get "manifest.webmanifest" => "metadata#manifest", as: :manifest + get "manifest.webmanifest" => "metadata#manifest", :as => :manifest get "manifest.json" => "metadata#manifest" get ".well-known/assetlinks.json" => "metadata#app_association_android" - get "apple-app-site-association" => "metadata#app_association_ios", format: false - get "opensearch" => "metadata#opensearch", constraints: { format: :xml } + get "apple-app-site-association" => "metadata#app_association_ios", :format => false + get "opensearch" => "metadata#opensearch", :constraints => { format: :xml } - scope '/tag/:tag_id' do + scope "/tag/:tag_id" do constraints format: :json do - get '/' => 'tags#show', as: 'tag_show' - get '/info' => 'tags#info' - get '/notifications' => 'tags#notifications' - put '/notifications' => 'tags#update_notifications' - put '/' => 'tags#update' - delete '/' => 'tags#destroy' - post '/synonyms' => 'tags#create_synonyms' - delete '/synonyms/:synonym_id' => 'tags#destroy_synonym' + get "/" => "tags#show", :as => "tag_show" + get "/info" => "tags#info" + get "/notifications" => "tags#notifications" + put "/notifications" => "tags#update_notifications" + put "/" => "tags#update" + delete "/" => "tags#destroy" + post "/synonyms" => "tags#create_synonyms" + delete "/synonyms/:synonym_id" => "tags#destroy_synonym" Discourse.filters.each do |filter| - get "/l/#{filter}" => "tags#show_#{filter}", as: "tag_show_#{filter}" + get "/l/#{filter}" => "tags#show_#{filter}", :as => "tag_show_#{filter}" end end constraints format: :rss do - get '/' => 'tags#tag_feed' + get "/" => "tags#tag_feed" end end scope "/tags" do - get '/' => 'tags#index' - get '/filter/list' => 'tags#index' - get '/filter/search' => 'tags#search' - get '/personal_messages/:username' => 'tags#personal_messages', constraints: { username: RouteFormat.username } - post '/upload' => 'tags#upload' - get '/unused' => 'tags#list_unused' - delete '/unused' => 'tags#destroy_unused' + get "/" => "tags#index" + get "/filter/list" => "tags#index" + get "/filter/search" => "tags#search" + get "/personal_messages/:username" => "tags#personal_messages", + :constraints => { + username: RouteFormat.username, + } + post "/upload" => "tags#upload" + get "/unused" => "tags#list_unused" + delete "/unused" => "tags#destroy_unused" - constraints(tag_id: /[^\/]+?/, format: /json|rss/) do - scope path: '/c/*category_slug_path_with_id' do + constraints(tag_id: %r{[^/]+?}, format: /json|rss/) do + scope path: "/c/*category_slug_path_with_id" do Discourse.filters.each do |filter| - get "/none/:tag_id/l/#{filter}" => "tags#show_#{filter}", as: "tag_category_none_show_#{filter}", defaults: { no_subcategories: true } - get "/all/:tag_id/l/#{filter}" => "tags#show_#{filter}", as: "tag_category_all_show_#{filter}", defaults: { no_subcategories: false } + get "/none/:tag_id/l/#{filter}" => "tags#show_#{filter}", + :as => "tag_category_none_show_#{filter}", + :defaults => { + no_subcategories: true, + } + get "/all/:tag_id/l/#{filter}" => "tags#show_#{filter}", + :as => "tag_category_all_show_#{filter}", + :defaults => { + no_subcategories: false, + } end - get '/none/:tag_id' => 'tags#show', as: 'tag_category_none_show', defaults: { no_subcategories: true } - get '/all/:tag_id' => 'tags#show', as: 'tag_category_all_show', defaults: { no_subcategories: false } + get "/none/:tag_id" => "tags#show", + :as => "tag_category_none_show", + :defaults => { + no_subcategories: true, + } + get "/all/:tag_id" => "tags#show", + :as => "tag_category_all_show", + :defaults => { + no_subcategories: false, + } Discourse.filters.each do |filter| - get "/:tag_id/l/#{filter}" => "tags#show_#{filter}", as: "tag_category_show_#{filter}" + get "/:tag_id/l/#{filter}" => "tags#show_#{filter}", + :as => "tag_category_show_#{filter}" end - get '/:tag_id' => 'tags#show', as: 'tag_category_show' + get "/:tag_id" => "tags#show", :as => "tag_category_show" end - get '/intersection/:tag_id/*additional_tag_ids' => 'tags#show', as: 'tag_intersection' + get "/intersection/:tag_id/*additional_tag_ids" => "tags#show", :as => "tag_intersection" end - get '*tag_id', to: redirect(relative_url_root + 'tag/%{tag_id}') + get "*tag_id", to: redirect(relative_url_root + "tag/%{tag_id}") end resources :tag_groups, constraints: StaffConstraint.new, except: [:edit] - get '/tag_groups/filter/search' => 'tag_groups#search', format: :json + get "/tag_groups/filter/search" => "tag_groups#search", :format => :json Discourse.filters.each do |filter| - root to: "list##{filter}", constraints: HomePageConstraint.new("#{filter}"), as: "list_#{filter}" + root to: "list##{filter}", + constraints: HomePageConstraint.new("#{filter}"), + as: "list_#{filter}" end # special case for categories - root to: "categories#index", constraints: HomePageConstraint.new("categories"), as: "categories_index" + root to: "categories#index", + constraints: HomePageConstraint.new("categories"), + as: "categories_index" - root to: 'finish_installation#index', constraints: HomePageConstraint.new("finish_installation"), as: 'installation_redirect' + root to: "finish_installation#index", + constraints: HomePageConstraint.new("finish_installation"), + as: "installation_redirect" get "/user-api-key/new" => "user_api_keys#new" post "/user-api-key" => "user_api_keys#create" @@ -1019,7 +1564,7 @@ Discourse::Application.routes.draw do post "/user-api-key/otp" => "user_api_keys#create_otp" get "/safe-mode" => "safe_mode#index" - post "/safe-mode" => "safe_mode#enter", as: "safe_mode_enter" + post "/safe-mode" => "safe_mode#enter", :as => "safe_mode_enter" get "/theme-qunit" => "qunit#theme" @@ -1028,7 +1573,7 @@ Discourse::Application.routes.draw do resources :csp_reports, only: [:create] - get "/permalink-check", to: 'permalinks#check' + get "/permalink-check", to: "permalinks#check" post "/do-not-disturb" => "do_not_disturb#create" delete "/do-not-disturb" => "do_not_disturb#destroy" @@ -1040,6 +1585,6 @@ Discourse::Application.routes.draw do put "user-status" => "user_status#set" delete "user-status" => "user_status#clear" - get "*url", to: 'permalinks#show', constraints: PermalinkConstraint.new + get "*url", to: "permalinks#show", constraints: PermalinkConstraint.new end end diff --git a/config/spring.rb b/config/spring.rb index 68b1b41a334..8d12edf4a80 100644 --- a/config/spring.rb +++ b/config/spring.rb @@ -7,7 +7,5 @@ # spring binstub rails # spring binstub rake # spring binstub rspec -Spring.after_fork do - Discourse.after_fork -end +Spring.after_fork { Discourse.after_fork } Spring::Commands::Rake.environment_matchers["spec"] = "test" diff --git a/config/unicorn.conf.rb b/config/unicorn.conf.rb index e69979adfe1..2e0b22f48f4 100644 --- a/config/unicorn.conf.rb +++ b/config/unicorn.conf.rb @@ -3,9 +3,9 @@ # See http://unicorn.bogomips.org/Unicorn/Configurator.html if (ENV["LOGSTASH_UNICORN_URI"] || "").length > 0 - require_relative '../lib/discourse_logstash_logger' - require_relative '../lib/unicorn_logstash_patch' - logger DiscourseLogstashLogger.logger(uri: ENV['LOGSTASH_UNICORN_URI'], type: :unicorn) + require_relative "../lib/discourse_logstash_logger" + require_relative "../lib/unicorn_logstash_patch" + logger DiscourseLogstashLogger.logger(uri: ENV["LOGSTASH_UNICORN_URI"], type: :unicorn) end discourse_path = File.expand_path(File.expand_path(File.dirname(__FILE__)) + "/../") @@ -16,11 +16,10 @@ worker_processes (ENV["UNICORN_WORKERS"] || 3).to_i working_directory discourse_path # listen "#{discourse_path}/tmp/sockets/unicorn.sock" -listen ENV["UNICORN_LISTENER"] || "#{(ENV["UNICORN_BIND_ALL"] ? "" : "127.0.0.1:")}#{(ENV["UNICORN_PORT"] || 3000).to_i}" +listen ENV["UNICORN_LISTENER"] || + "#{(ENV["UNICORN_BIND_ALL"] ? "" : "127.0.0.1:")}#{(ENV["UNICORN_PORT"] || 3000).to_i}" -if !File.exist?("#{discourse_path}/tmp/pids") - FileUtils.mkdir_p("#{discourse_path}/tmp/pids") -end +FileUtils.mkdir_p("#{discourse_path}/tmp/pids") if !File.exist?("#{discourse_path}/tmp/pids") # feel free to point this anywhere accessible on the filesystem pid (ENV["UNICORN_PID_PATH"] || "#{discourse_path}/tmp/pids/unicorn.pid") @@ -52,7 +51,6 @@ check_client_connection false initialized = false before_fork do |server, worker| - unless initialized Discourse.preload_rails! @@ -67,7 +65,7 @@ before_fork do |server, worker| initialized = true - supervisor = ENV['UNICORN_SUPERVISOR_PID'].to_i + supervisor = ENV["UNICORN_SUPERVISOR_PID"].to_i if supervisor > 0 Thread.new do while true @@ -80,14 +78,12 @@ before_fork do |server, worker| end end - sidekiqs = ENV['UNICORN_SIDEKIQS'].to_i + sidekiqs = ENV["UNICORN_SIDEKIQS"].to_i if sidekiqs > 0 server.logger.info "starting #{sidekiqs} supervised sidekiqs" - require 'demon/sidekiq' - Demon::Sidekiq.after_fork do - DiscourseEvent.trigger(:sidekiq_fork_started) - end + require "demon/sidekiq" + Demon::Sidekiq.after_fork { DiscourseEvent.trigger(:sidekiq_fork_started) } Demon::Sidekiq.start(sidekiqs) @@ -98,13 +94,14 @@ before_fork do |server, worker| # Trap USR1, so we can re-issue to sidekiq workers # but chain the default unicorn implementation as well - old_handler = Signal.trap("USR1") do - Demon::Sidekiq.kill("USR1") - old_handler.call - end + old_handler = + Signal.trap("USR1") do + Demon::Sidekiq.kill("USR1") + old_handler.call + end end - if ENV['DISCOURSE_ENABLE_EMAIL_SYNC_DEMON'] == 'true' + if ENV["DISCOURSE_ENABLE_EMAIL_SYNC_DEMON"] == "true" server.logger.info "starting up EmailSync demon" Demon::EmailSync.start Signal.trap("SIGTSTP") do @@ -119,13 +116,13 @@ before_fork do |server, worker| end class ::Unicorn::HttpServer - alias :master_sleep_orig :master_sleep + alias master_sleep_orig master_sleep def max_sidekiq_rss - rss = `ps -eo rss,args | grep sidekiq | grep -v grep | awk '{print $1}'` - .split("\n") - .map(&:to_i) - .max + rss = + `ps -eo rss,args | grep sidekiq | grep -v grep | awk '{print $1}'`.split("\n") + .map(&:to_i) + .max rss ||= 0 @@ -133,18 +130,24 @@ before_fork do |server, worker| end def max_allowed_sidekiq_rss - [ENV['UNICORN_SIDEKIQ_MAX_RSS'].to_i, 500].max.megabytes + [ENV["UNICORN_SIDEKIQ_MAX_RSS"].to_i, 500].max.megabytes end def force_kill_rogue_sidekiq info = `ps -eo pid,rss,args | grep sidekiq | grep -v grep | awk '{print $1,$2}'` - info.split("\n").each do |row| - pid, mem = row.split(" ").map(&:to_i) - if pid > 0 && (mem * 1024) > max_allowed_sidekiq_rss - Rails.logger.warn "Detected rogue Sidekiq pid #{pid} mem #{mem * 1024}, killing" - Process.kill("KILL", pid) rescue nil + info + .split("\n") + .each do |row| + pid, mem = row.split(" ").map(&:to_i) + if pid > 0 && (mem * 1024) > max_allowed_sidekiq_rss + Rails.logger.warn "Detected rogue Sidekiq pid #{pid} mem #{mem * 1024}, killing" + begin + Process.kill("KILL", pid) + rescue StandardError + nil + end + end end - end end def check_sidekiq_heartbeat @@ -152,13 +155,15 @@ before_fork do |server, worker| @sidekiq_next_heartbeat_check ||= Time.now.to_i + @sidekiq_heartbeat_interval if @sidekiq_next_heartbeat_check < Time.now.to_i - last_heartbeat = Jobs::RunHeartbeat.last_heartbeat restart = false sidekiq_rss = max_sidekiq_rss if sidekiq_rss > max_allowed_sidekiq_rss - Rails.logger.warn("Sidekiq is consuming too much memory (using: %0.2fM) for '%s', restarting" % [(sidekiq_rss.to_f / 1.megabyte), ENV["DISCOURSE_HOSTNAME"]]) + Rails.logger.warn( + "Sidekiq is consuming too much memory (using: %0.2fM) for '%s', restarting" % + [(sidekiq_rss.to_f / 1.megabyte), ENV["DISCOURSE_HOSTNAME"]], + ) restart = true end @@ -185,16 +190,18 @@ before_fork do |server, worker| email_sync_pids = Demon::EmailSync.demons.map { |uid, demon| demon.pid } return 0 if email_sync_pids.empty? - rss = `ps -eo pid,rss,args | grep '#{email_sync_pids.join('|')}' | grep -v grep | awk '{print $2}'` - .split("\n") - .map(&:to_i) - .max + rss = + `ps -eo pid,rss,args | grep '#{email_sync_pids.join("|")}' | grep -v grep | awk '{print $2}'`.split( + "\n", + ) + .map(&:to_i) + .max (rss || 0) * 1024 end def max_allowed_email_sync_rss - [ENV['UNICORN_EMAIL_SYNC_MAX_RSS'].to_i, 500].max.megabytes + [ENV["UNICORN_EMAIL_SYNC_MAX_RSS"].to_i, 500].max.megabytes end def check_email_sync_heartbeat @@ -207,16 +214,22 @@ before_fork do |server, worker| restart = false # Restart process if it does not respond anymore - last_heartbeat_ago = Time.now.to_i - Discourse.redis.get(Demon::EmailSync::HEARTBEAT_KEY).to_i + last_heartbeat_ago = + Time.now.to_i - Discourse.redis.get(Demon::EmailSync::HEARTBEAT_KEY).to_i if last_heartbeat_ago > Demon::EmailSync::HEARTBEAT_INTERVAL.to_i - STDERR.puts("EmailSync heartbeat test failed (last heartbeat was #{last_heartbeat_ago}s ago), restarting") + STDERR.puts( + "EmailSync heartbeat test failed (last heartbeat was #{last_heartbeat_ago}s ago), restarting", + ) restart = true end # Restart process if memory usage is too high email_sync_rss = max_email_sync_rss if email_sync_rss > max_allowed_email_sync_rss - STDERR.puts("EmailSync is consuming too much memory (using: %0.2fM) for '%s', restarting" % [(email_sync_rss.to_f / 1.megabyte), ENV["DISCOURSE_HOSTNAME"]]) + STDERR.puts( + "EmailSync is consuming too much memory (using: %0.2fM) for '%s', restarting" % + [(email_sync_rss.to_f / 1.megabyte), ENV["DISCOURSE_HOSTNAME"]], + ) restart = true end @@ -224,25 +237,22 @@ before_fork do |server, worker| end def master_sleep(sec) - sidekiqs = ENV['UNICORN_SIDEKIQS'].to_i + sidekiqs = ENV["UNICORN_SIDEKIQS"].to_i if sidekiqs > 0 Demon::Sidekiq.ensure_running check_sidekiq_heartbeat end - if ENV['DISCOURSE_ENABLE_EMAIL_SYNC_DEMON'] == 'true' + if ENV["DISCOURSE_ENABLE_EMAIL_SYNC_DEMON"] == "true" Demon::EmailSync.ensure_running check_email_sync_heartbeat end - DiscoursePluginRegistry.demon_processes.each do |demon_class| - demon_class.ensure_running - end + DiscoursePluginRegistry.demon_processes.each { |demon_class| demon_class.ensure_running } master_sleep_orig(sec) end end - end Discourse.redis.close