mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 06:19:17 +08:00
DEV: Upgrade to Rails 7
This patch upgrades Rails to version 7.0.2.4.
This commit is contained in:
parent
532f9cdb1a
commit
008b700a3f
|
@ -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
|
||||
- uri # Ruby
|
||||
|
|
10
Gemfile
10
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'
|
||||
|
|
89
Gemfile.lock
89
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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};"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'email/sender'
|
||||
|
||||
module Jobs
|
||||
class GroupSmtpEmail < ::Jobs::Base
|
||||
include Skippable
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'email/message_builder'
|
||||
|
||||
class GroupSmtpMailer < ActionMailer::Base
|
||||
include Email::BuildEmailHelper
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'global_path'
|
||||
require 'csv'
|
||||
require 'json_schemer'
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
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
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
return if GlobalSetting.skip_db?
|
||||
|
||||
# Some sanity checking so we don't count on an unindexed column on boot
|
||||
begin
|
||||
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
|
||||
|
@ -26,6 +27,7 @@ begin
|
|||
SiteSetting.has_login_hint = true
|
||||
end
|
||||
end
|
||||
rescue ActiveRecord::NoDatabaseError
|
||||
rescue ActiveRecord::NoDatabaseError
|
||||
# Database might not have been created
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
if Rails.env.development? && SiteSetting.port.to_i > 0
|
||||
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
|
||||
else
|
||||
Onebox.options = {
|
||||
twitter_client: TwitterApi,
|
||||
redirect_limit: 3,
|
||||
user_agent: "Discourse Forum Onebox v#{Discourse::VERSION::STRING}"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,18 +2,19 @@
|
|||
|
||||
return if GlobalSetting.skip_db?
|
||||
|
||||
require_dependency 'webpush'
|
||||
Rails.application.config.to_prepare do
|
||||
require 'webpush'
|
||||
|
||||
def generate_vapid_key?
|
||||
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
|
||||
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?
|
||||
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
|
||||
|
@ -24,8 +25,9 @@ if generate_vapid_key?
|
|||
if ActiveRecord::Base.connection.table_exists?(:push_subscriptions)
|
||||
PushSubscription.delete_all
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DiscourseEvent.on(:user_logged_out) do |user|
|
||||
DiscourseEvent.on(:user_logged_out) do |user|
|
||||
PushNotificationPusher.clear_subscriptions(user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
# 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
|
||||
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."
|
||||
|
@ -12,10 +17,5 @@ if Rails.env == "development" && SiteSetting.force_https
|
|||
STDERR.puts "Try: bin/rails c"
|
||||
STDERR.puts "SiteSetting.force_https = false"
|
||||
STDERR.puts
|
||||
end
|
||||
end
|
||||
|
||||
Discourse::Application.config.session_store(
|
||||
:discourse_cookie_store,
|
||||
key: '_forum_session',
|
||||
path: (Rails.application.config.relative_url_root.nil?) ? '/' : Rails.application.config.relative_url_root
|
||||
)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
if (Rails.env.production? && SiteSetting.logging_provider == 'lograge') || (ENV["ENABLE_LOGRAGE"] == "1")
|
||||
Rails.application.config.to_prepare do
|
||||
if (Rails.env.production? && SiteSetting.logging_provider == 'lograge') || (ENV["ENABLE_LOGRAGE"] == "1")
|
||||
require 'lograge'
|
||||
|
||||
if Rails.configuration.multisite
|
||||
|
@ -114,4 +115,5 @@ if (Rails.env.production? && SiteSetting.logging_provider == 'lograge') || (ENV[
|
|||
Rails.logger.chain(config.lograge.logger)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
99
config/initializers/assets.rb
Normal file
99
config/initializers/assets.rb
Normal file
|
@ -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
|
15
config/initializers/filter_parameter_logging.rb
Normal file
15
config/initializers/filter_parameter_logging.rb
Normal file
|
@ -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,
|
||||
]
|
106
config/initializers/new_framework_defaults_7_0.rb
Normal file
106
config/initializers/new_framework_defaults_7_0.rb
Normal file
|
@ -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"
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "common_passwords/common_passwords"
|
||||
require "common_passwords"
|
||||
|
||||
class ClearCommonPasswordsCache < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'has_errors'
|
||||
require 'has_errors'
|
||||
|
||||
class Auth::GithubAuthenticator < Auth::ManagedAuthenticator
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
require_dependency 'content_security_policy/default'
|
||||
require 'content_security_policy/default'
|
||||
|
||||
class ContentSecurityPolicy
|
||||
class Builder
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
require_dependency 'content_security_policy'
|
||||
require 'content_security_policy'
|
||||
|
||||
class ContentSecurityPolicy
|
||||
class Default
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
require_dependency 'content_security_policy'
|
||||
require 'content_security_policy'
|
||||
|
||||
class ContentSecurityPolicy
|
||||
class Middleware
|
||||
|
|
|
@ -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
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency "migration/base_dropper"
|
||||
require "migration/base_dropper"
|
||||
|
||||
class DbHelper
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'file_store/base_store'
|
||||
require 'file_store/base_store'
|
||||
|
||||
module FileStore
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
50
lib/freedom_patches/ar_references_fix.rb
Normal file
50
lib/freedom_patches/ar_references_fix.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "locale_file_walker"
|
||||
require "locale_file_walker"
|
||||
|
||||
class DuplicateKeyFinder < LocaleFileWalker
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'migration/base_dropper'
|
||||
require 'migration/base_dropper'
|
||||
|
||||
module Migration
|
||||
class ColumnDropper
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'migration/base_dropper'
|
||||
require 'migration/base_dropper'
|
||||
|
||||
module Migration
|
||||
class Migration::TableDropper
|
||||
|
|
53
lib/plugin.rb
Normal file
53
lib/plugin.rb
Normal file
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'has_errors'
|
||||
require 'has_errors'
|
||||
|
||||
class PostActionResult
|
||||
include HasErrors
|
||||
|
|
|
@ -18,5 +18,5 @@ module RequireDependencyBackwardCompatibility
|
|||
super
|
||||
end
|
||||
|
||||
ActiveSupport::Dependencies::ZeitwerkIntegration::RequireDependency.prepend(self)
|
||||
Object.prepend(self)
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'reviewable/collection'
|
||||
require 'reviewable/collection'
|
||||
|
||||
class Reviewable < ActiveRecord::Base
|
||||
class Actions < Reviewable::Collection
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency "s3_helper"
|
||||
require "s3_helper"
|
||||
|
||||
class S3CorsRulesets
|
||||
ASSETS = {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'stylesheet/importer'
|
||||
require 'stylesheet/functions'
|
||||
|
||||
module Stylesheet
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'global_path'
|
||||
require 'global_path'
|
||||
|
||||
module Stylesheet
|
||||
class Importer
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'compression/zip'
|
||||
require 'compression/zip'
|
||||
|
||||
module ThemeStore; end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency 'compression/engine'
|
||||
require 'compression/engine'
|
||||
|
||||
module ThemeStore; end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_dependency "file_helper"
|
||||
require "file_helper"
|
||||
|
||||
module Validators; end
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "i18n/duplicate_key_finder"
|
||||
|
||||
def extract_locale(path)
|
||||
path[/\.([^.]{2,})\.yml$/, 1]
|
||||
end
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'guardian'
|
||||
|
||||
describe Guardian do
|
||||
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
|
|
@ -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>"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'onpdiff'
|
||||
|
||||
describe ONPDiff do
|
||||
|
||||
describe "diff" do
|
||||
|
|
|
@ -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');}"
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'validators/max_emojis_validator'
|
||||
|
||||
describe MaxEmojisValidator do
|
||||
|
||||
# simulate Rails behavior (singleton)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'validators/quality_title_validator'
|
||||
require 'ostruct'
|
||||
|
||||
module QualityTitleValidatorSpec
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'validators/topic_title_length_validator'
|
||||
|
||||
describe TopicTitleLengthValidator do
|
||||
|
||||
# simulate Rails behavior (singleton)
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -22,14 +22,23 @@ 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 })
|
||||
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
|
||||
user_field = Fabricate(:user_field)
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user