This commit is contained in:
Oliver Azevedo Barnes 2013-08-07 15:05:34 -05:00
parent 689abfb49c
commit 5564644306
12 changed files with 363 additions and 339 deletions

View file

@ -1,64 +0,0 @@
# Copyright (c) 2010-2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
class RelayableRetraction < SignedRetraction
xml_name :relayable_retraction
xml_attr :parent_author_signature
attr_accessor :parent_author_signature
delegate :parent, :parent_author, to: :target, allow_nil: true
def signable_accessors
super - ['parent_author_signature']
end
# @param sender [User]
# @param target [Object]
def self.build(sender, target)
retraction = super
retraction.parent_author_signature = retraction.sign_with_key(sender.encryption_key) if defined?(target.parent) && sender.person == target.parent.author
retraction
end
def diaspora_handle
self.sender_handle
end
def relayable?
true
end
def perform receiving_user
Rails.logger.debug "Performing relayable retraction for #{target_guid}"
if not self.parent_author_signature.nil? or self.parent.author.remote?
# Don't destroy a relayable unless the top-level owner has received it, otherwise it may not get relayed
self.target.destroy
Rails.logger.info("event=relayable_retraction status =complete target_type=#{self.target_type} guid =#{self.target_guid}")
end
end
def receive(recipient, sender)
if self.target.nil?
Rails.logger.info("event=retraction status=abort reason='no post found' sender=#{sender.diaspora_handle} target_guid=#{target_guid}")
return
elsif self.parent.author == recipient.person && self.target_author_signature_valid?
#this is a retraction from the downstream object creator, and the recipient is the upstream owner
self.parent_author_signature = self.sign_with_key(recipient.encryption_key)
Postzord::Dispatcher.build(recipient, self).post
self.perform(recipient)
elsif self.parent_author_signature_valid?
#this is a retraction from the upstream owner
self.perform(recipient)
else
Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{recipient.diaspora_handle} sender=#{self.parent.author.diaspora_handle} payload_type=#{self.class} parent_id=#{self.parent.id}")
return
end
self
end
def parent_author_signature_valid?
verify_signature(self.parent_author_signature, self.parent.author)
end
end

View file

@ -0,0 +1,69 @@
# 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 Federated
module Messages
class RelayableRetraction < SignedRetraction
xml_name :relayable_retraction
xml_attr :parent_author_signature
attr_accessor :parent_author_signature
delegate :parent, :parent_author, to: :target, allow_nil: true
def signable_accessors
super - ['parent_author_signature']
end
# @param sender [User]
# @param target [Object]
def self.build(sender, target)
retraction = super
retraction.parent_author_signature = retraction.sign_with_key(sender.encryption_key) if defined?(target.parent) && sender.person == target.parent.author
retraction
end
def diaspora_handle
self.sender_handle
end
def relayable?
true
end
def perform receiving_user
Rails.logger.debug "Performing relayable retraction for #{target_guid}"
if not self.parent_author_signature.nil? or self.parent.author.remote?
# Don't destroy a relayable unless the top-level owner has received it, otherwise it may not get relayed
self.target.destroy
Rails.logger.info("event=relayable_retraction status =complete target_type=#{self.target_type} guid =#{self.target_guid}")
end
end
def receive(recipient, sender)
if self.target.nil?
Rails.logger.info("event=retraction status=abort reason='no post found' sender=#{sender.diaspora_handle} target_guid=#{target_guid}")
return
elsif self.parent.author == recipient.person && self.target_author_signature_valid?
#this is a retraction from the downstream object creator, and the recipient is the upstream owner
self.parent_author_signature = self.sign_with_key(recipient.encryption_key)
Postzord::Dispatcher.build(recipient, self).post
self.perform(recipient)
elsif self.parent_author_signature_valid?
#this is a retraction from the upstream owner
self.perform(recipient)
else
Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{recipient.diaspora_handle} sender=#{self.parent.author.diaspora_handle} payload_type=#{self.class} parent_id=#{self.parent.id}")
return
end
self
end
def parent_author_signature_valid?
verify_signature(self.parent_author_signature, self.parent.author)
end
end
end
end
end

