From f4e6d0d82b1414c4e2806c42952fd870baaa09da Mon Sep 17 00:00:00 2001 From: danielvincent Date: Mon, 28 Feb 2011 15:23:24 -0800 Subject: [PATCH] broke out some comment logic to a replayable module --- app/controllers/comments_controller.rb | 3 +- app/models/comment.rb | 75 +----- app/models/post.rb | 1 - app/models/user.rb | 14 +- ...me_post_to_parent_and_creator_to_author.rb | 11 + db/schema.rb | 14 +- lib/diaspora/relayable.rb | 125 ++++++++++ lib/encryptable.rb | 39 ---- spec/intergration/receiving_spec.rb | 2 +- spec/lib/diaspora/relayable_spec.rb | 58 +++++ spec/misc_spec.rb | 13 ++ spec/models/comment_spec.rb | 215 +++++++----------- spec/models/user/commenting_spec.rb | 43 ---- spec/support/user_methods.rb | 6 +- 14 files changed, 317 insertions(+), 302 deletions(-) create mode 100644 db/migrate/20110228220810_rename_post_to_parent_and_creator_to_author.rb create mode 100644 lib/diaspora/relayable.rb delete mode 100644 lib/encryptable.rb create mode 100644 spec/lib/diaspora/relayable_spec.rb delete mode 100644 spec/models/user/commenting_spec.rb diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 0409f31ff..6e2ac8f5e 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -18,8 +18,7 @@ class CommentsController < ApplicationController if @comment.save Rails.logger.info("event=create type=comment user=#{current_user.diaspora_handle} status=success comment=#{@comment.id} chars=#{params[:text].length}") - - current_user.dispatch_comment(@comment) + Postzord::Dispatch.new(current_user, @comment).post respond_to do |format| format.js{ diff --git a/app/models/comment.rb b/app/models/comment.rb index 334890632..1fdc47876 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -7,16 +7,15 @@ class Comment < ActiveRecord::Base require File.join(Rails.root, 'lib/youtube_titles') include YoutubeTitles include ROXML + include Diaspora::Webhooks - include Encryptable - include Diaspora::Socketable + include Diaspora::Relayable include Diaspora::Guid + include Diaspora::Socketable + xml_attr :text xml_attr :diaspora_handle - xml_attr :post_guid - xml_attr :creator_signature - xml_attr :post_creator_signature belongs_to :post, :touch => true belongs_to :person @@ -35,12 +34,6 @@ class Comment < ActiveRecord::Base def diaspora_handle= nh self.person = Webfinger.new(nh).fetch end - def post_guid - self.post.guid - end - def post_guid= new_post_guid - self.post = Post.where(:guid => new_post_guid).first - end def notification_type(user, person) if self.post.person == user.person @@ -52,63 +45,15 @@ class Comment < ActiveRecord::Base end end - def subscribers(user) - if user.owns?(self.post) - p = self.post.subscribers(user) - elsif user.owns?(self) - p = [self.post.person] - end - p + def parent_class + Post end - def receive(user, person) - local_comment = Comment.where(:guid => self.guid).first - comment = local_comment || self - - unless comment.post.person == user.person || comment.verify_post_creator_signature - Rails.logger.info("event=receive status=abort reason='comment signature not valid' recipient=#{user.diaspora_handle} sender=#{self.post.person.diaspora_handle} payload_type=#{self.class} post_id=#{self.post_id}") - return - end - - #sign comment as the post creator if you've been hit UPSTREAM - if user.owns? comment.post - comment.post_creator_signature = comment.sign_with_key(user.encryption_key) - comment.save - end - - #dispatch comment DOWNSTREAM, received it via UPSTREAM - unless user.owns?(comment) - comment.save - user.dispatch_comment(comment) - end - - comment.socket_to_user(user, :aspect_ids => comment.post.aspect_ids) - comment + def parent + self.post end - #ENCRYPTION - - - 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 + def parent= parent + self.post = parent 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 - - def signature_valid? - verify_signature(creator_signature, person) - end - end diff --git a/app/models/post.rb b/app/models/post.rb index dfff551f5..180e444d8 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -3,7 +3,6 @@ # the COPYRIGHT file. class Post < ActiveRecord::Base - require File.join(Rails.root, 'lib/encryptable') require File.join(Rails.root, 'lib/diaspora/web_socket') include ApplicationHelper include ROXML diff --git a/app/models/user.rb b/app/models/user.rb index c923a5856..0ef27da51 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -128,8 +128,7 @@ class User < ActiveRecord::Base end def salmon(post) - created_salmon = Salmon::SalmonSlap.create(self, post.to_diaspora_xml) - created_salmon + Salmon::SalmonSlap.create(self, post.to_diaspora_xml) end ######## Commenting ######## @@ -139,21 +138,16 @@ class User < ActiveRecord::Base :post => options[:on]) comment.set_guid #sign comment as commenter - comment.creator_signature = comment.sign_with_key(self.encryption_key) + comment.author_signature = comment.sign_with_key(self.encryption_key) - if !comment.post_id.blank? && person.owns?(comment.post) + if !comment.post_id.blank? && person.owns?(comment.parent) #sign comment as post owner - comment.post_creator_signature = comment.sign_with_key(self.encryption_key) + comment.parent_author_signature = comment.sign_with_key(self.encryption_key) end comment end - def dispatch_comment(comment) - mailman = Postzord::Dispatch.new(self, comment) - mailman.post - end - ######### Mailer ####################### def mail(job, *args) unless self.disable_mail diff --git a/db/migrate/20110228220810_rename_post_to_parent_and_creator_to_author.rb b/db/migrate/20110228220810_rename_post_to_parent_and_creator_to_author.rb new file mode 100644 index 000000000..ef43ad57a --- /dev/null +++ b/db/migrate/20110228220810_rename_post_to_parent_and_creator_to_author.rb @@ -0,0 +1,11 @@ +class RenamePostToParentAndCreatorToAuthor < ActiveRecord::Migration + def self.up + rename_column :comments, :creator_signature, :author_signature + rename_column :comments, :post_creator_signature, :parent_author_signature + end + + def self.down + rename_column :comments, :author_signature, :creator_signature + rename_column :comments, :parent_author_signature, :post_creator_signature + end +end diff --git a/db/schema.rb b/db/schema.rb index adea1e3a4..adb41d90a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110228201109) do +ActiveRecord::Schema.define(:version => 20110228220810) do create_table "aspect_memberships", :force => true do |t| t.integer "aspect_id", :null => false @@ -39,12 +39,12 @@ ActiveRecord::Schema.define(:version => 20110228201109) do add_index "aspects", ["user_id"], :name => "index_aspects_on_user_id" create_table "comments", :force => true do |t| - t.text "text", :null => false - t.integer "post_id", :null => false - t.integer "person_id", :null => false - t.string "guid", :null => false - t.text "creator_signature" - t.text "post_creator_signature" + t.text "text", :null => false + t.integer "post_id", :null => false + t.integer "person_id", :null => false + t.string "guid", :null => false + t.text "author_signature" + t.text "parent_author_signature" t.text "youtube_titles" t.datetime "created_at" t.datetime "updated_at" diff --git a/lib/diaspora/relayable.rb b/lib/diaspora/relayable.rb new file mode 100644 index 000000000..2db591761 --- /dev/null +++ b/lib/diaspora/relayable.rb @@ -0,0 +1,125 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +module Diaspora + module Relayable + + def self.included(model) + model.class_eval do + #these fields must be in the schema for a relayable model + xml_attr :parent_guid + xml_attr :parent_author_signature + xml_attr :author_signature + end + end + + def parent_guid + self.parent.guid + end + def parent_guid= new_parent_guid + self.parent = parent_class.where(:guid => new_parent_guid).first + end + + def subscribers(user) + if user.owns?(self.parent) + self.parent.subscribers(user) + elsif user.owns?(self) + [self.parent.person] + end + end + + def receive(user, person) + object = self.class.where(:guid => self.guid).first || self + + unless object.parent.person == user.person || object.verify_parent_author_signature + Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{user.diaspora_handle} sender=#{self.parent.person.diaspora_handle} payload_type=#{self.class} parent_id=#{self.parent.id}") + return + end + + #sign object as the parent creator if you've been hit UPSTREAM + if user.owns? object.parent + object.parent_author_signature = object.sign_with_key(user.encryption_key) + object.save + end + + #dispatch object DOWNSTREAM, received it via UPSTREAM + unless user.owns?(object) + object.save + Postzord::Dispatch.new(user, object).post + end + + object.socket_to_user(user, :aspect_ids => object.parent.aspect_ids) + object + end + + def signable_string + raise NotImplementedException("Override this in your encryptable class") + end + + def signature_valid? + verify_signature(creator_signature, person) + end + + 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}") + 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}") + return false + elsif signature.nil? + Rails.logger.info("event=verify_signature status=abort reason=no_signature guid=#{self.guid} model_id=#{self.id}") + return false + end + log_string = "event=verify_signature status=complete model_id=#{id}" + validity = person.public_key.verify "SHA", Base64.decode64(signature), signable_string + log_string += " validity=#{validity}" + Rails.logger.info(log_string) + validity + end + + 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}") + sig + end + + def signable_accessors + accessors = self.class.roxml_attrs.collect do |definition| + definition.accessor + end + ['person', 'author_signature', 'parent_author_signature'].each do |acc| + accessors.delete acc + end + accessors + end + + def signable_string + signable_accessors.collect{ |accessor| + (self.send accessor.to_sym).to_s + }.join(';') + end + + def verify_parent_author_signature + verify_signature(self.parent_author_signature, parent.person) + end + + def signature_valid? + verify_signature(self.author_signature, person) + end + + + def parent_class + raise NotImplementedError.new('you must override parent_class in order to enable relayable on this model') + end + + def parent + raise NotImplementedError.new('you must override parent in order to enable relayable on this model') + end + + def parent= parent + raise NotImplementedError.new('you must override parent= in order to enable relayable on this model') + end + end +end diff --git a/lib/encryptable.rb b/lib/encryptable.rb deleted file mode 100644 index 06cb31014..000000000 --- a/lib/encryptable.rb +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -module Encryptable - def signable_string - raise NotImplementedException("Override this in your encryptable class") - end - - def signature_valid? - verify_signature(creator_signature, person) - end - - 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}") - 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}") - return false - elsif signature.nil? - Rails.logger.info("event=verify_signature status=abort reason=no_signature guid=#{self.guid} model_id=#{self.id}") - return false - end - log_string = "event=verify_signature status=complete model_id=#{id}" - validity = person.public_key.verify "SHA", Base64.decode64(signature), signable_string - log_string += " validity=#{validity}" - Rails.logger.info(log_string) - validity - end - - 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}") - sig - end - -end - diff --git a/spec/intergration/receiving_spec.rb b/spec/intergration/receiving_spec.rb index 81fbc1ddb..5c0b52b03 100644 --- a/spec/intergration/receiving_spec.rb +++ b/spec/intergration/receiving_spec.rb @@ -186,7 +186,7 @@ describe 'a user receives a post' do receive_with_zord(@user3, @user1.person, xml) @comment = @user3.comment('tada',:on => @post) - @comment.post_creator_signature = @comment.sign_with_key(@user1.encryption_key) + @comment.parent_author_signature = @comment.sign_with_key(@user1.encryption_key) @xml = @comment.to_diaspora_xml @comment.delete end diff --git a/spec/lib/diaspora/relayable_spec.rb b/spec/lib/diaspora/relayable_spec.rb new file mode 100644 index 000000000..450990b9c --- /dev/null +++ b/spec/lib/diaspora/relayable_spec.rb @@ -0,0 +1,58 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require 'spec_helper' + +describe Diaspora::Relayable do + + before do + @alices_aspect = alice.aspects.first + @bobs_aspect = bob.aspects.first + @remote_message = bob.post :status_message, :message => "hello", :to => @bobs_aspect.id + @message = alice.post :status_message, :message => "hi", :to => @alices_aspect.id + end + + describe '#parent_author_signature' do + it 'should sign the comment if the user is the post author' do + message = alice.post :status_message, :message => "hi", :to => @alices_aspect.id + alice.comment "Yeah, it was great", :on => message + message.comments.reset + message.comments.first.signature_valid?.should be_true + message.comments.first.verify_parent_author_signature.should be_true + end + + it 'should verify a comment made on a remote post by a different contact' do + comment = Comment.new(:person => bob.person, :text => "cats", :post => @remote_message) + comment.author_signature = comment.send(:sign_with_key, bob.encryption_key) + comment.signature_valid?.should be_true + comment.verify_parent_author_signature.should be_false + comment.parent_author_signature = comment.send(:sign_with_key, alice.encryption_key) + comment.verify_parent_author_signature.should be_true + end + end + + describe '#author_signature' do + it 'should attach the author signature if the user is commenting' do + comment = alice.comment "Yeah, it was great", :on => @remote_message + @remote_message.comments.reset + @remote_message.comments.first.signature_valid?.should be_true + end + + it 'should reject comments on a remote post with only a author sig' do + comment = Comment.new(:person => bob.person, :text => "cats", :post => @remote_message) + comment.author_signature = comment.send(:sign_with_key, bob.encryption_key) + comment.signature_valid?.should be_true + comment.verify_parent_author_signature.should be_false + end + + it 'should receive remote comments on a user post with a author sig' do + comment = Comment.new(:person => bob.person, :text => "cats", :post => @message) + comment.author_signature = comment.send(:sign_with_key, bob.encryption_key) + comment.signature_valid?.should be_true + comment.verify_parent_author_signature.should be_false + end + end + +end + diff --git a/spec/misc_spec.rb b/spec/misc_spec.rb index 3ea7bbc6c..149a4e786 100644 --- a/spec/misc_spec.rb +++ b/spec/misc_spec.rb @@ -49,4 +49,17 @@ describe 'making sure the spec runner works' do @user2.reload.visible_posts.should include message end end + + describe '#comment' do + it "should send a user's comment on a person's post to that person" do + person = Factory.create(:person) + person_status = Factory.create(:status_message, :person => person) + m = mock() + m.stub!(:post) + Postzord::Dispatch.should_receive(:new).and_return(m) + + alice.comment "yo", :on => person_status + end + end + end diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index e80cfcf3d..edab46f58 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -8,48 +8,41 @@ describe Comment do before do @alices_aspect = alice.aspects.first @bobs_aspect = bob.aspects.first + + @bob = bob + @eve = eve + @status = alice.post(:status_message, :message => "hello", :to => @alices_aspect.id) end describe 'comment#notification_type' do - before do - @sam = Factory(:user_with_aspect) - connect_users(alice, @alices_aspect, @sam, @sam.aspects.first) - - @alices_post = alice.post(:status_message, :message => "hello", :to => @alices_aspect.id) - end - it "returns 'comment_on_post' if the comment is on a post you own" do - comment = bob.comment("why so formal?", :on => @alices_post) + comment = bob.comment("why so formal?", :on => @status) comment.notification_type(alice, bob.person).should == Notifications::CommentOnPost end it 'returns false if the comment is not on a post you own and no one "also_commented"' do - comment = alice.comment("I simply felt like issuing a greeting. Do step off.", :on => @alices_post) - comment.notification_type(@sam, alice.person).should == false + comment = alice.comment("I simply felt like issuing a greeting. Do step off.", :on => @status) + comment.notification_type(@bob, alice.person).should == false end context "also commented" do before do - bob.comment("a-commenta commenta", :on => @alices_post) - @comment = @sam.comment("I also commented on the first user's post", :on => @alices_post) + @bob.comment("a-commenta commenta", :on => @status) + @comment = @eve.comment("I also commented on the first user's post", :on => @status) end it 'does not return also commented if the user commented' do - @comment.notification_type(@sam, alice.person).should == false + @comment.notification_type(@eve, alice.person).should == false end it "returns 'also_commented' if another person commented on a post you commented on" do - @comment.notification_type(bob, alice.person).should == Notifications::AlsoCommented + @comment.notification_type(@bob, alice.person).should == Notifications::AlsoCommented end end end describe 'User#comment' do - before do - @status = alice.post(:status_message, :message => "hello", :to => @alices_aspect.id) - end - it "should be able to comment on one's own status" do alice.comment("Yeah, it was great", :on => @status) @status.reload.comments.first.text.should == "Yeah, it was great" @@ -59,66 +52,13 @@ describe Comment do bob.comment("sup dog", :on => @status) @status.reload.comments.first.text.should == "sup dog" end - end - - context 'comment propagation' do - before do - @person = Factory.create(:person) - alice.activate_contact(@person, @alices_aspect) - - @person2 = Factory.create(:person) - @person3 = Factory.create(:person) - alice.activate_contact(@person3, @alices_aspect) - - @person_status = Factory.create(:status_message, :person => @person) - - alice.reload - @user_status = alice.post :status_message, :message => "hi", :to => @alices_aspect.id - - @alices_aspect.reload - alice.reload - end - - it 'should send the comment to the postman' do - m = mock() - m.stub!(:post) - Postzord::Dispatch.should_receive(:new).and_return(m) - alice.comment "yo", :on => @person_status - end - - describe '#subscribers' do - it 'returns the posts original audience, if the post is owned by the user' do - comment = alice.build_comment "yo", :on => @person_status - comment.subscribers(alice).should =~ [@person] - end - - it 'returns the owner of the original post, if the user owns the comment' do - comment = alice.build_comment "yo", :on => @user_status - comment.subscribers(alice).map { |s| s.id }.should =~ [@person, @person3, bob.person].map { |s| s.id } - end - end - - context 'testing a method only used for testing' do - it "should send a user's comment on a person's post to that person" do - m = mock() - m.stub!(:post) - Postzord::Dispatch.should_receive(:new).and_return(m) - - alice.comment "yo", :on => @person_status - end - end - - it 'should not clear the aspect post array on receiving a comment' do - @alices_aspect.post_ids.include?(@user_status.id).should be_true - comment = Comment.new(:person_id => @person.id, :text => "cats", :post => @user_status) - - zord = Postzord::Receiver.new(alice, :person => @person) - zord.parse_and_receive(comment.to_diaspora_xml) - - @alices_aspect.reload - @alices_aspect.post_ids.include?(@user_status.id).should be_true + it 'does not multi-post a comment' do + lambda { + alice.comment 'hello', :on => @status + }.should change { Comment.count }.by(1) end end + describe 'xml' do before do @commenter = Factory.create(:user) @@ -146,59 +86,6 @@ describe Comment do end end end - describe 'local commenting' do - before do - @status = alice.post(:status_message, :message => "hello", :to => @alices_aspect.id) - end - it 'does not multi-post a comment' do - lambda { - alice.comment 'hello', :on => @status - }.should change { Comment.count }.by(1) - end - end - describe 'comments' do - before do - @remote_message = bob.post :status_message, :message => "hello", :to => @bobs_aspect.id - @message = alice.post :status_message, :message => "hi", :to => @alices_aspect.id - end - - it 'should attach the creator signature if the user is commenting' do - comment = alice.comment "Yeah, it was great", :on => @remote_message - @remote_message.comments.reset - @remote_message.comments.first.signature_valid?.should be_true - end - - it 'should sign the comment if the user is the post creator' do - message = alice.post :status_message, :message => "hi", :to => @alices_aspect.id - alice.comment "Yeah, it was great", :on => message - message.comments.reset - message.comments.first.signature_valid?.should be_true - message.comments.first.verify_post_creator_signature.should be_true - end - - it 'should verify a comment made on a remote post by a different contact' do - comment = Comment.new(:person => bob.person, :text => "cats", :post => @remote_message) - comment.creator_signature = comment.send(:sign_with_key, bob.encryption_key) - comment.signature_valid?.should be_true - comment.verify_post_creator_signature.should be_false - comment.post_creator_signature = comment.send(:sign_with_key, alice.encryption_key) - comment.verify_post_creator_signature.should be_true - end - - it 'should reject comments on a remote post with only a creator sig' do - comment = Comment.new(:person => bob.person, :text => "cats", :post => @remote_message) - comment.creator_signature = comment.send(:sign_with_key, bob.encryption_key) - comment.signature_valid?.should be_true - comment.verify_post_creator_signature.should be_false - end - - it 'should receive remote comments on a user post with a creator sig' do - comment = Comment.new(:person => bob.person, :text => "cats", :post => @message) - comment.creator_signature = comment.send(:sign_with_key, bob.encryption_key) - comment.signature_valid?.should be_true - comment.verify_post_creator_signature.should be_false - end - end describe 'youtube' do before do @@ -220,4 +107,74 @@ describe Comment do Comment.find(comment.id).youtube_titles.should == {video_id => CGI::escape(expected_title)} end end + + context 'comment propagation' do + before do + @local_luke, @local_leia, @remote_raphael = set_up_friends + @person_status = Factory.create(:status_message, :person => @remote_raphael) + @user_status = @local_luke.post :status_message, :message => "hi", :to => @local_luke.aspects.first + @lukes_aspect = @local_luke.aspects.first + end + + it 'should not clear the aspect post array on receiving a comment' do + @lukes_aspect.post_ids.include?(@user_status.id).should be_true + comment = Comment.new(:person_id => @remote_raphael.id, :text => "cats", :post => @user_status) + + zord = Postzord::Receiver.new(alice, :person => @remote_raphael) + zord.parse_and_receive(comment.to_diaspora_xml) + + @lukes_aspect.reload + @lukes_aspect.post_ids.include?(@user_status.id).should be_true + end + + describe '#receive' do + before do + @comment = @local_luke.comment("yo", :on => @user_status) + @comment2 = @local_leia.build_comment("yo", :on => @user_status) + @new_c = @comment.dup + end + + it 'does not overwrite a comment that is already in the db' do + lambda{ + @new_c.receive(@local_leia, @local_luke.person) + }.should_not change(Comment, :count) + end + + it 'does not process if post_creator_signature is invalid' do + @comment.delete # remove comment from db so we set a creator sig + @new_c.parent_author_signature = "dsfadsfdsa" + @new_c.receive(@local_leia, @local_luke.person).should == nil + end + + it 'signs when the person receiving is the parent author' do + @comment2.save + @comment2.receive(@local_luke, @local_leia.person) + @comment2.reload.parent_author_signature.should_not be_blank + end + + it 'dispatches when the person receiving is the parent author' do + p = Postzord::Dispatch.new(@local_luke, @comment2) + p.should_receive(:post) + Postzord::Dispatch.stub!(:new).and_return(p) + @comment2.receive(@local_luke, @local_leia.person) + end + + it 'sockets to the user' do + @comment2.should_receive(:socket_to_user).exactly(3).times + @comment2.receive(@local_luke, @local_leia.person) + end + end + + describe '#subscribers' do + it 'returns the posts original audience, if the post is owned by the user' do + comment = @local_luke.build_comment "yo", :on => @user_status + comment.subscribers(@local_luke).map(&:id).should =~ [@local_leia.person, @remote_raphael].map(&:id) + end + + it 'returns the owner of the original post, if the user owns the comment' do + comment = @local_leia.build_comment "yo", :on => @user_status + comment.subscribers(@local_leia).map(&:id).should =~ [@local_luke.person].map(&:id) + end + end + end end diff --git a/spec/models/user/commenting_spec.rb b/spec/models/user/commenting_spec.rb deleted file mode 100644 index 8534549e5..000000000 --- a/spec/models/user/commenting_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -require 'spec_helper' - -describe User do - - let!(:user1){alice} - let!(:user2){bob} - let!(:aspect1){user1.aspects.first} - let!(:aspect2){user2.aspects.first} - - before do - @post = user1.build_post(:status_message, :message => "hey", :to => aspect1.id) - @post.save - user1.dispatch_post(@post, :to => "all") - end - - describe '#dispatch_comment' do - context "post owner's contact is commenting" do - it "doesn't call receive on local users" do - user1.should_not_receive(:receive_comment) - user2.should_not_receive(:receive_comment) - - comment = user2.build_comment "why so formal?", :on => @post - comment.save! - user2.dispatch_comment comment - end - end - - context "post owner is commenting on own post" do - it "doesn't call receive on local users" do - user1.should_not_receive(:receive_comment) - user2.should_not_receive(:receive_comment) - - comment = user1.build_comment "why so formal?", :on => @post - comment.save! - user1.dispatch_comment comment - end - end - end -end diff --git a/spec/support/user_methods.rb b/spec/support/user_methods.rb index e47c2fd68..3d091d914 100644 --- a/spec/support/user_methods.rb +++ b/spec/support/user_methods.rb @@ -18,10 +18,7 @@ class User fantasy_resque do p = build_post(class_name, opts) if p.save! - raise 'MongoMapper failed to catch a failed save' unless p.id - self.aspects.reload - aspects = self.aspects_from_ids(opts[:to]) add_to_streams(p, aspects) dispatch_post(p, :to => opts[:to]) @@ -34,8 +31,7 @@ class User fantasy_resque do c = build_comment(text, options) if c.save! - raise 'MongoMapper failed to catch a failed save' unless c.id - dispatch_comment(c) + Postzord::Dispatch.new(self, c).post end c end