broke out some comment logic to a replayable module
This commit is contained in:
parent
bd908a9b95
commit
f4e6d0d82b
14 changed files with 317 additions and 302 deletions
|
|
@ -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{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
def parent
|
||||
self.post
|
||||
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
|
||||
def parent= parent
|
||||
self.post = parent
|
||||
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
|
||||
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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -43,8 +43,8 @@ ActiveRecord::Schema.define(:version => 20110228201109) do
|
|||
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 "author_signature"
|
||||
t.text "parent_author_signature"
|
||||
t.text "youtube_titles"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
|
|
|
|||
125
lib/diaspora/relayable.rb
Normal file
125
lib/diaspora/relayable.rb
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
58
spec/lib/diaspora/relayable_spec.rb
Normal file
58
spec/lib/diaspora/relayable_spec.rb
Normal file
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
it 'does not multi-post a comment' do
|
||||
lambda {
|
||||
alice.comment 'hello', :on => @status
|
||||
}.should change { Comment.count }.by(1)
|
||||
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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue