diff --git a/.licensed.yml b/.licensed.yml index 178118521fd..f89daae2bd0 100644 --- a/.licensed.yml +++ b/.licensed.yml @@ -13,6 +13,7 @@ allowed: ignored: bundler: - rchardet # Ruby terms + - strscan # Ruby reviewed: bundler: @@ -31,10 +32,16 @@ reviewed: - highline # GPL-2.0 OR Ruby terms - htmlentities # MIT - image_size # MIT + - io-wait # Ruby terms - json # Ruby terms - jwt # MIT - kgio # LGPL-2.1+ - logstash-event # Apache-2.0 + - net-http # Ruby + - net-imap # Ruby + - net-pop # Ruby + - net-protocol # Ruby + - net-smtp # Ruby - omniauth # MIT - openssl # Ruby terms - pg # Ruby terms @@ -44,5 +51,7 @@ reviewed: - rubyzip # Ruby terms - sidekiq # LGPL (Sidekiq) - tilt + - timeout # Ruby - unf # BSD-2-Clause - - unicorn \ No newline at end of file + - unicorn + - uri # Ruby diff --git a/Gemfile b/Gemfile index c66a3f25542..b7c7012bb1d 100644 --- a/Gemfile +++ b/Gemfile @@ -18,7 +18,7 @@ else # this allows us to include the bits of rails we use without pieces we do not. # # To issue a rails update bump the version number here - rails_version = '6.1.4.7' + rails_version = '7.0.2.4' gem 'actionmailer', rails_version gem 'actionpack', rails_version gem 'actionview', rails_version @@ -68,7 +68,7 @@ gem 'http_accept_language', require: false gem 'discourse-ember-rails', '0.18.6', require: 'ember-rails' gem 'discourse-ember-source', '~> 3.12.2' gem 'ember-handlebars-template', '0.8.0' -gem 'discourse-fonts' +gem 'discourse-fonts', require: 'discourse_fonts' gem 'barber' @@ -190,7 +190,7 @@ if ENV["ALLOW_DEV_POPULATE"] == "1" gem 'discourse_dev_assets' gem 'faker', "~> 2.16" else - group :development do + group :development, :test do gem 'discourse_dev_assets' gem 'faker', "~> 2.16" end @@ -268,3 +268,7 @@ gem 'colored2', require: false gem 'maxminddb' gem 'rails_failover', require: false + +# workaround for faraday-net_http, see +# https://github.com/ruby/net-imap/issues/16#issuecomment-803086765 +gem 'net-http' diff --git a/Gemfile.lock b/Gemfile.lock index 0b297095957..fa91ed2dc7e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,22 +8,25 @@ GIT GEM remote: https://rubygems.org/ specs: - actionmailer (6.1.4.7) - actionpack (= 6.1.4.7) - actionview (= 6.1.4.7) - activejob (= 6.1.4.7) - activesupport (= 6.1.4.7) + actionmailer (7.0.2.4) + actionpack (= 7.0.2.4) + actionview (= 7.0.2.4) + activejob (= 7.0.2.4) + activesupport (= 7.0.2.4) mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp rails-dom-testing (~> 2.0) - actionpack (6.1.4.7) - actionview (= 6.1.4.7) - activesupport (= 6.1.4.7) - rack (~> 2.0, >= 2.0.9) + actionpack (7.0.2.4) + actionview (= 7.0.2.4) + activesupport (= 7.0.2.4) + rack (~> 2.0, >= 2.2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actionview (6.1.4.7) - activesupport (= 6.1.4.7) + actionview (7.0.2.4) + activesupport (= 7.0.2.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -32,20 +35,19 @@ GEM actionview (>= 6.0.a) active_model_serializers (0.8.4) activemodel (>= 3.0) - activejob (6.1.4.7) - activesupport (= 6.1.4.7) + activejob (7.0.2.4) + activesupport (= 7.0.2.4) globalid (>= 0.3.6) - activemodel (6.1.4.7) - activesupport (= 6.1.4.7) - activerecord (6.1.4.7) - activemodel (= 6.1.4.7) - activesupport (= 6.1.4.7) - activesupport (6.1.4.7) + activemodel (7.0.2.4) + activesupport (= 7.0.2.4) + activerecord (7.0.2.4) + activemodel (= 7.0.2.4) + activesupport (= 7.0.2.4) + activesupport (7.0.2.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - zeitwerk (~> 2.3) addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) annotate (3.2.0) @@ -106,6 +108,7 @@ GEM debug_inspector (1.1.0) diff-lcs (1.5.0) diffy (3.4.0) + digest (3.1.0) discourse-ember-rails (0.18.6) active_model_serializers ember-data-source (>= 1.0.0.beta.5) @@ -185,6 +188,7 @@ GEM progress (~> 3.0, >= 3.0.1) image_size (3.0.1) in_threads (1.6.0) + io-wait (0.2.1) ipaddr (1.2.4) jmespath (1.6.1) jquery-rails (4.4.0) @@ -246,6 +250,24 @@ GEM multi_xml (0.6.0) multipart-post (2.1.1) mustache (1.1.1) + net-http (0.2.0) + net-protocol + uri + net-imap (0.2.3) + digest + net-protocol + strscan + net-pop (0.1.1) + digest + net-protocol + timeout + net-protocol (0.1.2) + io-wait + timeout + net-smtp (0.3.1) + digest + net-protocol + timeout nio4r (2.5.8) nokogiri (1.13.4) mini_portile2 (~> 2.8.0) @@ -332,12 +354,13 @@ GEM rails_multisite (4.0.1) activerecord (> 5.0, < 7.1) railties (> 5.0, < 7.1) - railties (6.1.4.7) - actionpack (= 6.1.4.7) - activesupport (= 6.1.4.7) + railties (7.0.2.4) + actionpack (= 7.0.2.4) + activesupport (= 7.0.2.4) method_source - rake (>= 0.13) + rake (>= 12.2) thor (~> 1.0) + zeitwerk (~> 2.5) rainbow (3.1.1) raindrops (0.20.0) rake (13.0.6) @@ -452,9 +475,11 @@ GEM sprockets (>= 3.0.0) sshkey (2.0.0) stackprof (0.2.19) + strscan (3.0.1) test-prof (1.0.8) thor (1.2.1) tilt (2.0.10) + timeout (0.2.0) tzinfo (2.0.4) concurrent-ruby (~> 1.0) uglifier (4.2.0) @@ -467,6 +492,7 @@ GEM kgio (~> 2.6) raindrops (~> 0.7) uniform_notifier (1.16.0) + uri (0.11.0) uri_template (0.7.0) webmock (3.14.0) addressable (>= 2.8.0) @@ -489,14 +515,14 @@ PLATFORMS x86_64-linux DEPENDENCIES - actionmailer (= 6.1.4.7) - actionpack (= 6.1.4.7) - actionview (= 6.1.4.7) + actionmailer (= 7.0.2.4) + actionpack (= 7.0.2.4) + actionview (= 7.0.2.4) actionview_precompiler active_model_serializers (~> 0.8.3) - activemodel (= 6.1.4.7) - activerecord (= 6.1.4.7) - activesupport (= 6.1.4.7) + activemodel (= 7.0.2.4) + activerecord (= 7.0.2.4) + activesupport (= 7.0.2.4) addressable annotate aws-sdk-s3 @@ -556,6 +582,7 @@ DEPENDENCIES mocha multi_json mustache + net-http nokogiri oj omniauth @@ -575,7 +602,7 @@ DEPENDENCIES rack-protection rails_failover rails_multisite - railties (= 6.1.4.7) + railties (= 7.0.2.4) rake rb-fsevent rbtrace diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4e6b69a49cc..3507affa497 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -68,7 +68,7 @@ class ApplicationController < ActionController::Base def use_crawler_layout? @use_crawler_layout ||= request.user_agent && - (request.content_type.blank? || request.content_type.include?('html')) && + (request.media_type.blank? || request.media_type.include?('html')) && !['json', 'rss'].include?(params[:format]) && (has_escaped_fragment? || params.key?("print") || show_browser_update? || CrawlerDetection.crawler?(request.user_agent, request.headers["HTTP_VIA"]) @@ -287,7 +287,7 @@ class ApplicationController < ActionController::Base # cause category / topic was deleted if permalink.present? && permalink.target_url # permalink present, redirect to that URL - redirect_with_client_support permalink.target_url, status: :moved_permanently + redirect_with_client_support permalink.target_url, status: :moved_permanently, allow_other_host: true return end end @@ -834,7 +834,7 @@ class ApplicationController < ActionController::Base end if UserApiKey.allowed_scopes.superset?(Set.new(["one_time_password"])) - redirect_to("#{params[:auth_redirect]}?otp=true") + redirect_to("#{params[:auth_redirect]}?otp=true", allow_other_host: true) return end end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index b7e0df39c52..f1292d4fe08 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true class PostsController < ApplicationController + # Bug with Rails 7+ + # see https://github.com/rails/rails/issues/44867 + self._flash_types -= [:notice] requires_login except: [ :show, diff --git a/app/controllers/session_controller.rb b/app/controllers/session_controller.rb index caa63596098..beefb526e20 100644 --- a/app/controllers/session_controller.rb +++ b/app/controllers/session_controller.rb @@ -33,7 +33,7 @@ class SessionController < ApplicationController if SiteSetting.verbose_discourse_connect_logging Rails.logger.warn("Verbose SSO log: Started SSO process\n\n#{sso.diagnostics}") end - redirect_to sso_url(sso) + redirect_to sso_url(sso), allow_other_host: true else render body: nil, status: 404 end @@ -69,14 +69,14 @@ class SessionController < ApplicationController # for the login modal cookies[:sso_destination_url] = data[:sso_redirect_url] else - redirect_to data[:sso_redirect_url] + redirect_to data[:sso_redirect_url], allow_other_host: true end elsif result.no_second_factors_enabled? if request.xhr? # for the login modal cookies[:sso_destination_url] = result.data[:sso_redirect_url] else - redirect_to result.data[:sso_redirect_url] + redirect_to result.data[:sso_redirect_url], allow_other_host: true end elsif result.second_factor_auth_completed? redirect_url = result.data[:sso_redirect_url] @@ -169,7 +169,7 @@ class SessionController < ApplicationController # they are already pre-approved because they have been invited if SiteSetting.must_approve_users? && !user.approved? && invite.blank? if SiteSetting.discourse_connect_not_approved_url.present? - redirect_to SiteSetting.discourse_connect_not_approved_url + redirect_to SiteSetting.discourse_connect_not_approved_url, allow_other_host: true else render_sso_error(text: I18n.t("discourse_connect.account_not_approved"), status: 403) end @@ -220,7 +220,7 @@ class SessionController < ApplicationController return_path = path("/") end - redirect_to return_path + redirect_to return_path, allow_other_host: true else render_sso_error(text: I18n.t("discourse_connect.not_found"), status: 500) end @@ -583,7 +583,7 @@ class SessionController < ApplicationController redirect_url: redirect_url } else - redirect_to redirect_url + redirect_to redirect_url, allow_other_host: true end end diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb index 5a509932230..ded832cb47b 100644 --- a/app/controllers/static_controller.rb +++ b/app/controllers/static_controller.rb @@ -30,7 +30,7 @@ class StaticController < ApplicationController if map.has_key?(@page) site_setting_key = map[@page][:redirect] url = SiteSetting.get(site_setting_key) if site_setting_key - return redirect_to(url) if url.present? + return redirect_to(url, allow_other_host: true) if url.present? end # The /guidelines route ALWAYS shows our FAQ, ignoring the faq_url site setting. diff --git a/app/controllers/svg_sprite_controller.rb b/app/controllers/svg_sprite_controller.rb index b5b6db3731e..5366654d9df 100644 --- a/app/controllers/svg_sprite_controller.rb +++ b/app/controllers/svg_sprite_controller.rb @@ -15,7 +15,7 @@ class SvgSpriteController < ApplicationController theme_id = params[:theme_id].to_i if params[:theme_id].present? if SvgSprite.version(theme_id) != params[:version] - return redirect_to UrlHelper.absolute((SvgSprite.path(theme_id))) + return redirect_to UrlHelper.absolute((SvgSprite.path(theme_id))), allow_other_host: true end svg_sprite = "window.__svg_sprite = #{SvgSprite.bundle(theme_id).inspect};" diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index 891320f7e35..9c87a938690 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -118,7 +118,7 @@ class UploadsController < ApplicationController if Discourse.store.internal? send_file_local_upload(upload) else - redirect_to Discourse.store.url_for(upload, force_download: force_download?) + redirect_to Discourse.store.url_for(upload, force_download: force_download?), allow_other_host: true end else render_404 @@ -149,7 +149,7 @@ class UploadsController < ApplicationController # private, so we don't want to go to the CDN url just yet otherwise we # will get a 403. if the upload is not secure we assume the ACL is public signed_secure_url = Discourse.store.signed_url_for_path(path_with_ext) - redirect_to upload.secure? ? signed_secure_url : Discourse.store.cdn_url(upload.url) + redirect_to upload.secure? ? signed_secure_url : Discourse.store.cdn_url(upload.url), allow_other_host: true end def handle_secure_upload_request(upload, path_with_ext = nil) @@ -166,14 +166,14 @@ class UploadsController < ApplicationController # url_for figures out the full URL, handling multisite DBs, # and will return a presigned URL for the upload if path_with_ext.blank? - return redirect_to Discourse.store.url_for(upload, force_download: force_download?) + return redirect_to Discourse.store.url_for(upload, force_download: force_download?), allow_other_host: true end redirect_to Discourse.store.signed_url_for_path( path_with_ext, expires_in: S3Helper::DOWNLOAD_URL_EXPIRES_AFTER_SECONDS, force_download: force_download? - ) + ), allow_other_host: true end def metadata diff --git a/app/controllers/user_api_keys_controller.rb b/app/controllers/user_api_keys_controller.rb index 402a38e1d97..0a34a33d65f 100644 --- a/app/controllers/user_api_keys_controller.rb +++ b/app/controllers/user_api_keys_controller.rb @@ -97,7 +97,7 @@ class UserApiKeysController < ApplicationController query_attributes << "oneTimePassword=#{CGI.escape(otp_payload)}" if scopes.include?("one_time_password") uri.query = query_attributes.compact.join('&') - redirect_to(uri.to_s) + redirect_to(uri.to_s, allow_other_host: true) else respond_to do |format| format.html { render :show } @@ -138,7 +138,7 @@ class UserApiKeysController < ApplicationController otp_payload = one_time_password(public_key, current_user.username) redirect_path = "#{params[:auth_redirect]}?oneTimePassword=#{CGI.escape(otp_payload)}" - redirect_to(redirect_path) + redirect_to(redirect_path, allow_other_host: true) end def revoke diff --git a/app/controllers/user_avatars_controller.rb b/app/controllers/user_avatars_controller.rb index 2d339e9f545..cc28143c0db 100644 --- a/app/controllers/user_avatars_controller.rb +++ b/app/controllers/user_avatars_controller.rb @@ -112,7 +112,7 @@ class UserAvatarsController < ApplicationController if !Discourse.avatar_sizes.include?(size) && Discourse.store.external? closest = Discourse.avatar_sizes.to_a.min { |a, b| (size - a).abs <=> (size - b).abs } avatar_url = UserAvatar.local_avatar_url(hostname, user.encoded_username(lower: true), upload_id, closest) - return redirect_to cdn_path(avatar_url) + return redirect_to cdn_path(avatar_url), allow_other_host: true end upload = Upload.find_by(id: upload_id) if user&.user_avatar&.contains_upload?(upload_id) @@ -120,7 +120,7 @@ class UserAvatarsController < ApplicationController if user.uploaded_avatar && !upload avatar_url = UserAvatar.local_avatar_url(hostname, user.encoded_username(lower: true), user.uploaded_avatar_id, size) - return redirect_to cdn_path(avatar_url) + return redirect_to cdn_path(avatar_url), allow_other_host: true elsif upload && optimized = get_optimized_image(upload, size) if optimized.local? optimized_path = Discourse.store.path_for(optimized) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 768053e00a6..2a0c900c8ca 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1024,7 +1024,7 @@ class UsersController < ApplicationController if SiteSetting.enable_discourse_connect_provider && payload = cookies.delete(:sso_payload) return redirect_to(session_sso_provider_url + "?" + payload) elsif destination_url = cookies.delete(:destination_url) - return redirect_to(destination_url) + return redirect_to(destination_url, allow_other_host: true) else return redirect_to(path('/')) end @@ -1086,7 +1086,7 @@ class UsersController < ApplicationController if Wizard.user_requires_completion?(@user) return redirect_to(wizard_path) elsif destination_url.present? - return redirect_to(destination_url) + return redirect_to(destination_url, allow_other_host: true) elsif SiteSetting.enable_discourse_connect_provider && payload = cookies.delete(:sso_payload) return redirect_to(session_sso_provider_url + "?" + payload) end diff --git a/app/jobs/regular/group_smtp_email.rb b/app/jobs/regular/group_smtp_email.rb index dbe9f822245..b06801be188 100644 --- a/app/jobs/regular/group_smtp_email.rb +++ b/app/jobs/regular/group_smtp_email.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require_dependency 'email/sender' - module Jobs class GroupSmtpEmail < ::Jobs::Base include Skippable diff --git a/app/jobs/scheduled/old_keys_reminder.rb b/app/jobs/scheduled/old_keys_reminder.rb index f5318c70079..de824fa5d0e 100644 --- a/app/jobs/scheduled/old_keys_reminder.rb +++ b/app/jobs/scheduled/old_keys_reminder.rb @@ -57,8 +57,8 @@ module Jobs end def keys_list - messages = old_site_settings_keys.map { |key| "#{key.name} - #{key.updated_at.to_date.to_s(:db)}" } - old_api_keys.each_with_object(messages) { |key, array| array << "#{[key.description, key.user&.username, key.created_at.to_date.to_s(:db)].compact.join(" - ")}" } + messages = old_site_settings_keys.map { |key| "#{key.name} - #{key.updated_at.to_date.to_fs(:db)}" } + old_api_keys.each_with_object(messages) { |key, array| array << "#{[key.description, key.user&.username, key.created_at.to_date.to_fs(:db)].compact.join(" - ")}" } messages.join("\n") end end diff --git a/app/mailers/group_smtp_mailer.rb b/app/mailers/group_smtp_mailer.rb index d47a75051ef..42a2c9a082f 100644 --- a/app/mailers/group_smtp_mailer.rb +++ b/app/mailers/group_smtp_mailer.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require_dependency 'email/message_builder' - class GroupSmtpMailer < ActionMailer::Base include Email::BuildEmailHelper diff --git a/app/models/theme.rb b/app/models/theme.rb index 596db2e2b2f..5c510086f7f 100644 --- a/app/models/theme.rb +++ b/app/models/theme.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require_dependency 'global_path' require 'csv' require 'json_schemer' diff --git a/app/models/topic_list.rb b/app/models/topic_list.rb index 2c564087ed8..bfa6960e0f3 100644 --- a/app/models/topic_list.rb +++ b/app/models/topic_list.rb @@ -153,7 +153,9 @@ class TopicList ft.topic_list = self end - ActiveRecord::Associations::Preloader.new.preload(@topics, [:image_upload, topic_thumbnails: :optimized_image]) + ActiveRecord::Associations::Preloader + .new(records: @topics, associations: [:image_upload, topic_thumbnails: :optimized_image]) + .call if preloaded_custom_fields.present? Topic.preload_custom_fields(@topics, preloaded_custom_fields) diff --git a/app/models/translation_override.rb b/app/models/translation_override.rb index 85b09c0e74a..932ac08fa66 100644 --- a/app/models/translation_override.rb +++ b/app/models/translation_override.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "i18n/i18n_interpolation_keys_finder" - class TranslationOverride < ActiveRecord::Base # Allowlist i18n interpolation keys that can be included when customizing translations ALLOWED_CUSTOM_INTERPOLATION_KEYS = { diff --git a/app/services/bookmarkable.rb b/app/services/bookmarkable.rb index 525f07ee65b..b5cd2e8ab60 100644 --- a/app/services/bookmarkable.rb +++ b/app/services/bookmarkable.rb @@ -73,8 +73,8 @@ class Bookmarkable # @param [Array] bookmarks The array of bookmarks after initial listing and filtering, note this is # array _not_ an ActiveRecord::Relation. def perform_preload(bookmarks) - ActiveRecord::Associations::Preloader.new.preload( - Bookmark.select_type(bookmarks, model.to_s), { bookmarkable: preload_associations } - ) + ActiveRecord::Associations::Preloader + .new(records: Bookmark.select_type(bookmarks, model.to_s), associations: [bookmarkable: preload_associations]) + .call end end diff --git a/config/application.rb b/config/application.rb index f17ea293a33..882ccda5b67 100644 --- a/config/application.rb +++ b/config/application.rb @@ -21,7 +21,7 @@ require 'action_mailer/railtie' require 'sprockets/railtie' # Plugin related stuff -require_relative '../lib/plugin_initialization_guard' +require_relative '../lib/plugin' require_relative '../lib/discourse_event' require_relative '../lib/discourse_plugin_registry' @@ -31,7 +31,13 @@ require_relative '../lib/plugin_gem' require_relative '../app/models/global_setting' GlobalSetting.configure! if GlobalSetting.load_plugins? - require_relative '../lib/custom_setting_providers' + # 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| + require p + end end GlobalSetting.load_defaults if GlobalSetting.try(:cdn_url).present? && GlobalSetting.cdn_url !~ /^https?:\/\// @@ -85,14 +91,11 @@ module Discourse # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. - # this pattern is somewhat odd but the reloader gets very - # confused here if we load the deps without `lib` it thinks - # discourse.rb is under the discourse folder incorrectly - require_dependency 'lib/discourse' - require_dependency 'lib/js_locale_helper' + require 'discourse' + require 'js_locale_helper' # tiny file needed by site settings - require_dependency 'lib/highlight_js/highlight_js' + require 'highlight_js' # we skip it cause we configure it in the initializer # the railtie for message_bus would insert it in the @@ -109,120 +112,19 @@ module Discourse # issue is image_optim crashes on missing dependencies config.assets.image_optim = false - config.autoloader = :zeitwerk - # Custom directories with classes and modules you want to be autoloadable. - config.autoload_paths += Dir["#{config.root}/lib"] - config.autoload_paths += Dir["#{config.root}/lib/common_passwords"] - config.autoload_paths += Dir["#{config.root}/lib/highlight_js"] - config.autoload_paths += Dir["#{config.root}/lib/i18n"] - config.autoload_paths += Dir["#{config.root}/lib/validators/"] - - Rails.autoloaders.main.ignore(Dir["#{config.root}/app/models/reports"]) - Rails.autoloaders.main.ignore(Dir["#{config.root}/lib/freedom_patches"]) - - def watchable_args - files, dirs = super - - # Skip the assets directory. It doesn't contain any .rb files, so watching it - # is just slowing things down and raising warnings about node_modules symlinks - app_file_extensions = dirs.delete("#{config.root}/app") - Dir["#{config.root}/app/*"].reject { |path| path.end_with? "/assets" }.each do |path| - dirs[path] = app_file_extensions - end - - [files, dirs] - end + config.autoload_paths << "#{root}/lib" + config.autoload_paths << "#{root}/lib/guardian" + config.autoload_paths << "#{root}/lib/i18n" + config.autoload_paths << "#{root}/lib/validators" # Only load the plugins named here, in the order given (default is alphabetical). # :all can be used as a placeholder for all plugins not explicitly named. # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - config.assets.paths += %W(#{config.root}/config/locales #{config.root}/public/javascripts) - # Allows us to skip minification on some files config.assets.skip_minification = [] - # explicitly precompile any images in plugins ( /assets/images ) path - config.assets.precompile += [lambda do |filename, path| - path =~ /assets\/images/ && !%w(.js .css).include?(File.extname(filename)) - end] - - config.assets.precompile += %w{ - vendor.js - admin.js - browser-detect.js - browser-update.js - break_string.js - ember_jquery.js - pretty-text-bundle.js - wizard-application.js - wizard-vendor.js - markdown-it-bundle.js - service-worker.js - google-tag-manager.js - google-universal-analytics-v3.js - google-universal-analytics-v4.js - start-discourse.js - print-page.js - omniauth-complete.js - activate-account.js - auto-redirect.js - wizard-start.js - locales/i18n.js - discourse/app/lib/webauthn.js - confirm-new-email/confirm-new-email.js - confirm-new-email/bootstrap.js - onpopstate-handler.js - embed-application.js - discourse/tests/active-plugins.js - admin-plugins.js - discourse/tests/test_starter.js - } - - if EmberCli.enabled? - config.assets.precompile += %w{ - discourse.js - test-support.js - test-helpers.js - scripts/discourse-test-listen-boot - scripts/discourse-boot - } - else - config.assets.precompile += %w{ - application.js - discourse/tests/test-support-rails.js - discourse/tests/test-helpers-rails.js - vendor-theme-tests.js - } - end - - # Precompile all available locales - unless GlobalSetting.try(:omit_base_locales) - Dir.glob("#{config.root}/app/assets/javascripts/locales/*.js.erb").each do |file| - 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, - # the exclusion list does not include hbs so you double compile all this stuff - initializer :fix_sprockets_loose_file_searcher, after: :set_default_precompile do |app| - app.config.assets.precompile.delete(Sprockets::Railtie::LOOSE_APP_ASSETS) - - # We don't want application from node_modules, only from the root - app.config.assets.precompile.delete(/(?:\/|\\|\A)application\.(css|js)$/) - app.config.assets.precompile += ['application.js'] - - start_path = ::Rails.root.join("app/assets").to_s - exclude = ['.es6', '.hbs', '.hbr', '.js', '.css', '.lock', '.json', '.log', '.html', ''] - app.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)) - end - end - # 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' @@ -234,24 +136,6 @@ module Discourse # Configure the default encoding used in templates for Ruby 1.9. config.encoding = 'utf-8' - # Configure sensitive parameters which will be filtered from the log file. - 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, - ] - - # Enable the asset pipeline - config.assets.enabled = true - - # Version of your assets, change this if you want to expire all your assets - config.assets.version = '1.2.5' - # see: http://stackoverflow.com/questions/11894180/how-does-one-correctly-add-custom-sql-dml-in-migrations/11894420#11894420 config.active_record.schema_format = :sql @@ -336,45 +220,21 @@ module Discourse if Rails.env.test? && GlobalSetting.load_plugins? Discourse.activate_plugins! elsif GlobalSetting.load_plugins? - plugin_initialization_guard do + Plugin.initialization_guard do Discourse.activate_plugins! end end - Discourse.find_plugin_js_assets(include_disabled: true).each do |file| - config.assets.precompile << "#{file}.js" - end - # Use discourse-fonts gem to symlink fonts and generate .scss file fonts_path = File.join(config.root, 'public/fonts') Discourse::Utils.atomic_ln_s(DiscourseFonts.path_for_fonts, fonts_path) - require_dependency 'stylesheet/manager' - require_dependency 'svg_sprite/svg_sprite' + require 'stylesheet/manager' + require 'svg_sprite' config.after_initialize do - # require common dependencies that are often required by plugins - # in the past observers would load them as side-effects - # correct behavior is for plugins to require stuff they need, - # however it would be a risky and breaking change not to require here - require_dependency 'category' - require_dependency 'post' - require_dependency 'topic' - require_dependency 'user' - require_dependency 'post_action' - require_dependency 'post_revision' - require_dependency 'notification' - require_dependency 'topic_user' - require_dependency 'topic_view' - require_dependency 'topic_list' - require_dependency 'group' - require_dependency 'user_field' - require_dependency 'post_action_type' - # Ensure that Discourse event triggers for web hooks are loaded - require_dependency 'web_hook' - # Load plugins - plugin_initialization_guard do + Plugin.initialization_guard do Discourse.plugins.each(&:notify_after_initialize) end diff --git a/config/environment.rb b/config/environment.rb index 516a139c3a8..7bb5d95ae90 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -# Load the rails application -require File.expand_path('../application', __FILE__) +# Load the Rails application. +require_relative "application" -# Initialize the rails application -Discourse::Application.initialize! +# Initialize the Rails application. +Rails.application.initialize! # When in "dev" mode, ensure we won't be sending any emails -if Rails.env.development? && ActionMailer::Base.smtp_settings != { 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/initializers/000-zeitwerk.rb b/config/initializers/000-zeitwerk.rb index 7fa14e8bf44..0d5e55d3d57 100644 --- a/config/initializers/000-zeitwerk.rb +++ b/config/initializers/000-zeitwerk.rb @@ -36,5 +36,15 @@ Rails.autoloaders.each do |autoloader| 'onceoff' => 'Jobs', 'regular' => 'Jobs', 'scheduled' => 'Jobs', + 'google_oauth2_authenticator' => 'GoogleOAuth2Authenticator', + 'omniauth_strategies' => 'OmniAuthStrategies', + 'csrf_token_verifier' => 'CSRFTokenVerifier', + 'html' => 'HTML', + 'json' => 'JSON' ) end +Rails.autoloaders.main.ignore("lib/tasks", + "lib/generators", + "lib/freedom_patches", + "lib/i18n/backend", + "lib/unicorn_logstash_patch.rb") diff --git a/config/initializers/002-rails_failover.rb b/config/initializers/002-rails_failover.rb index 7ff49b775c4..3f1463fdd87 100644 --- a/config/initializers/002-rails_failover.rb +++ b/config/initializers/002-rails_failover.rb @@ -30,14 +30,14 @@ if defined?(RailsFailover::ActiveRecord) return unless Rails.configuration.active_record_rails_failover if Rails.configuration.multisite - if ActiveRecord::Base.current_role == ActiveRecord::Base.reading_role + if ActiveRecord::Base.current_role == ActiveRecord.reading_role RailsMultisite::ConnectionManagement.default_connection_handler = - ActiveRecord::Base.connection_handlers[ActiveRecord::Base.reading_role] + ActiveRecord::Base.connection_handlers[ActiveRecord.reading_role] end end RailsFailover::ActiveRecord.on_failover do |role| - if role == ActiveRecord::Base.writing_role # Multisite master + if role == ActiveRecord.writing_role # Multisite master RailsMultisite::ConnectionManagement.each_connection do Discourse.enable_readonly_mode(Discourse::PG_READONLY_MODE_KEY) end @@ -47,16 +47,16 @@ if defined?(RailsFailover::ActiveRecord) end # Test connection to the master, and trigger master failover if needed - ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do + ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role) do ActiveRecord::Base.connection.active? rescue PG::ConnectionBad, PG::UnableToSend, PG::ServerError - RailsFailover::ActiveRecord.verify_primary(ActiveRecord::Base.writing_role) + RailsFailover::ActiveRecord.verify_primary(ActiveRecord.writing_role) end end end RailsFailover::ActiveRecord.on_fallback do |role| - if role == ActiveRecord::Base.writing_role # Multisite master + if role == ActiveRecord.writing_role # Multisite master RailsMultisite::ConnectionManagement.each_connection do Discourse.disable_readonly_mode(Discourse::PG_READONLY_MODE_KEY) end @@ -68,7 +68,7 @@ if defined?(RailsFailover::ActiveRecord) if Rails.configuration.multisite RailsMultisite::ConnectionManagement.default_connection_handler = - ActiveRecord::Base.connection_handlers[ActiveRecord::Base.writing_role] + ActiveRecord::Base.connection_handlers[ActiveRecord.writing_role] end end diff --git a/config/initializers/005-site_settings.rb b/config/initializers/005-site_settings.rb index 4ecaa85df33..9286affcbf0 100644 --- a/config/initializers/005-site_settings.rb +++ b/config/initializers/005-site_settings.rb @@ -6,17 +6,15 @@ Discourse.git_version if GlobalSetting.skip_redis? - # Requiring this file explicitly prevents it from being autoloaded and so the - # provider attribute is not cleared - require File.expand_path('../../../app/models/site_setting', __FILE__) - require 'site_settings/local_process_provider' Rails.cache = Discourse.cache - SiteSetting.provider = SiteSettings::LocalProcessProvider.new + Rails.application.config.to_prepare do + SiteSetting.provider = SiteSettings::LocalProcessProvider.new + end return end -reload_settings = lambda { +Rails.application.config.to_prepare do RailsMultisite::ConnectionManagement.safe_each_connection do begin SiteSetting.refresh! @@ -28,12 +26,4 @@ reload_settings = lambda { # This will happen when migrating a new database end end -} - -reload_settings.call - -if !Rails.configuration.cache_classes - ActiveSupport::Reloader.to_prepare do - reload_settings.call - end end diff --git a/config/initializers/006-ensure_login_hint.rb b/config/initializers/006-ensure_login_hint.rb index 837ab3f1ab8..06debac7564 100644 --- a/config/initializers/006-ensure_login_hint.rb +++ b/config/initializers/006-ensure_login_hint.rb @@ -2,30 +2,32 @@ return if GlobalSetting.skip_db? -# 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 +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 - notice = - if GlobalSetting.developer_emails.blank? - "Congratulations, you installed Discourse! Unfortunately, no administrator emails were defined during setup, so finalizing the configuration <a href='https://meta.discourse.org/t/create-admin-account-from-console/17274'>may be difficult</a>." - else - emails = GlobalSetting.developer_emails.split(",") - if emails.length > 1 - emails = emails[0..-2].join(', ') << " or #{emails[-1]} " + notice = + if GlobalSetting.developer_emails.blank? + "Congratulations, you installed Discourse! Unfortunately, no administrator emails were defined during setup, so finalizing the configuration <a href='https://meta.discourse.org/t/create-admin-account-from-console/17274'>may be difficult</a>." else - emails = emails[0] + emails = GlobalSetting.developer_emails.split(",") + if emails.length > 1 + emails = emails[0..-2].join(', ') << " or #{emails[-1]} " + else + emails = emails[0] + end + "Congratulations, you installed Discourse! Register a new admin account with #{emails} to finalize configuration." end - "Congratulations, you installed Discourse! Register a new admin account with #{emails} to finalize configuration." - end - if notice != SiteSetting.global_notice - SiteSetting.global_notice = notice - SiteSetting.has_login_hint = true + if notice != SiteSetting.global_notice + SiteSetting.global_notice = notice + SiteSetting.has_login_hint = true + end end + rescue ActiveRecord::NoDatabaseError + # Database might not have been created end -rescue ActiveRecord::NoDatabaseError - # Database might not have been created end diff --git a/config/initializers/100-onebox_options.rb b/config/initializers/100-onebox_options.rb index d98886e2ba3..3d2e4a2f055 100644 --- a/config/initializers/100-onebox_options.rb +++ b/config/initializers/100-onebox_options.rb @@ -1,16 +1,18 @@ # frozen_string_literal: true -if Rails.env.development? && SiteSetting.port.to_i > 0 - Onebox.options = { - twitter_client: TwitterApi, - redirect_limit: 3, - user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}", - 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}" - } +Rails.application.config.to_prepare do + if Rails.env.development? && SiteSetting.port.to_i > 0 + Onebox.options = { + twitter_client: TwitterApi, + redirect_limit: 3, + user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}", + 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}" + } + end end diff --git a/config/initializers/100-push-notifications.rb b/config/initializers/100-push-notifications.rb index 6b16a07a8e6..4a8166c077c 100644 --- a/config/initializers/100-push-notifications.rb +++ b/config/initializers/100-push-notifications.rb @@ -2,30 +2,32 @@ return if GlobalSetting.skip_db? -require_dependency 'webpush' +Rails.application.config.to_prepare do + require 'webpush' -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 -end + 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 + end -SiteSetting.vapid_base_url = Discourse.base_url if SiteSetting.vapid_base_url.blank? + SiteSetting.vapid_base_url = Discourse.base_url if SiteSetting.vapid_base_url.blank? -if generate_vapid_key? - vapid_key = Webpush.generate_key - SiteSetting.vapid_public_key = vapid_key.public_key - SiteSetting.vapid_private_key = vapid_key.private_key + if generate_vapid_key? + vapid_key = Webpush.generate_key + 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_base_url = Discourse.base_url + 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 + if ActiveRecord::Base.connection.table_exists?(:push_subscriptions) + PushSubscription.delete_all + end + end + + DiscourseEvent.on(:user_logged_out) do |user| + PushNotificationPusher.clear_subscriptions(user) end end - -DiscourseEvent.on(:user_logged_out) do |user| - PushNotificationPusher.clear_subscriptions(user) -end diff --git a/config/initializers/100-session_store.rb b/config/initializers/100-session_store.rb index 1827f6e552a..b2ce5d47b46 100644 --- a/config/initializers/100-session_store.rb +++ b/config/initializers/100-session_store.rb @@ -1,21 +1,21 @@ # frozen_string_literal: true # Be sure to restart your server when you modify this file. -# -require_dependency 'discourse_cookie_store' -if Rails.env == "development" && SiteSetting.force_https - STDERR.puts - STDERR.puts "WARNING: force_https is enabled in dev" - STDERR.puts "It is very unlikely you are running HTTPS in dev." - STDERR.puts "Without HTTPS your session cookie will not work" - STDERR.puts "Try: bin/rails c" - STDERR.puts "SiteSetting.force_https = false" - STDERR.puts -end - -Discourse::Application.config.session_store( +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 ) + +Rails.application.config.to_prepare do + if Rails.env.development? && SiteSetting.force_https + STDERR.puts + STDERR.puts "WARNING: force_https is enabled in dev" + STDERR.puts "It is very unlikely you are running HTTPS in dev." + STDERR.puts "Without HTTPS your session cookie will not work" + STDERR.puts "Try: bin/rails c" + STDERR.puts "SiteSetting.force_https = false" + STDERR.puts + end +end diff --git a/config/initializers/101-lograge.rb b/config/initializers/101-lograge.rb index bcbcc4c2a21..311c64c7533 100644 --- a/config/initializers/101-lograge.rb +++ b/config/initializers/101-lograge.rb @@ -1,117 +1,119 @@ # frozen_string_literal: true -if (Rails.env.production? && SiteSetting.logging_provider == 'lograge') || (ENV["ENABLE_LOGRAGE"] == "1") - require 'lograge' +Rails.application.config.to_prepare do + 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 - end + if Rails.configuration.multisite + Rails.logger.formatter = ActiveSupport::Logger::SimpleFormatter.new + end - Rails.application.configure do - config.lograge.enabled = true + 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 + config.lograge.custom_payload do |controller| + begin + username = + begin + if controller.respond_to?(:current_user) + controller.current_user&.username + end + rescue Discourse::InvalidAccess, Discourse::ReadOnly, ActiveRecord::ReadOnlyError + nil end - rescue Discourse::InvalidAccess, Discourse::ReadOnly, ActiveRecord::ReadOnlyError - nil - end - ip = - begin - controller.request.remote_ip - rescue ActionDispatch::RemoteIp::IpSpoofAttackError - nil - end + ip = + begin + controller.request.remote_ip + rescue ActionDispatch::RemoteIp::IpSpoofAttackError + nil + end - { - ip: ip, - username: username - } - rescue => e - Rails.logger.warn("Failed to append custom payload: #{e.message}\n#{e.backtrace.join("\n")}") - {} + { + ip: ip, + username: username + } + rescue => e + Rails.logger.warn("Failed to append custom payload: #{e.message}\n#{e.backtrace.join("\n")}") + {} + end 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 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 - - 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 + 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 - Rails.logger.chained.pop - Rails.logger.chain(config.lograge.logger) + # Remove ActiveSupport::Logger from the chain and replace with Lograge's + # logger + Rails.logger.chained.pop + Rails.logger.chain(config.lograge.logger) + end end end end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 00000000000..306dd044ab0 --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. + +# Enable the asset pipeline +Rails.application.config.assets.enabled = true + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = "1.2.5" + +# Add additional assets to the asset load path. +Rails.application.config.assets.paths << "#{Rails.root}/config/locales" +Rails.application.config.assets.paths << "#{Rails.root}/public/javascripts" + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# 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 += %w{ + vendor.js + admin.js + browser-detect.js + browser-update.js + break_string.js + ember_jquery.js + pretty-text-bundle.js + wizard-application.js + wizard-vendor.js + markdown-it-bundle.js + service-worker.js + google-tag-manager.js + google-universal-analytics-v3.js + google-universal-analytics-v4.js + start-discourse.js + print-page.js + omniauth-complete.js + activate-account.js + auto-redirect.js + wizard-start.js + locales/i18n.js + discourse/app/lib/webauthn.js + confirm-new-email/confirm-new-email.js + confirm-new-email/bootstrap.js + onpopstate-handler.js + embed-application.js + discourse/tests/active-plugins.js + admin-plugins.js + discourse/tests/test_starter.js + } + +if EmberCli.enabled? + Rails.application.config.assets.precompile += %w{ + discourse.js + test-support.js + test-helpers.js + scripts/discourse-test-listen-boot + scripts/discourse-boot + } +else + Rails.application.config.assets.precompile += %w{ + application.js + discourse/tests/test-support-rails.js + discourse/tests/test-helpers-rails.js + vendor-theme-tests.js + } +end + +# 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 +end + +# out of the box sprockets 3 grabs loose files that are hanging in assets, +# the exclusion list does not include hbs so you double compile all this stuff +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'] + +start_path = ::Rails.root.join("app/assets").to_s +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)) +end + +Discourse.find_plugin_js_assets(include_disabled: true).each do |file| + Rails.application.config.assets.precompile << "#{file}.js" +end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 00000000000..af4c108bf6e --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# 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, +] diff --git a/config/initializers/new_framework_defaults_7_0.rb b/config/initializers/new_framework_defaults_7_0.rb new file mode 100644 index 00000000000..69f37343efa --- /dev/null +++ b/config/initializers/new_framework_defaults_7_0.rb @@ -0,0 +1,106 @@ +# frozen_string_literal: true + +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 7.0 framework defaults upgrade. +# +# Uncomment each configuration one by one to switch to the new default. +# Once your application is ready to run with all new defaults, you can remove +# this file and set the `config.load_defaults` to `7.0`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +# `button_to` view helper will render `<button>` element, regardless of whether +# or not the content is passed as the first argument or as a block. +Rails.application.config.action_view.button_to_generates_button_tag = true + +# `stylesheet_link_tag` view helper will not render the media attribute by default. +Rails.application.config.action_view.apply_stylesheet_media_default = false + +# Change the digest class for the key generators to `OpenSSL::Digest::SHA256`. +# Changing this default means invalidate all encrypted messages generated by +# your application and, all the encrypted cookies. Only change this after you +# rotated all the messages using the key rotator. +# +# See upgrading guide for more information on how to build a rotator. +# https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html +# Rails.application.config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256 + +# Change the digest class for ActiveSupport::Digest. +# Changing this default means that for example Etags change and +# various cache keys leading to cache invalidation. +# Rails.application.config.active_support.hash_digest_class = OpenSSL::Digest::SHA256 + +# Don't override ActiveSupport::TimeWithZone.name and use the default Ruby +# implementation. +Rails.application.config.active_support.remove_deprecated_time_with_zone_name = true + +# Change the format of the cache entry. +# Changing this default means that all new cache entries added to the cache +# will have a different format that is not supported by Rails 6.1 applications. +# Only change this value after your application is fully deployed to Rails 7.0 +# and you have no plans to rollback. +# Rails.application.config.active_support.cache_format_version = 7.0 + +# Calls `Rails.application.executor.wrap` around test cases. +# This makes test cases behave closer to an actual request or job. +# Several features that are normally disabled in test, such as Active Record query cache +# and asynchronous queries will then be enabled. +Rails.application.config.active_support.executor_around_test_case = true + +# Define the isolation level of most of Rails internal state. +# If you use a fiber based server or job processor, you should set it to `:fiber`. +# Otherwise the default of `:thread` if preferable. +Rails.application.config.active_support.isolation_level = :thread + +# Set both the `:open_timeout` and `:read_timeout` values for `:smtp` delivery method. +Rails.application.config.action_mailer.smtp_timeout = 5 + +# Automatically infer `inverse_of` for associations with a scope. +Rails.application.config.active_record.automatic_scope_inversing = true + +# Raise when running tests if fixtures contained foreign key violations +Rails.application.config.active_record.verify_foreign_keys_for_fixtures = true + +# Disable partial inserts. +# This default means that all columns will be referenced in INSERT queries +# regardless of whether they have a default or not. +Rails.application.config.active_record.partial_inserts = false +# +# Protect from open redirect attacks in `redirect_back_or_to` and `redirect_to`. +Rails.application.config.action_controller.raise_on_open_redirects = true + +# If you're upgrading and haven't set `cookies_serializer` previously, your cookie serializer +# was `:marshal`. Convert all cookies to JSON, using the `:hybrid` formatter. +# +# If you're confident all your cookies are JSON formatted, you can switch to the `:json` formatter. +# +# Continue to use `:marshal` for backward-compatibility with old cookies. +# +# If you have configured the serializer elsewhere, you can remove this. +# +# See https://guides.rubyonrails.org/action_controller_overview.html#cookies for more information. +Rails.application.config.action_dispatch.cookies_serializer = :marshal + +# Enable parameter wrapping for JSON. +# Previously this was set in an initializer. It's fine to keep using that initializer if you've customized it. +# To disable parameter wrapping entirely, set this config to `false`. +# Rails.application.config.action_controller.wrap_parameters_by_default = true + +# Specifies whether generated namespaced UUIDs follow the RFC 4122 standard for namespace IDs provided as a +# `String` to `Digest::UUID.uuid_v3` or `Digest::UUID.uuid_v5` method calls. +# +# See https://guides.rubyonrails.org/configuring.html#config-active-support-use-rfc4122-namespaced-uuids for +# more information. +Rails.application.config.active_support.use_rfc4122_namespaced_uuids = true + +# Change the default headers to disable browsers' flawed legacy XSS protection. +Rails.application.config.action_dispatch.default_headers = { + "X-Frame-Options" => "SAMEORIGIN", + "X-XSS-Protection" => "0", + "X-Content-Type-Options" => "nosniff", + "X-Download-Options" => "noopen", + "X-Permitted-Cross-Domain-Policies" => "none", + "Referrer-Policy" => "strict-origin-when-cross-origin" +} diff --git a/db/migrate/20160303183607_clear_common_passwords_cache.rb b/db/migrate/20160303183607_clear_common_passwords_cache.rb index 421301e9ed9..92816452630 100644 --- a/db/migrate/20160303183607_clear_common_passwords_cache.rb +++ b/db/migrate/20160303183607_clear_common_passwords_cache.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "common_passwords/common_passwords" +require "common_passwords" class ClearCommonPasswordsCache < ActiveRecord::Migration[4.2] def change diff --git a/lib/discourse_cookie_store.rb b/lib/action_dispatch/session/discourse_cookie_store.rb similarity index 100% rename from lib/discourse_cookie_store.rb rename to lib/action_dispatch/session/discourse_cookie_store.rb diff --git a/lib/auth/github_authenticator.rb b/lib/auth/github_authenticator.rb index c082bd021eb..7a64e089fe2 100644 --- a/lib/auth/github_authenticator.rb +++ b/lib/auth/github_authenticator.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'has_errors' +require 'has_errors' class Auth::GithubAuthenticator < Auth::ManagedAuthenticator diff --git a/lib/auth/oauth2_authenticator.rb b/lib/auth/oauth2_authenticator.rb deleted file mode 100644 index 78880319a6d..00000000000 --- a/lib/auth/oauth2_authenticator.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -class Auth::OAuth2Authenticator < Auth::Authenticator - - def name - @name - end - - # only option at the moment is :trusted - def initialize(name, opts = {}) - Discourse.deprecate("OAuth2Authenticator is deprecated. Use `ManagedAuthenticator` and `UserAssociatedAccount` instead. For more information, see https://meta.discourse.org/t/106695", drop_from: '2.9.0', output_in_test: true) - @name = name - @opts = opts - end - - def after_authenticate(auth_token) - - result = Auth::Result.new - - oauth2_provider = auth_token[:provider] - oauth2_uid = auth_token[:uid] - data = auth_token[:info] - result.email = email = data[:email] - result.name = name = data[:name] - - oauth2_user_info = Oauth2UserInfo.find_by(uid: oauth2_uid, provider: oauth2_provider) - - if !oauth2_user_info && @opts[:trusted] && user = User.find_by_email(email) - oauth2_user_info = Oauth2UserInfo.create(uid: oauth2_uid, - provider: oauth2_provider, - name: name, - email: email, - user: user) - end - - result.user = oauth2_user_info.try(:user) - result.email_valid = @opts[:trusted] - - result.extra_data = { - uid: oauth2_uid, - provider: oauth2_provider - } - - result - end - - def after_create_account(user, auth) - data = auth[:extra_data] - association = Oauth2UserInfo.find_or_initialize_by(provider: data[:provider], uid: data[:uid]) - association.user = user - association.email = auth[:email] - association.save! - end - - def description_for_user(user) - info = Oauth2UserInfo.find_by(user_id: user.id, provider: @name) - info&.email || info&.name || info&.uid || "" - end -end diff --git a/lib/auth/result.rb b/lib/auth/result.rb index 09298af2d4e..675f40eadb0 100644 --- a/lib/auth/result.rb +++ b/lib/auth/result.rb @@ -75,7 +75,7 @@ class Auth::Result def self.from_session_data(data, user:) result = new - data = data.symbolize_keys + data = data.with_indifferent_access SESSION_ATTRIBUTES.each { |att| result.public_send("#{att}=", data[att]) } result.user = user result diff --git a/lib/backup_restore/backup_store.rb b/lib/backup_restore/backup_store.rb index 2243837fd0c..65a3acaa951 100644 --- a/lib/backup_restore/backup_store.rb +++ b/lib/backup_restore/backup_store.rb @@ -10,10 +10,10 @@ module BackupRestore def self.create(opts = {}) case opts[:location] || SiteSetting.backup_location when BackupLocationSiteSetting::LOCAL - require_dependency "backup_restore/local_backup_store" + require "backup_restore/local_backup_store" BackupRestore::LocalBackupStore.new(opts) when BackupLocationSiteSetting::S3 - require_dependency "backup_restore/s3_backup_store" + require "backup_restore/s3_backup_store" BackupRestore::S3BackupStore.new(opts) end end diff --git a/lib/common_passwords/common_passwords.rb b/lib/common_passwords.rb similarity index 100% rename from lib/common_passwords/common_passwords.rb rename to lib/common_passwords.rb diff --git a/lib/content_security_policy/builder.rb b/lib/content_security_policy/builder.rb index 9ff21f4af6f..af240829ba8 100644 --- a/lib/content_security_policy/builder.rb +++ b/lib/content_security_policy/builder.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require_dependency 'content_security_policy/default' +require 'content_security_policy/default' class ContentSecurityPolicy class Builder diff --git a/lib/content_security_policy/default.rb b/lib/content_security_policy/default.rb index 8029bad9e4f..1350874000e 100644 --- a/lib/content_security_policy/default.rb +++ b/lib/content_security_policy/default.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require_dependency 'content_security_policy' +require 'content_security_policy' class ContentSecurityPolicy class Default diff --git a/lib/content_security_policy/middleware.rb b/lib/content_security_policy/middleware.rb index 0435529bff7..54ec0f5a656 100644 --- a/lib/content_security_policy/middleware.rb +++ b/lib/content_security_policy/middleware.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require_dependency 'content_security_policy' +require 'content_security_policy' class ContentSecurityPolicy class Middleware diff --git a/lib/custom_setting_providers.rb b/lib/custom_setting_providers.rb deleted file mode 100644 index e096e900a89..00000000000 --- a/lib/custom_setting_providers.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -# 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| - require p -end diff --git a/lib/db_helper.rb b/lib/db_helper.rb index 6510d49d973..6bc79b044ef 100644 --- a/lib/db_helper.rb +++ b/lib/db_helper.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency "migration/base_dropper" +require "migration/base_dropper" class DbHelper diff --git a/lib/discourse.rb b/lib/discourse.rb index 6c9ae948f2c..e4a5c49c12c 100644 --- a/lib/discourse.rb +++ b/lib/discourse.rb @@ -2,8 +2,8 @@ require 'cache' require 'open3' -require_dependency 'plugin/instance' -require_dependency 'version' +require 'plugin/instance' +require 'version' module Discourse DB_POST_MIGRATE_PATH ||= "db/post_migrate" diff --git a/lib/file_store/local_store.rb b/lib/file_store/local_store.rb index 9e704efee98..4922eca7077 100644 --- a/lib/file_store/local_store.rb +++ b/lib/file_store/local_store.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'file_store/base_store' +require 'file_store/base_store' module FileStore diff --git a/lib/file_store/s3_store.rb b/lib/file_store/s3_store.rb index 951be4f6184..54d8dff720f 100644 --- a/lib/file_store/s3_store.rb +++ b/lib/file_store/s3_store.rb @@ -2,9 +2,9 @@ require "uri" require "mini_mime" -require_dependency "file_store/base_store" -require_dependency "s3_helper" -require_dependency "file_helper" +require "file_store/base_store" +require "s3_helper" +require "file_helper" module FileStore diff --git a/lib/freedom_patches/active_record_postgresql_adapter.rb b/lib/freedom_patches/active_record_postgresql_adapter.rb deleted file mode 100644 index bf64f9233c5..00000000000 --- a/lib/freedom_patches/active_record_postgresql_adapter.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -# Pulls in https://github.com/rails/rails/pull/42368 early since the query is -# definitely more efficient as it does not involved the PG planner. -# Remove once Rails 7 has been released. -module ActiveRecord - module ConnectionAdapters - class PostgreSQLAdapter - def active? - @lock.synchronize do - @connection.query ";" - end - true - rescue PG::Error - false - end - end - end -end diff --git a/lib/freedom_patches/ar_references_fix.rb b/lib/freedom_patches/ar_references_fix.rb new file mode 100644 index 00000000000..ba9db28010c --- /dev/null +++ b/lib/freedom_patches/ar_references_fix.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +# This patch is a backport of https://github.com/rails/rails/pull/42350 +# It fixes a bug introduced by Rails which affects reference columns marking +# them as integer instead of bigint. +# +# This should be deleted when version 7.0.3 is released. +module FreedomPatches + module ArReferencesFix + module SchemaDefinition + def index_options(table_name) + index_options = as_options(index) + + # legacy reference index names are used on versions 6.0 and earlier + return index_options if options[:_uses_legacy_reference_index_name] + + index_options[:name] ||= polymorphic_index_name(table_name) if polymorphic + index_options + end + + ActiveRecord::ConnectionAdapters::ReferenceDefinition.prepend(self) + end + end +end + +class ActiveRecord::Migration::Compatibility::V6_0 + module TableDefinition + def references(*args, **options) + options[:_uses_legacy_reference_index_name] = true + super + end + alias :belongs_to :references + end + + def add_reference(table_name, ref_name, **options) + if connection.adapter_name == "SQLite" + options[:type] = :integer + end + options[:_uses_legacy_reference_index_name] = true + super + end + alias :add_belongs_to :add_reference + + def compatible_table_definition(t) + class << t + prepend TableDefinition + end + super + end +end diff --git a/lib/freedom_patches/rails_multisite.rb b/lib/freedom_patches/rails_multisite.rb index 35c6b82624c..99244669d7e 100644 --- a/lib/freedom_patches/rails_multisite.rb +++ b/lib/freedom_patches/rails_multisite.rb @@ -10,7 +10,7 @@ module RailsMultisite break if !defined?(RailsFailover::ActiveRecord) break if db == RailsMultisite::ConnectionManagement::DEFAULT - reading_role = :"#{db}_#{ActiveRecord::Base.reading_role}" + reading_role = :"#{db}_#{ActiveRecord.reading_role}" spec = RailsMultisite::ConnectionManagement.connection_spec(db: db) ActiveRecord::Base.connection_handlers[reading_role] ||= begin diff --git a/lib/highlight_js/highlight_js.rb b/lib/highlight_js.rb similarity index 100% rename from lib/highlight_js/highlight_js.rb rename to lib/highlight_js.rb diff --git a/lib/html_to_markdown.rb b/lib/html_to_markdown.rb index 6cd05ded831..bcd0da81322 100644 --- a/lib/html_to_markdown.rb +++ b/lib/html_to_markdown.rb @@ -59,13 +59,13 @@ class HtmlToMarkdown before, after = parent.children.slice_when { |n| n == br }.to_a if before.size > 1 - b = Nokogiri::XML::Node.new(parent.name, doc) + b = Nokogiri::XML::Node.new(parent.name, doc.document) before[0...-1].each { |c| b.add_child(c) } parent.previous = b if b.inner_html.present? end if after.present? - a = Nokogiri::XML::Node.new(parent.name, doc) + a = Nokogiri::XML::Node.new(parent.name, doc.document) after.each { |c| a.add_child(c) } parent.next = a if a.inner_html.present? end diff --git a/lib/i18n/duplicate_key_finder.rb b/lib/i18n/duplicate_key_finder.rb index c1e99c93a7f..65b0f33d0e9 100644 --- a/lib/i18n/duplicate_key_finder.rb +++ b/lib/i18n/duplicate_key_finder.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "locale_file_walker" +require "locale_file_walker" class DuplicateKeyFinder < LocaleFileWalker diff --git a/lib/middleware/anonymous_cache.rb b/lib/middleware/anonymous_cache.rb index 270e71fb947..b9e0d0db8aa 100644 --- a/lib/middleware/anonymous_cache.rb +++ b/lib/middleware/anonymous_cache.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -require_dependency "mobile_detection" -require_dependency "crawler_detection" -require_dependency "guardian" -require_dependency "http_language_parser" +require "mobile_detection" +require "crawler_detection" +require "guardian" +require "http_language_parser" module Middleware class AnonymousCache diff --git a/lib/migration/column_dropper.rb b/lib/migration/column_dropper.rb index 754f5bf8267..71e472baa49 100644 --- a/lib/migration/column_dropper.rb +++ b/lib/migration/column_dropper.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'migration/base_dropper' +require 'migration/base_dropper' module Migration class ColumnDropper diff --git a/lib/migration/table_dropper.rb b/lib/migration/table_dropper.rb index 8b7e89a3749..bbd27f02e5b 100644 --- a/lib/migration/table_dropper.rb +++ b/lib/migration/table_dropper.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'migration/base_dropper' +require 'migration/base_dropper' module Migration class Migration::TableDropper diff --git a/lib/plugin.rb b/lib/plugin.rb new file mode 100644 index 00000000000..6a788379a8d --- /dev/null +++ b/lib/plugin.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module Plugin + def self.initialization_guard(&block) + begin + block.call + rescue => error + plugins_directory = Rails.root + 'plugins' + + if error.backtrace && error.backtrace_locations + plugin_path = error.backtrace_locations.lazy.map do |location| + Pathname.new(location.absolute_path) + .ascend + .lazy + .find { |path| path.parent == plugins_directory } + end.next + + raise unless plugin_path + + stack_trace = error.backtrace.each_with_index.inject([]) do |messages, (line, index)| + if index == 0 + messages << "#{line}: #{error} (#{error.class})" + else + messages << "\t#{index}: from #{line}" + end + end.reverse.join("\n") + + STDERR.puts <<~TEXT + #{stack_trace} + + ** INCOMPATIBLE PLUGIN ** + + You are unable to build Discourse due to errors in the plugin at + #{plugin_path} + + Please try removing this plugin and rebuilding again! + TEXT + else + STDERR.puts <<~TEXT + ** PLUGIN FAILURE ** + + You are unable to build Discourse due to this error during plugin + initialization: + + #{error} + + #{error.backtrace.join("\n")} + TEXT + end + exit 1 + end + end +end diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index 8482ff02109..574ad98f493 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -2,8 +2,8 @@ require 'digest/sha1' require 'fileutils' -require_dependency 'plugin/metadata' -require_dependency 'auth' +require 'plugin/metadata' +require 'auth' class Plugin::CustomEmoji CACHE_KEY ||= "plugin-emoji" diff --git a/lib/plugin_initialization_guard.rb b/lib/plugin_initialization_guard.rb deleted file mode 100644 index 9f9676ef159..00000000000 --- a/lib/plugin_initialization_guard.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true - -def plugin_initialization_guard(&block) - begin - block.call - rescue => error - plugins_directory = Rails.root + 'plugins' - - if error.backtrace && error.backtrace_locations - plugin_path = error.backtrace_locations.lazy.map do |location| - Pathname.new(location.absolute_path) - .ascend - .lazy - .find { |path| path.parent == plugins_directory } - end.next - - raise unless plugin_path - - stack_trace = error.backtrace.each_with_index.inject([]) do |messages, (line, index)| - if index == 0 - messages << "#{line}: #{error} (#{error.class})" - else - messages << "\t#{index}: from #{line}" - end - end.reverse.join("\n") - - STDERR.puts <<~TEXT - #{stack_trace} - - ** INCOMPATIBLE PLUGIN ** - - You are unable to build Discourse due to errors in the plugin at - #{plugin_path} - - Please try removing this plugin and rebuilding again! - TEXT - else - STDERR.puts <<~TEXT - ** PLUGIN FAILURE ** - - You are unable to build Discourse due to this error during plugin - initialization: - - #{error} - - #{error.backtrace.join("\n")} - TEXT - end - exit 1 - end -end diff --git a/lib/post_action_result.rb b/lib/post_action_result.rb index 9959821f248..88a7b5d0ce5 100644 --- a/lib/post_action_result.rb +++ b/lib/post_action_result.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'has_errors' +require 'has_errors' class PostActionResult include HasErrors diff --git a/lib/require_dependency_backward_compatibility.rb b/lib/require_dependency_backward_compatibility.rb index ced0bbbeeb4..efec53ced3d 100644 --- a/lib/require_dependency_backward_compatibility.rb +++ b/lib/require_dependency_backward_compatibility.rb @@ -18,5 +18,5 @@ module RequireDependencyBackwardCompatibility super end - ActiveSupport::Dependencies::ZeitwerkIntegration::RequireDependency.prepend(self) + Object.prepend(self) end diff --git a/lib/reviewable/actions.rb b/lib/reviewable/actions.rb index ba7858d87d2..3343ac0fb83 100644 --- a/lib/reviewable/actions.rb +++ b/lib/reviewable/actions.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'reviewable/collection' +require 'reviewable/collection' class Reviewable < ActiveRecord::Base class Actions < Reviewable::Collection diff --git a/lib/s3_cors_rulesets.rb b/lib/s3_cors_rulesets.rb index 788c6f6bb22..3c4e293dd81 100644 --- a/lib/s3_cors_rulesets.rb +++ b/lib/s3_cors_rulesets.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency "s3_helper" +require "s3_helper" class S3CorsRulesets ASSETS = { diff --git a/lib/stylesheet/compiler.rb b/lib/stylesheet/compiler.rb index 72231f41635..ba4769a2650 100644 --- a/lib/stylesheet/compiler.rb +++ b/lib/stylesheet/compiler.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'stylesheet/importer' -require 'stylesheet/functions' module Stylesheet diff --git a/lib/stylesheet/functions.rb b/lib/stylesheet/functions.rb deleted file mode 100644 index 072998ab767..00000000000 --- a/lib/stylesheet/functions.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -module Stylesheet - module ScssFunctions - def asset_url(path) - Discourse.deprecate("The `asset-url` SCSS function is deprecated. Use `absolute-image-url` instead.", drop_from: '2.9.0') - SassC::Script::Value::String.new("url('#{ActionController::Base.helpers.asset_url(path.value)}')") - end - def image_url(path) - Discourse.deprecate("The `image-url` SCSS function is deprecated. Use `absolute-image-url` instead.", drop_from: '2.9.0') - SassC::Script::Value::String.new("url('#{ActionController::Base.helpers.image_url(path.value)}')") - end - end -end - -::SassC::Script::Functions.include(Stylesheet::ScssFunctions) diff --git a/lib/stylesheet/importer.rb b/lib/stylesheet/importer.rb index 36de290b259..c53b5cb2d2c 100644 --- a/lib/stylesheet/importer.rb +++ b/lib/stylesheet/importer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'global_path' +require 'global_path' module Stylesheet class Importer diff --git a/lib/stylesheet/manager.rb b/lib/stylesheet/manager.rb index 8ec676d1a1d..328762f06c9 100644 --- a/lib/stylesheet/manager.rb +++ b/lib/stylesheet/manager.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true -require_dependency 'distributed_cache' -require_dependency 'stylesheet/compiler' +require 'distributed_cache' +require 'stylesheet/compiler' module Stylesheet; end diff --git a/lib/svg_sprite/svg_sprite.rb b/lib/svg_sprite.rb similarity index 100% rename from lib/svg_sprite/svg_sprite.rb rename to lib/svg_sprite.rb diff --git a/lib/tasks/emoji.rake b/lib/tasks/emoji.rake index 6471730edc1..f85e22b379b 100644 --- a/lib/tasks/emoji.rake +++ b/lib/tasks/emoji.rake @@ -5,7 +5,7 @@ require "fileutils" require "json" require "nokogiri" require "open-uri" -require_dependency "file_helper" +require "file_helper" EMOJI_GROUPS_PATH ||= "lib/emoji/groups.json" diff --git a/lib/tasks/images.rake b/lib/tasks/images.rake index b7af043ddf8..653b305f23d 100644 --- a/lib/tasks/images.rake +++ b/lib/tasks/images.rake @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency "file_helper" +require "file_helper" task "images:compress" => :environment do images = Dir.glob("#{Rails.root}/app/**/*.png") diff --git a/lib/tasks/topics.rake b/lib/tasks/topics.rake index f979e625c7e..e3bf5790e02 100644 --- a/lib/tasks/topics.rake +++ b/lib/tasks/topics.rake @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency "rake_helpers" +require "rake_helpers" def close_old_topics(category) topics = Topic.where(closed: false, category_id: category.id) diff --git a/lib/tasks/uploads.rake b/lib/tasks/uploads.rake index e3428629c08..3d24f95695d 100644 --- a/lib/tasks/uploads.rake +++ b/lib/tasks/uploads.rake @@ -8,7 +8,7 @@ require "base62" # gather # ################################################################################ -require_dependency "rake_helpers" +require "rake_helpers" task "uploads:gather" => :environment do ENV["RAILS_DB"] ? gather_uploads : gather_uploads_for_all_sites diff --git a/lib/theme_store/zip_exporter.rb b/lib/theme_store/zip_exporter.rb index ed1d64c187d..87a9c8bd066 100644 --- a/lib/theme_store/zip_exporter.rb +++ b/lib/theme_store/zip_exporter.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'compression/zip' +require 'compression/zip' module ThemeStore; end diff --git a/lib/theme_store/zip_importer.rb b/lib/theme_store/zip_importer.rb index deff98d3dfd..ff98ea49019 100644 --- a/lib/theme_store/zip_importer.rb +++ b/lib/theme_store/zip_importer.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency 'compression/engine' +require 'compression/engine' module ThemeStore; end diff --git a/lib/validators/upload_validator.rb b/lib/validators/upload_validator.rb index 450c8dafc39..7dd4f757812 100644 --- a/lib/validators/upload_validator.rb +++ b/lib/validators/upload_validator.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_dependency "file_helper" +require "file_helper" module Validators; end diff --git a/spec/integrity/i18n_spec.rb b/spec/integrity/i18n_spec.rb index 8f2dbfc1328..2ab21f50699 100644 --- a/spec/integrity/i18n_spec.rb +++ b/spec/integrity/i18n_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "i18n/duplicate_key_finder" - def extract_locale(path) path[/\.([^.]{2,})\.yml$/, 1] end diff --git a/spec/integrity/site_setting_spec.rb b/spec/integrity/site_setting_spec.rb index 5d7ecbf58df..51d17551837 100644 --- a/spec/integrity/site_setting_spec.rb +++ b/spec/integrity/site_setting_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "i18n/duplicate_key_finder" - describe "site setting integrity checks" do let(:site_setting_file) { File.join(Rails.root, 'config', 'site_settings.yml') } let(:yaml) { YAML.load_file(site_setting_file) } diff --git a/spec/jobs/create_linked_topic_spec.rb b/spec/jobs/create_linked_topic_spec.rb index ccc0a16fa15..e8ff6745542 100644 --- a/spec/jobs/create_linked_topic_spec.rb +++ b/spec/jobs/create_linked_topic_spec.rb @@ -1,13 +1,11 @@ # frozen_string_literal: true describe Jobs::CreateLinkedTopic do - it "returns when the post cannot be found" do expect { Jobs::CreateLinkedTopic.new.perform(post_id: 1, sync_exec: true) }.not_to raise_error end context 'with a post' do - fab!(:category) { Fabricate(:category) } fab!(:topic) { Fabricate(:topic, category: category) } fab!(:post) do @@ -54,5 +52,4 @@ describe Jobs::CreateLinkedTopic do expect(linked_topic.sequence).to eq(2) end end - end diff --git a/spec/jobs/feature_topic_users_spec.rb b/spec/jobs/feature_topic_users_spec.rb index 84d375da8c9..3d4aa0fe3d7 100644 --- a/spec/jobs/feature_topic_users_spec.rb +++ b/spec/jobs/feature_topic_users_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true describe Jobs::FeatureTopicUsers do - it "raises an error without a topic_id" do expect { Jobs::FeatureTopicUsers.new.execute({}) }.to raise_error(Discourse::InvalidParameters) end @@ -32,16 +31,13 @@ describe Jobs::FeatureTopicUsers do Jobs::FeatureTopicUsers.new.execute(topic_id: topic.id) expect(topic.reload.featured_user_ids.include?(evil_trout.id)).to eq(false) end - end context "participant count" do - let!(:post) { create_post } let(:topic) { post.topic } it "it works as expected" do - # It has 1 participant after creation expect(topic.participant_count).to eq(1) @@ -58,9 +54,6 @@ describe Jobs::FeatureTopicUsers do create_post(topic: topic, user: Fabricate(:evil_trout)) Jobs::FeatureTopicUsers.new.execute(topic_id: topic.id) expect(topic.reload.participant_count).to eq(2) - end - end - end diff --git a/spec/jobs/old_keys_reminder_spec.rb b/spec/jobs/old_keys_reminder_spec.rb index ac00d45b9ad..26407b31fc1 100644 --- a/spec/jobs/old_keys_reminder_spec.rb +++ b/spec/jobs/old_keys_reminder_spec.rb @@ -28,9 +28,9 @@ describe Jobs::OldKeysReminder do As a courtesy, we wanted to let you know that the following credentials used on your Discourse instance have not been updated in more than two years: - google_oauth2_client_secret - #{google_secret.updated_at.to_date.to_s(:db)} - github_client_secret - #{github_secret.updated_at.to_date.to_s(:db)} - api key description - #{api_key.created_at.to_date.to_s(:db)} + google_oauth2_client_secret - #{google_secret.updated_at.to_date.to_fs(:db)} + github_client_secret - #{github_secret.updated_at.to_date.to_fs(:db)} + api key description - #{api_key.created_at.to_date.to_fs(:db)} No action is required at this time, however, it is considered good security practice to cycle all your important credentials every few years. TEXT @@ -45,11 +45,11 @@ describe Jobs::OldKeysReminder do As a courtesy, we wanted to let you know that the following credentials used on your Discourse instance have not been updated in more than two years: - google_oauth2_client_secret - #{google_secret.updated_at.to_date.to_s(:db)} - github_client_secret - #{github_secret.updated_at.to_date.to_s(:db)} - twitter_consumer_secret - #{recent_twitter_secret.updated_at.to_date.to_s(:db)} - api key description - #{api_key.created_at.to_date.to_s(:db)} - recent api key description - #{admin.username} - #{recent_api_key.created_at.to_date.to_s(:db)} + google_oauth2_client_secret - #{google_secret.updated_at.to_date.to_fs(:db)} + github_client_secret - #{github_secret.updated_at.to_date.to_fs(:db)} + twitter_consumer_secret - #{recent_twitter_secret.updated_at.to_date.to_fs(:db)} + api key description - #{api_key.created_at.to_date.to_fs(:db)} + recent api key description - #{admin.username} - #{recent_api_key.created_at.to_date.to_fs(:db)} No action is required at this time, however, it is considered good security practice to cycle all your important credentials every few years. TEXT diff --git a/spec/jobs/process_post_spec.rb b/spec/jobs/process_post_spec.rb index 6d5d65bb791..fc20d8f5083 100644 --- a/spec/jobs/process_post_spec.rb +++ b/spec/jobs/process_post_spec.rb @@ -1,13 +1,11 @@ # frozen_string_literal: true describe Jobs::ProcessPost do - it "returns when the post cannot be found" do expect { Jobs::ProcessPost.new.perform(post_id: 1, sync_exec: true) }.not_to raise_error end context 'with a post' do - fab!(:post) { Fabricate(:post) } it 'does not erase posts when CookedPostProcessor malfunctions' do @@ -90,5 +88,4 @@ describe Jobs::ProcessPost do expect(post.topic.reload.excerpt).to eq("Some OP content") end end - end diff --git a/spec/jobs/pull_hotlinked_images_spec.rb b/spec/jobs/pull_hotlinked_images_spec.rb index 09fca0e6ab3..416d9a80ab4 100644 --- a/spec/jobs/pull_hotlinked_images_spec.rb +++ b/spec/jobs/pull_hotlinked_images_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true describe Jobs::PullHotlinkedImages do - let(:image_url) { "http://wiki.mozilla.org/images/2/2e/Longcat1.png" } let(:broken_image_url) { "http://wiki.mozilla.org/images/2/2e/Longcat2.png" } let(:large_image_url) { "http://wiki.mozilla.org/images/2/2e/Longcat3.png" } diff --git a/spec/jobs/send_system_message_spec.rb b/spec/jobs/send_system_message_spec.rb index db6540eee5e..5497e78dbfa 100644 --- a/spec/jobs/send_system_message_spec.rb +++ b/spec/jobs/send_system_message_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true describe Jobs::SendSystemMessage do - it "raises an error without a user_id" do expect { Jobs::SendSystemMessage.new.execute(message_type: 'welcome_invite') }.to raise_error(Discourse::InvalidParameters) end @@ -11,7 +10,6 @@ describe Jobs::SendSystemMessage do end context 'with valid parameters' do - fab!(:user) { Fabricate(:user) } it "should call SystemMessage.create" do @@ -24,7 +22,5 @@ describe Jobs::SendSystemMessage do SystemMessage.any_instance.expects(:create).with('post_hidden', options) Jobs::SendSystemMessage.new.execute(user_id: user.id, message_type: 'post_hidden', message_options: options) end - end - end diff --git a/spec/lib/guardian_spec.rb b/spec/lib/guardian_spec.rb index 4eb53beb696..57a464fc193 100644 --- a/spec/lib/guardian_spec.rb +++ b/spec/lib/guardian_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'guardian' - describe Guardian do fab!(:user) { Fabricate(:user) } diff --git a/spec/lib/hijack_spec.rb b/spec/lib/hijack_spec.rb index 43bb9814c92..beb8b8622ab 100644 --- a/spec/lib/hijack_spec.rb +++ b/spec/lib/hijack_spec.rb @@ -193,7 +193,7 @@ describe Hijack do Process.stubs(:clock_gettime).returns(1.0) tester.hijack_test do Process.stubs(:clock_gettime).returns(2.0) - redirect_to 'http://awesome.com' + redirect_to 'http://awesome.com', allow_other_host: true end result = "HTTP/1.1 302 Found\r\nLocation: http://awesome.com\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 84\r\nConnection: close\r\nX-Runtime: 1.000000\r\n\r\n<html><body>You are being <a href=\"http://awesome.com\">redirected</a>.</body></html>" diff --git a/spec/lib/i18n/i18n_interpolation_keys_finder_spec.rb b/spec/lib/i18n/i18n_interpolation_keys_finder_spec.rb index a19c70cc631..2fd987bee52 100644 --- a/spec/lib/i18n/i18n_interpolation_keys_finder_spec.rb +++ b/spec/lib/i18n/i18n_interpolation_keys_finder_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "i18n/i18n_interpolation_keys_finder" - RSpec.describe I18nInterpolationKeysFinder do describe '#find' do it 'should return the right keys' do diff --git a/spec/lib/onpdiff_spec.rb b/spec/lib/onpdiff_spec.rb index d025b843590..182e0ee5dfe 100644 --- a/spec/lib/onpdiff_spec.rb +++ b/spec/lib/onpdiff_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'onpdiff' - describe ONPDiff do describe "diff" do diff --git a/spec/lib/stylesheet/compiler_spec.rb b/spec/lib/stylesheet/compiler_spec.rb index 609c319baea..ef1a3b5c754 100644 --- a/spec/lib/stylesheet/compiler_spec.rb +++ b/spec/lib/stylesheet/compiler_spec.rb @@ -74,20 +74,6 @@ describe Stylesheet::Compiler do end end - it "supports asset-url" do - css, _map = Stylesheet::Compiler.compile(".body{background-image: asset-url('/images/favicons/github.png');}", "test.scss") - - expect(css).to include("url('/images/favicons/github.png')") - expect(css).not_to include('asset-url') - end - - it "supports image-url" do - css, _map = Stylesheet::Compiler.compile(".body{background-image: image-url('/favicons/github.png');}", "test.scss") - - expect(css).to include("url('/favicons/github.png')") - expect(css).not_to include('image-url') - end - it "supports absolute-image-url" do scss = Stylesheet::Importer.new({}).prepended_scss scss += ".body{background-image: absolute-image-url('/favicons/github.png');}" diff --git a/spec/lib/validators/category_search_priority_weights_validator_spec.rb b/spec/lib/validators/category_search_priority_weights_validator_spec.rb index a809635510b..86c081ff134 100644 --- a/spec/lib/validators/category_search_priority_weights_validator_spec.rb +++ b/spec/lib/validators/category_search_priority_weights_validator_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'validators/category_search_priority_weights_validator' - RSpec.describe CategorySearchPriorityWeightsValidator do it "should validate the results correctly" do [1, 1.1].each do |value| diff --git a/spec/lib/validators/max_emojis_validator_spec.rb b/spec/lib/validators/max_emojis_validator_spec.rb index 8a5e90917e5..b134e72257d 100644 --- a/spec/lib/validators/max_emojis_validator_spec.rb +++ b/spec/lib/validators/max_emojis_validator_spec.rb @@ -1,8 +1,6 @@ # encoding: UTF-8 # frozen_string_literal: true -require 'validators/max_emojis_validator' - describe MaxEmojisValidator do # simulate Rails behavior (singleton) diff --git a/spec/lib/validators/quality_title_validator_spec.rb b/spec/lib/validators/quality_title_validator_spec.rb index 2403490515c..42f6d40cf11 100644 --- a/spec/lib/validators/quality_title_validator_spec.rb +++ b/spec/lib/validators/quality_title_validator_spec.rb @@ -1,7 +1,6 @@ # encoding: UTF-8 # frozen_string_literal: true -require 'validators/quality_title_validator' require 'ostruct' module QualityTitleValidatorSpec diff --git a/spec/lib/validators/topic_title_length_validator_spec.rb b/spec/lib/validators/topic_title_length_validator_spec.rb index 47745ca6481..04ddbf4a1eb 100644 --- a/spec/lib/validators/topic_title_length_validator_spec.rb +++ b/spec/lib/validators/topic_title_length_validator_spec.rb @@ -1,8 +1,6 @@ # encoding: UTF-8 # frozen_string_literal: true -require 'validators/topic_title_length_validator' - describe TopicTitleLengthValidator do # simulate Rails behavior (singleton) diff --git a/spec/lib/validators/url_validator_spec.rb b/spec/lib/validators/url_validator_spec.rb index adf1a8337dd..146b168f352 100644 --- a/spec/lib/validators/url_validator_spec.rb +++ b/spec/lib/validators/url_validator_spec.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require 'validators/topic_title_length_validator' - RSpec.describe UrlValidator do let(:record) { Fabricate.build(:user_profile, user: Fabricate.build(:user)) } let(:validator) { described_class.new(attributes: :website) } diff --git a/spec/models/given_daily_like_spec.rb b/spec/models/given_daily_like_spec.rb index cf0b6863b2f..3ba850d6329 100644 --- a/spec/models/given_daily_like_spec.rb +++ b/spec/models/given_daily_like_spec.rb @@ -3,8 +3,8 @@ describe GivenDailyLike do it 'no errors without a user' do - expect(-> { GivenDailyLike.increment_for(nil) }).not_to raise_error - expect(-> { GivenDailyLike.decrement_for(nil) }).not_to raise_error + expect { GivenDailyLike.increment_for(nil) }.not_to raise_error + expect { GivenDailyLike.decrement_for(nil) }.not_to raise_error end context 'with a user' do diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 1b633bd3117..2c408aa03cd 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -487,7 +487,7 @@ end def decrypt_auth_cookie(cookie) request = ActionDispatch::Request.new(create_request_env.merge("HTTP_COOKIE" => "_t=#{cookie}")) - request.cookie_jar.encrypted["_t"] + request.cookie_jar.encrypted["_t"].with_indifferent_access end class SpecSecureRandom diff --git a/spec/requests/invites_controller_spec.rb b/spec/requests/invites_controller_spec.rb index 3a67d6f2c23..dd5e7d29eba 100644 --- a/spec/requests/invites_controller_spec.rb +++ b/spec/requests/invites_controller_spec.rb @@ -22,13 +22,22 @@ describe InvitesController do end end - it 'shows unobfuscated email if email data is present in authentication data' do - ActionDispatch::Request.any_instance.stubs(:session).returns(authentication: { email: invite.email }) - get "/invites/#{invite.invite_key}" - expect(response.status).to eq(200) - expect(response.body).to have_tag(:script, with: { src: "/assets/#{EmberCli.transform_name("application")}.js" }) - expect(response.body).to include(invite.email) - expect(response.body).not_to include('i*****g@a***********e.ooo') + context 'when email data is present in authentication data' do + let(:store) { ActionDispatch::Session::CookieStore.new({}) } + let(:session_stub) { ActionDispatch::Request::Session.create(store, ActionDispatch::TestRequest.create, {}) } + + before do + session_stub[:authentication] = { email: invite.email } + ActionDispatch::Request.any_instance.stubs(:session).returns(session_stub) + end + + it 'shows unobfuscated email' do + get "/invites/#{invite.invite_key}" + expect(response.status).to eq(200) + expect(response.body).to have_tag(:script, with: { src: "/assets/#{EmberCli.transform_name("application")}.js" }) + expect(response.body).to include(invite.email) + expect(response.body).not_to include('i*****g@a***********e.ooo') + end end it 'shows default user fields' do diff --git a/spec/services/email_settings_exception_handler_spec.rb b/spec/services/email_settings_exception_handler_spec.rb index b7d16d5e99a..0d525d0a8a5 100644 --- a/spec/services/email_settings_exception_handler_spec.rb +++ b/spec/services/email_settings_exception_handler_spec.rb @@ -38,7 +38,7 @@ RSpec.describe EmailSettingsExceptionHandler do end it "formats a Net::SMTPAuthenticationError with application-specific password Gmail error" do - exception = Net::SMTPAuthenticationError.new("Application-specific password required") + exception = Net::SMTPAuthenticationError.new(nil, message: "Application-specific password required") expect(subject.class.friendly_exception_message(exception, "smtp.gmail.com")).to eq( I18n.t("email_settings.authentication_error_gmail_app_password") ) @@ -52,15 +52,15 @@ RSpec.describe EmailSettingsExceptionHandler do end it "formats a Net::SMTPSyntaxError, Net::SMTPFatalError, and Net::SMTPUnknownError" do - exception = Net::SMTPSyntaxError.new("bad syntax") + exception = Net::SMTPSyntaxError.new(nil, message: "bad syntax") expect(subject.class.friendly_exception_message(exception, "smtp.test.com")).to eq( I18n.t("email_settings.smtp_unhandled_error", message: exception.message) ) - exception = Net::SMTPFatalError.new("fatal") + exception = Net::SMTPFatalError.new(nil, message: "fatal") expect(subject.class.friendly_exception_message(exception, "smtp.test.com")).to eq( I18n.t("email_settings.smtp_unhandled_error", message: exception.message) ) - exception = Net::SMTPUnknownError.new("unknown") + exception = Net::SMTPUnknownError.new(nil, message: "unknown") expect(subject.class.friendly_exception_message(exception, "smtp.test.com")).to eq( I18n.t("email_settings.smtp_unhandled_error", message: exception.message) ) diff --git a/spec/services/email_settings_validator_spec.rb b/spec/services/email_settings_validator_spec.rb index fee23271ff8..8abde6d3662 100644 --- a/spec/services/email_settings_validator_spec.rb +++ b/spec/services/email_settings_validator_spec.rb @@ -112,7 +112,7 @@ RSpec.describe EmailSettingsValidator do it "logs a warning if debug: true passed in and still raises the error" do Rails.logger.expects(:warn).with(regexp_matches(/\[EmailSettingsValidator\] Error encountered/)).at_least_once - net_smtp_stub.stubs(:start).raises(Net::SMTPAuthenticationError, "invalid credentials") + net_smtp_stub.stubs(:start).raises(Net::SMTPAuthenticationError, stub(message: "invalid credentials")) expect { subject.class.validate_smtp(host: host, port: port, username: username, password: password, debug: true, domain: domain) }.to raise_error(Net::SMTPAuthenticationError) end diff --git a/spec/views/omniauth_callbacks/failure.html.erb_spec.rb b/spec/views/omniauth_callbacks/failure.html.erb_spec.rb index 157d4aa4fff..96a5a01a7ea 100644 --- a/spec/views/omniauth_callbacks/failure.html.erb_spec.rb +++ b/spec/views/omniauth_callbacks/failure.html.erb_spec.rb @@ -1,12 +1,13 @@ # frozen_string_literal: true describe "users/omniauth_callbacks/failure.html.erb" do - - it "renders the failure page" do + before do flash[:error] = I18n.t("login.omniauth_error", strategy: 'test') - render - - expect(rendered.match(I18n.t("login.omniauth_error.generic", strategy: 'test'))).not_to eq(nil) end + it "renders the failure page" do + render template: 'users/omniauth_callbacks/failure' + + expect(rendered).to match I18n.t("login.omniauth_error.generic", strategy: 'test') + end end