mirror of
https://github.com/mastodon/mastodon.git
synced 2025-09-05 17:31:12 +00:00
Add PUT /api/v1/statuses/:status_id/interaction_policy
(#35769)
This commit is contained in:
parent
49a6e4cbb5
commit
2648bbdc51
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Statuses::InteractionPoliciesController < Api::V1::Statuses::BaseController
|
||||
include Api::InteractionPoliciesConcern
|
||||
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
|
||||
before_action -> { check_feature_enabled }
|
||||
|
||||
def update
|
||||
authorize @status, :update?
|
||||
|
||||
@status.update!(quote_approval_policy: quote_approval_policy)
|
||||
|
||||
broadcast_updates! if @status.quote_approval_policy_previously_changed?
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def status_params
|
||||
params.permit(:quote_approval_policy)
|
||||
end
|
||||
|
||||
def check_feature_enabled
|
||||
raise ActionController::RoutingError unless Mastodon::Feature.outgoing_quotes_enabled?
|
||||
end
|
||||
|
||||
def broadcast_updates!
|
||||
DistributionWorker.perform_async(@status.id, { 'update' => true })
|
||||
ActivityPub::StatusUpdateDistributionWorker.perform_async(@status.id)
|
||||
end
|
||||
end
|
|
@ -3,6 +3,7 @@
|
|||
class Api::V1::StatusesController < Api::BaseController
|
||||
include Authorization
|
||||
include AsyncRefreshesConcern
|
||||
include Api::InteractionPoliciesConcern
|
||||
|
||||
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy]
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :update, :destroy]
|
||||
|
@ -205,23 +206,6 @@ class Api::V1::StatusesController < Api::BaseController
|
|||
)
|
||||
end
|
||||
|
||||
def quote_approval_policy
|
||||
# TODO: handle `nil` separately
|
||||
return nil unless Mastodon::Feature.outgoing_quotes_enabled? && status_params[:quote_approval_policy].present?
|
||||
|
||||
case status_params[:quote_approval_policy]
|
||||
when 'public'
|
||||
Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] << 16
|
||||
when 'followers'
|
||||
Status::QUOTE_APPROVAL_POLICY_FLAGS[:followers] << 16
|
||||
when 'nobody'
|
||||
0
|
||||
else
|
||||
# TODO: raise more useful message
|
||||
raise ActiveRecord::RecordInvalid
|
||||
end
|
||||
end
|
||||
|
||||
def serializer_for_status
|
||||
@status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
|
||||
end
|
||||
|
|
22
app/controllers/concerns/api/interaction_policies_concern.rb
Normal file
22
app/controllers/concerns/api/interaction_policies_concern.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Api::InteractionPoliciesConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def quote_approval_policy
|
||||
# TODO: handle `nil` separately
|
||||
return nil unless Mastodon::Feature.outgoing_quotes_enabled? && status_params[:quote_approval_policy].present?
|
||||
|
||||
case status_params[:quote_approval_policy]
|
||||
when 'public'
|
||||
Status::QUOTE_APPROVAL_POLICY_FLAGS[:public] << 16
|
||||
when 'followers'
|
||||
Status::QUOTE_APPROVAL_POLICY_FLAGS[:followers] << 16
|
||||
when 'nobody'
|
||||
0
|
||||
else
|
||||
# TODO: raise more useful message
|
||||
raise ActiveRecord::RecordInvalid
|
||||
end
|
||||
end
|
||||
end
|
|
@ -39,6 +39,8 @@ namespace :api, format: false do
|
|||
resource :history, only: :show
|
||||
resource :source, only: :show
|
||||
|
||||
resource :interaction_policy, only: :update
|
||||
|
||||
post :translate, to: 'translations#create'
|
||||
end
|
||||
|
||||
|
|
94
spec/requests/api/v1/statuses/interaction_policies_spec.rb
Normal file
94
spec/requests/api/v1/statuses/interaction_policies_spec.rb
Normal file
|
@ -0,0 +1,94 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe 'Interaction policies', feature: :outgoing_quotes do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:scopes) { 'write:statuses' }
|
||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||
let(:status) { Fabricate(:status, account: user.account) }
|
||||
let(:params) { { quote_approval_policy: 'followers' } }
|
||||
|
||||
describe 'PUT /api/v1/statuses/:status_id/interaction_policy' do
|
||||
subject do
|
||||
put "/api/v1/statuses/#{status.id}/interaction_policy", headers: headers, params: params
|
||||
end
|
||||
|
||||
it_behaves_like 'forbidden for wrong scope', 'read read:statuses'
|
||||
|
||||
context 'without an authorization header' do
|
||||
let(:headers) { {} }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
expect { subject }
|
||||
.to_not(change { status.reload.quote_approval_policy })
|
||||
|
||||
expect(response).to have_http_status(401)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a status from a different user' do
|
||||
let(:status) { Fabricate(:status) }
|
||||
|
||||
it 'returns http unauthorized' do
|
||||
expect { subject }
|
||||
.to_not(change { status.reload.quote_approval_policy })
|
||||
|
||||
expect(response).to have_http_status(403)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when changing the interaction policy' do
|
||||
it 'changes the interaction policy, returns the updated status, and schedules distribution jobs' do
|
||||
expect { subject }
|
||||
.to change { status.reload.quote_approval_policy }.to(Status::QUOTE_APPROVAL_POLICY_FLAGS[:followers] << 16)
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body).to include(
|
||||
'quote_approval' => match(
|
||||
'automatic' => ['followers'],
|
||||
'manual' => [],
|
||||
'current_user' => 'automatic'
|
||||
)
|
||||
)
|
||||
|
||||
expect(DistributionWorker)
|
||||
.to have_enqueued_sidekiq_job(status.id, { 'update' => true })
|
||||
expect(ActivityPub::StatusUpdateDistributionWorker)
|
||||
.to have_enqueued_sidekiq_job(status.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not changing the interaction policy' do
|
||||
let(:params) { { quote_approval_policy: 'nobody' } }
|
||||
|
||||
it 'keeps the interaction policy, returns the status, and does not schedule distribution jobs' do
|
||||
expect { subject }
|
||||
.to_not(change { status.reload.quote_approval_policy }.from(0))
|
||||
|
||||
expect(response).to have_http_status(200)
|
||||
expect(response.content_type)
|
||||
.to start_with('application/json')
|
||||
expect(response.parsed_body).to include(
|
||||
'quote_approval' => match(
|
||||
'automatic' => [],
|
||||
'manual' => [],
|
||||
'current_user' => 'automatic'
|
||||
)
|
||||
)
|
||||
|
||||
expect(DistributionWorker)
|
||||
.to_not have_enqueued_sidekiq_job
|
||||
expect(ActivityPub::StatusUpdateDistributionWorker)
|
||||
.to_not have_enqueued_sidekiq_job
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user