From 6084461cd0a6f4e7e4a3c0aa660484b7eee72d14 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 25 Apr 2023 15:41:34 +0200 Subject: [PATCH 1/5] Change unauthenticated responses to be cached in REST API (#24348) --- app/controllers/api/base_controller.rb | 3 +++ .../api/v1/accounts/follower_accounts_controller.rb | 1 + .../v1/accounts/following_accounts_controller.rb | 1 + .../api/v1/accounts/lookup_controller.rb | 1 + .../api/v1/accounts/statuses_controller.rb | 1 + app/controllers/api/v1/accounts_controller.rb | 1 + app/controllers/api/v1/custom_emojis_controller.rb | 4 +++- app/controllers/api/v1/directories_controller.rb | 1 + .../api/v1/instances/activity_controller.rb | 4 +++- .../api/v1/instances/domain_blocks_controller.rb | 4 +++- .../instances/extended_descriptions_controller.rb | 4 +++- .../api/v1/instances/peers_controller.rb | 4 +++- .../api/v1/instances/privacy_policies_controller.rb | 4 +++- .../api/v1/instances/rules_controller.rb | 3 +++ .../instances/translation_languages_controller.rb | 4 +++- app/controllers/api/v1/instances_controller.rb | 4 +++- app/controllers/api/v1/polls_controller.rb | 1 + .../statuses/favourited_by_accounts_controller.rb | 1 + .../api/v1/statuses/histories_controller.rb | 1 + .../v1/statuses/reblogged_by_accounts_controller.rb | 1 + app/controllers/api/v1/statuses_controller.rb | 3 +++ app/controllers/api/v1/tags_controller.rb | 1 + .../api/v1/timelines/public_controller.rb | 1 + app/controllers/api/v1/timelines/tag_controller.rb | 1 + app/controllers/api/v1/trends/links_controller.rb | 3 +++ .../api/v1/trends/statuses_controller.rb | 3 +++ app/controllers/api/v1/trends/tags_controller.rb | 1 + app/controllers/api/v2/instances_controller.rb | 2 +- app/controllers/concerns/api_caching_concern.rb | 13 +++++++++++++ 29 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 app/controllers/concerns/api_caching_concern.rb diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 21a79f8926..56bf69c402 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -6,6 +6,7 @@ class Api::BaseController < ApplicationController include RateLimitHeaders include AccessTokenTrackingConcern + include ApiCachingConcern skip_before_action :store_current_location skip_before_action :require_functional!, unless: :whitelist_mode? @@ -13,6 +14,8 @@ class Api::BaseController < ApplicationController before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access? before_action :require_not_suspended! + vary_by 'Authorization' + protect_from_forgery with: :null_session content_security_policy do |p| diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb index 68952de893..1a996d362a 100644 --- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb @@ -6,6 +6,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController after_action :insert_pagination_headers def index + cache_if_unauthenticated! @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb index 0a4d2ae7b3..6e6ebae43b 100644 --- a/app/controllers/api/v1/accounts/following_accounts_controller.rb +++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb @@ -6,6 +6,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController after_action :insert_pagination_headers def index + cache_if_unauthenticated! @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/accounts/lookup_controller.rb b/app/controllers/api/v1/accounts/lookup_controller.rb index 8597f891d6..6d63398781 100644 --- a/app/controllers/api/v1/accounts/lookup_controller.rb +++ b/app/controllers/api/v1/accounts/lookup_controller.rb @@ -5,6 +5,7 @@ class Api::V1::Accounts::LookupController < Api::BaseController before_action :set_account def show + cache_if_unauthenticated! render json: @account, serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb index 7ed48cf658..51f541bd23 100644 --- a/app/controllers/api/v1/accounts/statuses_controller.rb +++ b/app/controllers/api/v1/accounts/statuses_controller.rb @@ -7,6 +7,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) } def index + cache_if_unauthenticated! @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) end diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 7dff66efac..8af4242ba3 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -18,6 +18,7 @@ class Api::V1::AccountsController < Api::BaseController override_rate_limit_headers :follow, family: :follows def show + cache_if_unauthenticated! render json: @account, serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/custom_emojis_controller.rb b/app/controllers/api/v1/custom_emojis_controller.rb index 380dbe8bf3..d4e7c43cb0 100644 --- a/app/controllers/api/v1/custom_emojis_controller.rb +++ b/app/controllers/api/v1/custom_emojis_controller.rb @@ -1,8 +1,10 @@ # frozen_string_literal: true class Api::V1::CustomEmojisController < Api::BaseController + vary_by '' + def index - expires_in 3.minutes, public: true + cache_even_if_authenticated! render_with_cache(each_serializer: REST::CustomEmojiSerializer) { CustomEmoji.listed.includes(:category) } end end diff --git a/app/controllers/api/v1/directories_controller.rb b/app/controllers/api/v1/directories_controller.rb index c91543e3a3..c0585e8599 100644 --- a/app/controllers/api/v1/directories_controller.rb +++ b/app/controllers/api/v1/directories_controller.rb @@ -5,6 +5,7 @@ class Api::V1::DirectoriesController < Api::BaseController before_action :set_accounts def show + cache_if_unauthenticated! render json: @accounts, each_serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/instances/activity_controller.rb b/app/controllers/api/v1/instances/activity_controller.rb index 7ccfec7036..3d55d990af 100644 --- a/app/controllers/api/v1/instances/activity_controller.rb +++ b/app/controllers/api/v1/instances/activity_controller.rb @@ -5,8 +5,10 @@ class Api::V1::Instances::ActivityController < Api::BaseController skip_before_action :require_authenticated_user!, unless: :whitelist_mode? + vary_by '' + def show - expires_in 1.day, public: true + cache_even_if_authenticated! render_with_cache json: :activity, expires_in: 1.day end diff --git a/app/controllers/api/v1/instances/domain_blocks_controller.rb b/app/controllers/api/v1/instances/domain_blocks_controller.rb index 37a6906fb6..49fd8fa987 100644 --- a/app/controllers/api/v1/instances/domain_blocks_controller.rb +++ b/app/controllers/api/v1/instances/domain_blocks_controller.rb @@ -6,8 +6,10 @@ class Api::V1::Instances::DomainBlocksController < Api::BaseController before_action :require_enabled_api! before_action :set_domain_blocks + vary_by '' + def index - expires_in 3.minutes, public: true + cache_even_if_authenticated! render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?)) end diff --git a/app/controllers/api/v1/instances/extended_descriptions_controller.rb b/app/controllers/api/v1/instances/extended_descriptions_controller.rb index c72e16cff2..17cf0d790d 100644 --- a/app/controllers/api/v1/instances/extended_descriptions_controller.rb +++ b/app/controllers/api/v1/instances/extended_descriptions_controller.rb @@ -5,8 +5,10 @@ class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController before_action :set_extended_description + vary_by '' + def show - expires_in 3.minutes, public: true + cache_even_if_authenticated! render json: @extended_description, serializer: REST::ExtendedDescriptionSerializer end diff --git a/app/controllers/api/v1/instances/peers_controller.rb b/app/controllers/api/v1/instances/peers_controller.rb index b2669a84eb..20809d7553 100644 --- a/app/controllers/api/v1/instances/peers_controller.rb +++ b/app/controllers/api/v1/instances/peers_controller.rb @@ -5,8 +5,10 @@ class Api::V1::Instances::PeersController < Api::BaseController skip_before_action :require_authenticated_user!, unless: :whitelist_mode? + vary_by '' + def index - expires_in 1.day, public: true + cache_even_if_authenticated! render_with_cache(expires_in: 1.day) { Instance.where.not(domain: DomainBlock.select(:domain)).pluck(:domain) } end diff --git a/app/controllers/api/v1/instances/privacy_policies_controller.rb b/app/controllers/api/v1/instances/privacy_policies_controller.rb index dbd69f54d4..36889f7335 100644 --- a/app/controllers/api/v1/instances/privacy_policies_controller.rb +++ b/app/controllers/api/v1/instances/privacy_policies_controller.rb @@ -5,8 +5,10 @@ class Api::V1::Instances::PrivacyPoliciesController < Api::BaseController before_action :set_privacy_policy + vary_by '' + def show - expires_in 1.day, public: true + cache_even_if_authenticated! render json: @privacy_policy, serializer: REST::PrivacyPolicySerializer end diff --git a/app/controllers/api/v1/instances/rules_controller.rb b/app/controllers/api/v1/instances/rules_controller.rb index 93cf3c7594..cd5cc7b086 100644 --- a/app/controllers/api/v1/instances/rules_controller.rb +++ b/app/controllers/api/v1/instances/rules_controller.rb @@ -5,7 +5,10 @@ class Api::V1::Instances::RulesController < Api::BaseController before_action :set_rules + vary_by '' + def index + cache_even_if_authenticated! render json: @rules, each_serializer: REST::RuleSerializer end diff --git a/app/controllers/api/v1/instances/translation_languages_controller.rb b/app/controllers/api/v1/instances/translation_languages_controller.rb index 3910a499e8..c4680cccb8 100644 --- a/app/controllers/api/v1/instances/translation_languages_controller.rb +++ b/app/controllers/api/v1/instances/translation_languages_controller.rb @@ -5,8 +5,10 @@ class Api::V1::Instances::TranslationLanguagesController < Api::BaseController before_action :set_languages + vary_by '' + def show - expires_in 1.day, public: true + cache_even_if_authenticated! render json: @languages end diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb index 3cdb404cb8..d4c822e64a 100644 --- a/app/controllers/api/v1/instances_controller.rb +++ b/app/controllers/api/v1/instances_controller.rb @@ -3,8 +3,10 @@ class Api::V1::InstancesController < Api::BaseController skip_before_action :require_authenticated_user!, unless: :whitelist_mode? + vary_by '' + def show - expires_in 3.minutes, public: true + cache_even_if_authenticated! render_with_cache json: InstancePresenter.new, serializer: REST::V1::InstanceSerializer, root: 'instance' end end diff --git a/app/controllers/api/v1/polls_controller.rb b/app/controllers/api/v1/polls_controller.rb index 6435e9f0dc..ffc70a8496 100644 --- a/app/controllers/api/v1/polls_controller.rb +++ b/app/controllers/api/v1/polls_controller.rb @@ -8,6 +8,7 @@ class Api::V1::PollsController < Api::BaseController before_action :refresh_poll def show + cache_if_unauthenticated! render json: @poll, serializer: REST::PollSerializer, include_results: true end diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb index b138fa2650..73eb11e711 100644 --- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb @@ -8,6 +8,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController after_action :insert_pagination_headers def index + cache_if_unauthenticated! @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/statuses/histories_controller.rb b/app/controllers/api/v1/statuses/histories_controller.rb index 7fe73a6f54..dff2425d06 100644 --- a/app/controllers/api/v1/statuses/histories_controller.rb +++ b/app/controllers/api/v1/statuses/histories_controller.rb @@ -7,6 +7,7 @@ class Api::V1::Statuses::HistoriesController < Api::BaseController before_action :set_status def show + cache_if_unauthenticated! render json: @status.edits.includes(:account, status: [:account]), each_serializer: REST::StatusEditSerializer end diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb index 4b545f9826..41672e7539 100644 --- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb +++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb @@ -8,6 +8,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController after_action :insert_pagination_headers def index + cache_if_unauthenticated! @accounts = load_accounts render json: @accounts, each_serializer: REST::AccountSerializer end diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index fadd1b0451..064e7632a8 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -24,11 +24,14 @@ class Api::V1::StatusesController < Api::BaseController DESCENDANTS_DEPTH_LIMIT = 20 def show + cache_if_unauthenticated! @status = cache_collection([@status], Status).first render json: @status, serializer: REST::StatusSerializer end def context + cache_if_unauthenticated! + ancestors_limit = CONTEXT_LIMIT descendants_limit = CONTEXT_LIMIT descendants_depth_limit = nil diff --git a/app/controllers/api/v1/tags_controller.rb b/app/controllers/api/v1/tags_controller.rb index a08fd21877..284ec85937 100644 --- a/app/controllers/api/v1/tags_controller.rb +++ b/app/controllers/api/v1/tags_controller.rb @@ -8,6 +8,7 @@ class Api::V1::TagsController < Api::BaseController override_rate_limit_headers :follow, family: :follows def show + cache_if_unauthenticated! render json: @tag, serializer: REST::TagSerializer end diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb index d253b744f9..5bbd92b9ee 100644 --- a/app/controllers/api/v1/timelines/public_controller.rb +++ b/app/controllers/api/v1/timelines/public_controller.rb @@ -5,6 +5,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController after_action :insert_pagination_headers, unless: -> { @statuses.empty? } def show + cache_if_unauthenticated! @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) end diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb index 64a1db58df..9cd7b99046 100644 --- a/app/controllers/api/v1/timelines/tag_controller.rb +++ b/app/controllers/api/v1/timelines/tag_controller.rb @@ -5,6 +5,7 @@ class Api::V1::Timelines::TagController < Api::BaseController after_action :insert_pagination_headers, unless: -> { @statuses.empty? } def show + cache_if_unauthenticated! @statuses = load_statuses render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id) end diff --git a/app/controllers/api/v1/trends/links_controller.rb b/app/controllers/api/v1/trends/links_controller.rb index 3ce20fb786..57cfa0b7e4 100644 --- a/app/controllers/api/v1/trends/links_controller.rb +++ b/app/controllers/api/v1/trends/links_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Api::V1::Trends::LinksController < Api::BaseController + vary_by 'Authorization, Accept-Language' + before_action :set_links after_action :insert_pagination_headers @@ -8,6 +10,7 @@ class Api::V1::Trends::LinksController < Api::BaseController DEFAULT_LINKS_LIMIT = 10 def index + cache_if_unauthenticated! render json: @links, each_serializer: REST::Trends::LinkSerializer end diff --git a/app/controllers/api/v1/trends/statuses_controller.rb b/app/controllers/api/v1/trends/statuses_controller.rb index 3aab92477d..c186864c3b 100644 --- a/app/controllers/api/v1/trends/statuses_controller.rb +++ b/app/controllers/api/v1/trends/statuses_controller.rb @@ -1,11 +1,14 @@ # frozen_string_literal: true class Api::V1::Trends::StatusesController < Api::BaseController + vary_by 'Authorization, Accept-Language' + before_action :set_statuses after_action :insert_pagination_headers def index + cache_if_unauthenticated! render json: @statuses, each_serializer: REST::StatusSerializer end diff --git a/app/controllers/api/v1/trends/tags_controller.rb b/app/controllers/api/v1/trends/tags_controller.rb index 75c3ed218b..aca3dd7089 100644 --- a/app/controllers/api/v1/trends/tags_controller.rb +++ b/app/controllers/api/v1/trends/tags_controller.rb @@ -8,6 +8,7 @@ class Api::V1::Trends::TagsController < Api::BaseController DEFAULT_TAGS_LIMIT = 10 def index + cache_if_unauthenticated! render json: @tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@tags, current_user&.account_id) end diff --git a/app/controllers/api/v2/instances_controller.rb b/app/controllers/api/v2/instances_controller.rb index bcd90cff22..8346e28830 100644 --- a/app/controllers/api/v2/instances_controller.rb +++ b/app/controllers/api/v2/instances_controller.rb @@ -2,7 +2,7 @@ class Api::V2::InstancesController < Api::V1::InstancesController def show - expires_in 3.minutes, public: true + cache_even_if_authenticated! render_with_cache json: InstancePresenter.new, serializer: REST::InstanceSerializer, root: 'instance' end end diff --git a/app/controllers/concerns/api_caching_concern.rb b/app/controllers/concerns/api_caching_concern.rb new file mode 100644 index 0000000000..705abce80f --- /dev/null +++ b/app/controllers/concerns/api_caching_concern.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module ApiCachingConcern + extend ActiveSupport::Concern + + def cache_if_unauthenticated! + expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in? + end + + def cache_even_if_authenticated! + expires_in(5.minutes, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless whitelist_mode? + end +end From 276c39361b8ac13b0604716c815de9db24cdcc57 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Apr 2023 16:51:38 +0200 Subject: [PATCH 2/5] Fix anonymous visitors getting a session cookie on first visit (#24584) --- app/controllers/api/base_controller.rb | 1 - app/controllers/application_controller.rb | 18 ++++++-- .../concerns/web_app_controller_concern.rb | 4 ++ app/controllers/media_controller.rb | 1 - app/controllers/media_proxy_controller.rb | 1 - app/views/layouts/application.html.haml | 2 +- .../application_controller_spec.rb | 19 -------- spec/requests/anonymous_cookies_spec.rb | 44 +++++++++++++++++++ 8 files changed, 64 insertions(+), 26 deletions(-) create mode 100644 spec/requests/anonymous_cookies_spec.rb diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 56bf69c402..2629ab782f 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -8,7 +8,6 @@ class Api::BaseController < ApplicationController include AccessTokenTrackingConcern include ApiCachingConcern - skip_before_action :store_current_location skip_before_action :require_functional!, unless: :whitelist_mode? before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access? diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5fec3bf173..f966b18ab5 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -20,6 +20,7 @@ class ApplicationController < ActionController::Base helper_method :sso_account_settings helper_method :whitelist_mode? helper_method :body_class_string + helper_method :skip_csrf_meta_tags? rescue_from ActionController::ParameterMissing, Paperclip::AdapterRegistry::NoHandlerError, with: :bad_request rescue_from Mastodon::NotPermittedError, with: :forbidden @@ -36,7 +37,7 @@ class ApplicationController < ActionController::Base service_unavailable end - before_action :store_current_location, except: :raise_not_found, unless: :devise_controller? + before_action :store_referrer, except: :raise_not_found, if: :devise_controller? before_action :require_functional!, if: :user_signed_in? before_action :set_cache_control_defaults @@ -57,14 +58,25 @@ class ApplicationController < ActionController::Base !authorized_fetch_mode? end - def store_current_location - store_location_for(:user, request.url) unless [:json, :rss].include?(request.format&.to_sym) + def store_referrer + return if request.referer.blank? + + redirect_uri = URI(request.referer) + return if redirect_uri.path.start_with?('/auth') + + stored_url = redirect_uri.to_s if redirect_uri.host == request.host && redirect_uri.port == request.port + + store_location_for(:user, stored_url) end def require_functional! redirect_to edit_user_registration_path unless current_user.functional? end + def skip_csrf_meta_tags? + false + end + def after_sign_out_path_for(_resource_or_scope) if ENV['OMNIAUTH_ONLY'] == 'true' && ENV['OIDC_ENABLED'] == 'true' '/auth/auth/openid_connect/logout' diff --git a/app/controllers/concerns/web_app_controller_concern.rb b/app/controllers/concerns/web_app_controller_concern.rb index 7f2fbae78e..6cd32a377c 100644 --- a/app/controllers/concerns/web_app_controller_concern.rb +++ b/app/controllers/concerns/web_app_controller_concern.rb @@ -10,6 +10,10 @@ module WebAppControllerConcern vary_by 'Accept, Accept-Language, Cookie' end + def skip_csrf_meta_tags? + current_user.nil? + end + def set_app_body_class @body_classes = 'app-body' end diff --git a/app/controllers/media_controller.rb b/app/controllers/media_controller.rb index 133564ee7e..99a3f3431d 100644 --- a/app/controllers/media_controller.rb +++ b/app/controllers/media_controller.rb @@ -3,7 +3,6 @@ class MediaController < ApplicationController include Authorization - skip_before_action :store_current_location skip_before_action :require_functional!, unless: :whitelist_mode? before_action :authenticate_user!, if: :whitelist_mode? diff --git a/app/controllers/media_proxy_controller.rb b/app/controllers/media_proxy_controller.rb index f29b69a24a..1b5486c122 100644 --- a/app/controllers/media_proxy_controller.rb +++ b/app/controllers/media_proxy_controller.rb @@ -6,7 +6,6 @@ class MediaProxyController < ApplicationController include Redisable include Lockable - skip_before_action :store_current_location skip_before_action :require_functional! before_action :authenticate_user!, if: :whitelist_mode? diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 7b9434d6f3..3fa5fef09b 100755 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -30,7 +30,7 @@ = stylesheet_pack_tag current_theme, media: 'all', crossorigin: 'anonymous' = javascript_pack_tag 'common', crossorigin: 'anonymous' = javascript_pack_tag "locale_#{I18n.locale}", crossorigin: 'anonymous' - = csrf_meta_tags + = csrf_meta_tags unless skip_csrf_meta_tags? %meta{ name: 'style-nonce', content: request.content_security_policy_nonce } = stylesheet_link_tag '/inert.css', skip_pipeline: true, media: 'all', id: 'inert-style' diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index bc6c6c0c5e..c4710f3495 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -132,25 +132,6 @@ describe ApplicationController, type: :controller do include_examples 'respond_with_error', 422 end - describe 'before_action :store_current_location' do - it 'stores location for user if it is not devise controller' do - routes.draw { get 'success' => 'anonymous#success' } - get 'success' - expect(controller.stored_location_for(:user)).to eq '/success' - end - - context do - controller Devise::SessionsController do - end - - it 'does not store location for user if it is devise controller' do - @request.env['devise.mapping'] = Devise.mappings[:user] - get 'create' - expect(controller.stored_location_for(:user)).to be_nil - end - end - end - describe 'before_action :check_suspension' do before do routes.draw { get 'success' => 'anonymous#success' } diff --git a/spec/requests/anonymous_cookies_spec.rb b/spec/requests/anonymous_cookies_spec.rb new file mode 100644 index 0000000000..427f54e449 --- /dev/null +++ b/spec/requests/anonymous_cookies_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'rails_helper' + +context 'when visited anonymously' do + around do |example| + old = ActionController::Base.allow_forgery_protection + ActionController::Base.allow_forgery_protection = true + + example.run + + ActionController::Base.allow_forgery_protection = old + end + + describe 'account pages' do + it 'do not set cookies' do + alice = Fabricate(:account, username: 'alice', display_name: 'Alice') + _status = Fabricate(:status, account: alice, text: 'Hello World') + + get '/@alice' + + expect(response.cookies).to be_empty + end + end + + describe 'status pages' do + it 'do not set cookies' do + alice = Fabricate(:account, username: 'alice', display_name: 'Alice') + status = Fabricate(:status, account: alice, text: 'Hello World') + + get short_account_status_url(alice, status) + + expect(response.cookies).to be_empty + end + end + + describe 'the /about page' do + it 'does not set cookies' do + get '/about' + + expect(response.cookies).to be_empty + end + end +end From 1419f90ef2252e7ef87418b12749968a9eab3de9 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Apr 2023 22:14:44 +0200 Subject: [PATCH 3/5] Fix some user-independent endpoints potentially reading session cookies (#24650) --- .../api/v1/instances/extended_descriptions_controller.rb | 6 ++++++ app/controllers/api/v1/instances/peers_controller.rb | 6 ++++++ app/controllers/api/v1/instances/rules_controller.rb | 6 ++++++ app/controllers/api/v1/instances_controller.rb | 6 ++++++ app/controllers/manifests_controller.rb | 4 ++++ app/controllers/well_known/nodeinfo_controller.rb | 4 ++++ 6 files changed, 32 insertions(+) diff --git a/app/controllers/api/v1/instances/extended_descriptions_controller.rb b/app/controllers/api/v1/instances/extended_descriptions_controller.rb index 17cf0d790d..a0665725bd 100644 --- a/app/controllers/api/v1/instances/extended_descriptions_controller.rb +++ b/app/controllers/api/v1/instances/extended_descriptions_controller.rb @@ -2,11 +2,17 @@ class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController skip_before_action :require_authenticated_user!, unless: :whitelist_mode? + skip_around_action :set_locale before_action :set_extended_description vary_by '' + # Override `current_user` to avoid reading session cookies unless in whitelist mode + def current_user + super if whitelist_mode? + end + def show cache_even_if_authenticated! render json: @extended_description, serializer: REST::ExtendedDescriptionSerializer diff --git a/app/controllers/api/v1/instances/peers_controller.rb b/app/controllers/api/v1/instances/peers_controller.rb index 20809d7553..70281362a8 100644 --- a/app/controllers/api/v1/instances/peers_controller.rb +++ b/app/controllers/api/v1/instances/peers_controller.rb @@ -4,9 +4,15 @@ class Api::V1::Instances::PeersController < Api::BaseController before_action :require_enabled_api! skip_before_action :require_authenticated_user!, unless: :whitelist_mode? + skip_around_action :set_locale vary_by '' + # Override `current_user` to avoid reading session cookies unless in whitelist mode + def current_user + super if whitelist_mode? + end + def index cache_even_if_authenticated! render_with_cache(expires_in: 1.day) { Instance.where.not(domain: DomainBlock.select(:domain)).pluck(:domain) } diff --git a/app/controllers/api/v1/instances/rules_controller.rb b/app/controllers/api/v1/instances/rules_controller.rb index cd5cc7b086..d3eeca3262 100644 --- a/app/controllers/api/v1/instances/rules_controller.rb +++ b/app/controllers/api/v1/instances/rules_controller.rb @@ -2,11 +2,17 @@ class Api::V1::Instances::RulesController < Api::BaseController skip_before_action :require_authenticated_user!, unless: :whitelist_mode? + skip_around_action :set_locale before_action :set_rules vary_by '' + # Override `current_user` to avoid reading session cookies unless in whitelist mode + def current_user + super if whitelist_mode? + end + def index cache_even_if_authenticated! render json: @rules, each_serializer: REST::RuleSerializer diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb index d4c822e64a..5a6701ff96 100644 --- a/app/controllers/api/v1/instances_controller.rb +++ b/app/controllers/api/v1/instances_controller.rb @@ -2,9 +2,15 @@ class Api::V1::InstancesController < Api::BaseController skip_before_action :require_authenticated_user!, unless: :whitelist_mode? + skip_around_action :set_locale vary_by '' + # Override `current_user` to avoid reading session cookies unless in whitelist mode + def current_user + super if whitelist_mode? + end + def show cache_even_if_authenticated! render_with_cache json: InstancePresenter.new, serializer: REST::V1::InstanceSerializer, root: 'instance' diff --git a/app/controllers/manifests_controller.rb b/app/controllers/manifests_controller.rb index 593b76c536..4fba9198f3 100644 --- a/app/controllers/manifests_controller.rb +++ b/app/controllers/manifests_controller.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true class ManifestsController < ActionController::Base # rubocop:disable Rails/ApplicationController + # Prevent `active_model_serializer`'s `ActionController::Serialization` from calling `current_user` + # and thus re-issuing session cookies + serialization_scope nil + def show expires_in 3.minutes, public: true render json: InstancePresenter.new, serializer: ManifestSerializer, root: 'instance' diff --git a/app/controllers/well_known/nodeinfo_controller.rb b/app/controllers/well_known/nodeinfo_controller.rb index ab6b8f5a40..e20e8c62a0 100644 --- a/app/controllers/well_known/nodeinfo_controller.rb +++ b/app/controllers/well_known/nodeinfo_controller.rb @@ -4,6 +4,10 @@ module WellKnown class NodeInfoController < ActionController::Base # rubocop:disable Rails/ApplicationController include CacheConcern + # Prevent `active_model_serializer`'s `ActionController::Serialization` from calling `current_user` + # and thus re-issuing session cookies + serialization_scope nil + def index expires_in 3.days, public: true render_with_cache json: {}, serializer: NodeInfo::DiscoverySerializer, adapter: NodeInfo::Adapter, expires_in: 3.days, root: 'nodeinfo' From 1527b02c6d7b542dfdfab41e55b8b8b437c8c46f Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Apr 2023 22:15:00 +0200 Subject: [PATCH 4/5] Fix sass warning about deprecated slash as division (#24653) Co-authored-by: Nick Schonning --- app/javascript/styles/mastodon/components.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index e985afea0b..c2cd71756a 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1170,7 +1170,7 @@ body > [data-popper-placement] { width: 0; position: absolute; top: 0; - inset-inline-start: 16px + ((46px - 2px) / 2); + inset-inline-start: 16px + ((46px - 2px) * 0.5); &--full { top: 0; From 36631e40cc0af6735965f75ef82d0c3ae160c71c Mon Sep 17 00:00:00 2001 From: Tim Campbell Date: Tue, 25 Apr 2023 14:11:31 -0700 Subject: [PATCH 5/5] Inf 123 dated nightly containers (#24656) --- .github/workflows/build-nightly.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml index 31fef5d28a..501db6e9c6 100644 --- a/.github/workflows/build-nightly.yml +++ b/.github/workflows/build-nightly.yml @@ -37,6 +37,7 @@ jobs: latest=auto tags: | type=raw,value=nightly + type=schedule,pattern=nightly-{{date 'YYYY-MM-DD' tz='Etc/UTC'}} labels: | org.opencontainers.image.description=Nightly build image used for testing purposes