Refactor Cache-Control and Vary definitions (#24347)
				
					
				
			This commit is contained in:
		@@ -1224,9 +1224,6 @@ Rails/ActiveRecordCallbacksOrder:
 | 
			
		||||
Rails/ApplicationController:
 | 
			
		||||
  Exclude:
 | 
			
		||||
    - 'app/controllers/health_controller.rb'
 | 
			
		||||
    - 'app/controllers/well_known/host_meta_controller.rb'
 | 
			
		||||
    - 'app/controllers/well_known/nodeinfo_controller.rb'
 | 
			
		||||
    - 'app/controllers/well_known/webfinger_controller.rb'
 | 
			
		||||
 | 
			
		||||
# Configuration parameters: Database, Include.
 | 
			
		||||
# SupportedDatabases: mysql, postgresql
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,9 @@ class AccountsController < ApplicationController
 | 
			
		||||
  include AccountControllerConcern
 | 
			
		||||
  include SignatureAuthentication
 | 
			
		||||
 | 
			
		||||
  vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
 | 
			
		||||
  skip_before_action :require_functional!, unless: :whitelist_mode?
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,6 @@ class ActivityPub::BaseController < Api::BaseController
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.headers['Vary'] = 'Signature' if authorized_fetch_mode?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def skip_temporary_suspension_response?
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -4,11 +4,12 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController
 | 
			
		||||
  include SignatureVerification
 | 
			
		||||
  include AccountOwnedConcern
 | 
			
		||||
 | 
			
		||||
  vary_by -> { 'Signature' if authorized_fetch_mode? }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!, if: :authorized_fetch_mode?
 | 
			
		||||
  before_action :set_items
 | 
			
		||||
  before_action :set_size
 | 
			
		||||
  before_action :set_type
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
    expires_in 3.minutes, public: public_fetch_mode?
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,10 @@ class ActivityPub::FollowersSynchronizationsController < ActivityPub::BaseContro
 | 
			
		||||
  include SignatureVerification
 | 
			
		||||
  include AccountOwnedConcern
 | 
			
		||||
 | 
			
		||||
  vary_by -> { 'Signature' if authorized_fetch_mode? }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!
 | 
			
		||||
  before_action :set_items
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
    expires_in 0, public: false
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,10 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
 | 
			
		||||
  include SignatureVerification
 | 
			
		||||
  include AccountOwnedConcern
 | 
			
		||||
 | 
			
		||||
  vary_by -> { 'Signature' if authorized_fetch_mode? || page_requested? }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!, if: :authorized_fetch_mode?
 | 
			
		||||
  before_action :set_statuses
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
    if page_requested?
 | 
			
		||||
@@ -16,6 +17,7 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
 | 
			
		||||
    else
 | 
			
		||||
      expires_in(3.minutes, public: public_fetch_mode?)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    render json: outbox_presenter, serializer: ActivityPub::OutboxSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -80,8 +82,4 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
 | 
			
		||||
  def set_account
 | 
			
		||||
    @account = params[:account_username].present? ? Account.find_local!(username_param) : Account.representative
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.headers['Vary'] = 'Signature' if authorized_fetch_mode? || page_requested?
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,10 @@ class ActivityPub::RepliesController < ActivityPub::BaseController
 | 
			
		||||
 | 
			
		||||
  DESCENDANTS_LIMIT = 60
 | 
			
		||||
 | 
			
		||||
  vary_by -> { 'Signature' if authorized_fetch_mode? }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!, if: :authorized_fetch_mode?
 | 
			
		||||
  before_action :set_status
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
  before_action :set_replies
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@ module Admin
 | 
			
		||||
    layout 'admin'
 | 
			
		||||
 | 
			
		||||
    before_action :set_body_classes
 | 
			
		||||
    before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
    after_action :verify_authorized
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
@@ -16,6 +18,10 @@ module Admin
 | 
			
		||||
      @body_classes = 'admin'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def set_cache_headers
 | 
			
		||||
      response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def set_user
 | 
			
		||||
      @user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
 | 
			
		||||
    end
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ class Api::BaseController < ApplicationController
 | 
			
		||||
 | 
			
		||||
  before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
 | 
			
		||||
  before_action :require_not_suspended!
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
  before_action :set_cache_control_defaults
 | 
			
		||||
 | 
			
		||||
  protect_from_forgery with: :null_session
 | 
			
		||||
 | 
			
		||||
@@ -148,8 +148,8 @@ class Api::BaseController < ApplicationController
 | 
			
		||||
    doorkeeper_authorize!(*scopes) if doorkeeper_token
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.headers['Cache-Control'] = 'private, no-store'
 | 
			
		||||
  def set_cache_control_defaults
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def disallow_unauthenticated_api_access?
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,6 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::V1::CustomEmojisController < Api::BaseController
 | 
			
		||||
  skip_before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
    expires_in 3.minutes, public: true
 | 
			
		||||
    render_with_cache(each_serializer: REST::CustomEmojiSerializer) { CustomEmoji.listed.includes(:category) }
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@
 | 
			
		||||
class Api::V1::Instances::ActivityController < Api::BaseController
 | 
			
		||||
  before_action :require_enabled_api!
 | 
			
		||||
 | 
			
		||||
  skip_before_action :set_cache_headers
 | 
			
		||||
  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,6 @@
 | 
			
		||||
class Api::V1::Instances::PeersController < Api::BaseController
 | 
			
		||||
  before_action :require_enabled_api!
 | 
			
		||||
 | 
			
		||||
  skip_before_action :set_cache_headers
 | 
			
		||||
  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class Api::V1::InstancesController < Api::BaseController
 | 
			
		||||
  skip_before_action :set_cache_headers
 | 
			
		||||
  skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
 
 | 
			
		||||
@@ -152,6 +152,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.headers['Cache-Control'] = 'private, no-store'
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -155,8 +155,16 @@ module CacheConcern
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class_methods do
 | 
			
		||||
    def vary_by(value)
 | 
			
		||||
      before_action do |controller|
 | 
			
		||||
        response.headers['Vary'] = value.respond_to?(:call) ? controller.instance_exec(&value) : value
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def render_with_cache(**options)
 | 
			
		||||
    raise ArgumentError, 'only JSON render calls are supported' unless options.key?(:json) || block_given?
 | 
			
		||||
    raise ArgumentError, 'Only JSON render calls are supported' unless options.key?(:json) || block_given?
 | 
			
		||||
 | 
			
		||||
    key        = options.delete(:key) || [[params[:controller], params[:action]].join('/'), options[:json].respond_to?(:cache_key) ? options[:json].cache_key : nil, options[:fields].nil? ? nil : options[:fields].join(',')].compact.join(':')
 | 
			
		||||
    expires_in = options.delete(:expires_in) || 3.minutes
 | 
			
		||||
@@ -176,10 +184,6 @@ module CacheConcern
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.headers['Vary'] = public_fetch_mode? ? 'Accept' : 'Accept, Signature'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def cache_collection(raw, klass)
 | 
			
		||||
    return raw unless klass.respond_to?(:with_includes)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,8 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class CustomCssController < ApplicationController
 | 
			
		||||
  skip_before_action :store_current_location
 | 
			
		||||
  skip_before_action :require_functional!
 | 
			
		||||
  skip_before_action :update_user_sign_in
 | 
			
		||||
  skip_before_action :set_session_activity
 | 
			
		||||
 | 
			
		||||
  skip_around_action :set_locale
 | 
			
		||||
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
class CustomCssController < ActionController::Base # rubocop:disable Rails/ApplicationController
 | 
			
		||||
  def show
 | 
			
		||||
    expires_in 3.minutes, public: true
 | 
			
		||||
    request.session_options[:skip] = true
 | 
			
		||||
    render content_type: 'text/css'
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -9,10 +9,15 @@ class Disputes::BaseController < ApplicationController
 | 
			
		||||
 | 
			
		||||
  before_action :set_body_classes
 | 
			
		||||
  before_action :authenticate_user!
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def set_body_classes
 | 
			
		||||
    @body_classes = 'admin'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -2,15 +2,12 @@
 | 
			
		||||
 | 
			
		||||
class EmojisController < ApplicationController
 | 
			
		||||
  before_action :set_emoji
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  vary_by -> { 'Signature' if authorized_fetch_mode? }
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
    respond_to do |format|
 | 
			
		||||
      format.json do
 | 
			
		||||
        expires_in 3.minutes, public: true
 | 
			
		||||
        render_with_cache json: @emoji, content_type: 'application/activity+json', serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    expires_in 3.minutes, public: true
 | 
			
		||||
    render_with_cache json: @emoji, content_type: 'application/activity+json', serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ class Filters::StatusesController < ApplicationController
 | 
			
		||||
  before_action :set_filter
 | 
			
		||||
  before_action :set_status_filters
 | 
			
		||||
  before_action :set_body_classes
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  PER_PAGE = 20
 | 
			
		||||
 | 
			
		||||
@@ -44,4 +45,8 @@ class Filters::StatusesController < ApplicationController
 | 
			
		||||
  def set_body_classes
 | 
			
		||||
    @body_classes = 'admin'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ class FiltersController < ApplicationController
 | 
			
		||||
  before_action :authenticate_user!
 | 
			
		||||
  before_action :set_filter, only: [:edit, :update, :destroy]
 | 
			
		||||
  before_action :set_body_classes
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
    @filters = current_account.custom_filters.includes(:keywords, :statuses).order(:phrase)
 | 
			
		||||
@@ -54,4 +55,8 @@ class FiltersController < ApplicationController
 | 
			
		||||
  def set_body_classes
 | 
			
		||||
    @body_classes = 'admin'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,9 @@ class FollowerAccountsController < ApplicationController
 | 
			
		||||
  include SignatureVerification
 | 
			
		||||
  include WebAppControllerConcern
 | 
			
		||||
 | 
			
		||||
  vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  skip_around_action :set_locale, if: -> { request.format == :json }
 | 
			
		||||
  skip_before_action :require_functional!, unless: :whitelist_mode?
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,9 @@ class FollowingAccountsController < ApplicationController
 | 
			
		||||
  include SignatureVerification
 | 
			
		||||
  include WebAppControllerConcern
 | 
			
		||||
 | 
			
		||||
  vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  skip_around_action :set_locale, if: -> { request.format == :json }
 | 
			
		||||
  skip_before_action :require_functional!, unless: :whitelist_mode?
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ class InvitesController < ApplicationController
 | 
			
		||||
 | 
			
		||||
  before_action :authenticate_user!
 | 
			
		||||
  before_action :set_body_classes
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
    authorize :invite, :create?
 | 
			
		||||
@@ -49,4 +50,8 @@ class InvitesController < ApplicationController
 | 
			
		||||
  def set_body_classes
 | 
			
		||||
    @body_classes = 'admin'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,6 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
class ManifestsController < ApplicationController
 | 
			
		||||
  skip_before_action :store_current_location
 | 
			
		||||
  skip_before_action :require_functional!
 | 
			
		||||
 | 
			
		||||
class ManifestsController < ActionController::Base # rubocop:disable Rails/ApplicationController
 | 
			
		||||
  def show
 | 
			
		||||
    expires_in 3.minutes, public: true
 | 
			
		||||
    render json: InstancePresenter.new, serializer: ManifestSerializer, root: 'instance'
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.headers['Cache-Control'] = 'private, no-store'
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
 | 
			
		||||
  before_action :authenticate_resource_owner!
 | 
			
		||||
  before_action :require_not_suspended!, only: :destroy
 | 
			
		||||
  before_action :set_body_classes
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  skip_before_action :require_functional!
 | 
			
		||||
 | 
			
		||||
@@ -30,4 +31,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
 | 
			
		||||
  def require_not_suspended!
 | 
			
		||||
    forbidden if current_account.suspended?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ class RelationshipsController < ApplicationController
 | 
			
		||||
  before_action :set_accounts, only: :show
 | 
			
		||||
  before_action :set_relationships, only: :show
 | 
			
		||||
  before_action :set_body_classes
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship?
 | 
			
		||||
 | 
			
		||||
@@ -70,4 +71,8 @@ class RelationshipsController < ApplicationController
 | 
			
		||||
  def set_body_classes
 | 
			
		||||
    @body_classes = 'admin'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ class Settings::BaseController < ApplicationController
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.headers['Cache-Control'] = 'private, no-store'
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def require_not_suspended!
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ class StatusesCleanupController < ApplicationController
 | 
			
		||||
  before_action :authenticate_user!
 | 
			
		||||
  before_action :set_policy
 | 
			
		||||
  before_action :set_body_classes
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
 | 
			
		||||
  def show; end
 | 
			
		||||
 | 
			
		||||
@@ -36,4 +37,8 @@ class StatusesCleanupController < ApplicationController
 | 
			
		||||
  def set_body_classes
 | 
			
		||||
    @body_classes = 'admin'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_cache_headers
 | 
			
		||||
    response.cache_control.replace(private: true, no_store: true)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,12 @@ class StatusesController < ApplicationController
 | 
			
		||||
  include Authorization
 | 
			
		||||
  include AccountOwnedConcern
 | 
			
		||||
 | 
			
		||||
  vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? }
 | 
			
		||||
  before_action :set_status
 | 
			
		||||
  before_action :set_instance_presenter
 | 
			
		||||
  before_action :redirect_to_original, only: :show
 | 
			
		||||
  before_action :set_cache_headers
 | 
			
		||||
  before_action :set_body_classes, only: :embed
 | 
			
		||||
 | 
			
		||||
  after_action :set_link_headers
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,8 @@ class TagsController < ApplicationController
 | 
			
		||||
  PAGE_SIZE     = 20
 | 
			
		||||
  PAGE_SIZE_MAX = 200
 | 
			
		||||
 | 
			
		||||
  vary_by -> { public_fetch_mode? ? 'Accept' : 'Accept, Signature' }
 | 
			
		||||
 | 
			
		||||
  before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
 | 
			
		||||
  before_action :authenticate_user!, if: :whitelist_mode?
 | 
			
		||||
  before_action :set_local
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,9 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module WellKnown
 | 
			
		||||
  class HostMetaController < ActionController::Base
 | 
			
		||||
  class HostMetaController < ActionController::Base # rubocop:disable Rails/ApplicationController
 | 
			
		||||
    include RoutingHelper
 | 
			
		||||
 | 
			
		||||
    before_action { response.headers['Vary'] = 'Accept' }
 | 
			
		||||
 | 
			
		||||
    def show
 | 
			
		||||
      @webfinger_template = "#{webfinger_url}?resource={uri}"
 | 
			
		||||
      expires_in 3.days, public: true
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,9 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module WellKnown
 | 
			
		||||
  class NodeInfoController < ActionController::Base
 | 
			
		||||
  class NodeInfoController < ActionController::Base # rubocop:disable Rails/ApplicationController
 | 
			
		||||
    include CacheConcern
 | 
			
		||||
 | 
			
		||||
    before_action { response.headers['Vary'] = 'Accept' }
 | 
			
		||||
 | 
			
		||||
    def index
 | 
			
		||||
      expires_in 3.days, public: true
 | 
			
		||||
      render_with_cache json: {}, serializer: NodeInfo::DiscoverySerializer, adapter: NodeInfo::Adapter, expires_in: 3.days, root: 'nodeinfo'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module WellKnown
 | 
			
		||||
  class WebfingerController < ActionController::Base
 | 
			
		||||
  class WebfingerController < ActionController::Base # rubocop:disable Rails/ApplicationController
 | 
			
		||||
    include RoutingHelper
 | 
			
		||||
 | 
			
		||||
    before_action :set_account
 | 
			
		||||
