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
|
if @comment.save
|
||||||
Rails.logger.info("event=create type=comment user=#{current_user.diaspora_handle} status=success comment=#{@comment.id} chars=#{params[:text].length}")
|
Rails.logger.info("event=create type=comment user=#{current_user.diaspora_handle} status=success comment=#{@comment.id} chars=#{params[:text].length}")
|
||||||
|
Postzord::Dispatch.new(current_user, @comment).post
|
||||||
current_user.dispatch_comment(@comment)
|
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.js{
|
format.js{
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,15 @@ class Comment < ActiveRecord::Base
|
||||||
require File.join(Rails.root, 'lib/youtube_titles')
|
require File.join(Rails.root, 'lib/youtube_titles')
|
||||||
include YoutubeTitles
|
include YoutubeTitles
|
||||||
include ROXML
|
include ROXML
|
||||||
|
|
||||||
include Diaspora::Webhooks
|
include Diaspora::Webhooks
|
||||||
include Encryptable
|
include Diaspora::Relayable
|
||||||
include Diaspora::Socketable
|
|
||||||
include Diaspora::Guid
|
include Diaspora::Guid
|
||||||
|
|
||||||
|
include Diaspora::Socketable
|
||||||
|
|
||||||
xml_attr :text
|
xml_attr :text
|
||||||
xml_attr :diaspora_handle
|
xml_attr :diaspora_handle
|
||||||
xml_attr :post_guid
|
|
||||||
xml_attr :creator_signature
|
|
||||||
xml_attr :post_creator_signature
|
|
||||||
|
|
||||||
belongs_to :post, :touch => true
|
belongs_to :post, :touch => true
|
||||||
belongs_to :person
|
belongs_to :person
|
||||||
|
|
@ -35,12 +34,6 @@ class Comment < ActiveRecord::Base
|
||||||
def diaspora_handle= nh
|
def diaspora_handle= nh
|
||||||
self.person = Webfinger.new(nh).fetch
|
self.person = Webfinger.new(nh).fetch
|
||||||
end
|
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)
|
def notification_type(user, person)
|
||||||
if self.post.person == user.person
|
if self.post.person == user.person
|
||||||
|
|
@ -52,63 +45,15 @@ class Comment < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribers(user)
|
def parent_class
|
||||||
if user.owns?(self.post)
|
Post
|
||||||
p = self.post.subscribers(user)
|
|
||||||
elsif user.owns?(self)
|
|
||||||
p = [self.post.person]
|
|
||||||
end
|
|
||||||
p
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def receive(user, person)
|
def parent
|
||||||
local_comment = Comment.where(:guid => self.guid).first
|
self.post
|
||||||
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
|
end
|
||||||
|
|
||||||
#sign comment as the post creator if you've been hit UPSTREAM
|
def parent= parent
|
||||||
if user.owns? comment.post
|
self.post = parent
|
||||||
comment.post_creator_signature = comment.sign_with_key(user.encryption_key)
|
|
||||||
comment.save
|
|
||||||
end
|
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
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class Post < ActiveRecord::Base
|
class Post < ActiveRecord::Base
|
||||||
require File.join(Rails.root, 'lib/encryptable')
|
|
||||||
require File.join(Rails.root, 'lib/diaspora/web_socket')
|
require File.join(Rails.root, 'lib/diaspora/web_socket')
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
include ROXML
|
include ROXML
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,7 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def salmon(post)
|
def salmon(post)
|
||||||
created_salmon = Salmon::SalmonSlap.create(self, post.to_diaspora_xml)
|
Salmon::SalmonSlap.create(self, post.to_diaspora_xml)
|
||||||
created_salmon
|
|
||||||
end
|
end
|
||||||
|
|
||||||
######## Commenting ########
|
######## Commenting ########
|
||||||
|
|
@ -139,21 +138,16 @@ class User < ActiveRecord::Base
|
||||||
:post => options[:on])
|
:post => options[:on])
|
||||||
comment.set_guid
|
comment.set_guid
|
||||||
#sign comment as commenter
|
#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
|
#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
|
end
|
||||||
|
|
||||||
comment
|
comment
|
||||||
end
|
end
|
||||||
|
|
||||||
def dispatch_comment(comment)
|
|
||||||
mailman = Postzord::Dispatch.new(self, comment)
|
|
||||||
mailman.post
|
|
||||||
end
|
|
||||||
|
|
||||||
######### Mailer #######################
|
######### Mailer #######################
|
||||||
def mail(job, *args)
|
def mail(job, *args)
|
||||||
unless self.disable_mail
|
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.
|
# 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|
|
create_table "aspect_memberships", :force => true do |t|
|
||||||
t.integer "aspect_id", :null => false
|
t.integer "aspect_id", :null => false
|
||||||
|
|
@ -43,8 +43,8 @@ ActiveRecord::Schema.define(:version => 20110228201109) do
|
||||||
t.integer "post_id", :null => false
|
t.integer "post_id", :null => false
|
||||||
t.integer "person_id", :null => false
|
t.integer "person_id", :null => false
|
||||||
t.string "guid", :null => false
|
t.string "guid", :null => false
|
||||||
t.text "creator_signature"
|
t.text "author_signature"
|
||||||
t.text "post_creator_signature"
|
t.text "parent_author_signature"
|
||||||
t.text "youtube_titles"
|
t.text "youtube_titles"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_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)
|
receive_with_zord(@user3, @user1.person, xml)
|
||||||
|
|
||||||
@comment = @user3.comment('tada',:on => @post)
|
@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
|
@xml = @comment.to_diaspora_xml
|
||||||
@comment.delete
|
@comment.delete
|
||||||
end
|
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
|
@user2.reload.visible_posts.should include message
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
||||||
|
|
@ -8,48 +8,41 @@ describe Comment do
|
||||||
before do
|
before do
|
||||||
@alices_aspect = alice.aspects.first
|
@alices_aspect = alice.aspects.first
|
||||||
@bobs_aspect = bob.aspects.first
|
@bobs_aspect = bob.aspects.first
|
||||||
|
|
||||||
|
@bob = bob
|
||||||
|
@eve = eve
|
||||||
|
@status = alice.post(:status_message, :message => "hello", :to => @alices_aspect.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'comment#notification_type' do
|
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
|
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
|
comment.notification_type(alice, bob.person).should == Notifications::CommentOnPost
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns false if the comment is not on a post you own and no one "also_commented"' do
|
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 = alice.comment("I simply felt like issuing a greeting. Do step off.", :on => @status)
|
||||||
comment.notification_type(@sam, alice.person).should == false
|
comment.notification_type(@bob, alice.person).should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
context "also commented" do
|
context "also commented" do
|
||||||
before do
|
before do
|
||||||
bob.comment("a-commenta commenta", :on => @alices_post)
|
@bob.comment("a-commenta commenta", :on => @status)
|
||||||
@comment = @sam.comment("I also commented on the first user's post", :on => @alices_post)
|
@comment = @eve.comment("I also commented on the first user's post", :on => @status)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not return also commented if the user commented' do
|
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
|
end
|
||||||
|
|
||||||
it "returns 'also_commented' if another person commented on a post you commented on" do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
describe 'User#comment' do
|
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
|
it "should be able to comment on one's own status" do
|
||||||
alice.comment("Yeah, it was great", :on => @status)
|
alice.comment("Yeah, it was great", :on => @status)
|
||||||
@status.reload.comments.first.text.should == "Yeah, it was great"
|
@status.reload.comments.first.text.should == "Yeah, it was great"
|
||||||
|
|
@ -59,66 +52,13 @@ describe Comment do
|
||||||
bob.comment("sup dog", :on => @status)
|
bob.comment("sup dog", :on => @status)
|
||||||
@status.reload.comments.first.text.should == "sup dog"
|
@status.reload.comments.first.text.should == "sup dog"
|
||||||
end
|
end
|
||||||
end
|
it 'does not multi-post a comment' do
|
||||||
|
lambda {
|
||||||
context 'comment propagation' do
|
alice.comment 'hello', :on => @status
|
||||||
before do
|
}.should change { Comment.count }.by(1)
|
||||||
@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
|
||||||
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
|
describe 'xml' do
|
||||||
before do
|
before do
|
||||||
@commenter = Factory.create(:user)
|
@commenter = Factory.create(:user)
|
||||||
|
|
@ -146,59 +86,6 @@ describe Comment do
|
||||||
end
|
end
|
||||||
end
|
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
|
describe 'youtube' do
|
||||||
before do
|
before do
|
||||||
|
|
@ -220,4 +107,74 @@ describe Comment do
|
||||||
Comment.find(comment.id).youtube_titles.should == {video_id => CGI::escape(expected_title)}
|
Comment.find(comment.id).youtube_titles.should == {video_id => CGI::escape(expected_title)}
|
||||||
end
|
end
|
||||||
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
|
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
|
fantasy_resque do
|
||||||
p = build_post(class_name, opts)
|
p = build_post(class_name, opts)
|
||||||
if p.save!
|
if p.save!
|
||||||
raise 'MongoMapper failed to catch a failed save' unless p.id
|
|
||||||
|
|
||||||
self.aspects.reload
|
self.aspects.reload
|
||||||
|
|
||||||
aspects = self.aspects_from_ids(opts[:to])
|
aspects = self.aspects_from_ids(opts[:to])
|
||||||
add_to_streams(p, aspects)
|
add_to_streams(p, aspects)
|
||||||
dispatch_post(p, :to => opts[:to])
|
dispatch_post(p, :to => opts[:to])
|
||||||
|
|
@ -34,8 +31,7 @@ class User
|
||||||
fantasy_resque do
|
fantasy_resque do
|
||||||
c = build_comment(text, options)
|
c = build_comment(text, options)
|
||||||
if c.save!
|
if c.save!
|
||||||
raise 'MongoMapper failed to catch a failed save' unless c.id
|
Postzord::Dispatch.new(self, c).post
|
||||||
dispatch_comment(c)
|
|
||||||
end
|
end
|
||||||
c
|
c
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue