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