From 2d5d3a2f2daae52f81a543011242fa3c737fb62d Mon Sep 17 00:00:00 2001
From: Raphael <raphael@joindiaspora.com>
Date: Thu, 15 Jul 2010 13:29:21 -0700
Subject: [PATCH] commit more often

---
 app/models/comment.rb                       |  39 +++++++-
 app/models/post.rb                          |  54 ++++-------
 db/seeds/request.rb                         |   6 ++
 gpg/diaspora-test/pubring.gpg               | Bin 37824 -> 38446 bytes
 gpg/diaspora-test/secring.gpg               | Bin 1332 -> 2006 bytes
 gpg/diaspora-test/trustdb.gpg               | Bin 1520 -> 1600 bytes
 lib/encryptable.rb                          |  33 +++++++
 spec/controllers/publics_controller_spec.rb |   2 +-
 spec/models/person_spec.rb                  |   1 +
 spec/spec_helper.rb                         |   9 +-
 spec/user_encryption_spec.rb                |  99 +++++++++++++++-----
 11 files changed, 173 insertions(+), 70 deletions(-)
 create mode 100644 db/seeds/request.rb
 create mode 100644 lib/encryptable.rb

diff --git a/app/models/comment.rb b/app/models/comment.rb
index b1cdc493b9..67918dd96b 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -2,12 +2,13 @@ class Comment
   include MongoMapper::Document
   include ROXML
   include Diaspora::Webhooks
-
+  include Encryptable
   
   xml_accessor :text
   xml_accessor :person, :as => Person
   xml_accessor :post_id
   
+  
   key :text, String
   timestamps!
   
@@ -25,10 +26,42 @@ class Comment
     (self.message == other.message) && (self.person.email == other.person.email)
   end
   
+  #ENCRYPTION
   
-  protected
+  before_validation :sign_if_mine, :sign_if_my_post
+  validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature}
   
-  def send_people_comments_on_my_posts
+  xml_accessor :creator_signature
+  key :creator_signature, String
+  key :post_creator_signature, String
+
+  def signable_accessors
+    accessors = self.class.roxml_attrs.collect{|definition| 
+      definition.accessor}
+    accessors.delete 'person'
+    accessors.delete 'creator_signature'
+    accessors.delete 'post_creator_signature'
+    accessors
+  end
+
+  def signable_string
+    signable_accessors.collect{|accessor| 
+      (self.send accessor.to_sym).to_s}.join ';'
+  end
+
+    def verify_post_creator_signature
+    verify_signature(post_creator_signature, post.person)
+  end
+  
+  
+  protected
+   def sign_if_my_post
+    if self.post.person == User.owner
+      self.post_creator_signature = sign
+    end
+  end 
+ 
+   def send_people_comments_on_my_posts
     if User.owner.mine?(self.post) && !(self.person.is_a? User)
       self.push_to(self.post.people_with_permissions)
     end
diff --git a/app/models/post.rb b/app/models/post.rb
index a4d710f191..9b711d6ce7 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -4,9 +4,9 @@ class Post
   include MongoMapper::Document
   include ROXML
   include Diaspora::Webhooks
+  include Encryptable
 
   xml_accessor :_id
-  xml_accessor :owner_signature
   xml_accessor :person, :as => Person
 
   key :person_id, ObjectId
@@ -44,45 +44,27 @@ class Post
   end
 
 #ENCRYPTION
-  
   before_validation :sign_if_mine
-  validates_true_for :owner_signature, :logic => lambda {self.verify_signature}
-  
-  key :owner_signature, String
-  
-  def signable_accessors
-    accessors = self.class.roxml_attrs.collect{|definition| 
-      definition.accessor}
-    accessors.delete 'person'
-    accessors.delete 'owner_signature'
-    accessors
-  end
-
-  def signable_string
-    signable_accessors.collect{|accessor| 
-      (self.send accessor.to_sym).to_s}.join ';'
-  end
+    validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature}
+    
+    xml_accessor :creator_signature
+    key :creator_signature, String
+    
+    def signable_accessors
+      accessors = self.class.roxml_attrs.collect{|definition| 
+        definition.accessor}
+      accessors.delete 'person'
+      accessors.delete 'creator_signature'
+      accessors
+    end
 
