diff --git a/app/models/relayable_retraction.rb b/app/models/relayable_retraction.rb index 554f678ad..d2218af68 100644 --- a/app/models/relayable_retraction.rb +++ b/app/models/relayable_retraction.rb @@ -2,81 +2,28 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -class RelayableRetraction - include ROXML - include Diaspora::Webhooks - include Diaspora::Encryptable - +class RelayableRetraction < SignedRetraction xml_name :relayable_retraction - xml_attr :target_guid - xml_attr :target_type - xml_attr :sender_handle xml_attr :parent_author_signature - xml_attr :target_author_signature - attr_accessor :target_guid, - :target_type, - :parent_author_signature, - :target_author_signature, - :sender + attr_accessor :parent_author_signature def signable_accessors - accessors = self.class.roxml_attrs.collect do |definition| - definition.accessor - end - ['target_author_signature', 'parent_author_signature'].each do |acc| - accessors.delete acc - end - accessors - end - - def sender_handle= new_sender_handle - @sender = Person.where(:diaspora_handle => new_sender_handle).first - end - - def sender_handle - @sender.diaspora_handle - end - - def diaspora_handle - self.sender_handle - end - - def subscribers(user) - self.target.subscribers(user) + super - ['parent_author_signature'] end def self.build(sender, target) - retraction = self.new - retraction.sender = sender - retraction.target = target - retraction.target_author_signature = retraction.sign_with_key(sender.encryption_key) if sender.person == target.author + retraction = super retraction.parent_author_signature = retraction.sign_with_key(sender.encryption_key) if defined?(target.parent) && sender.person == target.parent.author retraction end - def target - @target ||= self.target_type.constantize.where(:guid => target_guid).first - end - - def guid - target_guid - end - def target= new_target - @target = new_target - @target_type = new_target.class.to_s - @target_guid = new_target.guid - end - def parent self.target.parent end - def perform receiving_user - Rails.logger.debug "Performing retraction for #{target_guid}" - self.target.unsocket_from_user receiving_user if target.respond_to? :unsocket_from_user - self.target.destroy - Rails.logger.info(:event => :retraction, :status => :complete, :target_type => self.target_type, :guid => self.target_guid) + def diaspora_handle + self.sender_handle end def receive(recipient, sender) @@ -101,8 +48,4 @@ class RelayableRetraction def parent_author_signature_valid? verify_signature(self.parent_author_signature, self.parent.author) end - - def target_author_signature_valid? - verify_signature(self.target_author_signature, self.target.author) - end end diff --git a/app/models/reshare.rb b/app/models/reshare.rb index 80bbeb47f..72e3ccbca 100644 --- a/app/models/reshare.rb +++ b/app/models/reshare.rb @@ -3,6 +3,7 @@ class Reshare < Post belongs_to :root, :class_name => 'Post' validate :root_must_be_public attr_accessible :root_id, :public + validates_presence_of :root, :on => :create xml_attr :root_diaspora_id xml_attr :root_guid @@ -61,7 +62,7 @@ class Reshare < Post end def root_must_be_public - if !self.root.public + if self.root && !self.root.public errors[:base] << "you must reshare public posts" return false end diff --git a/app/models/user.rb b/app/models/user.rb index a37445555..fdd391b7f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -233,26 +233,19 @@ class User < ActiveRecord::Base def retract(target, opts={}) if target.respond_to?(:relayable?) && target.relayable? retraction = RelayableRetraction.build(self, target) + elsif target.is_a? Post + retraction = SignedRetraction.build(self, target) else retraction = Retraction.for(target) end - if target.is_a?(Post) && target.reshares.size != 0 - reshare_retraction = RelayableRetraction.build(self, target) - end - -# if target.is_a?(Post) -# opts[:additional_subscribers] = target.resharers -# end + if target.is_a?(Post) + opts[:additional_subscribers] = target.resharers + end mailman = Postzord::Dispatch.new(self, retraction, opts) mailman.post - if reshare_retraction - mailman = Postzord::Dispatch.new(self, reshare_retraction) - mailman.post - end - retraction.perform(self) retraction diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index b58bc862b..b1def8023 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -41,7 +41,7 @@ describe Person do context 'local people' do it 'uses the pod config url to set the diaspora_handle' do new_person = User.build(:username => "foo123", :email => "foo123@example.com", :password => "password", :password_confirmation => "password").person - new_person.diaspora_handle.should == "foo123@#{AppConfig[:pod_uri].host}" + new_person.diaspora_handle.should == "foo123@#{AppConfig[:pod_uri].authority}" end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 23a25a49b..f8c7fdaf7 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -760,9 +760,9 @@ describe User do @post = Factory(:status_message, :author => bob.person, :public => true) end - context "regular retractions" do + context "posts" do before do - Retraction.stub(:for).and_return(@retraction) + SignedRetraction.stub(:build).and_return(@retraction) @retraction.stub(:perform) end @@ -791,21 +791,25 @@ describe User do end end - context "relayable retractions" do + context "signed retractions" do before do - @post.reshares << Factory.create(:reshare, :author => remote_raphael) + @post.reshares << Factory.create(:reshare,:root_id => @post.id, :author => Factory(:user).person) @post.save! end - it 'sends a relayable retraction if the object is relayable' do - r_ret = RelayableRetraction.build(bob, @post) - RelayableRetraction.should_receive(:build).and_return(r_ret) - - dis = mock - dis.should_receive(:post) - Postzord::Dispatch.should_receive(:new).with(bob, r_ret).and_return(dis) + it 'relays the signed retraction onwards to recipients of reshares' do + r_ret = SignedRetraction.build(bob, @post) + SignedRetraction.should_receive(:build).and_return(r_ret) - bob.retract(@post) + dis = mock + dis_2 = mock + dis.should_receive(:post) + dis_2.should_receive(:post) + Postzord::Dispatch.should_receive(:new).with(bob, r_ret, anything()).and_return(dis, dis_2) + + fantasy_resque do + bob.retract(@post) + end end end end diff --git a/spec/multi_server/repost_spec.rb b/spec/multi_server/repost_spec.rb index 48577eb4c..c8ea9f535 100644 --- a/spec/multi_server/repost_spec.rb +++ b/spec/multi_server/repost_spec.rb @@ -18,16 +18,16 @@ unless Server.all.empty? #Server.all.each{|s| puts "Server at port #{s.port} still running." if s.running?} WebMock::Config.instance.allow_localhost = false end - - it 'fetches the original post from the root server' do - original_post = nil + before do + Server.all.each{|s| s.truncate_database; puts "Truncating database for server #{s}" } + @original_post = nil Server[0].in_scope do original_poster = Factory.create(:user_with_aspect, :username => "original_poster") resharer = Factory.create(:user_with_aspect, :username => "resharer") connect_users_with_aspects(original_poster, resharer) - original_post = original_poster.post(:status_message, + @original_post = original_poster.post(:status_message, :public => true, :text => "Awesome Sauce!", :to => 'all') @@ -50,14 +50,28 @@ unless Server.all.empty? Server[0].in_scope do r = User.find_by_username("resharer") - r.post(:reshare, :root_id => original_post.id, :to => 'all') - debugger + r.post(:reshare, :root_id => @original_post.id, :to => 'all') + end + end + + it 'fetches the original post from the root server' do + Server[1].in_scope do + Post.exists?(:guid => @original_post.guid).should be_true + end + end + + it 'relays the retraction for the root post to recipients of the reshare' do + Server[0].in_scope do + poster = User.find_by_username 'original_poster' + fantasy_resque do + poster.retract @original_post + end end Server[1].in_scope do - Post.exists?(:guid => original_post.guid).should be_true + Post.exists?(:guid => @original_post.guid).should be_false end - end + end end