@@ -34,7 +34,12 @@ module WellKnown
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def check_account_suspension
 | 
			
		||||
      expires_in(3.minutes, public: true) && gone if @account.suspended_permanently?
 | 
			
		||||
      gone if @account.suspended_permanently?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def gone
 | 
			
		||||
      expires_in(3.minutes, public: true)
 | 
			
		||||
      head 410
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def bad_request
 | 
			
		||||
@@ -46,9 +51,5 @@ module WellKnown
 | 
			
		||||
      expires_in(3.minutes, public: true)
 | 
			
		||||
      head 404
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def gone
 | 
			
		||||
      head 410
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@ require_relative '../lib/chewy/strategy/bypass_with_warning'
 | 
			
		||||
require_relative '../lib/webpacker/manifest_extensions'
 | 
			
		||||
require_relative '../lib/webpacker/helper_extensions'
 | 
			
		||||
require_relative '../lib/rails/engine_extensions'
 | 
			
		||||
require_relative '../lib/action_controller/conditional_get_extensions'
 | 
			
		||||
require_relative '../lib/active_record/database_tasks_extensions'
 | 
			
		||||
require_relative '../lib/active_record/batches'
 | 
			
		||||
require_relative '../lib/simple_navigation/item_extensions'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								lib/action_controller/conditional_get_extensions.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								lib/action_controller/conditional_get_extensions.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
module ActionController
 | 
			
		||||
  module ConditionalGetExtensions
 | 
			
		||||
    def expires_in(*)
 | 
			
		||||
      # This backports a fix from Rails 7 so that a more private Cache-Control
 | 
			
		||||
      # can be overriden by calling expires_in on a specific controller action
 | 
			
		||||
      response.cache_control.delete(:no_store)
 | 
			
		||||
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
ActionController::ConditionalGet.prepend(ActionController::ConditionalGetExtensions)
 | 
			
		||||
