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
# 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

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?}
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