diaspora/lib/diaspora/relayable.rb
2011-09-14 15:50:07 -07:00

120 lines
3.7 KiB
Ruby

# Copyright (c) 2010-2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
module Diaspora
module Relayable
include Encryptable
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
validates_associated :parent
validates :author, :presence => true
end
end
# @return [Boolean] true
def relayable?
true
end
# @return [String]
def parent_guid
self.parent.guid
end
def parent_guid= new_parent_guid
self.parent = parent_class.where(:guid => new_parent_guid).first
end
# @return [Array<Person>]
def subscribers(user)
if user.owns?(self.parent)
self.parent.subscribers(user)
elsif user.owns?(self)
[self.parent.author]
else
[]
end
end
def receive(user, person)
self.class.transaction do
comment_or_like = self.class.where(:guid => self.guid).first || self
#check to make sure the signature of the comment or like comes from the person claiming to authoring said comment or like
unless comment_or_like.parent.author == user.person || comment_or_like.verify_parent_author_signature
Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{user.diaspora_handle} sender=#{self.parent.author.diaspora_handle} payload_type=#{self.class} parent_id=#{self.parent.id}")
return
end
#as the owner of the post being liked or commented on, you need to add your own signature in order to pass it to the people who received your original post
if user.owns? comment_or_like.parent
comment_or_like.parent_author_signature = comment_or_like.sign_with_key(user.encryption_key)
comment_or_like.save!
end
#dispatch object DOWNSTREAM, received it via UPSTREAM
unless user.owns?(comment_or_like)
comment_or_like.save!
Postzord::Dispatcher.build(user, comment_or_like).post
end
comment_or_like.socket_to_user(user) if comment_or_like.respond_to? :socket_to_user
if comment_or_like.after_receive(user, person)
comment_or_like
end
end
end
# @return [Object]
def after_receive(user, person)
self
end
def initialize_signatures
#sign relayable as model creator
self.author_signature = self.sign_with_key(author.owner.encryption_key)
if !self.parent.blank? && self.author.owns?(self.parent)
#sign relayable as parent object owner
self.parent_author_signature = sign_with_key(author.owner.encryption_key)
end
end
# @return [Boolean]
def verify_parent_author_signature
verify_signature(self.parent_author_signature, self.parent.author)
end
# @return [Boolean]
def signature_valid?
verify_signature(self.author_signature, self.author)
end
# @abstract
# @return [Class]
def parent_class
raise NotImplementedError.new('you must override parent_class in order to enable relayable on this model')
end
# @abstract
# @return An instance of Relayable#parent_class
def parent
raise NotImplementedError.new('you must override parent in order to enable relayable on this model')
end
# @abstract
# @param parent An instance of Relayable#parent_class
def parent= parent
raise NotImplementedError.new('you must override parent= in order to enable relayable on this model')
end
end
end