View file

@ -0,0 +1,107 @@
# Copyright (c) 2010-2011, Diaspora Inc. This file is
# t
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
module Diaspora
module Federated
module Messages
class Request
include Diaspora::Federated::Base
include ActiveModel::Validations
attr_accessor :sender, :recipient, :aspect
xml_accessor :sender_handle
xml_accessor :recipient_handle
validates :sender, :presence => true
validates :recipient, :presence => true
validate :not_already_connected
validate :not_friending_yourself
# Initalize variables
# @note we should be using ActiveModel::Serialization for this
# @return [Request]
def self.diaspora_initialize(opts = {})
req = self.new
req.sender = opts[:from]
req.recipient = opts[:to]
req.aspect = opts[:into]
req
end
# Alias of sender_handle
# @return [String]
def diaspora_handle
sender_handle
end
# @note Used for XML marshalling
# @return [String]
def sender_handle
sender.diaspora_handle
end
def sender_handle= sender_handle
self.sender = Person.where(:diaspora_handle => sender_handle).first
end
# @note Used for XML marshalling
# @return [String]
def recipient_handle
recipient.diaspora_handle
end
def recipient_handle= recipient_handle
self.recipient = Person.where(:diaspora_handle => recipient_handle).first
end
# Defines the abstract interface used in sending a corresponding [Notification] given the [Request]
# @param user [User]
# @param person [Person]
# @return [Notifications::StartedSharing]
def notification_type(user, person)
Notifications::StartedSharing
end
# Defines the abstract interface used in sending the [Request]
# @param user [User]
# @return [Array<Person>] The recipient of the request
def subscribers(user)
[self.recipient]
end
# Finds or initializes a corresponding [Contact], and will set Contact#sharing to true
# Follows back if user setting is set so
# @note A [Contact] may already exist if the [Request]'s recipient is sharing with the sender
# @return [Request]
def receive(user, person)
Rails.logger.info("event=receive payload_type=request sender=#{self.sender} to=#{self.recipient}")
contact = user.contacts.find_or_initialize_by_person_id(self.sender.id)
contact.sharing = true
contact.save
user.share_with(person, user.auto_follow_back_aspect) if user.auto_follow_back && !contact.receiving
self
end
private
# Checks if a [Contact] does not already exist between the requesting [User] and receiving [Person]
def not_already_connected
if sender && recipient && Contact.where(:user_id => self.recipient.owner_id, :person_id => self.sender.id).exists?
errors[:base] << 'You have already connected to this person'
end
end
# Checks to see that the requesting [User] is not sending a request to himself
def not_friending_yourself
if self.recipient == self.sender
errors[:base] << 'You can not friend yourself'
end
end
end
end
end
end

View file

@ -0,0 +1,69 @@
# 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 Federated
module Messages
class Retraction
include Diaspora::Federated::Base
xml_accessor :post_guid
xml_accessor :diaspora_handle
xml_accessor :type
attr_accessor :person, :object, :subscribers
def subscribers(user)
unless self.type == 'Person'
@subscribers ||= self.object.subscribers(user)
@subscribers -= self.object.resharers unless self.object.is_a?(Photo)
@subscribers
else
raise 'HAX: you must set the subscribers manaully before unfriending' if @subscribers.nil?
@subscribers
end
end
def self.for(object)
retraction = self.new
if object.is_a? User
retraction.post_guid = object.person.guid
retraction.type = object.person.class.to_s
else
retraction.post_guid = object.guid
retraction.type = object.class.to_s
retraction.object = object
end
retraction.diaspora_handle = object.diaspora_handle
retraction
end
def target
@target ||= self.type.constantize.where(:guid => post_guid).first
end
def perform receiving_user
Rails.logger.debug "Performing retraction for #{post_guid}"
self.target.destroy if self.target
Rails.logger.info("event=retraction status=complete type=#{self.type} guid=#{self.post_guid}")
end
def receive(user, person)
if self.type == 'Person'
unless self.person.guid.to_s == self.post_guid.to_s
Rails.logger.info("event=receive status=abort reason='sender is not the person he is trying to retract' recipient=#{self.diaspora_handle} sender=#{self.person.diaspora_handle} payload_type=#{self.class} retraction_type=person")
return
end
user.disconnected_by(self.target)
elsif self.target.nil? || self.target.author != self.person
Rails.logger.info("event=retraction status=abort reason='no post found authored by retractor' sender=#{person.diaspora_handle} post_guid=#{post_guid}")
else
self.perform(user)
end
self
end
end
end
end
end

