From 17774d8b3b94ab0f3c6917c65d30552959fa387e Mon Sep 17 00:00:00 2001
From: Raphael Sofaer <raphael@joindiaspora.com>
Date: Thu, 21 Jul 2011 19:15:47 -0700
Subject: [PATCH] Getting repost back to almost green.

---
 app/models/signed_retraction.rb          | 94 ++++++++++++++++++++++++
 features/step_definitions/oauth_steps.rb |  4 +
 lib/tasks/db.rake                        |  2 +-
 spec/models/reshare_spec.rb              |  8 +-
 spec/models/user_spec.rb                 | 16 ++--
 spec/multi_server/repost_spec.rb         |  2 +-
 spec/support/server.rb                   |  2 +-
 7 files changed, 113 insertions(+), 15 deletions(-)
 create mode 100644 app/models/signed_retraction.rb

diff --git a/app/models/signed_retraction.rb b/app/models/signed_retraction.rb
new file mode 100644
index 0000000000..75a4e54777
--- /dev/null
+++ b/app/models/signed_retraction.rb
@@ -0,0 +1,94 @@
+#   Copyright (c) 2010, Diaspora Inc.  This file is
+#   licensed under the Affero General Public License version 3 or later.  See
+#   the COPYRIGHT file.
+
+class SignedRetraction
+  include ROXML
+  include Diaspora::Webhooks
+  include Diaspora::Encryptable
+
+  xml_name :signed_retraction
+  xml_attr :target_guid
+  xml_attr :target_type
+  xml_attr :sender_handle
+  xml_attr :target_author_signature
+
+  attr_accessor :target_guid,
+                :target_type,
+                :target_author_signature,
+                :sender
+
+  def signable_accessors
+      accessors = self.class.roxml_attrs.collect do |definition|
+        definition.accessor
+      end
+      accessors - ['target_author_signature']
+  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.target.diaspora_handle
+  end
+
+  def subscribers(user)
+    self.target.subscribers(user)
+  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
+  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 perform receiving_user
+    Rails.logger.debug "Performing retraction for #{target_guid}"
+    puts "Performing retraction for #{target_guid}"
+    if reshare = Reshare.where(:author_id => receiving_user.person.id, :root_id => target.id).first
+      Postzord::Dispatch.new(receiving_user, self).post
+    end
+    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
+
+  def receive(recipient, sender)
+    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.target_author_signature_valid?
+      #this is a retraction from the upstream owner
+      self.perform(recipient)
+    else
+      Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{recipient.diaspora_handle} sender=#{self.parent.author.diaspora_handle} payload_type=#{self.class} parent_id=#{self.parent.id}")
+      return
+    end
+    self
+  end
+
+  def target_author_signature_valid?
+    verify_signature(self.target_author_signature, self.target.author)
+  end
+end
+
diff --git a/features/step_definitions/oauth_steps.rb b/features/step_definitions/oauth_steps.rb
index a14d83db75..444648fc32 100644
--- a/features/step_definitions/oauth_steps.rb
+++ b/features/step_definitions/oauth_steps.rb
@@ -71,6 +71,10 @@ class Chubbies
     end
   end
 
+  def self.nullify
+    "2> /dev/null > /dev/null"
+  end
+
   def self.kill
     `kill -9 #{get_pid}`
   end
diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake
index 77b35bc085..705d12fed9 100644
--- a/lib/tasks/db.rake
+++ b/lib/tasks/db.rake
@@ -85,7 +85,7 @@ namespace :db do
     ActiveRecord::Base.configurations.keys.select{ |k|
       k.include?("integration")
     }.each{ |k|
-      drop_database ActiveRecord::Base.configurations[k]
+      drop_database ActiveRecord::Base.configurations[k] rescue Mysql2::Error
     }
   end
 
diff --git a/spec/models/reshare_spec.rb b/spec/models/reshare_spec.rb
index 02a74db0af..cc24ef8e99 100644
--- a/spec/models/reshare_spec.rb
+++ b/spec/models/reshare_spec.rb
@@ -49,19 +49,19 @@ describe Reshare do
 
     context 'serialization' do
       it 'serializes root_diaspora_id' do