-  def verify_signature
-    return false unless owner_signature && person.key_fingerprint
-    validity = nil
-    GPGME::verify(owner_signature, signable_string, 
-      {:armor => true, :always_trust => true}){ |signature|
-        validity =  signature.status == GPGME::GPG_ERR_NO_ERROR &&
-          signature.fpr == person.key_fingerprint
-    }
-    return validity
-  end
-  
-  protected
-  def sign_if_mine
-    if self.person == User.owner
-      self.owner_signature = GPGME::sign(signable_string,nil,
-        {:armor=> true, :mode => GPGME::SIG_MODE_DETACH})
+    def signable_string
+      signable_accessors.collect{|accessor| 
+        (self.send accessor.to_sym).to_s}.join ';'
     end
-  end
 
-  def destroy_comments
+protected
+   def destroy_comments
     comments.each{|c| c.destroy}
   end
   
diff --git a/db/seeds/request.rb b/db/seeds/request.rb
new file mode 100644
index 0000000000..b0c652ca85
--- /dev/null
+++ b/db/seeds/request.rb
@@ -0,0 +1,6 @@
+
+require 'config/environment'
+
+Request.all.each{|r| 
+  User.owner.accept_friend_request(r.id)
+}
diff --git a/gpg/diaspora-test/pubring.gpg b/gpg/diaspora-test/pubring.gpg
index 46e8a37d1e84b145278442b92bfe4314e1562434..6949770abe15219a8dcf14b912cd2644bb33bfae 100644
GIT binary patch
delta 587
zcmV-R0<`_Wrvk350<gf7f0*I~Og=t>5dr|0qY0$kdxdzTE6fSs<V%@j{w)?B!y-P*
za$lg@`d#De9D{5d&Rn~FWH-s4#biak1dDwWGx-9CZ<z-CsBl97pwXl6S>(WcMRqa|
zALLYdZ%#zKSpoh(mgvSaG5%;4GrrfXJv6VQN=0)e)bVb`G<U#Ie_L{Go7p#=g+<KI
zHre-}^_4)pGMfI`J4IjNXEVf#Se)#A0sIeX0XbS^1fD(f+Ejo=0Aus^2cuPN`3E#&
zdU01dM)|yGQLjvemdExQ;HagQapl}Ohr-^vyDb=N^j<11Rb;e6Q)OdsZe$=va%p95
zWFRPLbaZe!FE3<i8gq1EZggdGEoFFNZE$R5E@N+PFDW2AWo&bkK#m&&K0bnzzzHCK
zqFix^H1BqmfI|SFffQ5bJU@`~KDWd8Za%D15w%100G=yflUwy`3ruLTL3)z>#vFzz
zxQnm?00X#<1WZ0Yf)D}#!5w|QHp|6JRj3MAdABt04O&k#*sJn<L#h|CjHoQC^o3NP
z+|Vke1F7u=SOSw}0&bdsY9+%f{t9(}vmm_9g8%~s0sb&~>Jp@W#o*8tYqV#i`x3Ah
zmm01}y)Z|ilU2w>^jTjcv+(O82+6<SG6<OslP5SIZ`@a58J=>_dd2bBVE%|n1Q-zl
z00{*GOg=t>0vikf3JDORTycmr?{<}H0|1|0O;rypspQg~Zy<YMA-#6DG_9W+0HC1q
Z3RkT}oAQf(M*6E$yIWOPz-O=m00VWo2HgMv

delta 9
RcmZ3thUvg^rVR%s0{|C;1jzsZ

diff --git a/gpg/diaspora-test/secring.gpg b/gpg/diaspora-test/secring.gpg
index 81164ee0e2175f201621b3d36808fc614a4e2428..9f945d3f1e68aac39851a98abd25127a806880bd 100644
GIT binary patch
delta 659
zcmV;E0&M-X3f2#>GzEW@`vgorK7tVf0GFc)q}+Rjc%v)K3E$*PnPdJf79PVQKFe}n
zpxXLf<LexQY#Yv8yM1Ig$)3ezMZN@!eG@bJ0*7yz2K=aSLja)BqwiVdz<fn^G7lf*
zRC#YsM7&u6{y&!J#xpVgXcjZR*Q`A>ucJyub0yUAZpAcrz)*i%a&4R0H=Tt=%+EI2
z_n`HaK)f=V{@FW4U*Tsn#EMv)?0o_J4`~58T4V&CJ@eXBfJFdf^Y#a$Rc!eOG-7&j
zS2;%cyl7FcOof)m_8Q=*rIm5z+&PEB-nzRj7;E%iDlS!I005pWY^j{;f+MpPB~s;}
z+`1oUf%M)BJ+x6mQ)OdsZe$=va%p95WFRPLbaZe!FE3<ib97;DbY*faWq4t2aBO8R
zV{dIQDIh#$Y;$FIXk~I`KxJ%mWiDfHZ9a%%1QQVg03rnfOg=t>li&j&f1+G*h&1nZ
zm4HJ4pn()q<~%=;@;<l2_-;O|QW3R7^#GnLUz1z)YYR+hvO#*1{Kg!HDY%QU0ssJ<
zs02(tK7tSe0Kpx7y*A6mOI4@}S9!NI?+sc{GuW&0d_$@iv5crJs`Q0apWM(Yr30z$
z1y}-;Wdd%RfNCYfEB*>~f3qOG&4T~~1p)prdFm3Re#PL>6>GF-r27)E7nd5YNWCye
zp_5g}MD$r-BeU@9A_&R9-!cf94U;E0A8*`OVHuus&w9o2*kJwu0I<VplR-i1Q8KU|
zRIUtdx+upu<lY?13o(dE1Q-zl00{*GOg=t>0vikf3JDORTycmrHScznY6AeCGlKBj
t91<_~e$6eBBNMFl2Ch*d0G=qQyaCj?7?`a0p;!n(q;h(qyGO7B006xAAsGMw

delta 7
Ocmcb{zlCdq2`c~$WCD!<

diff --git a/gpg/diaspora-test/trustdb.gpg b/gpg/diaspora-test/trustdb.gpg
index 45e0c76adf3c9bab923cb7a571bcdc1d64ff4598..1fec81fc8c39a371e7de456d93e66eb9dd3172ee 100644
GIT binary patch
delta 119
zcmeyseSk-RF})z2nVFH5k%581$Ifo`#6a<l>TZmTY7+yMHcwzoU<u%1@aTz{@_gf5
z*%SLXLKnppc9^^`o5}`M4+QEE3PkcU)c@0EI#H98;(YY!!F``5^UFpYR)wlVC}RKs
DxWyh-

delta 36
scmX@W^MPA{F})z2nVFH5k%581$7cDliGku9)!i5;o^{x~meH970JIAVcK`qY