View file

@ -0,0 +1,110 @@
# 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 Federated
module Messages
class SignedRetraction
include Diaspora::Federated::Base
include Diaspora::Encryptable
xml_name :signed_retraction
xml_attr :target_guid
xml_attr :target_type
xml_attr :sender_handle
xml_attr :target_author_signature
attr_accessor :target_guid,
:target_type,
:target_author_signature,
:sender
#NOTE(fix this hack -- go through the app and make sure we only call RelayableRetraction in a unified way)
def author
if sender.is_a?(User)
sender.person
else
sender
end
end
def signable_accessors
accessors = self.class.roxml_attrs.collect do |definition|
definition.accessor
end
accessors - ['target_author_signature', 'sender_handle']
end
def sender_handle= new_sender_handle
@sender = Person.where(:diaspora_handle => new_sender_handle).first
end
def sender_handle
@sender.diaspora_handle
end
def diaspora_handle
self.sender_handle
end
def subscribers(user)
self.target.subscribers(user)
end
def self.build(sender, target)
retraction = self.new
retraction.sender = sender
retraction.target = target
retraction.target_author_signature = retraction.sign_with_key(sender.encryption_key) if sender.person == target.author
retraction
end
def target
@target ||= self.target_type.constantize.where(:guid => target_guid).first
end
def guid
target_guid
end
def target= new_target
@target = new_target
@target_type = new_target.class.to_s
@target_guid = new_target.guid
end
def perform receiving_user
Rails.logger.debug "Performing retraction for #{target_guid}"
if reshare = Reshare.where(:author_id => receiving_user.person.id, :root_guid => target_guid).first
onward_retraction = self.dup
onward_retraction.sender = receiving_user.person
Postzord::Dispatcher.build(receiving_user, onward_retraction).post
end
if target
self.target.destroy
end
Rails.logger.info("event=retraction status =complete target_type=#{self.target_type} guid =#{self.target_guid}")
end
def receive(recipient, sender)
if self.target.nil?
Rails.logger.info("event=retraction status=abort reason='no post found' sender=#{sender.diaspora_handle} target_guid=#{target_guid}")
return
elsif self.target_author_signature_valid?
#this is a retraction from the upstream owner
self.perform(recipient)
else
Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{recipient.diaspora_handle} sender=#{self.sender_handle} payload_type=#{self.class}")
return
end
self
end
def target_author_signature_valid?
verify_signature(self.target_author_signature, self.target.author)
end
end
end
end
end

View file

