More work on retracting posts with reshares, one failing spec on User#retract

This commit is contained in:
Raphael Sofaer 2011-07-20 19:00:28 -07:00
parent 7382dfb7be
commit a1bf22fe7e
6 changed files with 52 additions and 97 deletions

View file

@ -2,81 +2,28 @@
# licensed under the Affero General Public License version 3 or later. See # licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file. # the COPYRIGHT file.
class RelayableRetraction class RelayableRetraction < SignedRetraction
include ROXML
include Diaspora::Webhooks
include Diaspora::Encryptable
xml_name :relayable_retraction xml_name :relayable_retraction
xml_attr :target_guid
xml_attr :target_type
xml_attr :sender_handle
xml_attr :parent_author_signature xml_attr :parent_author_signature
xml_attr :target_author_signature
attr_accessor :target_guid, attr_accessor :parent_author_signature
:target_type,
:parent_author_signature,
:target_author_signature,
:sender
def signable_accessors def signable_accessors
accessors = self.class.roxml_attrs.collect do |definition| super - ['parent_author_signature']
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)
end end
def self.build(sender, target) def self.build(sender, target)
retraction = self.new retraction = super
retraction.sender = sender
retraction.target = target
retraction.target_author_signature = retraction.sign_with_key(sender.encryption_key) if sender.person == target.author
retraction.parent_author_signature = retraction.sign_with_key(sender.encryption_key) if defined?(target.parent) && sender.person == target.parent.author retraction.parent_author_signature = retraction.sign_with_key(sender.encryption_key) if defined?(target.parent) && sender.person == target.parent.author
retraction retraction
end 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 def parent
self.target.parent self.target.parent
end end
def perform receiving_user def diaspora_handle
Rails.logger.debug "Performing retraction for #{target_guid}" self.sender_handle
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)
end end
def receive(recipient, sender) def receive(recipient, sender)
@ -101,8 +48,4 @@ class RelayableRetraction
def parent_author_signature_valid? def parent_author_signature_valid?
verify_signature(self.parent_author_signature, self.parent.author) verify_signature(self.parent_author_signature, self.parent.author)
end end
def target_author_signature_valid?
verify_signature(self.target_author_signature, self.target.author)
end
end end

View file

@ -3,6 +3,7 @@ class Reshare < Post
belongs_to :root, :class_name => 'Post' belongs_to :root, :class_name => 'Post'
validate :root_must_be_public validate :root_must_be_public
attr_accessible :root_id, :public attr_accessible :root_id, :public
validates_presence_of :root, :on => :create
xml_attr :root_diaspora_id xml_attr :root_diaspora_id
xml_attr :root_guid xml_attr :root_guid
@ -61,7 +62,7 @@ class Reshare < Post
end end
def root_must_be_public def root_must_be_public
if !self.root.public if self.root && !self.root.public
errors[:base] << "you must reshare public posts" errors[:base] << "you must reshare public posts"
return false return false
end end

View file

@ -233,26 +233,19 @@ class User < ActiveRecord::Base
def retract(target, opts={}) def retract(target, opts={})
if target.respond_to?(:relayable?) && target.relayable? if target.respond_to?(:relayable?) && target.relayable?
retraction = RelayableRetraction.build(self, target) retraction = RelayableRetraction.build(self, target)
elsif target.is_a? Post
retraction = SignedRetraction.build(self, target)
else else
retraction = Retraction.for(target) retraction = Retraction.for(target)
end end
if target.is_a?(Post) && target.reshares.size != 0 if target.is_a?(Post)
reshare_retraction = RelayableRetraction.build(self, target) opts[:additional_subscribers] = target.resharers
end end
# if target.is_a?(Post)
# opts[:additional_subscribers] = target.resharers
# end
mailman = Postzord::Dispatch.new(self, retraction, opts) mailman = Postzord::Dispatch.new(self, retraction, opts)
mailman.post mailman.post
if reshare_retraction
mailman = Postzord::Dispatch.new(self, reshare_retraction)
mailman.post
end
retraction.perform(self) retraction.perform(self)
retraction retraction

View file

@ -41,7 +41,7 @@ describe Person do
context 'local people' do context 'local people' do
it 'uses the pod config url to set the diaspora_handle' 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 = 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
end end

View file

@ -760,9 +760,9 @@ describe User do
@post = Factory(:status_message, :author => bob.person, :public => true) @post = Factory(:status_message, :author => bob.person, :public => true)
end end
context "regular retractions" do context "posts" do
before do before do
Retraction.stub(:for).and_return(@retraction) SignedRetraction.stub(:build).and_return(@retraction)
@retraction.stub(:perform) @retraction.stub(:perform)
end end
@ -791,21 +791,25 @@ describe User do
end end
end end
context "relayable retractions" do context "signed retractions" do
before 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! @post.save!
end end
it 'sends a relayable retraction if the object is relayable' do it 'relays the signed retraction onwards to recipients of reshares' do
r_ret = RelayableRetraction.build(bob, @post) r_ret = SignedRetraction.build(bob, @post)
RelayableRetraction.should_receive(:build).and_return(r_ret) SignedRetraction.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)
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 end
end end

View file

@ -18,16 +18,16 @@ unless Server.all.empty?
#Server.all.each{|s| puts "Server at port #{s.port} still running." if s.running?} #Server.all.each{|s| puts "Server at port #{s.port} still running." if s.running?}
WebMock::Config.instance.allow_localhost = false WebMock::Config.instance.allow_localhost = false
end end
before do
it 'fetches the original post from the root server' do Server.all.each{|s| s.truncate_database; puts "Truncating database for server #{s}" }
original_post = nil @original_post = nil
Server[0].in_scope do Server[0].in_scope do
original_poster = Factory.create(:user_with_aspect, :username => "original_poster") original_poster = Factory.create(:user_with_aspect, :username => "original_poster")
resharer = Factory.create(:user_with_aspect, :username => "resharer") resharer = Factory.create(:user_with_aspect, :username => "resharer")
connect_users_with_aspects(original_poster, resharer) connect_users_with_aspects(original_poster, resharer)
original_post = original_poster.post(:status_message, @original_post = original_poster.post(:status_message,
:public => true, :public => true,
:text => "Awesome Sauce!", :text => "Awesome Sauce!",
:to => 'all') :to => 'all')
@ -50,14 +50,28 @@ unless Server.all.empty?
Server[0].in_scope do Server[0].in_scope do
r = User.find_by_username("resharer") r = User.find_by_username("resharer")
r.post(:reshare, :root_id => original_post.id, :to => 'all') r.post(:reshare, :root_id => @original_post.id, :to => 'all')
debugger 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 end
Server[1].in_scope do 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
end end
end end