diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | lib/diaspora/federation/receive.rb | 22 | ||||
-rw-r--r-- | spec/integration/federation/receive_federation_messages_spec.rb | 5 | ||||
-rw-r--r-- | spec/integration/federation/shared_receive_stream_items.rb | 9 | ||||
-rw-r--r-- | spec/lib/diaspora/federation/receive_spec.rb | 16 | ||||
-rw-r--r-- | spec/shared_behaviors/receiving.rb | 73 |
6 files changed, 125 insertions, 1 deletions
diff --git a/Changelog.md b/Changelog.md index 7655de013..6ff634234 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ * Improve password autocomplete with password managers [#7642](https://github.com/diaspora/diaspora/pull/7642) * Remove the limit of participants in private conversations [#7705](https://github.com/diaspora/diaspora/pull/7705) * Send blocks to the blocked persons pod for better UX [#7705](https://github.com/diaspora/diaspora/pull/7705) +* Send a dummy participation on all incoming public posts to increase interaction consistency [#7708](https://github.com/diaspora/diaspora/pull/7708) ## Bug fixes * Fix invite link on the contacts page when the user has no contacts [#7690](https://github.com/diaspora/diaspora/pull/7690) diff --git a/lib/diaspora/federation/receive.rb b/lib/diaspora/federation/receive.rb index d4dcea34d..51954db01 100644 --- a/lib/diaspora/federation/receive.rb +++ b/lib/diaspora/federation/receive.rb @@ -153,7 +153,7 @@ module Diaspora guid: entity.guid, created_at: entity.created_at, root_guid: entity.root_guid - ) + ).tap {|reshare| send_participation_for(reshare) } end end @@ -193,6 +193,8 @@ module Diaspora status_message.photos = save_or_load_photos(entity.photos) status_message.save! + + send_participation_for(status_message) end end end @@ -328,6 +330,24 @@ module Diaspora end end end + + private_class_method def self.send_participation_for(post) + return unless post.public? + user = user_for_participation + participation = Participation.new(target: post, author: user.person) + Diaspora::Federation::Dispatcher.build(user, participation, subscribers: [post.author]).dispatch + rescue => e # rubocop:disable Lint/RescueWithoutErrorClass + logger.warn "failed to send participation for post #{post.guid}: #{e.class}: #{e.message}" + end + + # Use configured admin account if available, + # or use first user with admin role if available, + # or use first user who isn't closed + private_class_method def self.user_for_participation + User.find_by(username: AppConfig.admins.account.to_s) || + Role.admins.first&.person&.owner || + User.where(locked_at: nil).first + end end end end diff --git a/spec/integration/federation/receive_federation_messages_spec.rb b/spec/integration/federation/receive_federation_messages_spec.rb index c9a67aeb4..b53bc97c1 100644 --- a/spec/integration/federation/receive_federation_messages_spec.rb +++ b/spec/integration/federation/receive_federation_messages_spec.rb @@ -116,6 +116,11 @@ describe "Receive federation messages feature" do alice, instance_of(Reshare) ).and_return(double(create!: true)) + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |_user, participation, _opts| + expect(participation.target.guid).to eq(reshare.guid) + instance_double(:dispatch) + end + post_message(generate_payload(reshare, sender)) expect(Reshare.exists?(root_guid: post.guid)).to be_truthy diff --git a/spec/integration/federation/shared_receive_stream_items.rb b/spec/integration/federation/shared_receive_stream_items.rb index 347848e35..1431b9e1a 100644 --- a/spec/integration/federation/shared_receive_stream_items.rb +++ b/spec/integration/federation/shared_receive_stream_items.rb @@ -8,6 +8,15 @@ shared_examples_for "messages which are indifferent about sharing fact" do it "treats status message receive correctly" do entity = Fabricate(:status_message_entity, author: sender_id, public: public) + if public + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |_user, participation, _opts| + expect(participation.target.guid).to eq(entity.guid) + instance_double(:dispatch) + end + else + expect(Diaspora::Federation::Dispatcher).not_to receive(:build) + end + post_message(generate_payload(entity, sender, recipient), recipient) expect(StatusMessage.exists?(guid: entity.guid)).to be_truthy diff --git a/spec/lib/diaspora/federation/receive_spec.rb b/spec/lib/diaspora/federation/receive_spec.rb index 2c2e7e110..767e67796 100644 --- a/spec/lib/diaspora/federation/receive_spec.rb +++ b/spec/lib/diaspora/federation/receive_spec.rb @@ -541,6 +541,10 @@ describe Diaspora::Federation::Receive do it_behaves_like "it ignores existing object received twice", Reshare do let(:entity) { reshare_entity } end + + it_behaves_like "it sends a participation to the author" do + let(:entity) { reshare_entity } + end end describe ".retraction" do @@ -766,6 +770,18 @@ describe Diaspora::Federation::Receive do expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid) expect(status_message.photos.map(&:text)).to include(received_photo.text, photo2.text) end + + it_behaves_like "it sends a participation to the author" do + let(:entity) { status_message_entity } + end + + it "doesn't send participations for a private post" do + status_message_entity = Fabricate(:status_message_entity, author: sender.diaspora_handle, public: false) + + expect(Diaspora::Federation::Dispatcher).not_to receive(:build) + + Diaspora::Federation::Receive.perform(status_message_entity) + end end end end diff --git a/spec/shared_behaviors/receiving.rb b/spec/shared_behaviors/receiving.rb index 6a563e237..8c2c8da65 100644 --- a/spec/shared_behaviors/receiving.rb +++ b/spec/shared_behaviors/receiving.rb @@ -73,3 +73,76 @@ shared_examples_for "it relays relayables" do |klass| Diaspora::Federation::Receive.perform(entity) end end + +shared_examples_for "it sends a participation to the author" do + it "sends a participation for the post to the author" do + dispatcher = double + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |user, participation, opts| + expect(user).to be_a(User) + expect(participation.target.guid).to eq(entity.guid) + + subscribers = opts[:subscribers] + expect(subscribers.size).to eq(1) + expect(subscribers.first.diaspora_handle).to eq(entity.author) + + dispatcher + end + expect(dispatcher).to receive(:dispatch) + + Diaspora::Federation::Receive.perform(entity) + end + + it "doesn't save the participation in the database" do + participation_guid = nil + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |_user, participation, _opts| + participation_guid = participation.guid + instance_double(:dispatch) + end + + Diaspora::Federation::Receive.perform(entity) + + expect(Participation.where(guid: participation_guid)).not_to exist + end + + it "uses the configured admin as sender for the participation" do + AppConfig.admins.account = bob.username + + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |user, _participation, _opts| + expect(user.username).to eq(bob.username) + instance_double(:dispatch) + end + + Diaspora::Federation::Receive.perform(entity) + end + + it "uses the first user with an admin role if no admin is configured in the config" do + AppConfig.admins.account = nil + admin_role = FactoryGirl.create(:role, name: "admin") + + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |user, _participation, _opts| + expect(user.username).to eq(admin_role.person.owner.username) + instance_double(:dispatch) + end + + Diaspora::Federation::Receive.perform(entity) + end + + it "uses the first open account if no admin is available" do + AppConfig.admins.account = nil + expect(Role.admins).to be_empty + User.first.close_account! + + expect(Diaspora::Federation::Dispatcher).to receive(:build) do |user, _participation, _opts| + expect(user.username).to eq(User.second.username) + instance_double(:dispatch) + end + + Diaspora::Federation::Receive.perform(entity) + end + + it "still receives the entity successfully if there is an error while sending the participation" do + expect(Diaspora::Federation::Dispatcher).to receive(:build).and_raise "FooBar" + + Diaspora::Federation::Receive.perform(entity) + end +end |