From cdbb35ea74f71efb1c38f7f02140b21dd09da29b Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Thu, 14 Aug 2025 13:36:05 -0400 Subject: [PATCH] Use before_action to protect hidden collections in following/followers lists --- app/controllers/follower_accounts_controller.rb | 7 +++++-- app/controllers/following_accounts_controller.rb | 10 +++++----- spec/controllers/follower_accounts_controller_spec.rb | 11 +++++++++++ .../controllers/following_accounts_controller_spec.rb | 11 +++++++++++ 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index f4c7b37088a..ba1f618d487 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -7,6 +7,7 @@ class FollowerAccountsController < ApplicationController vary_by -> { public_fetch_mode? ? 'Accept, Accept-Language, Cookie' : 'Accept, Accept-Language, Cookie, Signature' } before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } + before_action :protect_hidden_collections, if: -> { request.format.json? } skip_around_action :set_locale, if: -> { request.format == :json } skip_before_action :require_functional!, unless: :limited_federation_mode? @@ -18,8 +19,6 @@ class FollowerAccountsController < ApplicationController end format.json do - raise Mastodon::NotPermittedError if page_requested? && @account.hide_collections? - expires_in(page_requested? ? 0 : 3.minutes, public: public_fetch_mode?) render json: collection_presenter, @@ -41,6 +40,10 @@ class FollowerAccountsController < ApplicationController @follows = scope.recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account) end + def protect_hidden_collections + raise Mastodon::NotPermittedError if page_requested? && @account.hide_collections? + end + def page_requested? params[:page].present? end diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 268fad96d09..dc75166f01e 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -7,6 +7,7 @@ class FollowingAccountsController < ApplicationController vary_by -> { public_fetch_mode? ? 'Accept, Accept-Language, Cookie' : 'Accept, Accept-Language, Cookie, Signature' } before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } + before_action :protect_hidden_collections, if: -> { request.format.json? } skip_around_action :set_locale, if: -> { request.format == :json } skip_before_action :require_functional!, unless: :limited_federation_mode? @@ -18,11 +19,6 @@ class FollowingAccountsController < ApplicationController end format.json do - if page_requested? && @account.hide_collections? - forbidden - next - end - expires_in(page_requested? ? 0 : 3.minutes, public: public_fetch_mode?) render json: collection_presenter, @@ -44,6 +40,10 @@ class FollowingAccountsController < ApplicationController @follows = scope.recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account) end + def protect_hidden_collections + raise Mastodon::NotPermittedError if page_requested? && @account.hide_collections? + end + def page_requested? params[:page].present? end diff --git a/spec/controllers/follower_accounts_controller_spec.rb b/spec/controllers/follower_accounts_controller_spec.rb index e14ed00e609..e07a6115e90 100644 --- a/spec/controllers/follower_accounts_controller_spec.rb +++ b/spec/controllers/follower_accounts_controller_spec.rb @@ -57,6 +57,17 @@ RSpec.describe FollowerAccountsController do ) end + context 'when account hides their network' do + before { alice.update(hide_collections: true) } + + it 'returns forbidden response' do + expect(response) + .to have_http_status(403) + expect(response.parsed_body) + .to include(error: /forbidden/i) + end + end + context 'when account is permanently suspended' do before do alice.suspend! diff --git a/spec/controllers/following_accounts_controller_spec.rb b/spec/controllers/following_accounts_controller_spec.rb index fea4d4845c8..0abdc5165f9 100644 --- a/spec/controllers/following_accounts_controller_spec.rb +++ b/spec/controllers/following_accounts_controller_spec.rb @@ -57,6 +57,17 @@ RSpec.describe FollowingAccountsController do ) end + context 'when account hides their network' do + before { alice.update(hide_collections: true) } + + it 'returns forbidden response' do + expect(response) + .to have_http_status(403) + expect(response.parsed_body) + .to include(error: /forbidden/i) + end + end + context 'when account is permanently suspended' do before do alice.suspend!