Relayable retractions pretty much done
This commit is contained in:
parent
31f43696cb
commit
b9af450628
5 changed files with 115 additions and 46 deletions
|
|
@ -24,8 +24,6 @@ class Post < ActiveRecord::Base
|
|||
cattr_reader :per_page
|
||||
@@per_page = 10
|
||||
|
||||
after_destroy :propogate_retraction
|
||||
|
||||
def user_refs
|
||||
self.post_visibilities.count
|
||||
end
|
||||
|
|
@ -93,10 +91,5 @@ class Post < ActiveRecord::Base
|
|||
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason='update not from post owner' existing_post=#{self.id}")
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def propogate_retraction
|
||||
self.author.owner.retract(self) if self.author.owner
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
class RelayableRetraction
|
||||
include ROXML
|
||||
include Diaspora::Webhooks
|
||||
include Diaspora::Encryptable
|
||||
|
||||
xml_attr :target_guid
|
||||
xml_attr :target_type
|
||||
|
|
@ -18,6 +19,16 @@ class RelayableRetraction
|
|||
:target_author_signature,
|
||||
:sender
|
||||
|
||||
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
|
||||
|
|
@ -27,18 +38,25 @@ class RelayableRetraction
|
|||
end
|
||||
|
||||
def subscribers(user)
|
||||
@subscribers ||= self.target.subscribers(user)
|
||||
self.target.subscribers(user)
|
||||
end
|
||||
|
||||
def self.initialize(sender, target)
|
||||
self.sender = sender
|
||||
self.target = target
|
||||
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.parent_author_signature = retraction.sign_with_key(sender.encryption_key) if 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
|
||||
|
|
@ -49,20 +67,18 @@ class RelayableRetraction
|
|||
self.target.parent
|
||||
end
|
||||
|
||||
def parent_class
|
||||
self.target.parent_class
|
||||
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
|
||||
target.post_visibilities.delete_all
|
||||
Rails.logger.info("event=retraction status=complete target_type=#{self.target_type} guid=#{self.target_guid}")
|
||||
Rails.logger.info(:event => :retraction, :status => :complete, :target_type => self.target_type, :guid => self.target_guid)
|
||||
end
|
||||
|
||||
def receive(recipient, sender)
|
||||
if self.parent.author == recipient.person && self.target_author_signature_valid?
|
||||
if self.target.nil?
|
||||
Rails.logger.info("event=retraction status=abort reason='no post found' sender=#{sender.diaspora_handle} target_guid=#{target_guid}")
|
||||
return
|
||||
elsif self.parent.author == recipient.person && self.target_author_signature_valid?
|
||||
#this is a retraction from the downstream object creator, and the recipient is the upstream owner
|
||||
self.parent_author_signature = self.sign_with_key(recipient.encryption_key)
|
||||
Postzord::Dispatch.new(recipient, self).post
|
||||
|
|
@ -82,6 +98,6 @@ class RelayableRetraction
|
|||
end
|
||||
|
||||
def target_author_signature_valid?
|
||||
verify_signature(self.target_author_signature, self.author)
|
||||
verify_signature(self.target_author_signature, self.target.author)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -218,14 +218,14 @@ class User < ActiveRecord::Base
|
|||
|
||||
######### Posts and Such ###############
|
||||
def retract(post)
|
||||
aspects = post.aspects
|
||||
|
||||
if post.relayable
|
||||
retraction = RelayableRetraction.new(self, post)
|
||||
aspects = post.parent.aspects
|
||||
retraction = RelayableRetraction.build(self, post)
|
||||
else
|
||||
aspects = post.aspects
|
||||
retraction = Retraction.for(post)
|
||||
end
|
||||
post.unsocket_from_user(self, :aspect_ids => aspects.map { |a| a.id.to_s }) if post.respond_to? :unsocket_from_user
|
||||
retraction.perform(self)
|
||||
mailman = Postzord::Dispatch.new(self, retraction)
|
||||
mailman.post
|
||||
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ module Diaspora
|
|||
module Encryptable
|
||||
def verify_signature(signature, person)
|
||||
if person.nil?
|
||||
Rails.logger.info("event=verify_signature status=abort reason=no_person guid=#{self.guid} model_id=#{self.id}")
|
||||
Rails.logger.info("event=verify_signature status=abort reason=no_person guid=#{self.guid}")
|
||||
return false
|
||||
elsif person.public_key.nil?
|
||||
Rails.logger.info("event=verify_signature status=abort reason=no_key guid=#{self.guid} model_id=#{self.id}")
|
||||
Rails.logger.info("event=verify_signature status=abort reason=no_key guid=#{self.guid}")
|
||||
return false
|
||||
elsif signature.nil?
|
||||
Rails.logger.info("event=verify_signature status=abort reason=no_signature guid=#{self.guid} model_id=#{self.id}")
|
||||
Rails.logger.info("event=verify_signature status=abort reason=no_signature guid=#{self.guid}")
|
||||
return false
|
||||
end
|
||||
log_string = "event=verify_signature status=complete model_id=#{id}"
|
||||
log_string = "event=verify_signature status=complete guid=#{self.guid}"
|
||||
validity = person.public_key.verify "SHA", Base64.decode64(signature), signable_string
|
||||
log_string += " validity=#{validity}"
|
||||
Rails.logger.info(log_string)
|
||||
|
|
@ -20,7 +20,9 @@ module Diaspora
|
|||
|
||||
def sign_with_key(key)
|
||||
sig = Base64.encode64(key.sign "SHA", signable_string)
|
||||
Rails.logger.info("event=sign_with_key status=complete model_id=#{id}")
|
||||
log_hash = {:event => :sign_with_key, :status => :complete}
|
||||
log_hash.merge(:model_id => self.id) if self.respond_to?(:persisted?)
|
||||
Rails.logger.info(log_hash)
|
||||
sig
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -10,52 +10,110 @@ describe RelayableRetraction do
|
|||
@local_luke, @local_leia, @remote_raphael = set_up_friends
|
||||
@remote_parent = Factory.create(:status_message, :author => @remote_raphael)
|
||||
@local_parent = @local_luke.post :status_message, :text => "hi", :to => @local_luke.aspects.first
|
||||
@comment_by_parent_author = @local_luke.comment("yo", :on => @local_parent)
|
||||
@retraction_by_parent_author = @local_luke.retract(@comment_by_parent_author)
|
||||
|
||||
@comment_by_recipient = @local_leia.build_comment("yo", :on => @local_parent)
|
||||
@retraction_by_recipient = @local_leia.retract(@comment_by_recipient)
|
||||
|
||||
@comment_on_remote_parent = @local_luke.comment("Yeah, it was great", :on => @remote_parent)
|
||||
@retraction_from_remote_author = RelayableRetraction.new(@remote_raphael, @comment_on_remote_parent)
|
||||
end
|
||||
|
||||
describe '#subscribers' do
|
||||
before do
|
||||
@comment= @local_luke.comment("yo", :on => @local_parent)
|
||||
@retraction= @local_luke.retract(@comment)
|
||||
end
|
||||
it 'delegates it to target' do
|
||||
arg = mock()
|
||||
@retraction_by_parent_author.target.should_receive(:subscribers).with(arg)
|
||||
@retraction_by_parent_author.subscribers(arg)
|
||||
@retraction.target.should_receive(:subscribers).with(arg)
|
||||
@retraction.subscribers(arg)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#receive' do
|
||||
context 'from the downstream author' do
|
||||
it 'signs' do
|
||||
it 'discards a retraction with a nil target' do
|
||||
@comment= @local_luke.comment("yo", :on => @local_parent)
|
||||
@retraction= @local_luke.retract(@comment)
|
||||
|
||||
@retraction.instance_variable_set(:@target, nil)
|
||||
@retraction.target_guid = 135245
|
||||
@retraction.should_not_receive(:perform)
|
||||
@retraction.receive(@local_luke, @remote_raphael)
|
||||
end
|
||||
context 'from the downstream author' do
|
||||
before do
|
||||
@comment = @local_leia.comment("yo", :on => @local_parent)
|
||||
@retraction = @local_leia.retract(@comment)
|
||||
@recipient = @local_luke
|
||||
end
|
||||
it 'signs' do
|
||||
@retraction.should_receive(:sign_with_key) do |key|
|
||||
key.to_s.should == @recipient.encryption_key.to_s
|
||||
end
|
||||
@retraction.receive(@recipient, @comment.author)
|
||||
end
|
||||
it 'dispatches' do
|
||||
|
||||
zord = mock()
|
||||
zord.should_receive(:post)
|
||||
Postzord::Dispatch.should_receive(:new).with(@local_luke, @retraction).and_return zord
|
||||
@retraction.receive(@recipient, @comment.author)
|
||||
end
|
||||
it 'performs' do
|
||||
|
||||
@retraction.should_receive(:perform).with(@local_luke)
|
||||
@retraction.receive(@recipient, @comment.author)
|
||||
end
|
||||
end
|
||||
context 'from the upstream owner' do
|
||||
before do
|
||||
@comment = @local_luke.comment("Yeah, it was great", :on => @remote_parent)
|
||||
@retraction = RelayableRetraction.allocate
|
||||
@retraction.sender = @remote_raphael
|
||||
@retraction.target = @comment
|
||||
@retraction.stub!(:parent_author_signature_valid?).and_return(true)
|
||||
@recipient = @local_luke
|
||||
end
|
||||
it 'performs' do
|
||||
|
||||
@retraction.should_receive(:perform).with(@recipient)
|
||||
@retraction.receive(@recipient, @remote_raphael)
|
||||
end
|
||||
it 'does not dispatch' do
|
||||
|
||||
Postzord::Dispatch.should_not_receive(:new)
|
||||
@retraction.receive(@recipient, @remote_raphael)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'xml' do
|
||||
before do
|
||||
@comment = @local_leia.comment("yo", :on => @local_parent)
|
||||
@retraction = RelayableRetraction.build(@local_leia, @comment)
|
||||
@retraction.parent_author_signature = 'PARENTSIGNATURE'
|
||||
@retraction.target_author_signature = 'TARGETSIGNATURE'
|
||||
@xml = @retraction.to_xml.to_s
|
||||
end
|
||||
describe '#to_xml' do
|
||||
|
||||
it 'serializes target_guid' do
|
||||
@xml.should include(@comment.guid)
|
||||
end
|
||||
it 'serializes target_type' do
|
||||
@xml.should include(@comment.class.to_s)
|
||||
end
|
||||
it 'serializes sender_handle' do
|
||||
@xml.should include(@local_leia.diaspora_handle)
|
||||
end
|
||||
it 'serializes signatures' do
|
||||
@xml.should include('TARGETSIGNATURE')
|
||||
@xml.should include('PARENTSIGNATURE')
|
||||
end
|
||||
end
|
||||
describe '.from_xml' do
|
||||
|
||||
before do
|
||||
@marshalled = RelayableRetraction.from_xml(@xml)
|
||||
end
|
||||
it 'marshals the target' do
|
||||
@marshalled.target.should == @comment
|
||||
end
|
||||
it 'marshals the sender' do
|
||||
@marshalled.sender.should == @local_leia.person
|
||||
end
|
||||
it 'marshals the signature' do
|
||||
@marshalled.target_author_signature.should == 'TARGETSIGNATURE'
|
||||
@marshalled.parent_author_signature.should == 'PARENTSIGNATURE'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue