Federate updates to collections (#37790)
This commit is contained in:
parent
0763ad0d96
commit
03f73377d9
@ -51,7 +51,7 @@ class Api::V1Alpha::CollectionsController < Api::BaseController
|
||||
def update
|
||||
authorize @collection, :update?
|
||||
|
||||
@collection.update!(collection_update_params) # TODO: Create a service for this to federate changes
|
||||
UpdateCollectionService.new.call(@collection, collection_update_params)
|
||||
|
||||
render json: @collection, serializer: REST::CollectionSerializer, adapter: :json
|
||||
end
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ActivityPub::UpdateFeaturedCollectionSerializer < ActivityPub::Serializer
|
||||
attributes :id, :type, :actor, :to
|
||||
|
||||
has_one :object, serializer: ActivityPub::FeaturedCollectionSerializer
|
||||
|
||||
def id
|
||||
[ActivityPub::TagManager.instance.uri_for(object), '#updates/', object.updated_at.to_i].join
|
||||
end
|
||||
|
||||
def type
|
||||
'Update'
|
||||
end
|
||||
|
||||
def actor
|
||||
ActivityPub::TagManager.instance.uri_for(object.account)
|
||||
end
|
||||
|
||||
def to
|
||||
[ActivityPub::TagManager::COLLECTIONS[:public]]
|
||||
end
|
||||
end
|
||||
28
app/services/update_collection_service.rb
Normal file
28
app/services/update_collection_service.rb
Normal file
@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UpdateCollectionService
|
||||
UPDATEABLE_PARAMS = %w(name description language sensitive discoverable tag_id).freeze
|
||||
|
||||
def call(collection, params)
|
||||
@collection = collection
|
||||
@collection.update!(params)
|
||||
|
||||
distribute_update_activity if Mastodon::Feature.collections_federation_enabled?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def distribute_update_activity
|
||||
return unless relevant_attributes_changed?
|
||||
|
||||
ActivityPub::AccountRawDistributionWorker.perform_async(activity_json, @collection.account.id)
|
||||
end
|
||||
|
||||
def activity_json
|
||||
ActiveModelSerializers::SerializableResource.new(@collection, serializer: ActivityPub::UpdateFeaturedCollectionSerializer, adapter: ActivityPub::Adapter).to_json
|
||||
end
|
||||
|
||||
def relevant_attributes_changed?
|
||||
(@collection.saved_changes.keys & UPDATEABLE_PARAMS).any?
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,27 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ActivityPub::UpdateFeaturedCollectionSerializer do
|
||||
subject { serialized_record_json(collection, described_class, adapter: ActivityPub::Adapter) }
|
||||
|
||||
let(:tag_manager) { ActivityPub::TagManager.instance }
|
||||
let(:collection) { Fabricate(:collection) }
|
||||
|
||||
it 'serializes to the expected json' do
|
||||
expect(subject).to include({
|
||||
'id' => "#{tag_manager.uri_for(collection)}#updates/#{collection.updated_at.to_i}",
|
||||
'type' => 'Update',
|
||||
'actor' => tag_manager.uri_for(collection.account),
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'object' => a_hash_including({
|
||||
'id' => tag_manager.uri_for(collection),
|
||||
'type' => 'FeaturedCollection',
|
||||
}),
|
||||
})
|
||||
|
||||
expect(subject).to_not have_key('published')
|
||||
expect(subject).to_not have_key('cc')
|
||||
expect(subject).to_not have_key('target')
|
||||
end
|
||||
end
|
||||
43
spec/services/update_collection_service_spec.rb
Normal file
43
spec/services/update_collection_service_spec.rb
Normal file
@ -0,0 +1,43 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe UpdateCollectionService do
|
||||
subject { described_class.new }
|
||||
|
||||
let(:collection) { Fabricate(:collection) }
|
||||
|
||||
describe '#call' do
|
||||
context 'when given valid parameters' do
|
||||
it 'updates the collection' do
|
||||
subject.call(collection, { name: 'Newly updated name' })
|
||||
|
||||
expect(collection.name).to eq 'Newly updated name'
|
||||
end
|
||||
|
||||
context 'when something actually changed' do
|
||||
it 'federates an `Update` activity', feature: :collections_federation do
|
||||
subject.call(collection, { name: 'updated' })
|
||||
|
||||
expect(ActivityPub::AccountRawDistributionWorker).to have_enqueued_sidekiq_job
|
||||
end
|
||||
end
|
||||
|
||||
context 'when nothing changed' do
|
||||
it 'does not federate an activity', feature: :collections_federation do
|
||||
subject.call(collection, { name: collection.name })
|
||||
|
||||
expect(ActivityPub::AccountRawDistributionWorker).to_not have_enqueued_sidekiq_job
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when given invalid parameters' do
|
||||
it 'raises an exception' do
|
||||
expect do
|
||||
subject.call(collection, { name: '' })
|
||||
end.to raise_error(ActiveRecord::RecordInvalid)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user