-        @xml.should include("root_diaspora_id")  
+        @xml.should include("root_diaspora_id")
       end
 
       it 'serializes root_guid' do
-        @xml.should include("root_guid")  
+        @xml.should include("root_guid")
       end
     end
 
     context 'marshalling' do
       context 'local' do
         before do
-          @original_author = @reshare.root.author.dup
-          @root_object = @reshare.root.dup
+          @original_author = @reshare.root.author
+          @root_object = @reshare.root
         end
 
         it 'fetches the root post from root_guid' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index f8c7fdaf7c..b71da5ee63 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -114,13 +114,13 @@ describe User do
         alice.email = eve.email
         alice.should_not be_valid
       end
-      
+
       it "requires a vaild email address" do
         alice.email = "somebody@anywhere"
         alice.should_not be_valid
       end
     end
-    
+
     describe "of unconfirmed_email" do
       it "unconfirmed_email address can be nil/blank" do
         alice.unconfirmed_email = nil
@@ -134,7 +134,7 @@ describe User do
         alice.unconfirmed_email = "new@email.com"
         alice.should be_valid
       end
-      
+
       it "requires a vaild unconfirmed_email address" do
         alice.unconfirmed_email = "somebody@anywhere"
         alice.should_not be_valid
@@ -679,7 +679,7 @@ describe User do
         user.confirm_email_token.size.should eql(30)
       end
     end
-    
+
     describe '#mail_confirm_email' do
       it 'enqueues a mail job on user with unconfirmed email' do
         user.update_attribute(:unconfirmed_email, "alice@newmail.com")
@@ -712,14 +712,14 @@ describe User do
           user.unconfirmed_email.should_not eql(nil)
           user.confirm_email_token.should_not eql(nil)
         end
-        
+
         it 'returns false and does not change anything on blank token' do
           user.confirm_email("").should eql(false)
           user.email.should_not eql("alice@newmail.com")
           user.unconfirmed_email.should_not eql(nil)
           user.confirm_email_token.should_not eql(nil)
         end
-        
+
         it 'returns false and does not change anything on blank token' do
           user.confirm_email(nil).should eql(false)
           user.email.should_not eql("alice@newmail.com")
@@ -803,8 +803,8 @@ describe User do
 
         dis = mock
         dis_2 = mock
-        dis.should_receive(:post)
-        dis_2.should_receive(:post)
+        dis.should_receive(:post).and_return{ r_ret.perform(@post.reshares.first.author.owner)}
+        #dis_2.should_receive(:post)
         Postzord::Dispatch.should_receive(:new).with(bob, r_ret, anything()).and_return(dis, dis_2)
 
         fantasy_resque do
diff --git a/spec/multi_server/repost_spec.rb b/spec/multi_server/repost_spec.rb
index c8ea9f535b..39bacb1641 100644
--- a/spec/multi_server/repost_spec.rb
+++ b/spec/multi_server/repost_spec.rb
@@ -19,7 +19,7 @@ unless Server.all.empty?
       WebMock::Config.instance.allow_localhost = false
     end
     before do
-      Server.all.each{|s| s.truncate_database; puts "Truncating database for server #{s}" }
+      Server.all.each{|s| s.truncate_database; }
       @original_post = nil
       Server[0].in_scope do
         original_poster = Factory.create(:user_with_aspect, :username => "original_poster")
diff --git a/spec/support/server.rb b/spec/support/server.rb
index 898a7614ab..0432247526 100644
--- a/spec/support/server.rb
+++ b/spec/support/server.rb
@@ -34,7 +34,7 @@ class Server
 
   def run
     @pid = fork do
-      Process.exec "cd #{Rails.root} && RAILS_ENV=#{@env} bundle exec #{run_command} 2> /dev/null"
+      Process.exec "cd #{Rails.root} && RAILS_ENV=#{@env} bundle exec #{run_command}"# 2> /dev/null"
     end
   end
 
-- 
GitLab