@@ -17,6 +17,10 @@ RSpec.describe AccountsController, type: :controller do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns Vary header' do
 | 
			
		||||
      expect(response.headers['Vary']).to include 'Accept'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public Cache-Control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
    end
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,14 @@ describe Admin::BaseController, type: :controller do
 | 
			
		||||
    expect(response).to have_http_status(403)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it 'returns private cache control headers' do
 | 
			
		||||
    routes.draw { get 'success' => 'admin/base#success' }
 | 
			
		||||
    sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Moderator')))
 | 
			
		||||
    get :success
 | 
			
		||||
 | 
			
		||||
    expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it 'renders admin layout as a moderator' do
 | 
			
		||||
    routes.draw { get 'success' => 'admin/base#success' }
 | 
			
		||||
    sign_in(Fabricate(:user, role: UserRole.find_by(name: 'Moderator')))
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,12 @@ describe Api::BaseController do
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it 'returns private cache control headers by default' do
 | 
			
		||||
    routes.draw { get 'success' => 'api/base#success' }
 | 
			
		||||
    get :success
 | 
			
		||||
    expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'forgery protection' do
 | 
			
		||||
    before do
 | 
			
		||||
      routes.draw { post 'success' => 'api/base#success' }
 | 
			
		||||
 
 | 
			
		||||
