mirror of
https://github.com/mastodon/mastodon.git
synced 2025-09-06 01:41:08 +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
|
class Api::V1::StatusesController < Api::BaseController
|
||||||
include Authorization
|
include Authorization
|
||||||
include AsyncRefreshesConcern
|
include AsyncRefreshesConcern
|
||||||
|
include Api::InteractionPoliciesConcern
|
||||||
|
|
||||||
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy]
|
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy]
|
||||||
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [: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
|
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
|
def serializer_for_status
|
||||||
@status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
|
@status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
|
||||||
end
|
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 :history, only: :show
|
||||||
resource :source, only: :show
|
resource :source, only: :show
|
||||||
|
|
||||||
|
resource :interaction_policy, only: :update
|
||||||
|
|
||||||
post :translate, to: 'translations#create'
|
post :translate, to: 'translations#create'
|
||||||
end
|
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