mirror of
https://github.com/discourse/discourse.git
synced 2025-05-23 16:07:03 +08:00
DEV: Apply syntax_tree formatting to app/*
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'current_user'
|
||||
require "current_user"
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
include CurrentUser
|
||||
@ -43,17 +43,18 @@ class ApplicationController < ActionController::Base
|
||||
before_action :block_if_requires_login
|
||||
before_action :preload_json
|
||||
before_action :check_xhr
|
||||
after_action :add_readonly_header
|
||||
after_action :perform_refresh_session
|
||||
after_action :dont_cache_page
|
||||
after_action :conditionally_allow_site_embedding
|
||||
after_action :ensure_vary_header
|
||||
after_action :add_noindex_header, if: -> { is_feed_request? || !SiteSetting.allow_index_in_robots_txt }
|
||||
after_action :add_noindex_header_to_non_canonical, if: :spa_boot_request?
|
||||
after_action :add_readonly_header
|
||||
after_action :perform_refresh_session
|
||||
after_action :dont_cache_page
|
||||
after_action :conditionally_allow_site_embedding
|
||||
after_action :ensure_vary_header
|
||||
after_action :add_noindex_header,
|
||||
if: -> { is_feed_request? || !SiteSetting.allow_index_in_robots_txt }
|
||||
after_action :add_noindex_header_to_non_canonical, if: :spa_boot_request?
|
||||
around_action :link_preload, if: -> { spa_boot_request? && GlobalSetting.preload_link_header }
|
||||
|
||||
HONEYPOT_KEY ||= 'HONEYPOT_KEY'
|
||||
CHALLENGE_KEY ||= 'CHALLENGE_KEY'
|
||||
HONEYPOT_KEY ||= "HONEYPOT_KEY"
|
||||
CHALLENGE_KEY ||= "CHALLENGE_KEY"
|
||||
|
||||
layout :set_layout
|
||||
|
||||
@ -68,12 +69,12 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
def use_crawler_layout?
|
||||
@use_crawler_layout ||=
|
||||
request.user_agent &&
|
||||
(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"])
|
||||
)
|
||||
request.user_agent && (request.media_type.blank? || request.media_type.include?("html")) &&
|
||||
!%w[json rss].include?(params[:format]) &&
|
||||
(
|
||||
has_escaped_fragment? || params.key?("print") || show_browser_update? ||
|
||||
CrawlerDetection.crawler?(request.user_agent, request.headers["HTTP_VIA"])
|
||||
)
|
||||
end
|
||||
|
||||
def perform_refresh_session
|
||||
@ -91,19 +92,16 @@ class ApplicationController < ActionController::Base
|
||||
response.cache_control[:no_cache] = true
|
||||
response.cache_control[:extras] = ["no-store"]
|
||||
end
|
||||
if SiteSetting.login_required
|
||||
response.headers['Discourse-No-Onebox'] = '1'
|
||||
end
|
||||
response.headers["Discourse-No-Onebox"] = "1" if SiteSetting.login_required
|
||||
end
|
||||
|
||||
def conditionally_allow_site_embedding
|
||||
if SiteSetting.allow_embedding_site_in_an_iframe
|
||||
response.headers.delete('X-Frame-Options')
|
||||
end
|
||||
response.headers.delete("X-Frame-Options") if SiteSetting.allow_embedding_site_in_an_iframe
|
||||
end
|
||||
|
||||
def ember_cli_required?
|
||||
Rails.env.development? && ENV["ALLOW_EMBER_CLI_PROXY_BYPASS"] != "1" && request.headers['X-Discourse-Ember-CLI'] != 'true'
|
||||
Rails.env.development? && ENV["ALLOW_EMBER_CLI_PROXY_BYPASS"] != "1" &&
|
||||
request.headers["X-Discourse-Ember-CLI"] != "true"
|
||||
end
|
||||
|
||||
def application_layout
|
||||
@ -118,14 +116,16 @@ class ApplicationController < ActionController::Base
|
||||
return "crawler"
|
||||
end
|
||||
|
||||
use_crawler_layout? ? 'crawler' : application_layout
|
||||
use_crawler_layout? ? "crawler" : application_layout
|
||||
end
|
||||
|
||||
class RenderEmpty < StandardError; end
|
||||
class PluginDisabled < StandardError; end
|
||||
class RenderEmpty < StandardError
|
||||
end
|
||||
class PluginDisabled < StandardError
|
||||
end
|
||||
|
||||
rescue_from RenderEmpty do
|
||||
with_resolved_locale { render 'default/empty' }
|
||||
with_resolved_locale { render "default/empty" }
|
||||
end
|
||||
|
||||
rescue_from ArgumentError do |e|
|
||||
@ -147,10 +147,10 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
rescue_from Discourse::SiteSettingMissing do |e|
|
||||
render_json_error I18n.t('site_setting_missing', name: e.message), status: 500
|
||||
render_json_error I18n.t("site_setting_missing", name: e.message), status: 500
|
||||
end
|
||||
|
||||
rescue_from ActionController::RoutingError, PluginDisabled do
|
||||
rescue_from ActionController::RoutingError, PluginDisabled do
|
||||
rescue_discourse_actions(:not_found, 404)
|
||||
end
|
||||
|
||||
@ -180,21 +180,20 @@ class ApplicationController < ActionController::Base
|
||||
rescue_from RateLimiter::LimitExceeded do |e|
|
||||
retry_time_in_seconds = e&.available_in
|
||||
|
||||
response_headers = {
|
||||
'Retry-After': retry_time_in_seconds.to_s
|
||||
}
|
||||
response_headers = { "Retry-After": retry_time_in_seconds.to_s }
|
||||
|
||||
if e&.error_code
|
||||
response_headers['Discourse-Rate-Limit-Error-Code'] = e.error_code
|
||||
end
|
||||
response_headers["Discourse-Rate-Limit-Error-Code"] = e.error_code if e&.error_code
|
||||
|
||||
with_resolved_locale do
|
||||
render_json_error(
|
||||
e.description,
|
||||
type: :rate_limit,
|
||||
status: 429,
|
||||
extras: { wait_seconds: retry_time_in_seconds, time_left: e&.time_left },
|
||||
headers: response_headers
|
||||
extras: {
|
||||
wait_seconds: retry_time_in_seconds,
|
||||
time_left: e&.time_left,
|
||||
},
|
||||
headers: response_headers,
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -208,10 +207,7 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
rescue_from Discourse::InvalidParameters do |e|
|
||||
opts = {
|
||||
custom_message: 'invalid_params',
|
||||
custom_message_params: { message: e.message }
|
||||
}
|
||||
opts = { custom_message: "invalid_params", custom_message_params: { message: e.message } }
|
||||
|
||||
if (request.format && request.format.json?) || request.xhr? || !request.get?
|
||||
rescue_discourse_actions(:invalid_parameters, 400, opts.merge(include_ember: true))
|
||||
@ -226,14 +222,12 @@ class ApplicationController < ActionController::Base
|
||||
e.status,
|
||||
check_permalinks: e.check_permalinks,
|
||||
original_path: e.original_path,
|
||||
custom_message: e.custom_message
|
||||
custom_message: e.custom_message,
|
||||
)
|
||||
end
|
||||
|
||||
rescue_from Discourse::InvalidAccess do |e|
|
||||
if e.opts[:delete_cookie].present?
|
||||
cookies.delete(e.opts[:delete_cookie])
|
||||
end
|
||||
cookies.delete(e.opts[:delete_cookie]) if e.opts[:delete_cookie].present?
|
||||
|
||||
rescue_discourse_actions(
|
||||
:invalid_access,
|
||||
@ -241,7 +235,7 @@ class ApplicationController < ActionController::Base
|
||||
include_ember: true,
|
||||
custom_message: e.custom_message,
|
||||
custom_message_params: e.custom_message_params,
|
||||
group: e.group
|
||||
group: e.group,
|
||||
)
|
||||
end
|
||||
|
||||
@ -249,20 +243,16 @@ class ApplicationController < ActionController::Base
|
||||
unless response_body
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render_json_error I18n.t('read_only_mode_enabled'), type: :read_only, status: 503
|
||||
end
|
||||
format.html do
|
||||
render status: 503, layout: 'no_ember', template: 'exceptions/read_only'
|
||||
render_json_error I18n.t("read_only_mode_enabled"), type: :read_only, status: 503
|
||||
end
|
||||
format.html { render status: 503, layout: "no_ember", template: "exceptions/read_only" }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
rescue_from SecondFactor::AuthManager::SecondFactorRequired do |e|
|
||||
if request.xhr?
|
||||
render json: {
|
||||
second_factor_challenge_nonce: e.nonce
|
||||
}, status: 403
|
||||
render json: { second_factor_challenge_nonce: e.nonce }, status: 403
|
||||
else
|
||||
redirect_to session_2fa_path(nonce: e.nonce)
|
||||
end
|
||||
@ -274,7 +264,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
def redirect_with_client_support(url, options = {})
|
||||
if request.xhr?
|
||||
response.headers['Discourse-Xhr-Redirect'] = 'true'
|
||||
response.headers["Discourse-Xhr-Redirect"] = "true"
|
||||
render plain: url
|
||||
else
|
||||
redirect_to url, options
|
||||
@ -283,9 +273,9 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
def rescue_discourse_actions(type, status_code, opts = nil)
|
||||
opts ||= {}
|
||||
show_json_errors = (request.format && request.format.json?) ||
|
||||
(request.xhr?) ||
|
||||
((params[:external_id] || '').ends_with? '.json')
|
||||
show_json_errors =
|
||||
(request.format && request.format.json?) || (request.xhr?) ||
|
||||
((params[:external_id] || "").ends_with? ".json")
|
||||
|
||||
if type == :not_found && opts[:check_permalinks]
|
||||
url = opts[:original_path] || request.fullpath
|
||||
@ -295,7 +285,9 @@ 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, allow_other_host: true
|
||||
redirect_with_client_support permalink.target_url,
|
||||
status: :moved_permanently,
|
||||
allow_other_host: true
|
||||
return
|
||||
end
|
||||
end
|
||||
@ -321,11 +313,15 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
with_resolved_locale(check_current_user: false) do
|
||||
# Include error in HTML format for topics#show.
|
||||
if (request.params[:controller] == 'topics' && request.params[:action] == 'show') || (request.params[:controller] == 'categories' && request.params[:action] == 'find_by_slug')
|
||||
if (request.params[:controller] == "topics" && request.params[:action] == "show") ||
|
||||
(
|
||||
request.params[:controller] == "categories" &&
|
||||
request.params[:action] == "find_by_slug"
|
||||
)
|
||||
opts[:extras] = {
|
||||
title: I18n.t('page_not_found.page_title'),
|
||||
title: I18n.t("page_not_found.page_title"),
|
||||
html: build_not_found_page(error_page_opts),
|
||||
group: error_page_opts[:group]
|
||||
group: error_page_opts[:group],
|
||||
}
|
||||
end
|
||||
end
|
||||
@ -340,7 +336,7 @@ class ApplicationController < ActionController::Base
|
||||
return render plain: message, status: status_code
|
||||
end
|
||||
with_resolved_locale do
|
||||
error_page_opts[:layout] = (opts[:include_ember] && @preloaded) ? 'application' : 'no_ember'
|
||||
error_page_opts[:layout] = (opts[:include_ember] && @preloaded) ? "application" : "no_ember"
|
||||
render html: build_not_found_page(error_page_opts)
|
||||
end
|
||||
end
|
||||
@ -373,9 +369,8 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
def clear_notifications
|
||||
if current_user && !@readonly_mode
|
||||
|
||||
cookie_notifications = cookies['cn']
|
||||
notifications = request.headers['Discourse-Clear-Notifications']
|
||||
cookie_notifications = cookies["cn"]
|
||||
notifications = request.headers["Discourse-Clear-Notifications"]
|
||||
|
||||
if cookie_notifications
|
||||
if notifications.present?
|
||||
@ -392,22 +387,28 @@ class ApplicationController < ActionController::Base
|
||||
current_user.publish_notifications_state
|
||||
cookie_args = {}
|
||||
cookie_args[:path] = Discourse.base_path if Discourse.base_path.present?
|
||||
cookies.delete('cn', cookie_args)
|
||||
cookies.delete("cn", cookie_args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def with_resolved_locale(check_current_user: true)
|
||||
if check_current_user && (user = current_user rescue nil)
|
||||
if check_current_user &&
|
||||
(
|
||||
user =
|
||||
begin
|
||||
current_user
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
)
|
||||
locale = user.effective_locale
|
||||
else
|
||||
locale = Discourse.anonymous_locale(request)
|
||||
locale ||= SiteSetting.default_locale
|
||||
end
|
||||
|
||||
if !I18n.locale_available?(locale)
|
||||
locale = SiteSettings::DefaultsProvider::DEFAULT_LOCALE
|
||||
end
|
||||
locale = SiteSettings::DefaultsProvider::DEFAULT_LOCALE if !I18n.locale_available?(locale)
|
||||
|
||||
I18n.ensure_all_loaded!
|
||||
I18n.with_locale(locale) { yield }
|
||||
@ -458,7 +459,8 @@ class ApplicationController < ActionController::Base
|
||||
safe_mode = safe_mode.split(",")
|
||||
request.env[NO_THEMES] = safe_mode.include?(NO_THEMES) || safe_mode.include?(LEGACY_NO_THEMES)
|
||||
request.env[NO_PLUGINS] = safe_mode.include?(NO_PLUGINS)
|
||||
request.env[NO_UNOFFICIAL_PLUGINS] = safe_mode.include?(NO_UNOFFICIAL_PLUGINS) || safe_mode.include?(LEGACY_NO_UNOFFICIAL_PLUGINS)
|
||||
request.env[NO_UNOFFICIAL_PLUGINS] = safe_mode.include?(NO_UNOFFICIAL_PLUGINS) ||
|
||||
safe_mode.include?(LEGACY_NO_UNOFFICIAL_PLUGINS)
|
||||
end
|
||||
end
|
||||
|
||||
@ -471,8 +473,7 @@ class ApplicationController < ActionController::Base
|
||||
theme_id = nil
|
||||
|
||||
if (preview_theme_id = request[:preview_theme_id]&.to_i) &&
|
||||
guardian.allow_themes?([preview_theme_id], include_preview: true)
|
||||
|
||||
guardian.allow_themes?([preview_theme_id], include_preview: true)
|
||||
theme_id = preview_theme_id
|
||||
end
|
||||
|
||||
@ -491,7 +492,8 @@ class ApplicationController < ActionController::Base
|
||||
theme_id = ids.first if guardian.allow_themes?(ids)
|
||||
end
|
||||
|
||||
if theme_id.blank? && SiteSetting.default_theme_id != -1 && guardian.allow_themes?([SiteSetting.default_theme_id])
|
||||
if theme_id.blank? && SiteSetting.default_theme_id != -1 &&
|
||||
guardian.allow_themes?([SiteSetting.default_theme_id])
|
||||
theme_id = SiteSetting.default_theme_id
|
||||
end
|
||||
|
||||
@ -533,13 +535,11 @@ class ApplicationController < ActionController::Base
|
||||
def render_json_dump(obj, opts = nil)
|
||||
opts ||= {}
|
||||
if opts[:rest_serializer]
|
||||
obj['__rest_serializer'] = "1"
|
||||
opts.each do |k, v|
|
||||
obj[k] = v if k.to_s.start_with?("refresh_")
|
||||
end
|
||||
obj["__rest_serializer"] = "1"
|
||||
opts.each { |k, v| obj[k] = v if k.to_s.start_with?("refresh_") }
|
||||
|
||||
obj['extras'] = opts[:extras] if opts[:extras]
|
||||
obj['meta'] = opts[:meta] if opts[:meta]
|
||||
obj["extras"] = opts[:extras] if opts[:extras]
|
||||
obj["meta"] = opts[:meta] if opts[:meta]
|
||||
end
|
||||
|
||||
render json: MultiJson.dump(obj), status: opts[:status] || 200
|
||||
@ -557,29 +557,33 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
def fetch_user_from_params(opts = nil, eager_load = [])
|
||||
opts ||= {}
|
||||
user = if params[:username]
|
||||
username_lower = params[:username].downcase.chomp('.json')
|
||||
user =
|
||||
if params[:username]
|
||||
username_lower = params[:username].downcase.chomp(".json")
|
||||
|
||||
if current_user && current_user.username_lower == username_lower
|
||||
current_user
|
||||
else
|
||||
find_opts = { username_lower: username_lower }
|
||||
find_opts[:active] = true unless opts[:include_inactive] || current_user.try(:staff?)
|
||||
result = User
|
||||
(result = result.includes(*eager_load)) if !eager_load.empty?
|
||||
result.find_by(find_opts)
|
||||
if current_user && current_user.username_lower == username_lower
|
||||
current_user
|
||||
else
|
||||
find_opts = { username_lower: username_lower }
|
||||
find_opts[:active] = true unless opts[:include_inactive] || current_user.try(:staff?)
|
||||
result = User
|
||||
(result = result.includes(*eager_load)) if !eager_load.empty?
|
||||
result.find_by(find_opts)
|
||||
end
|
||||
elsif params[:external_id]
|
||||
external_id = params[:external_id].chomp(".json")
|
||||
if provider_name = params[:external_provider]
|
||||
raise Discourse::InvalidAccess unless guardian.is_admin? # external_id might be something sensitive
|
||||
provider = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
|
||||
raise Discourse::NotFound if !provider&.is_managed? # Only managed authenticators use UserAssociatedAccount
|
||||
UserAssociatedAccount.find_by(
|
||||
provider_name: provider_name,
|
||||
provider_uid: external_id,
|
||||
)&.user
|
||||
else
|
||||
SingleSignOnRecord.find_by(external_id: external_id).try(:user)
|
||||
end
|
||||
end
|
||||
elsif params[:external_id]
|
||||
external_id = params[:external_id].chomp('.json')
|
||||
if provider_name = params[:external_provider]
|
||||
raise Discourse::InvalidAccess unless guardian.is_admin? # external_id might be something sensitive
|
||||
provider = Discourse.enabled_authenticators.find { |a| a.name == provider_name }
|
||||
raise Discourse::NotFound if !provider&.is_managed? # Only managed authenticators use UserAssociatedAccount
|
||||
UserAssociatedAccount.find_by(provider_name: provider_name, provider_uid: external_id)&.user
|
||||
else
|
||||
SingleSignOnRecord.find_by(external_id: external_id).try(:user)
|
||||
end
|
||||
end
|
||||
raise Discourse::NotFound if user.blank?
|
||||
|
||||
guardian.ensure_can_see!(user)
|
||||
@ -587,15 +591,17 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def post_ids_including_replies
|
||||
post_ids = params[:post_ids].map(&:to_i)
|
||||
post_ids |= PostReply.where(post_id: params[:reply_post_ids]).pluck(:reply_post_id) if params[:reply_post_ids]
|
||||
post_ids = params[:post_ids].map(&:to_i)
|
||||
post_ids |= PostReply.where(post_id: params[:reply_post_ids]).pluck(:reply_post_id) if params[
|
||||
:reply_post_ids
|
||||
]
|
||||
post_ids
|
||||
end
|
||||
|
||||
def no_cookies
|
||||
# do your best to ensure response has no cookies
|
||||
# longer term we may want to push this into middleware
|
||||
headers.delete 'Set-Cookie'
|
||||
headers.delete "Set-Cookie"
|
||||
request.session_options[:skip] = true
|
||||
end
|
||||
|
||||
@ -615,9 +621,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
RateLimiter.new(nil, "second-factor-min-#{request.remote_ip}", 6, 1.minute).performed!
|
||||
|
||||
if user
|
||||
RateLimiter.new(nil, "second-factor-min-#{user.username}", 6, 1.minute).performed!
|
||||
end
|
||||
RateLimiter.new(nil, "second-factor-min-#{user.username}", 6, 1.minute).performed! if user
|
||||
end
|
||||
|
||||
private
|
||||
@ -634,11 +638,17 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def preload_current_user_data
|
||||
store_preloaded("currentUser", MultiJson.dump(CurrentUserSerializer.new(current_user, scope: guardian, root: false)))
|
||||
report = TopicTrackingState.report(current_user)
|
||||
serializer = ActiveModel::ArraySerializer.new(
|
||||
report, each_serializer: TopicTrackingStateSerializer, scope: guardian
|
||||
store_preloaded(
|
||||
"currentUser",
|
||||
MultiJson.dump(CurrentUserSerializer.new(current_user, scope: guardian, root: false)),
|
||||
)
|
||||
report = TopicTrackingState.report(current_user)
|
||||
serializer =
|
||||
ActiveModel::ArraySerializer.new(
|
||||
report,
|
||||
each_serializer: TopicTrackingStateSerializer,
|
||||
scope: guardian,
|
||||
)
|
||||
store_preloaded("topicTrackingStates", MultiJson.dump(serializer))
|
||||
end
|
||||
|
||||
@ -648,20 +658,18 @@ class ApplicationController < ActionController::Base
|
||||
data =
|
||||
if @theme_id.present?
|
||||
{
|
||||
top: Theme.lookup_field(@theme_id, target, "after_header"),
|
||||
footer: Theme.lookup_field(@theme_id, target, "footer")
|
||||
top: Theme.lookup_field(@theme_id, target, "after_header"),
|
||||
footer: Theme.lookup_field(@theme_id, target, "footer"),
|
||||
}
|
||||
else
|
||||
{}
|
||||
end
|
||||
|
||||
if DiscoursePluginRegistry.custom_html
|
||||
data.merge! DiscoursePluginRegistry.custom_html
|
||||
end
|
||||
data.merge! DiscoursePluginRegistry.custom_html if DiscoursePluginRegistry.custom_html
|
||||
|
||||
DiscoursePluginRegistry.html_builders.each do |name, _|
|
||||
if name.start_with?("client:")
|
||||
data[name.sub(/^client:/, '')] = DiscoursePluginRegistry.build_html(name, self)
|
||||
data[name.sub(/^client:/, "")] = DiscoursePluginRegistry.build_html(name, self)
|
||||
end
|
||||
end
|
||||
|
||||
@ -703,7 +711,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
render(
|
||||
json: MultiJson.dump(create_errors_json(obj, opts)),
|
||||
status: opts[:status] || status_code(obj)
|
||||
status: opts[:status] || status_code(obj),
|
||||
)
|
||||
end
|
||||
|
||||
@ -714,11 +722,11 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def success_json
|
||||
{ success: 'OK' }
|
||||
{ success: "OK" }
|
||||
end
|
||||
|
||||
def failed_json
|
||||
{ failed: 'FAILED' }
|
||||
{ failed: "FAILED" }
|
||||
end
|
||||
|
||||
def json_result(obj, opts = {})
|
||||
@ -727,17 +735,21 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
# If we were given a serializer, add the class to the json that comes back
|
||||
if opts[:serializer].present?
|
||||
json[obj.class.name.underscore] = opts[:serializer].new(obj, scope: guardian).serializable_hash
|
||||
json[obj.class.name.underscore] = opts[:serializer].new(
|
||||
obj,
|
||||
scope: guardian,
|
||||
).serializable_hash
|
||||
end
|
||||
|
||||
render json: MultiJson.dump(json)
|
||||
else
|
||||
error_obj = nil
|
||||
if opts[:additional_errors]
|
||||
error_target = opts[:additional_errors].find do |o|
|
||||
target = obj.public_send(o)
|
||||
target && target.errors.present?
|
||||
end
|
||||
error_target =
|
||||
opts[:additional_errors].find do |o|
|
||||
target = obj.public_send(o)
|
||||
target && target.errors.present?
|
||||
end
|
||||
error_obj = obj.public_send(error_target) if error_target
|
||||
end
|
||||
render_json_error(error_obj || obj)
|
||||
@ -756,11 +768,15 @@ class ApplicationController < ActionController::Base
|
||||
def check_xhr
|
||||
# bypass xhr check on PUT / POST / DELETE provided api key is there, otherwise calling api is annoying
|
||||
return if !request.get? && (is_api? || is_user_api?)
|
||||
raise ApplicationController::RenderEmpty.new unless ((request.format && request.format.json?) || request.xhr?)
|
||||
unless ((request.format && request.format.json?) || request.xhr?)
|
||||
raise ApplicationController::RenderEmpty.new
|
||||
end
|
||||
end
|
||||
|
||||
def apply_cdn_headers
|
||||
Discourse.apply_cdn_headers(response.headers) if Discourse.is_cdn_request?(request.env, request.method)
|
||||
if Discourse.is_cdn_request?(request.env, request.method)
|
||||
Discourse.apply_cdn_headers(response.headers)
|
||||
end
|
||||
end
|
||||
|
||||
def self.requires_login(arg = {})
|
||||
@ -811,8 +827,9 @@ class ApplicationController < ActionController::Base
|
||||
if SiteSetting.auth_immediately && SiteSetting.enable_discourse_connect?
|
||||
# save original URL in a session so we can redirect after login
|
||||
session[:destination_url] = destination_url
|
||||
redirect_to path('/session/sso')
|
||||
elsif SiteSetting.auth_immediately && !SiteSetting.enable_local_logins && Discourse.enabled_authenticators.length == 1 && !cookies[:authentication_data]
|
||||
redirect_to path("/session/sso")
|
||||
elsif SiteSetting.auth_immediately && !SiteSetting.enable_local_logins &&
|
||||
Discourse.enabled_authenticators.length == 1 && !cookies[:authentication_data]
|
||||
# Only one authentication provider, direct straight to it.
|
||||
# If authentication_data is present, then we are halfway though registration. Don't redirect offsite
|
||||
cookies[:destination_url] = destination_url
|
||||
@ -831,9 +848,7 @@ class ApplicationController < ActionController::Base
|
||||
# Redirects to provided URL scheme if
|
||||
# - request uses a valid public key and auth_redirect scheme
|
||||
# - one_time_password scope is allowed
|
||||
if !current_user &&
|
||||
params.has_key?(:user_api_public_key) &&
|
||||
params.has_key?(:auth_redirect)
|
||||
if !current_user && params.has_key?(:user_api_public_key) && params.has_key?(:auth_redirect)
|
||||
begin
|
||||
OpenSSL::PKey::RSA.new(params[:user_api_public_key])
|
||||
rescue OpenSSL::PKey::RSAError
|
||||
@ -872,26 +887,45 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
def should_enforce_2fa?
|
||||
disqualified_from_2fa_enforcement = request.format.json? || is_api? || current_user.anonymous?
|
||||
enforcing_2fa = ((SiteSetting.enforce_second_factor == 'staff' && current_user.staff?) || SiteSetting.enforce_second_factor == 'all')
|
||||
!disqualified_from_2fa_enforcement && enforcing_2fa && !current_user.has_any_second_factor_methods_enabled?
|
||||
enforcing_2fa =
|
||||
(
|
||||
(SiteSetting.enforce_second_factor == "staff" && current_user.staff?) ||
|
||||
SiteSetting.enforce_second_factor == "all"
|
||||
)
|
||||
!disqualified_from_2fa_enforcement && enforcing_2fa &&
|
||||
!current_user.has_any_second_factor_methods_enabled?
|
||||
end
|
||||
|
||||
def build_not_found_page(opts = {})
|
||||
if SiteSetting.bootstrap_error_pages?
|
||||
preload_json
|
||||
opts[:layout] = 'application' if opts[:layout] == 'no_ember'
|
||||
opts[:layout] = "application" if opts[:layout] == "no_ember"
|
||||
end
|
||||
|
||||
@current_user = current_user rescue nil
|
||||
@current_user =
|
||||
begin
|
||||
current_user
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
if !SiteSetting.login_required? || @current_user
|
||||
key = "page_not_found_topics:#{I18n.locale}"
|
||||
@topics_partial = Discourse.cache.fetch(key, expires_in: 10.minutes) do
|
||||
category_topic_ids = Category.pluck(:topic_id).compact
|
||||
@top_viewed = TopicQuery.new(nil, except_topic_ids: category_topic_ids).list_top_for("monthly").topics.first(10)
|
||||
@recent = Topic.includes(:category).where.not(id: category_topic_ids).recent(10)
|
||||
render_to_string partial: '/exceptions/not_found_topics', formats: [:html]
|
||||
end.html_safe
|
||||
@topics_partial =
|
||||
Discourse
|
||||
.cache
|
||||
.fetch(key, expires_in: 10.minutes) do
|
||||
category_topic_ids = Category.pluck(:topic_id).compact
|
||||
@top_viewed =
|
||||
TopicQuery
|
||||
.new(nil, except_topic_ids: category_topic_ids)
|
||||
.list_top_for("monthly")
|
||||
.topics
|
||||
.first(10)
|
||||
@recent = Topic.includes(:category).where.not(id: category_topic_ids).recent(10)
|
||||
render_to_string partial: "/exceptions/not_found_topics", formats: [:html]
|
||||
end
|
||||
.html_safe
|
||||
end
|
||||
|
||||
@container_class = "wrap not-found-container"
|
||||
@ -902,13 +936,16 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
params[:slug] = params[:slug].first if params[:slug].kind_of?(Array)
|
||||
params[:id] = params[:id].first if params[:id].kind_of?(Array)
|
||||
@slug = (params[:slug].presence || params[:id].presence || "").to_s.tr('-', ' ')
|
||||
@slug = (params[:slug].presence || params[:id].presence || "").to_s.tr("-", " ")
|
||||
|
||||
render_to_string status: opts[:status], layout: opts[:layout], formats: [:html], template: '/exceptions/not_found'
|
||||
render_to_string status: opts[:status],
|
||||
layout: opts[:layout],
|
||||
formats: [:html],
|
||||
template: "/exceptions/not_found"
|
||||
end
|
||||
|
||||
def is_asset_path
|
||||
request.env['DISCOURSE_IS_ASSET_PATH'] = 1
|
||||
request.env["DISCOURSE_IS_ASSET_PATH"] = 1
|
||||
end
|
||||
|
||||
def is_feed_request?
|
||||
@ -916,19 +953,20 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def add_noindex_header
|
||||
if request.get? && !response.headers['X-Robots-Tag']
|
||||
if request.get? && !response.headers["X-Robots-Tag"]
|
||||
if SiteSetting.allow_index_in_robots_txt
|
||||
response.headers['X-Robots-Tag'] = 'noindex'
|
||||
response.headers["X-Robots-Tag"] = "noindex"
|
||||
else
|
||||
response.headers['X-Robots-Tag'] = 'noindex, nofollow'
|
||||
response.headers["X-Robots-Tag"] = "noindex, nofollow"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_noindex_header_to_non_canonical
|
||||
canonical = (@canonical_url || @default_canonical)
|
||||
if canonical.present? && canonical != request.url && !SiteSetting.allow_indexing_non_canonical_urls
|
||||
response.headers['X-Robots-Tag'] ||= 'noindex'
|
||||
if canonical.present? && canonical != request.url &&
|
||||
!SiteSetting.allow_indexing_non_canonical_urls
|
||||
response.headers["X-Robots-Tag"] ||= "noindex"
|
||||
end
|
||||
end
|
||||
|
||||
@ -955,7 +993,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
# returns an array of integers given a param key
|
||||
# returns nil if key is not found
|
||||
def param_to_integer_list(key, delimiter = ',')
|
||||
def param_to_integer_list(key, delimiter = ",")
|
||||
case params[key]
|
||||
when String
|
||||
params[key].split(delimiter).map(&:to_i)
|
||||
@ -978,20 +1016,19 @@ class ApplicationController < ActionController::Base
|
||||
user_agent = request.user_agent&.downcase
|
||||
return if user_agent.blank?
|
||||
|
||||
SiteSetting.slow_down_crawler_user_agents.downcase.split("|").each do |crawler|
|
||||
if user_agent.include?(crawler)
|
||||
key = "#{crawler}_crawler_rate_limit"
|
||||
limiter = RateLimiter.new(
|
||||
nil,
|
||||
key,
|
||||
1,
|
||||
SiteSetting.slow_down_crawler_rate,
|
||||
error_code: key
|
||||
)
|
||||
limiter.performed!
|
||||
break
|
||||
SiteSetting
|
||||
.slow_down_crawler_user_agents
|
||||
.downcase
|
||||
.split("|")
|
||||
.each do |crawler|
|
||||
if user_agent.include?(crawler)
|
||||
key = "#{crawler}_crawler_rate_limit"
|
||||
limiter =
|
||||
RateLimiter.new(nil, key, 1, SiteSetting.slow_down_crawler_rate, error_code: key)
|
||||
limiter.performed!
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run_second_factor!(action_class, action_data = nil)
|
||||
@ -1000,9 +1037,8 @@ class ApplicationController < ActionController::Base
|
||||
yield(manager) if block_given?
|
||||
result = manager.run!(request, params, secure_session)
|
||||
|
||||
if !result.no_second_factors_enabled? &&
|
||||
!result.second_factor_auth_completed? &&
|
||||
!result.second_factor_auth_skipped?
|
||||
if !result.no_second_factors_enabled? && !result.second_factor_auth_completed? &&
|
||||
!result.second_factor_auth_skipped?
|
||||
# should never happen, but I want to know if somehow it does! (osama)
|
||||
raise "2fa process ended up in a bad state!"
|
||||
end
|
||||
@ -1013,7 +1049,7 @@ class ApplicationController < ActionController::Base
|
||||
def link_preload
|
||||
@links_to_preload = []
|
||||
yield
|
||||
response.headers['Link'] = @links_to_preload.join(', ') if !@links_to_preload.empty?
|
||||
response.headers["Link"] = @links_to_preload.join(", ") if !@links_to_preload.empty?
|
||||
end
|
||||
|
||||
def spa_boot_request?
|
||||
|
Reference in New Issue
Block a user