@ -1,102 +0,0 @@
# Copyright (c) 2010-2011, Diaspora Inc. This file is
# t
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
class Request
include Diaspora::Federated::Base
include ActiveModel::Validations
attr_accessor :sender, :recipient, :aspect
xml_accessor :sender_handle
xml_accessor :recipient_handle
validates :sender, :presence => true
validates :recipient, :presence => true
validate :not_already_connected
validate :not_friending_yourself
# Initalize variables
# @note we should be using ActiveModel::Serialization for this
# @return [Request]
def self.diaspora_initialize(opts = {})
req = self.new
req.sender = opts[:from]
req.recipient = opts[:to]
req.aspect = opts[:into]
req
end
# Alias of sender_handle
# @return [String]
def diaspora_handle
sender_handle
end
# @note Used for XML marshalling
# @return [String]
def sender_handle
sender.diaspora_handle
end
def sender_handle= sender_handle
self.sender = Person.where(:diaspora_handle => sender_handle).first
end
# @note Used for XML marshalling
# @return [String]
def recipient_handle
recipient.diaspora_handle
end
def recipient_handle= recipient_handle
self.recipient = Person.where(:diaspora_handle => recipient_handle).first
end
# Defines the abstract interface used in sending a corresponding [Notification] given the [Request]
# @param user [User]
# @param person [Person]
# @return [Notifications::StartedSharing]
def notification_type(user, person)
Notifications::StartedSharing
end
# Defines the abstract interface used in sending the [Request]
# @param user [User]
# @return [Array<Person>] The recipient of the request
def subscribers(user)
[self.recipient]
end
# Finds or initializes a corresponding [Contact], and will set Contact#sharing to true
# Follows back if user setting is set so
# @note A [Contact] may already exist if the [Request]'s recipient is sharing with the sender
# @return [Request]
def receive(user, person)
Rails.logger.info("event=receive payload_type=request sender=#{self.sender} to=#{self.recipient}")
contact = user.contacts.find_or_initialize_by_person_id(self.sender.id)
contact.sharing = true
contact.save
user.share_with(person, user.auto_follow_back_aspect) if user.auto_follow_back && !contact.receiving
self
end
private
# Checks if a [Contact] does not already exist between the requesting [User] and receiving [Person]
def not_already_connected
if sender && recipient && Contact.where(:user_id => self.recipient.owner_id, :person_id => self.sender.id).exists?
errors[:base] << 'You have already connected to this person'
end
end
# Checks to see that the requesting [User] is not sending a request to himself
def not_friending_yourself
if self.recipient == self.sender
errors[:base] << 'You can not friend yourself'
end
end
end

View file

@ -1,64 +0,0 @@
# Copyright (c) 2010-2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
class Retraction
include Diaspora::Federated::Base
xml_accessor :post_guid
xml_accessor :diaspora_handle
xml_accessor :type
attr_accessor :person, :object, :subscribers
def subscribers(user)
unless self.type == 'Person'
@subscribers ||= self.object.subscribers(user)
@subscribers -= self.object.resharers unless self.object.is_a?(Photo)
@subscribers
else
raise 'HAX: you must set the subscribers manaully before unfriending' if @subscribers.nil?
@subscribers
end
end
def self.for(object)
retraction = self.new
if object.is_a? User
retraction.post_guid = object.person.guid
retraction.type = object.person.class.to_s
else
retraction.post_guid = object.guid
retraction.type = object.class.to_s
retraction.object = object
end
retraction.diaspora_handle = object.diaspora_handle
retraction
end
def target
@target ||= self.type.constantize.where(:guid => post_guid).first
end
def perform receiving_user
Rails.logger.debug "Performing retraction for #{post_guid}"
self.target.destroy if self.target
Rails.logger.info("event=retraction status=complete type=#{self.type} guid=#{self.post_guid}")
end
def receive(user, person)
if self.type == 'Person'
unless self.person.guid.to_s == self.post_guid.to_s
Rails.logger.info("event=receive status=abort reason='sender is not the person he is trying to retract' recipient=#{self.diaspora_handle} sender=#{self.person.diaspora_handle} payload_type=#{self.class} retraction_type=person")
return
end
user.disconnected_by(self.target)
elsif self.target.nil? || self.target.author != self.person
Rails.logger.info("event=retraction status=abort reason='no post found authored by retractor' sender=#{person.diaspora_handle} post_guid=#{post_guid}")
else
self.perform(user)
end
self
end
end

View file

