diaspora/lib/diaspora/federated/shareable.rb

116 lines
No EOL
4.3 KiB
Ruby

# Copyright (c) 2012, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
#this module attempts to be what you need to mix into
# base level federation objects that are not relayable, and not persistable
#assumes there is an author, author_id, id,
module Diaspora
module Federated
module Shareable
def self.included(model)
model.instance_eval do
#we are order dependant so you don't have to be!
include Diaspora::Federated::Base
include Diaspora::Federated::Shareable::InstanceMethods
include Diaspora::Guid
xml_attr :diaspora_handle
xml_attr :public
xml_attr :created_at
end
end
module InstanceMethods
def diaspora_handle
read_attribute(:diaspora_handle) || self.author.diaspora_handle
end
def diaspora_handle=(author_handle)
self.author = Person.where(:diaspora_handle => author_handle).first
write_attribute(:diaspora_handle, author_handle)
end
# @param [User] user The user that is receiving this shareable.
# @param [Person] person The person who dispatched this shareable to the
# @return [void]
def receive(user, person)
#exists locally, but you dont know about it
#does not exsist locally, and you dont know about it
#exists_locally?
#you know about it, and it is mutable
#you know about it, and it is not mutable
self.class.transaction do
local_shareable = persisted_shareable
if local_shareable && verify_persisted_shareable(local_shareable)
self.receive_persisted(user, person, local_shareable)
elsif !local_shareable
self.receive_non_persisted(user, person)
else
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason='update not from shareable owner' existing_shareable=#{self.id}")
false
end
end
end
# The list of people that should receive this Shareable.
#
# @param [User] user The context, or dispatching user.
# @return [Array<Person>] The list of subscribers to this shareable
def subscribers(user)
if self.public?
user.contact_people
else
user.people_in_aspects(user.aspects_with_shareable(self.class, self.id))
end
end
protected
# @return [Shareable,void]
def persisted_shareable
self.class.where(:guid => self.guid).first
end
# @return [Boolean]
def verify_persisted_shareable(persisted_shareable)
persisted_shareable.author_id == self.author_id
end
def receive_persisted(user, person, local_shareable)
known_shareable = user.find_visible_shareable_by_id(self.class.base_class, self.guid, :key => :guid)
if known_shareable
if known_shareable.mutable?
known_shareable.update_attributes(self.attributes)
true
else
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason=immutable") #existing_shareable=#{known_shareable.id}")
false
end
else
user.contact_for(person).receive_shareable(local_shareable)
user.notify_if_mentioned(local_shareable)
Rails.logger.info("event=receive payload_type=#{self.class} update=true status=complete sender=#{self.diaspora_handle}") #existing_shareable=#{local_shareable.id}")
true
end
end
def receive_non_persisted(user, person)
if self.save
user.contact_for(person).receive_shareable(self)
user.notify_if_mentioned(self)
Rails.logger.info("event=receive payload_type=#{self.class} update=false status=complete sender=#{self.diaspora_handle}")
true
else
Rails.logger.info("event=receive payload_type=#{self.class} update=false status=abort sender=#{self.diaspora_handle} reason=#{self.errors.full_messages}")
false
end
end
end
end
end
end