@@ -17,5 +17,9 @@ RSpec.describe Api::OEmbedController, type: :controller do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -33,27 +33,42 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #edit' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      request.env['devise.mapping'] = Devise.mappings[:user]
 | 
			
		||||
      sign_in(Fabricate(:user))
 | 
			
		||||
      get :edit
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #update' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    let(:user) { Fabricate(:user) }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      request.env['devise.mapping'] = Devise.mappings[:user]
 | 
			
		||||
      sign_in(Fabricate(:user), scope: :user)
 | 
			
		||||
      sign_in(user, scope: :user)
 | 
			
		||||
      post :update
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when suspended' do
 | 
			
		||||
      let(:user) { Fabricate(:user, account_attributes: { username: 'test', suspended_at: Time.now.utc }) }
 | 
			
		||||
 | 
			
		||||
      it 'returns http forbidden' do
 | 
			
		||||
        request.env['devise.mapping'] = Devise.mappings[:user]
 | 
			
		||||
        sign_in(Fabricate(:user, account_attributes: { username: 'test', suspended_at: Time.now.utc }), scope: :user)
 | 
			
		||||
        post :update
 | 
			
		||||
        expect(response).to have_http_status(403)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,25 @@ describe CustomCssController do
 | 
			
		||||
  render_views
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :show
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public cache control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('public')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set cookies' do
 | 
			
		||||
      expect(response.cookies).to be_empty
 | 
			
		||||
      expect(response.headers['Set-Cookies']).to be_nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set sessions' do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -18,21 +18,27 @@ describe Filters::StatusesController do
 | 
			
		||||
 | 
			
		||||
    context 'with a signed in user' do
 | 
			
		||||
      context 'with the filter user signed in' do
 | 
			
		||||
        before { sign_in(filter.account.user) }
 | 
			
		||||
        before do
 | 
			
		||||
          sign_in(filter.account.user)
 | 
			
		||||
          get :index, params: { filter_id: filter }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns http success' do
 | 
			
		||||
          get :index, params: { filter_id: filter }
 | 
			
		||||
 | 
			
		||||
          expect(response).to have_http_status(200)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns private cache control headers' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'with another user signed in' do
 | 
			
		||||
        before { sign_in(Fabricate(:user)) }
 | 
			
		||||
        before do
 | 
			
		||||
          sign_in(Fabricate(:user))
 | 
			
		||||
          get :index, params: { filter_id: filter }
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns http not found' do
 | 
			
		||||
          get :index, params: { filter_id: filter }
 | 
			
		||||
 | 
			
		||||
          expect(response).to have_http_status(404)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 
 | 
			
		||||
