diff --git a/app/controllers/blocks_controller.rb b/app/controllers/blocks_controller.rb index a9bcae865..7256a38c8 100644 --- a/app/controllers/blocks_controller.rb +++ b/app/controllers/blocks_controller.rb @@ -6,7 +6,7 @@ class BlocksController < ApplicationController def create block = current_user.blocks.new(block_params) - disconnect_if_contact(block.person) if block.save + send_message(block) if block.save respond_to do |format| format.json { head :no_content } @@ -14,7 +14,9 @@ class BlocksController < ApplicationController end def destroy - notice = if current_user.blocks.find_by(id: params[:id])&.delete + block = current_user.blocks.find_by(id: params[:id]) + notice = if block&.delete + ContactRetraction.for(block).defer_dispatch(current_user) {notice: t("blocks.destroy.success")} else {error: t("blocks.destroy.failure")} @@ -28,8 +30,14 @@ class BlocksController < ApplicationController private - def disconnect_if_contact(person) - current_user.contact_for(person).try {|contact| current_user.disconnect(contact) } + def send_message(block) + contact = current_user.contact_for(block.person) + + if contact + current_user.disconnect(contact) + elsif block.person.remote? + Diaspora::Federation::Dispatcher.defer_dispatch(current_user, block) + end end def block_params diff --git a/app/models/block.rb b/app/models/block.rb index f0e79b22b..147361cac 100644 --- a/app/models/block.rb +++ b/app/models/block.rb @@ -15,4 +15,9 @@ class Block < ApplicationRecord errors[:person_id] << "stop blocking yourself!" end end + + # @return [Array] The recipient of the block + def subscribers + [person] + end end diff --git a/lib/diaspora/federated/contact_retraction.rb b/lib/diaspora/federated/contact_retraction.rb index 57efd2f45..69ec85f7f 100644 --- a/lib/diaspora/federated/contact_retraction.rb +++ b/lib/diaspora/federated/contact_retraction.rb @@ -6,11 +6,11 @@ class ContactRetraction < Retraction end def self.retraction_data_for(target) - Diaspora::Federation::Entities.contact(target).to_h + Diaspora::Federation::Entities.build(target).to_h end def self.for(target) - target.receiving = false + target.receiving = false if target.is_a?(Contact) super end diff --git a/lib/diaspora/federation/entities.rb b/lib/diaspora/federation/entities.rb index e6dbff2a0..f8d8aa1a5 100644 --- a/lib/diaspora/federation/entities.rb +++ b/lib/diaspora/federation/entities.rb @@ -31,6 +31,16 @@ module Diaspora ) end + def self.block(block) + DiasporaFederation::Entities::Contact.new( + author: block.user.diaspora_handle, + recipient: block.person.diaspora_handle, + sharing: false, + following: false, + blocking: Block.exists?(user: block.user, person: block.person) + ) + end + def self.comment(comment) DiasporaFederation::Entities::Comment.new( { @@ -52,7 +62,8 @@ module Diaspora author: contact.user.diaspora_handle, recipient: contact.person.diaspora_handle, sharing: contact.receiving, - following: contact.receiving + following: contact.receiving, + blocking: Block.exists?(user: contact.user, person: contact.person) ) end diff --git a/lib/diaspora/federation/mappings.rb b/lib/diaspora/federation/mappings.rb index 91ccefee6..ac10929c5 100644 --- a/lib/diaspora/federation/mappings.rb +++ b/lib/diaspora/federation/mappings.rb @@ -29,6 +29,7 @@ module Diaspora case diaspora_entity when AccountMigration then :account_migration when AccountDeletion then :account_deletion + when Block then :block when Comment then :comment when Contact then :contact when Conversation then :conversation diff --git a/spec/controllers/blocks_controller_spec.rb b/spec/controllers/blocks_controller_spec.rb index b3d7b1567..11acfdccb 100644 --- a/spec/controllers/blocks_controller_spec.rb +++ b/spec/controllers/blocks_controller_spec.rb @@ -17,8 +17,8 @@ describe BlocksController, :type => :controller do expect(response.status).to eq(204) end - it "calls #disconnect_if_contact" do - expect(@controller).to receive(:disconnect_if_contact).with(bob.person) + it "calls #send_message" do + expect(@controller).to receive(:send_message).with(an_instance_of(Block)) post :create, params: {block: {person_id: bob.person.id}}, format: :json end end @@ -38,6 +38,13 @@ describe BlocksController, :type => :controller do expect(flash[:notice]).to eq(I18n.t("blocks.destroy.success")) end + it "sends a message" do + retraction = double + expect(ContactRetraction).to receive(:for).with(@block).and_return(retraction) + expect(retraction).to receive(:defer_dispatch).with(alice) + delete :destroy, params: {id: @block.id} + end + it "responds with 204 with json" do delete :destroy, params: {id: @block.id}, format: :json expect(response.status).to eq(204) @@ -60,21 +67,32 @@ describe BlocksController, :type => :controller do end end - describe "#disconnect_if_contact" do + describe "#send_message" do before do allow(@controller).to receive(:current_user).and_return(alice) end - it "calls disconnect with the force option if there is a contact for a given user" do + it "calls disconnect if there is a contact for a given user" do + block = alice.blocks.create(person: bob.person) contact = alice.contact_for(bob.person) - allow(alice).to receive(:contact_for).and_return(contact) + expect(alice).to receive(:contact_for).and_return(contact) expect(alice).to receive(:disconnect).with(contact) - @controller.send(:disconnect_if_contact, bob.person) + expect(Diaspora::Federation::Dispatcher).not_to receive(:defer_dispatch) + @controller.send(:send_message, block) end - it "doesn't call disconnect if there is a contact for a given user" do + it "queues a message with the block if the person is remote and there is no contact for a given user" do + block = alice.blocks.create(person: remote_raphael) expect(alice).not_to receive(:disconnect) - @controller.send(:disconnect_if_contact, eve.person) + expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, block) + @controller.send(:send_message, block) + end + + it "does nothing if the person is local and there is no contact for a given user" do + block = alice.blocks.create(person: eve.person) + expect(alice).not_to receive(:disconnect) + expect(Diaspora::Federation::Dispatcher).not_to receive(:defer_dispatch) + @controller.send(:send_message, block) end end end diff --git a/spec/lib/diaspora/federation/entities_spec.rb b/spec/lib/diaspora/federation/entities_spec.rb index 0b80c1cc8..c0ab1aff8 100644 --- a/spec/lib/diaspora/federation/entities_spec.rb +++ b/spec/lib/diaspora/federation/entities_spec.rb @@ -56,6 +56,19 @@ describe Diaspora::Federation::Entities do expect(federation_entity.recipient).to eq(diaspora_entity.person.diaspora_handle) expect(federation_entity.sharing).to be_truthy expect(federation_entity.following).to be_truthy + expect(federation_entity.blocking).to be_falsey + end + + it "builds a contact for a block" do + diaspora_entity = FactoryGirl.create(:block) + federation_entity = described_class.build(diaspora_entity) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Contact) + expect(federation_entity.author).to eq(diaspora_entity.user.diaspora_handle) + expect(federation_entity.recipient).to eq(diaspora_entity.person.diaspora_handle) + expect(federation_entity.sharing).to be_falsey + expect(federation_entity.following).to be_falsey + expect(federation_entity.blocking).to be_truthy end context "Conversation" do @@ -237,6 +250,35 @@ describe Diaspora::Federation::Entities do expect(federation_entity.recipient).to eq(target.person.diaspora_handle) expect(federation_entity.sharing).to be_falsey expect(federation_entity.following).to be_falsey + expect(federation_entity.blocking).to be_falsey + end + + it "builds a Contact for a Contact retraction with block" do + target = FactoryGirl.create(:contact, receiving: false) + FactoryGirl.create(:block, user: target.user, person: target.person) + retraction = ContactRetraction.for(target) + federation_entity = described_class.build(retraction) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Contact) + expect(federation_entity.author).to eq(target.user.diaspora_handle) + expect(federation_entity.recipient).to eq(target.person.diaspora_handle) + expect(federation_entity.sharing).to be_falsey + expect(federation_entity.following).to be_falsey + expect(federation_entity.blocking).to be_truthy + end + + it "builds a Contact for a Block retraction" do + target = FactoryGirl.create(:block) + target.delete + retraction = ContactRetraction.for(target) + federation_entity = described_class.build(retraction) + + expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Contact) + expect(federation_entity.author).to eq(target.user.diaspora_handle) + expect(federation_entity.recipient).to eq(target.person.diaspora_handle) + expect(federation_entity.sharing).to be_falsey + expect(federation_entity.following).to be_falsey + expect(federation_entity.blocking).to be_falsey end end diff --git a/spec/models/block_spec.rb b/spec/models/block_spec.rb index e3ee01c42..27f12848e 100644 --- a/spec/models/block_spec.rb +++ b/spec/models/block_spec.rb @@ -1,10 +1,17 @@ # frozen_string_literal: true -describe Block, :type => :model do +describe Block, type: :model do describe "validations" do it "doesnt allow you to block yourself" do block = alice.blocks.create(person: alice.person) expect(block.errors[:person_id].size).to eq(1) end end + + describe "#subscribers" do + it "returns an array with recipient of the block" do + block = alice.blocks.create(person: eve.person) + expect(block.subscribers).to match_array([eve.person]) + end + end end