introduce the idea of Federated::Base. this is mostly just renaming and collasping of different federation modules, but also starting a direct hiearchy of these federation classes to make everything easier to refactor
This commit is contained in:
parent
49b0a44738
commit
27a4c1bf2d
24 changed files with 236 additions and 262 deletions
|
|
@ -3,8 +3,7 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class AccountDeletion < ActiveRecord::Base
|
class AccountDeletion < ActiveRecord::Base
|
||||||
include ROXML
|
include Diaspora::Federated::Base
|
||||||
include Diaspora::Webhooks
|
|
||||||
|
|
||||||
|
|
||||||
belongs_to :person
|
belongs_to :person
|
||||||
|
|
@ -15,6 +14,7 @@ class AccountDeletion < ActiveRecord::Base
|
||||||
xml_name :account_deletion
|
xml_name :account_deletion
|
||||||
xml_attr :diaspora_handle
|
xml_attr :diaspora_handle
|
||||||
|
|
||||||
|
|
||||||
def person=(person)
|
def person=(person)
|
||||||
self[:diaspora_handle] = person.diaspora_handle
|
self[:diaspora_handle] = person.diaspora_handle
|
||||||
self[:person_id] = person.id
|
self[:person_id] = person.id
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class Comment < ActiveRecord::Base
|
class Comment < ActiveRecord::Base
|
||||||
include ROXML
|
|
||||||
|
|
||||||
include Diaspora::Webhooks
|
include Diaspora::Federated::Base
|
||||||
|
|
||||||
include Diaspora::Guid
|
include Diaspora::Guid
|
||||||
include Diaspora::Relayable
|
include Diaspora::Relayable
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
class Conversation < ActiveRecord::Base
|
class Conversation < ActiveRecord::Base
|
||||||
include ROXML
|
include Diaspora::Federated::Base
|
||||||
include Diaspora::Guid
|
include Diaspora::Guid
|
||||||
include Diaspora::Webhooks
|
|
||||||
|
|
||||||
xml_attr :subject
|
xml_attr :subject
|
||||||
xml_attr :created_at
|
xml_attr :created_at
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
class NotVisibleError < RuntimeError; end
|
class NotVisibleError < RuntimeError; end
|
||||||
class Message < ActiveRecord::Base
|
class Message < ActiveRecord::Base
|
||||||
include ROXML
|
include Diaspora::Federated::Base
|
||||||
|
|
||||||
include Diaspora::Guid
|
include Diaspora::Guid
|
||||||
include Diaspora::Webhooks
|
|
||||||
include Diaspora::Relayable
|
include Diaspora::Relayable
|
||||||
|
|
||||||
xml_attr :text
|
xml_attr :text
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,12 @@
|
||||||
class Photo < ActiveRecord::Base
|
class Photo < ActiveRecord::Base
|
||||||
require 'carrierwave/orm/activerecord'
|
require 'carrierwave/orm/activerecord'
|
||||||
|
|
||||||
|
include Diaspora::Federated::Shareable
|
||||||
include Diaspora::Commentable
|
include Diaspora::Commentable
|
||||||
include Diaspora::Shareable
|
include Diaspora::Shareable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# NOTE API V1 to be extracted
|
# NOTE API V1 to be extracted
|
||||||
acts_as_api
|
acts_as_api
|
||||||
api_accessible :backbone do |t|
|
api_accessible :backbone do |t|
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,13 @@
|
||||||
class Post < ActiveRecord::Base
|
class Post < ActiveRecord::Base
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
|
||||||
|
include Diaspora::Federated::Shareable
|
||||||
|
|
||||||
include Diaspora::Likeable
|
include Diaspora::Likeable
|
||||||
include Diaspora::Commentable
|
include Diaspora::Commentable
|
||||||
include Diaspora::Shareable
|
include Diaspora::Shareable
|
||||||
|
|
||||||
|
|
||||||
has_many :participations, :dependent => :delete_all, :as => :target
|
has_many :participations, :dependent => :delete_all, :as => :target
|
||||||
|
|
||||||
attr_accessor :user_like,
|
attr_accessor :user_like,
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,8 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class Profile < ActiveRecord::Base
|
class Profile < ActiveRecord::Base
|
||||||
require File.join(Rails.root, 'lib/diaspora/webhooks')
|
include Diaspora::Federated::Base
|
||||||
include Diaspora::Webhooks
|
|
||||||
include Diaspora::Taggable
|
include Diaspora::Taggable
|
||||||
include ROXML
|
|
||||||
|
|
||||||
attr_accessor :tag_string
|
attr_accessor :tag_string
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class Request
|
class Request
|
||||||
include ROXML
|
include Diaspora::Federated::Base
|
||||||
include Diaspora::Webhooks
|
|
||||||
include ActiveModel::Validations
|
include ActiveModel::Validations
|
||||||
|
|
||||||
attr_accessor :sender, :recipient, :aspect
|
attr_accessor :sender, :recipient, :aspect
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class Retraction
|
class Retraction
|
||||||
include ROXML
|
include Diaspora::Federated::Base
|
||||||
include Diaspora::Webhooks
|
|
||||||
|
|
||||||
xml_accessor :post_guid
|
xml_accessor :post_guid
|
||||||
xml_accessor :diaspora_handle
|
xml_accessor :diaspora_handle
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class SignedRetraction
|
class SignedRetraction
|
||||||
include ROXML
|
include Diaspora::Federated::Base
|
||||||
include Diaspora::Webhooks
|
|
||||||
include Diaspora::Encryptable
|
include Diaspora::Encryptable
|
||||||
|
|
||||||
xml_name :signed_retraction
|
xml_name :signed_retraction
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,4 @@
|
||||||
|
|
||||||
module Diaspora
|
module Diaspora
|
||||||
autoload :Parser
|
autoload :Parser
|
||||||
autoload :Webhooks
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
56
lib/diaspora/federated/base.rb
Normal file
56
lib/diaspora/federated/base.rb
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
# Copyright (c) 2010-2012, Diaspora Inc. This file is
|
||||||
|
# licensed under the Affero General Public License version 3 or later. See
|
||||||
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
|
#the base level federation contract, which right now means that the object
|
||||||
|
#can be serialized and deserialized from xml, and respond to methods
|
||||||
|
#in the federation flow
|
||||||
|
|
||||||
|
|
||||||
|
#including this module lets you federate an object at the most basic of level
|
||||||
|
|
||||||
|
require 'builder/xchar'
|
||||||
|
|
||||||
|
module Diaspora
|
||||||
|
module Federated
|
||||||
|
module Base
|
||||||
|
def self.included(model)
|
||||||
|
model.instance_eval do
|
||||||
|
include ROXML
|
||||||
|
include Diaspora::Federated::Base::InstanceMethods
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module InstanceMethods
|
||||||
|
def to_diaspora_xml
|
||||||
|
<<-XML
|
||||||
|
<XML>
|
||||||
|
<post>#{to_xml.to_s}</post>
|
||||||
|
</XML>
|
||||||
|
XML
|
||||||
|
end
|
||||||
|
|
||||||
|
def x(input)
|
||||||
|
input.to_s.to_xs
|
||||||
|
end
|
||||||
|
|
||||||
|
# @abstract
|
||||||
|
# @note this must return [Array<Person>]
|
||||||
|
# @return [Array<Person>]
|
||||||
|
def subscribers(user)
|
||||||
|
raise 'You must override subscribers in order to enable federation on this model'
|
||||||
|
end
|
||||||
|
|
||||||
|
# @abstract
|
||||||
|
def receive(user, person)
|
||||||
|
raise 'You must override receive in order to enable federation on this model'
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param [User] sender
|
||||||
|
# @note this is a hook(optional)
|
||||||
|
def after_dispatch(sender)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
116
lib/diaspora/federated/shareable.rb
Normal file
116
lib/diaspora/federated/shareable.rb
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
# 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
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
|
#implicitly requires roxml
|
||||||
|
|
||||||
module Diaspora::Guid
|
module Diaspora::Guid
|
||||||
# Creates a before_create callback which calls #set_guid and makes the guid serialize in to_xml
|
# Creates a before_create callback which calls #set_guid and makes the guid serialize in to_xml
|
||||||
def self.included(model)
|
def self.included(model)
|
||||||
model.class_eval do
|
model.class_eval do
|
||||||
before_create :set_guid
|
before_create :set_guid
|
||||||
xml_attr :guid
|
xml_attr :guid
|
||||||
|
validates :guid, :uniqueness => true
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,80 +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.
|
|
||||||
|
|
||||||
module Diaspora
|
|
||||||
|
|
||||||
class Director
|
|
||||||
def initialize
|
|
||||||
@structure = [:create_headers, :create_endpoints, :create_subject,
|
|
||||||
:create_body, :create_footer]
|
|
||||||
end
|
|
||||||
|
|
||||||
def build(builder)
|
|
||||||
@structure.inject("") do |xml, method|
|
|
||||||
xml << builder.send(method) if builder.respond_to? method
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
class OstatusBuilder
|
|
||||||
include Diaspora::Webhooks
|
|
||||||
include PeopleHelper
|
|
||||||
|
|
||||||
def initialize(user, posts)
|
|
||||||
@user = user
|
|
||||||
@posts = posts
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_headers
|
|
||||||
<<-XML
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:georss="http://www.georss.org/georss" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:media="http://purl.org/syndication/atommedia" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:statusnet="http://status.net/schema/api/1/">
|
|
||||||
<generator uri="#{AppConfig[:pod_url]}">Diaspora</generator>
|
|
||||||
<id>#{@user.public_url}.atom</id>
|
|
||||||
<title>#{x(@user.name)}'s Public Feed</title>
|
|
||||||
<subtitle>Updates from #{x(@user.name)} on Diaspora</subtitle>
|
|
||||||
<logo>#{@user.person.profile.image_url(:thumb_small)}</logo>
|
|
||||||
<updated>#{Time.now.xmlschema}</updated>
|
|
||||||
XML
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_subject
|
|
||||||
<<-XML
|
|
||||||
<author>
|
|
||||||
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
|
|
||||||
<name>#{x(@user.name)}</name>
|
|
||||||
<uri>#{local_or_remote_person_path(@user.person, :absolute => true)}</uri>
|
|
||||||
<poco:preferredUsername>#{x(@user.username)}</poco:preferredUsername>
|
|
||||||
<poco:displayName>#{x(@user.person.name)}</poco:displayName>
|
|
||||||
</author>
|
|
||||||
XML
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_endpoints
|
|
||||||
<<-XML
|
|
||||||
<link rel="alternate" type="text/html" href="#{@user.public_url}" />
|
|
||||||
<link rel="avatar" type="image/jpeg" media:width="100" media:height="100" href="#{@user.profile.image_url}"/>
|
|
||||||
<link href="#{AppConfig[:pubsub_server]}" rel="hub"/>
|
|
||||||
<link href="#{@user.public_url}.atom" rel="self" type="application/atom+xml"/>
|
|
||||||
XML
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_body
|
|
||||||
@posts.inject("") do |xml,curr|
|
|
||||||
if curr.respond_to?(:to_activity)
|
|
||||||
xml + curr.to_activity(:author => @user.person)
|
|
||||||
else
|
|
||||||
xml
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_footer
|
|
||||||
<<-XML
|
|
||||||
</feed>
|
|
||||||
XML
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
# Copyright (c) 2010, Diaspora Inc. This file is
|
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||||
# licensed under the Affero General Public License version 3 or later. See
|
# licensed under the Affero General Public License version 3 or later. See
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
#the pont of this object is to centralize the simmilarities of Photo and post,
|
||||||
|
# as they used to be the same class
|
||||||
module Diaspora
|
module Diaspora
|
||||||
module Shareable
|
module Shareable
|
||||||
include Diaspora::Webhooks
|
|
||||||
|
|
||||||
def self.included(model)
|
def self.included(model)
|
||||||
model.instance_eval do
|
model.instance_eval do
|
||||||
include ROXML
|
|
||||||
include Diaspora::Guid
|
|
||||||
|
|
||||||
has_many :aspect_visibilities, :as => :shareable
|
has_many :aspect_visibilities, :as => :shareable
|
||||||
has_many :aspects, :through => :aspect_visibilities
|
has_many :aspects, :through => :aspect_visibilities
|
||||||
|
|
@ -19,7 +16,6 @@ module Diaspora
|
||||||
|
|
||||||
belongs_to :author, :class_name => 'Person'
|
belongs_to :author, :class_name => 'Person'
|
||||||
|
|
||||||
validates :guid, :uniqueness => true
|
|
||||||
|
|
||||||
#scopes
|
#scopes
|
||||||
scope :all_public, where(:public => true, :pending => false)
|
scope :all_public, where(:public => true, :pending => false)
|
||||||
|
|
@ -27,7 +23,8 @@ module Diaspora
|
||||||
def self.owned_or_visible_by_user(user)
|
def self.owned_or_visible_by_user(user)
|
||||||
self.joins("LEFT OUTER JOIN share_visibilities ON share_visibilities.shareable_id = posts.id AND share_visibilities.shareable_type = 'Post'").
|
self.joins("LEFT OUTER JOIN share_visibilities ON share_visibilities.shareable_id = posts.id AND share_visibilities.shareable_type = 'Post'").
|
||||||
joins("LEFT OUTER JOIN contacts ON contacts.id = share_visibilities.contact_id").
|
joins("LEFT OUTER JOIN contacts ON contacts.id = share_visibilities.contact_id").
|
||||||
where(Contact.arel_table[:user_id].eq(user.id).or(
|
where(
|
||||||
|
Contact.arel_table[:user_id].eq(user.id).or(
|
||||||
self.arel_table[:public].eq(true).or(
|
self.arel_table[:public].eq(true).or(
|
||||||
self.arel_table[:author_id].eq(user.person.id)
|
self.arel_table[:author_id].eq(user.person.id)
|
||||||
)
|
)
|
||||||
|
|
@ -45,56 +42,6 @@ module Diaspora
|
||||||
def self.by_max_time(max_time, order='created_at')
|
def self.by_max_time(max_time, order='created_at')
|
||||||
where("#{self.table_name}.#{order} < ?", max_time).order("#{self.table_name}.#{order} desc")
|
where("#{self.table_name}.#{order} < ?", max_time).order("#{self.table_name}.#{order} desc")
|
||||||
end
|
end
|
||||||
|
|
||||||
xml_attr :diaspora_handle
|
|
||||||
xml_attr :public
|
|
||||||
xml_attr :created_at
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def diaspora_handle
|
|
||||||
read_attribute(:diaspora_handle) || self.author.diaspora_handle
|
|
||||||
end
|
|
||||||
|
|
||||||
def diaspora_handle= nd
|
|
||||||
self.author = Person.where(:diaspora_handle => nd).first
|
|
||||||
write_attribute(:diaspora_handle, nd)
|
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -103,48 +50,5 @@ module Diaspora
|
||||||
self.class.where(:id => self.id).
|
self.class.where(:id => self.id).
|
||||||
update_all(:reshares_count => self.reshares.count)
|
update_all(:reshares_count => self.reshares.count)
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -1,38 +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.
|
|
||||||
|
|
||||||
module Diaspora
|
|
||||||
module Webhooks
|
|
||||||
require 'builder/xchar'
|
|
||||||
|
|
||||||
def to_diaspora_xml
|
|
||||||
<<XML
|
|
||||||
<XML>
|
|
||||||
<post>#{to_xml.to_s}</post>
|
|
||||||
</XML>
|
|
||||||
XML
|
|
||||||
end
|
|
||||||
|
|
||||||
def x(input)
|
|
||||||
input.to_s.to_xs
|
|
||||||
end
|
|
||||||
|
|
||||||
# @abstract
|
|
||||||
# @note this must return [Array<Person>]
|
|
||||||
# @return [Array<Person>]
|
|
||||||
def subscribers(user)
|
|
||||||
raise 'You must override subscribers in order to enable federation on this model'
|
|
||||||
end
|
|
||||||
|
|
||||||
# @abstract
|
|
||||||
def receive(user, person)
|
|
||||||
raise 'You must override receive in order to enable federation on this model'
|
|
||||||
end
|
|
||||||
|
|
||||||
# @param [User] sender
|
|
||||||
# @note this is a hook
|
|
||||||
def after_dispatch sender
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -3,9 +3,7 @@ module Federated
|
||||||
self.abstract_class = true
|
self.abstract_class = true
|
||||||
|
|
||||||
#crazy ordering issues - DEATH TO ROXML
|
#crazy ordering issues - DEATH TO ROXML
|
||||||
include ROXML
|
include Diaspora::Federated::Base
|
||||||
|
|
||||||
include Diaspora::Webhooks
|
|
||||||
include Diaspora::Guid
|
include Diaspora::Guid
|
||||||
|
|
||||||
#seriously, don't try to move this shit around until you have killed ROXML
|
#seriously, don't try to move this shit around until you have killed ROXML
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class Postzord::Dispatcher
|
||||||
# @return [Postzord::Dispatcher] Public or private dispatcher depending on the object's intended audience
|
# @return [Postzord::Dispatcher] Public or private dispatcher depending on the object's intended audience
|
||||||
def self.build(user, object, opts={})
|
def self.build(user, object, opts={})
|
||||||
unless object.respond_to? :to_diaspora_xml
|
unless object.respond_to? :to_diaspora_xml
|
||||||
raise 'This object does not respond_to? to_diaspora xml. Try including Diaspora::Webhooks into your object'
|
raise 'This object does not respond_to? to_diaspora xml. Try including Diaspora::Federated::Base into your object'
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.object_should_be_processed_as_public?(object)
|
if self.object_should_be_processed_as_public?(object)
|
||||||
|
|
|
||||||
33
lib/postzord/presenter.rb
Normal file
33
lib/postzord/presenter.rb
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#dispatching
|
||||||
|
#a class that figures out the markup of an object
|
||||||
|
class Federated::Presenter
|
||||||
|
end
|
||||||
|
|
||||||
|
#a class that detects the audience of a post
|
||||||
|
class Federated::Audience
|
||||||
|
end
|
||||||
|
|
||||||
|
#this class dispatchs the post to services, like facebook, twitter, etc
|
||||||
|
class ServiceDispatcher
|
||||||
|
#interacts with a single post, and many provided services
|
||||||
|
end
|
||||||
|
|
||||||
|
#Receiving Phases
|
||||||
|
#receive request => check author
|
||||||
|
#xml payload
|
||||||
|
#decode
|
||||||
|
#convert to meta object
|
||||||
|
#perfom various validations
|
||||||
|
#recieve! <= save object, if applicable
|
||||||
|
#after_receive hook
|
||||||
|
|
||||||
|
|
||||||
|
Ideas:
|
||||||
|
Federated objects are delegated stubs of real objects, with converstion constuctors
|
||||||
|
- this turns receive to "make model level object from payload"
|
||||||
|
- seperate validations and checking with persistance and noticiation layer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
http => deserliaization/decoding/descrypting => meta object => validations => receive => cleanup
|
||||||
|
|
||||||
|
|
@ -47,12 +47,10 @@ describe UsersController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'redirects to a profile page if html is requested' do
|
it 'redirects to a profile page if html is requested' do
|
||||||
Diaspora::OstatusBuilder.should_not_receive(:new)
|
|
||||||
get :public, :username => @user.username
|
get :public, :username => @user.username
|
||||||
response.should be_redirect
|
response.should be_redirect
|
||||||
end
|
end
|
||||||
it 'redirects to a profile page if mobile is requested' do
|
it 'redirects to a profile page if mobile is requested' do
|
||||||
Diaspora::OstatusBuilder.should_not_receive(:new)
|
|
||||||
get :public, :username => @user.username, :format => :mobile
|
get :public, :username => @user.username, :format => :mobile
|
||||||
response.should be_redirect
|
response.should be_redirect
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@
|
||||||
|
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe Diaspora::Webhooks do
|
describe Diaspora::Federated::Base do
|
||||||
describe '#subscribers' do
|
describe '#subscribers' do
|
||||||
it 'throws an error if the including module does not redefine it' do
|
it 'throws an error if the including module does not redefine it' do
|
||||||
class Foo
|
class Foo
|
||||||
include Diaspora::Webhooks
|
include Diaspora::Federated::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
f = Foo.new
|
f = Foo.new
|
||||||
|
|
@ -42,7 +42,7 @@ describe Postzord::Dispatcher do
|
||||||
it 'raises and gives you a helpful message if the object can not federate' do
|
it 'raises and gives you a helpful message if the object can not federate' do
|
||||||
expect {
|
expect {
|
||||||
Postzord::Dispatcher.build(alice, [])
|
Postzord::Dispatcher.build(alice, [])
|
||||||
}.should raise_error /Diaspora::Webhooks/
|
}.should raise_error /Diaspora::Federated::Base/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +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.
|
|
||||||
|
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Diaspora::Webhooks do
|
|
||||||
it "should add the following methods to Post on inclusion" do
|
|
||||||
user = Factory.build(:user)
|
|
||||||
post = Factory.build(:status_message, :author => user.person)
|
|
||||||
|
|
||||||
post.respond_to?(:to_diaspora_xml).should be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Loading…
Reference in a new issue