@@ -7,21 +7,28 @@ describe FiltersController do
 | 
			
		||||
 | 
			
		||||
  describe 'GET #index' do
 | 
			
		||||
    context 'with signed out user' do
 | 
			
		||||
      it 'redirects' do
 | 
			
		||||
      before do
 | 
			
		||||
        get :index
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'redirects' do
 | 
			
		||||
        expect(response).to be_redirect
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with a signed in user' do
 | 
			
		||||
      before { sign_in(Fabricate(:user)) }
 | 
			
		||||
      before do
 | 
			
		||||
        sign_in(Fabricate(:user))
 | 
			
		||||
        get :index
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns http success' do
 | 
			
		||||
        get :index
 | 
			
		||||
 | 
			
		||||
        expect(response).to have_http_status(200)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns private cache control headers' do
 | 
			
		||||
        expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -5,35 +5,40 @@ require 'rails_helper'
 | 
			
		||||
describe InvitesController do
 | 
			
		||||
  render_views
 | 
			
		||||
 | 
			
		||||
  let(:user) { Fabricate(:user) }
 | 
			
		||||
 | 
			
		||||
  before do
 | 
			
		||||
    sign_in user
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #index' do
 | 
			
		||||
    subject { get :index }
 | 
			
		||||
 | 
			
		||||
    let(:user) { Fabricate(:user) }
 | 
			
		||||
    let!(:invite) { Fabricate(:invite, user: user) }
 | 
			
		||||
    before do
 | 
			
		||||
      Fabricate(:invite, user: user)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when everyone can invite' do
 | 
			
		||||
      before do
 | 
			
		||||
        UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
 | 
			
		||||
        get :index
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'renders index page' do
 | 
			
		||||
        expect(subject).to render_template :index
 | 
			
		||||
        expect(assigns(:invites)).to include invite
 | 
			
		||||
        expect(assigns(:invites).count).to eq 1
 | 
			
		||||
      it 'returns http success' do
 | 
			
		||||
        expect(response).to have_http_status(:success)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns private cache control headers' do
 | 
			
		||||
        expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when not everyone can invite' do
 | 
			
		||||
      before do
 | 
			
		||||
        UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
 | 
			
		||||
        get :index
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns 403' do
 | 
			
		||||
        expect(subject).to have_http_status 403
 | 
			
		||||
      it 'returns http forbidden' do
 | 
			
		||||
        expect(response).to have_http_status(403)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