diff --git a/lib/encryptable.rb b/lib/encryptable.rb
new file mode 100644
index 0000000000..10a9ac39c0
--- /dev/null
+++ b/lib/encryptable.rb
@@ -0,0 +1,33 @@
+  module Encryptable
+   def signable_string
+     ""
+   end
+    def verify_creator_signature
+      verify_signature(creator_signature, person)
+    end
+    
+    def verify_signature(signature, person)
+      return false unless signature && person.key_fingerprint
+      validity = nil
+      GPGME::verify(creator_signature, signable_string, 
+        {:armor => true, :always_trust => true}){ |signature|
+        puts signature  
+        validity =  signature.status == GPGME::GPG_ERR_NO_ERROR &&
+            signature.fpr == person.key_fingerprint
+      }
+      return validity
+    end
+    
+    protected
+    def sign_if_mine
+      if self.person == User.owner
+        self.creator_signature = sign
+      end
+    end
+
+    def sign
+      GPGME::sign(signable_string,nil,
+          {:armor=> true, :mode => GPGME::SIG_MODE_DETACH, :signers => [User.owner.key]})
+    end
+  end
+
diff --git a/spec/controllers/publics_controller_spec.rb b/spec/controllers/publics_controller_spec.rb
index e9539b4641..be297a64fa 100644
--- a/spec/controllers/publics_controller_spec.rb
+++ b/spec/controllers/publics_controller_spec.rb
@@ -4,7 +4,7 @@ describe PublicsController do
  render_views
   
   before do
-    @user = Factory.create(:user, :profile => Profile.create( :first_name => "bob", :last_name => "smith"))
+    @user = Factory.create(:user, :profile => Profile.new( :first_name => "bob", :last_name => "smith"))
     request.env['warden'] = mock_model(Warden, :authenticate? => @user, :authenticate! => @user, :authenticate => @user)
   end
 
diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb
index a882b9849f..72cad89ace 100644
--- a/spec/models/person_spec.rb
+++ b/spec/models/person_spec.rb
@@ -65,6 +65,7 @@ describe Person do
     Person.friends.all.count.should == 1
     u.unfriend(f.id)
     Person.friends.all.count.should == 0
+    Person.all.count.should == 1
   end
 
 end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 7273c0d282..79412d92d4 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -42,10 +42,11 @@ end
   end
 
   def stub_signature_verification
-    Post.any_instance.stubs(:verify_signature).returns(true)
-    StatusMessage.any_instance.stubs(:verify_signature).returns(true)
-    Blog.any_instance.stubs(:verify_signature).returns(true)
-    Bookmark.any_instance.stubs(:verify_signature).returns(true)
+    Post.any_instance.stubs(:verify_creator_signature).returns(true)
+    StatusMessage.any_instance.stubs(:verify_creator_signature).returns(true)
+    Blog.any_instance.stubs(:verify_creator_signature).returns(true)
+    Bookmark.any_instance.stubs(:verify_creator_signature).returns(true)
+    Comment.any_instance.stubs(:verify_creator_signature).returns(true)
   end
 
   def unstub_mocha_stubs
diff --git a/spec/user_encryption_spec.rb b/spec/user_encryption_spec.rb
index af4fcfc4e3..63f4785c9c 100644
--- a/spec/user_encryption_spec.rb
+++ b/spec/user_encryption_spec.rb
@@ -10,17 +10,21 @@ describe 'user encryption' do
   end
   before do
     unstub_mocha_stubs
-    @u = Factory.create(:user)
-    @u.send(:assign_key)
-    @u.save
+    @user = Factory.create(:user)
+    @user.send(:assign_key)
+    @user.save
     @person = Factory.create(:person,
       :key_fingerprint => GPGME.list_keys("Remote Friend").first.subkeys.first.fpr,
       :profile => Profile.new(:first_name => 'Remote',
                               :last_name => 'Friend'),
       :email => 'somewhere@else.com',
-      :url => 'http://distant-example.com/',
-      :key_fingerprint => '57F553EE2C230991566B7C60D3638485F3960087')
-
+      :url => 'http://distant-example.com/')
+    @person2 = Factory.create(:person,
+      :key_fingerprint => GPGME.list_keys("Second Friend").first.subkeys.first.fpr,
+      :profile => Profile.new(:first_name => 'Second',
+                              :last_name => 'Friend'),
+      :email => 'elsewhere@else.com',
+      :url => 'http://distanter-example.com/')
   end
 
   after  do
@@ -44,18 +48,18 @@ describe 'user encryption' do
   end
 
   it 'should have a key fingerprint' do
-    @u.key_fingerprint.should_not be nil
+    @user.key_fingerprint.should_not be nil
   end
 
   it 'should retrieve a user key' do
-    @u.key.subkeys[0].fpr.should  == @u.key_fingerprint
+    @user.key.subkeys[0].fpr.should  == @user.key_fingerprint
   end
 
   describe 'key exchange on friending' do
        it 'should send over a public key' do
       Comment.send(:class_variable_get, :@@queue).stub!(:add_post_request)
-      request = @u.send_friend_request_to("http://example.com/")
-      Request.build_xml_for([request]).include?( @u.export_key).should be true
+      request = @user.send_friend_request_to("http://example.com/")
+      Request.build_xml_for([request]).include?( @user.export_key).should be true
     end
 
     it 'should receive and marshal a public key from a request' do
@@ -70,8 +74,9 @@ describe 'user encryption' do
       
       xml = Request.build_xml_for [request]
       person.destroy
+      personcount = Person.all.count
       store_objects_from_xml(xml)
-      Person.all.count.should == 3 
+      Person.all.count.should == personcount + 1
       new_person = Person.first(:url => "http://test.url/")
       new_person.key_fingerprint.nil?.should == false
       new_person.id.should == id
@@ -83,54 +88,54 @@ describe 'user encryption' do
   describe 'signing and verifying' do
 
     it 'should sign a message on create' do
