From 97ba08113d4877fb2cfe38561fc41b057d07fb21 Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 8 Apr 2026 18:03:24 +0200 Subject: [PATCH] Fix being able to quote someone you blocked (#38608) --- app/policies/status_policy.rb | 3 +- spec/requests/api/v1/statuses_spec.rb | 50 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb index 8cd011042f..0ec4a03a35 100644 --- a/app/policies/status_policy.rb +++ b/app/policies/status_policy.rb @@ -13,9 +13,8 @@ class StatusPolicy < ApplicationPolicy end end - # This is about requesting a quote post, not validating it def quote? - show? && record.quote_policy_for_account(current_account) != :denied + show? && !blocking_author? && record.quote_policy_for_account(current_account) != :denied end def reblog? diff --git a/spec/requests/api/v1/statuses_spec.rb b/spec/requests/api/v1/statuses_spec.rb index f9845ada7e..82ad845185 100644 --- a/spec/requests/api/v1/statuses_spec.rb +++ b/spec/requests/api/v1/statuses_spec.rb @@ -317,6 +317,56 @@ RSpec.describe '/api/v1/statuses' do end end + context 'with a quote in an unlisted message' do + let!(:quoted_status) { Fabricate(:status, quote_approval_policy: InteractionPolicy::POLICY_FLAGS[:public] << 16) } + let(:params) do + { + status: 'Hello, this is a quote', + quoted_status_id: quoted_status.id, + visibility: 'unlisted', + } + end + + it 'returns a quote post, as well as rate limit headers', :aggregate_failures do + expect { subject }.to change(user.account.statuses, :count).by(1) + + expect(response).to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect(response.parsed_body[:quote]).to be_present + expect(response.headers['X-RateLimit-Limit']).to eq RateLimiter::FAMILIES[:statuses][:limit].to_s + expect(response.headers['X-RateLimit-Remaining']).to eq (RateLimiter::FAMILIES[:statuses][:limit] - 1).to_s + end + + context 'when the quoter is blocked by the quotee' do + before do + quoted_status.account.block!(user.account) + end + + it 'returns an error and does not create a post', :aggregate_failures do + expect { subject }.to_not change(user.account.statuses, :count) + + expect(response).to have_http_status(404) + expect(response.content_type) + .to start_with('application/json') + end + end + + context 'when the quotee is blocked by the quoter' do + before do + user.account.block!(quoted_status.account) + end + + it 'returns an error and does not create a post', :aggregate_failures do + expect { subject }.to_not change(user.account.statuses, :count) + + expect(response).to have_http_status(404) + expect(response.content_type) + .to start_with('application/json') + end + end + end + context 'with a quote of a reblog' do let(:quoted_status) { Fabricate(:status, quote_approval_policy: InteractionPolicy::POLICY_FLAGS[:public] << 16) } let(:reblog) { Fabricate(:status, reblog: quoted_status) }