@ -1,105 +0,0 @@
# Copyright (c) 2010-2011, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
class SignedRetraction
include Diaspora::Federated::Base
include Diaspora::Encryptable
xml_name :signed_retraction
xml_attr :target_guid
xml_attr :target_type
xml_attr :sender_handle
xml_attr :target_author_signature
attr_accessor :target_guid,
:target_type,
:target_author_signature,
:sender
#NOTE(fix this hack -- go through the app and make sure we only call RelayableRetraction in a unified way)
def author
if sender.is_a?(User)
sender.person
else
sender
end
end
def signable_accessors
accessors = self.class.roxml_attrs.collect do |definition|
definition.accessor
end
accessors - ['target_author_signature', 'sender_handle']
end
def sender_handle= new_sender_handle
@sender = Person.where(:diaspora_handle => new_sender_handle).first
end
def sender_handle
@sender.diaspora_handle
end
def diaspora_handle
self.sender_handle
end
def subscribers(user)
self.target.subscribers(user)
end
def self.build(sender, target)
retraction = self.new
retraction.sender = sender
retraction.target = target
retraction.target_author_signature = retraction.sign_with_key(sender.encryption_key) if sender.person == target.author
retraction
end
def target
@target ||= self.target_type.constantize.where(:guid => target_guid).first
end
def guid
target_guid
end
def target= new_target
@target = new_target
@target_type = new_target.class.to_s
@target_guid = new_target.guid
end
def perform receiving_user
Rails.logger.debug "Performing retraction for #{target_guid}"
if reshare = Reshare.where(:author_id => receiving_user.person.id, :root_guid => target_guid).first
onward_retraction = self.dup
onward_retraction.sender = receiving_user.person
Postzord::Dispatcher.build(receiving_user, onward_retraction).post
end
if target
self.target.destroy
end
Rails.logger.info("event=retraction status =complete target_type=#{self.target_type} guid =#{self.target_guid}")
end
def receive(recipient, sender)
if self.target.nil?
Rails.logger.info("event=retraction status=abort reason='no post found' sender=#{sender.diaspora_handle} target_guid=#{target_guid}")
return
elsif self.target_author_signature_valid?
#this is a retraction from the upstream owner
self.perform(recipient)
else
Rails.logger.info("event=receive status=abort reason='object signature not valid' recipient=#{recipient.diaspora_handle} sender=#{self.sender_handle} payload_type=#{self.class}")
return
end
self
end
def target_author_signature_valid?
verify_signature(self.target_author_signature, self.target.author)
end
end

View file

@ -4,8 +4,9 @@
require 'spec_helper'
require Rails.root.join("spec", "shared_behaviors", "relayable")
require Rails.root.join('lib', 'diaspora', 'federated', 'messages')
describe RelayableRetraction do
describe Diaspora::Federated::Messages::RelayableRetraction do
before do
@local_luke, @local_leia, @remote_raphael = set_up_friends
@remote_parent = FactoryGirl.build(:status_message, :author => @remote_raphael)

View file

@ -3,8 +3,9 @@
# the COPYRIGHT file.
require 'spec_helper'
require Rails.root.join('lib', 'diaspora', 'federated', 'messages')
describe Request do
describe Diaspora::Federated::Messages::Request do
before do
@aspect = alice.aspects.first
end

View file

@ -3,8 +3,9 @@
# the COPYRIGHT file.
require 'spec_helper'
require Rails.root.join('lib', 'diaspora', 'federated', 'messages')
describe Retraction do
describe Diaspora::Federated::Messages::Retraction do
before do
@aspect = alice.aspects.first
alice.contacts.create(:person => eve.person, :aspects => [@aspect])

View file

@ -1,6 +1,7 @@
require 'spec_helper'
require Rails.root.join('lib', 'diaspora', 'federated', 'messages')
describe SignedRetraction do
describe Diaspora::Federated::Messages::SignedRetraction do
before do
@post = FactoryGirl.create(:status_message, :author => bob.person, :public => true)
@resharer = FactoryGirl.create(:user)