-      message = Factory.create(:status_message, :person => @u)
-      message.verify_signature.should be true 
+      message = Factory.create(:status_message, :person => @user)
+      message.verify_creator_signature.should be true 
     end
     
     it 'should not be able to verify a message from a person without a key' do 
       person = Factory.create(:person, :key_fingerprint => "123")
       message = Factory.build(:status_message, :person => person)
       message.save(:validate => false)
-      message.verify_signature.should be false
+      message.verify_creator_signature.should be false
     end
     
     it 'should verify a remote signature' do 
       message = Factory.build(:status_message, :person => @person)
-      message.owner_signature = GPGME.sign(message.signable_string, nil,
+      message.creator_signature = GPGME.sign(message.signable_string, nil,
         {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person.key]})
       message.save(:validate => false)
-      message.verify_signature.should be true
+      message.verify_creator_signature.should be true
     end
     
     it 'should know if the signature is from the wrong person' do
       message = Factory.build(:status_message, :person => @person)
       message.save(:validate => false)
-      message.owner_signature = GPGME.sign(message.signable_string, nil,
+      message.creator_signature = GPGME.sign(message.signable_string, nil,
         {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person.key]})
-      message.person = @u
-      message.verify_signature.should be false
+      message.person = @user
+      message.verify_creator_signature.should be false
     end
    
     it 'should know if the signature is for the wrong text' do
       message = Factory.build(:status_message, :person => @person)
-      message.owner_signature = GPGME.sign(message.signable_string, nil,
+      message.creator_signature = GPGME.sign(message.signable_string, nil,
         {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person.key]})
       message.message = 'I love VENISON'
       message.save(:validate => false)
-      message.verify_signature.should be false
+      message.verify_creator_signature.should be false
     end
   end
 
   describe 'sending and recieving signatures' do
     it 'should contain the signature in the xml' do
-      message = Factory.create(:status_message, :person => @u)
+      message = Factory.create(:status_message, :person => @user)
       xml = message.to_xml.to_s
-      xml.include?(message.owner_signature).should be true
+      xml.include?(message.creator_signature).should be true
     end
-    it 'the signature should be verified on marshaling' do
+    it 'A message with an invalid signature should be rejected' do
       message = Factory.build(:status_message, :person => @person)
-      message.owner_signature = GPGME.sign(message.signable_string, nil,
-        {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@u.key]})
+      message.creator_signature = GPGME.sign(message.signable_string, nil,
+        {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@user.key]})
       message.save
       xml = Post.build_xml_for([message])
       message.destroy
@@ -140,4 +145,46 @@ describe 'user encryption' do
     end
 
   end
+  describe 'comments' do
+    before do
+      @remote_message = Factory.build(:status_message, :person => @person)
+      @remote_message.creator_signature = GPGME.sign(@remote_message.signable_string, nil,
+        {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person.key]})
+      @remote_message.save 
+
+    end
+    it 'should attach the creator signature if the user is commenting' do
+      @user.comment "Yeah, it was great", :on => @remote_message
+      @remote_message.comments.first.verify_creator_signature.should be true
+    end
+
+    it 'should sign the comment if the user is the post creator' do
+      message = Factory.create(:status_message, :person => @user)
+      @user.comment "Yeah, it was great", :on => message
+      StatusMessage.first.comments.first.verify_creator_signature.should be true
+      StatusMessage.first.comments.first.verify_post_creator_signature.should be true
+    end
+    
+    it 'should verify a comment made on a remote post by a different friend' do
+      comment = Comment.new(:person => @person2, :text => "balls", :post => @remote_message)
+      comment.creator_signature = GPGME.sign(@remote_message.signable_string, nil,
+        {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person2.key]})
+      comment.verify_creator_signature.should be true
+
+    end
+
+    it 'should reject comments on a remote post with only a creator sig' do
+        comment = Comment.new(:person => @person2, :text => "balls", :post => @remote_message)
+        comment.creator_signature = GPGME.sign(@remote_message.signable_string, nil,
+          {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person2.key]})
+        comment.verify_creator_signature.should be true
+        comment.verify_post_creator_signature.should be false
+        comment.save.should be false
+    end
+
+    it 'should receive remote comments on a user post with a creator sig' do
+      
+    end
+
+  end
 end
-- 
GitLab