From 4b42fe6aba3b0e2315c560605a0cea459128e2ea Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 28 Oct 2025 09:05:23 +0100 Subject: [PATCH] Change API behavior of reblogs wrt. quotes for consistency (#36559) --- app/controllers/api/v1/statuses_controller.rb | 2 +- app/lib/status_cache_hydrator.rb | 1 + app/serializers/rest/status_serializer.rb | 6 ++--- spec/requests/api/v1/statuses_spec.rb | 23 +++++++++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb index 6c4e7619b..0627acc30 100644 --- a/app/controllers/api/v1/statuses_controller.rb +++ b/app/controllers/api/v1/statuses_controller.rb @@ -157,7 +157,7 @@ class Api::V1::StatusesController < Api::BaseController end def set_quoted_status - @quoted_status = Status.find(status_params[:quoted_status_id]) if status_params[:quoted_status_id].present? + @quoted_status = Status.find(status_params[:quoted_status_id])&.proper if status_params[:quoted_status_id].present? authorize(@quoted_status, :quote?) if @quoted_status.present? rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError # TODO: distinguish between non-existing and non-quotable posts diff --git a/app/lib/status_cache_hydrator.rb b/app/lib/status_cache_hydrator.rb index 5ba706c4c..b6a5e3705 100644 --- a/app/lib/status_cache_hydrator.rb +++ b/app/lib/status_cache_hydrator.rb @@ -61,6 +61,7 @@ class StatusCacheHydrator payload[:filtered] = payload[:reblog][:filtered] payload[:favourited] = payload[:reblog][:favourited] payload[:reblogged] = payload[:reblog][:reblogged] + payload[:quote_approval] = payload[:reblog][:quote_approval] end end diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb index a06ddc686..96751fbd5 100644 --- a/app/serializers/rest/status_serializer.rb +++ b/app/serializers/rest/status_serializer.rb @@ -168,9 +168,9 @@ class REST::StatusSerializer < ActiveModel::Serializer def quote_approval { - automatic: object.quote_policy_as_keys(:automatic), - manual: object.quote_policy_as_keys(:manual), - current_user: object.quote_policy_for_account(current_user&.account), + automatic: object.proper.quote_policy_as_keys(:automatic), + manual: object.proper.quote_policy_as_keys(:manual), + current_user: object.proper.quote_policy_for_account(current_user&.account), } end diff --git a/spec/requests/api/v1/statuses_spec.rb b/spec/requests/api/v1/statuses_spec.rb index 249abc244..ed41e5420 100644 --- a/spec/requests/api/v1/statuses_spec.rb +++ b/spec/requests/api/v1/statuses_spec.rb @@ -248,6 +248,29 @@ RSpec.describe '/api/v1/statuses' do end end + context 'with a quote of a reblog' do + let(:quoted_status) { Fabricate(:status, quote_approval_policy: Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] << 16) } + let(:reblog) { Fabricate(:status, reblog: quoted_status) } + let(:params) do + { + status: 'Hello world, this is a self-quote', + quoted_status_id: reblog.id, + } + end + + it 'returns a quote post, as well as rate limit headers', :aggregate_failures do + subject + + 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.parsed_body[:quote][:quoted_status][:id]).to eq quoted_status.id.to_s + 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 + end + context 'with a self-quote post and a CW but no text' do let(:quoted_status) { Fabricate(:status, account: user.account) } let(:params) do