diff options
Diffstat (limited to 'app/controllers/application_controller.rb')
-rw-r--r-- | app/controllers/application_controller.rb | 100 |
1 files changed, 42 insertions, 58 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 333082f68..599c64062 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,6 +10,8 @@ class ApplicationController < ActionController::Base include Localized include UserTrackingConcern include SessionTrackingConcern + include CacheConcern + include DomainControlHelper helper_method :current_account helper_method :current_session @@ -17,15 +19,21 @@ class ApplicationController < ActionController::Base helper_method :current_skin helper_method :single_user_mode? helper_method :use_seamless_external_login? + helper_method :whitelist_mode? rescue_from ActionController::RoutingError, with: :not_found - rescue_from ActiveRecord::RecordNotFound, with: :not_found rescue_from ActionController::InvalidAuthenticityToken, with: :unprocessable_entity rescue_from ActionController::UnknownFormat, with: :not_acceptable + rescue_from ActionController::ParameterMissing, with: :bad_request + rescue_from ActiveRecord::RecordNotFound, with: :not_found rescue_from Mastodon::NotPermittedError, with: :forbidden + rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error + rescue_from Mastodon::RaceConditionError, with: :service_unavailable before_action :store_current_location, except: :raise_not_found, unless: :devise_controller? - before_action :check_user_permissions, if: :user_signed_in? + before_action :require_functional!, if: :user_signed_in? + + skip_before_action :verify_authenticity_token, only: :raise_not_found def raise_not_found raise ActionController::RoutingError, "No route matches #{params[:unmatched_route]}" @@ -34,7 +42,15 @@ class ApplicationController < ActionController::Base private def https_enabled? - Rails.env.production? + Rails.env.production? && !request.path.start_with?('/health') + end + + def authorized_fetch_mode? + ENV['AUTHORIZED_FETCH'] == 'true' || Rails.configuration.x.whitelist_mode + end + + def public_fetch_mode? + !authorized_fetch_mode? end def store_current_location @@ -49,8 +65,8 @@ class ApplicationController < ActionController::Base forbidden unless current_user&.staff? end - def check_user_permissions - forbidden if current_user.disabled? || current_user.account.suspended? + def require_functional! + redirect_to edit_user_registration_path unless current_user.functional? end def after_sign_out_path_for(_resource_or_scope) @@ -152,8 +168,20 @@ class ApplicationController < ActionController::Base respond_with_error(406) end + def bad_request + respond_with_error(400) + end + + def internal_server_error + respond_with_error(500) + end + + def service_unavailable + respond_with_error(503) + end + def single_user_mode? - @single_user_mode ||= Rails.configuration.x.single_user_mode && Account.exists? + @single_user_mode ||= Rails.configuration.x.single_user_mode && Account.where('id > 0').exists? end def use_seamless_external_login? @@ -161,11 +189,15 @@ class ApplicationController < ActionController::Base end def current_account - @current_account ||= current_user.try(:account) + return @current_account if defined?(@current_account) + + @current_account = current_user&.account end def current_session - @current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id']) + return @current_session if defined?(@current_session) + + @current_session = SessionActivation.find_by(session_id: cookies.signed['_session_id']) if cookies.signed['_session_id'].present? end def current_flavour @@ -178,56 +210,8 @@ class ApplicationController < ActionController::Base current_user.setting_skin end - def cache_collection(raw, klass) - return raw unless klass.respond_to?(:with_includes) - - raw = raw.cache_ids.to_a if raw.is_a?(ActiveRecord::Relation) - cached_keys_with_value = Rails.cache.read_multi(*raw).transform_keys(&:id) - uncached_ids = raw.map(&:id) - cached_keys_with_value.keys - - klass.reload_stale_associations!(cached_keys_with_value.values) if klass.respond_to?(:reload_stale_associations!) - - unless uncached_ids.empty? - uncached = klass.where(id: uncached_ids).with_includes.each_with_object({}) { |item, h| h[item.id] = item } - - uncached.each_value do |item| - Rails.cache.write(item, item) - end - end - - raw.map { |item| cached_keys_with_value[item.id] || uncached[item.id] }.compact - end - def respond_with_error(code) - respond_to do |format| - format.any { head code } - - format.html do - set_locale - use_pack 'error' - render "errors/#{code}", layout: 'error', status: code - end - end - end - - def render_cached_json(cache_key, **options) - options[:expires_in] ||= 3.minutes - cache_public = options.key?(:public) ? options.delete(:public) : true - content_type = options.delete(:content_type) || 'application/json' - - data = Rails.cache.fetch(cache_key, { raw: true }.merge(options)) do - yield.to_json - end - - expires_in options[:expires_in], public: cache_public - render json: data, content_type: content_type - end - - def set_cache_headers - response.headers['Vary'] = 'Accept' - end - - def mark_cacheable! - expires_in 0, public: true + use_pack 'error' + render "errors/#{code}", layout: 'error', status: code end end |