@@ -42,8 +47,6 @@ describe InvitesController do
 | 
			
		||||
    subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
 | 
			
		||||
 | 
			
		||||
    context 'when everyone can invite' do
 | 
			
		||||
      let(:user) { Fabricate(:user) }
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        UserRole.everyone.update(permissions: UserRole.everyone.permissions | UserRole::FLAGS[:invite_users])
 | 
			
		||||
      end
 | 
			
		||||
@@ -56,26 +59,28 @@ describe InvitesController do
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when not everyone can invite' do
 | 
			
		||||
      let(:user) { Fabricate(:user) }
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        UserRole.everyone.update(permissions: UserRole.everyone.permissions & ~UserRole::FLAGS[:invite_users])
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns 403' do
 | 
			
		||||
        expect(subject).to have_http_status 403
 | 
			
		||||
      it 'returns http forbidden' do
 | 
			
		||||
        expect(subject).to have_http_status(403)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'DELETE #create' do
 | 
			
		||||
    subject { delete :destroy, params: { id: invite.id } }
 | 
			
		||||
    let(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
 | 
			
		||||
 | 
			
		||||
    let(:user) { Fabricate(:user) }
 | 
			
		||||
    let!(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
 | 
			
		||||
    before do
 | 
			
		||||
      delete :destroy, params: { id: invite.id }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'redirects' do
 | 
			
		||||
      expect(response).to redirect_to invites_path
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'expires invite' do
 | 
			
		||||
      expect(subject).to redirect_to invites_path
 | 
			
		||||
      expect(invite.reload).to be_expired
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -7,11 +7,24 @@ describe ManifestsController do
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :show, format: :json
 | 
			
		||||
      get :show
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public cache control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('public')
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set cookies' do
 | 
			
		||||
      expect(response.cookies).to be_empty
 | 
			
		||||
      expect(response.headers['Set-Cookies']).to be_nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'does not set sessions' do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,11 @@ RSpec.describe Oauth::AuthorizationsController, type: :controller do
 | 
			
		||||
        expect(response).to have_http_status(200)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns private cache control headers' do
 | 
			
		||||
        subject
 | 
			
		||||
        expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'gives options to authorize and deny' do
 | 
			
		||||
        subject
 | 
			
		||||
        expect(response.body).to match(/Authorize/)
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,11 @@ describe Oauth::AuthorizedApplicationsController do
 | 
			
		||||
        expect(response).to have_http_status(200)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns private cache control headers' do
 | 
			
		||||
        subject
 | 
			
		||||
        expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      include_examples 'stores location for user'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,42 +7,39 @@ describe RelationshipsController do
 | 
			
		||||
 | 
			
		||||
  let(:user) { Fabricate(:user) }
 | 
			
		||||
 | 
			
		||||
  shared_examples 'authenticate user' do
 | 
			
		||||
    it 'redirects when not signed in' do
 | 
			
		||||
      expect(subject).to redirect_to '/auth/sign_in'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    subject { get :show, params: { page: 2, relationship: 'followed_by' } }
 | 
			
		||||
    context 'when signed in' do
 | 
			
		||||
      before do
 | 
			
		||||
        sign_in user, scope: :user
 | 
			
		||||
        get :show, params: { page: 2, relationship: 'followed_by' }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
    it 'assigns @accounts' do
 | 
			
		||||
      Fabricate(:account, domain: 'old').follow!(user.account)
 | 
			
		||||
      Fabricate(:account, domain: 'recent').follow!(user.account)
 | 
			
		||||
      it 'returns http success' do
 | 
			
		||||
        expect(response).to have_http_status(200)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      sign_in user, scope: :user
 | 
			
		||||
      subject
 | 
			
		||||
 | 
			
		||||
      assigned = assigns(:accounts).per(1).to_a
 | 
			
		||||
      expect(assigned.size).to eq 1
 | 
			
		||||
      expect(assigned[0].domain).to eq 'old'
 | 
			
		||||
      it 'returns private cache control headers' do
 | 
			
		||||
        expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      sign_in user, scope: :user
 | 
			
		||||
      subject
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
    context 'when not signed in' do
 | 
			
		||||
      before do
 | 
			
		||||
        get :show, params: { page: 2, relationship: 'followed_by' }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
    include_examples 'authenticate user'
 | 
			
		||||
      it 'redirects when not signed in' do
 | 
			
		||||
        expect(response).to redirect_to '/auth/sign_in'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'PATCH #update' do
 | 
			
		||||
    let(:poopfeast) { Fabricate(:account, username: 'poopfeast', domain: 'example.com') }
 | 
			
		||||
    let(:alice) { Fabricate(:account, username: 'alice', domain: 'example.com') }
 | 
			
		||||
 | 
			
		||||
    shared_examples 'redirects back to followers page' do
 | 
			
		||||
      it 'redirects back to followers page' do
 | 
			
		||||
        poopfeast.follow!(user.account)
 | 
			
		||||
        alice.follow!(user.account)
 | 
			
		||||
 | 
			
		||||
        sign_in user, scope: :user
 | 
			
		||||
        subject
 | 
			
		||||
@@ -58,27 +55,36 @@ describe RelationshipsController do
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when select parameter is provided' do
 | 
			
		||||
      subject { patch :update, params: { form_account_batch: { account_ids: [poopfeast.id] }, remove_domains_from_followers: '' } }
 | 
			
		||||
      subject { patch :update, params: { form_account_batch: { account_ids: [alice.id] }, remove_domains_from_followers: '' } }
 | 
			
		||||
 | 
			
		||||
      it 'soft-blocks followers from selected domains' do
 | 
			
		||||
        poopfeast.follow!(user.account)
 | 
			
		||||
        alice.follow!(user.account)
 | 
			
		||||
 | 
			
		||||
        sign_in user, scope: :user
 | 
			
		||||
        subject
 | 
			
		||||
 | 
			
		||||
        expect(poopfeast.following?(user.account)).to be false
 | 
			
		||||
        expect(alice.following?(user.account)).to be false
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'does not unfollow users from selected domains' do
 | 
			
		||||
        user.account.follow!(poopfeast)
 | 
			
		||||
        user.account.follow!(alice)
 | 
			
		||||
 | 
			
		||||
        sign_in user, scope: :user
 | 
			
		||||
        subject
 | 
			
		||||
 | 
			
		||||
        expect(user.account.following?(poopfeast)).to be true
 | 
			
		||||
        expect(user.account.following?(alice)).to be true
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'when not signed in' do
 | 
			
		||||
        before do
 | 
			
		||||
          subject
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'redirects when not signed in' do
 | 
			
		||||
          expect(response).to redirect_to '/auth/sign_in'
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      include_examples 'authenticate user'
 | 
			
		||||
      include_examples 'redirects back to followers page'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 
 | 
			
		||||
@@ -13,10 +13,17 @@ describe Settings::AliasesController do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #index' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :index
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'POST #create' do
 | 
			
		||||
 
 | 
			
		||||
@@ -13,13 +13,17 @@ describe Settings::ApplicationsController do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #index' do
 | 
			
		||||
    let!(:other_app) { Fabricate(:application) }
 | 
			
		||||
 | 
			
		||||
    it 'shows apps' do
 | 
			
		||||
    before do
 | 
			
		||||
      Fabricate(:application)
 | 
			
		||||
      get :index
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
      expect(assigns(:applications)).to include(app)
 | 
			
		||||
      expect(assigns(:applications)).to_not include(other_app)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,20 +11,27 @@ describe Settings::DeletesController do
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        sign_in user, scope: :user
 | 
			
		||||
        get :show
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'renders confirmation page' do
 | 
			
		||||
        get :show
 | 
			
		||||
        expect(response).to have_http_status(200)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns private cache control headers' do
 | 
			
		||||
        expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'when suspended' do
 | 
			
		||||
        let(:user) { Fabricate(:user, account_attributes: { suspended_at: Time.now.utc }) }
 | 
			
		||||
 | 
			
		||||
        it 'returns http forbidden' do
 | 
			
		||||
          get :show
 | 
			
		||||
          expect(response).to have_http_status(403)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns private cache control headers' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,16 +11,16 @@ describe Settings::ExportsController do
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        sign_in user, scope: :user
 | 
			
		||||
        get :show
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'renders export' do
 | 
			
		||||
        get :show
 | 
			
		||||
 | 
			
		||||
        export = assigns(:export)
 | 
			
		||||
        expect(export).to be_instance_of Export
 | 
			
		||||
        expect(export.account).to eq user.account
 | 
			
		||||
      it 'returns http success' do
 | 
			
		||||
        expect(response).to have_http_status(200)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'returns private cache control headers' do
 | 
			
		||||
        expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when not signed in' do
 | 
			
		||||
 
 | 
			
		||||
@@ -10,10 +10,17 @@ RSpec.describe Settings::ImportsController, type: :controller do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :show
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'POST #create' do
 | 
			
		||||
 
 | 
			
		||||
@@ -12,9 +12,16 @@ describe Settings::LoginActivitiesController do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #index' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :index
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,17 @@ describe Settings::Migration::RedirectsController do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #new' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :new
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'POST #create' do
 | 
			
		||||
 
 | 
			
		||||
@@ -12,11 +12,17 @@ describe Settings::Preferences::AppearanceController do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :show
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'PUT #update' do
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,17 @@ describe Settings::Preferences::NotificationsController do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :show
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'PUT #update' do
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,17 @@ describe Settings::Preferences::OtherController do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :show
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'PUT #update' do
 | 
			
		||||
 
 | 
			
		||||
@@ -13,10 +13,17 @@ RSpec.describe Settings::ProfilesController, type: :controller do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :show
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'PUT #update' do
 | 
			
		||||
 
 | 
			
		||||
@@ -26,23 +26,25 @@ describe Settings::TwoFactorAuthenticationMethodsController do
 | 
			
		||||
      describe 'when user has enabled otp' do
 | 
			
		||||
        before do
 | 
			
		||||
          user.update(otp_required_for_login: true)
 | 
			
		||||
          get :index
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns http success' do
 | 
			
		||||
          get :index
 | 
			
		||||
 | 
			
		||||
          expect(response).to have_http_status(200)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns private cache control headers' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      describe 'when user has not enabled otp' do
 | 
			
		||||
        before do
 | 
			
		||||
          user.update(otp_required_for_login: false)
 | 
			
		||||
          get :index
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'redirects to enable otp' do
 | 
			
		||||
          get :index
 | 
			
		||||
 | 
			
		||||
          expect(response).to redirect_to(settings_otp_authentication_path)
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 
 | 
			
		||||
@@ -11,19 +11,32 @@ RSpec.describe StatusesCleanupController, type: :controller do
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
    before do
 | 
			
		||||
      get :show
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns http success' do
 | 
			
		||||
      expect(response).to have_http_status(200)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns private cache control headers' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include('private, no-store')
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe 'PUT #update' do
 | 
			
		||||
    it 'updates the account status cleanup policy' do
 | 
			
		||||
    before do
 | 
			
		||||
      put :update, params: { account_statuses_cleanup_policy: { enabled: true, min_status_age: 2.weeks.seconds, keep_direct: false, keep_polls: true } }
 | 
			
		||||
      expect(response).to redirect_to(statuses_cleanup_path)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'updates the account status cleanup policy' do
 | 
			
		||||
      expect(@user.account.statuses_cleanup_policy.enabled).to be true
 | 
			
		||||
      expect(@user.account.statuses_cleanup_policy.keep_direct).to be false
 | 
			
		||||
      expect(@user.account.statuses_cleanup_policy.keep_polls).to be true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'redirects' do
 | 
			
		||||
      expect(response).to redirect_to(statuses_cleanup_path)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,10 @@ describe StatusesController do
 | 
			
		||||
      expect(session).to be_empty
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns Vary header' do
 | 
			
		||||
      expect(response.headers['Vary']).to include 'Accept'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'returns public Cache-Control header' do
 | 
			
		||||
      expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
    end
 | 
			
		||||
 
 | 
			
		||||
@@ -6,21 +6,50 @@ RSpec.describe TagsController, type: :controller do
 | 
			
		||||
  render_views
 | 
			
		||||
 | 
			
		||||
  describe 'GET #show' do
 | 
			
		||||
    let!(:tag)     { Fabricate(:tag, name: 'test') }
 | 
			
		||||
    let!(:local)   { Fabricate(:status, tags: [tag], text: 'local #test') }
 | 
			
		||||
    let!(:remote)  { Fabricate(:status, tags: [tag], text: 'remote #test', account: Fabricate(:account, domain: 'remote')) }
 | 
			
		||||
    let!(:late)    { Fabricate(:status, tags: [tag], text: 'late #test') }
 | 
			
		||||
    let(:format) { 'html' }
 | 
			
		||||
    let(:tag) { Fabricate(:tag, name: 'test') }
 | 
			
		||||
    let(:tag_name) { tag&.name }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      get :show, params: { id: tag_name, format: format }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when tag exists' do
 | 
			
		||||
      it 'returns http success' do
 | 
			
		||||
        get :show, params: { id: 'test', max_id: late.id }
 | 
			
		||||
        expect(response).to have_http_status(200)
 | 
			
		||||
      context 'when requested as HTML' do
 | 
			
		||||
        it 'returns http success' do
 | 
			
		||||
          expect(response).to have_http_status(200)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns Vary header' do
 | 
			
		||||
          expect(response.headers['Vary']).to eq 'Accept'
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'when requested as JSON' do
 | 
			
		||||
        let(:format) { 'json' }
 | 
			
		||||
 | 
			
		||||
        it 'returns http success' do
 | 
			
		||||
          expect(response).to have_http_status(200)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns Vary header' do
 | 
			
		||||
          expect(response.headers['Vary']).to eq 'Accept'
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns public Cache-Control header' do
 | 
			
		||||
          expect(response.headers['Cache-Control']).to include 'public'
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when tag does not exist' do
 | 
			
		||||
      let(:tag_name) { 'hoge' }
 | 
			
		||||
 | 
			
		||||
      it 'returns http not found' do
 | 
			
		||||
        get :show, params: { id: 'none' }
 | 
			
		||||
        expect(response).to have_http_status(404)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user