diff --git a/app/models/account_deletion.rb b/app/models/account_deletion.rb
index ee99a00bb..581593b04 100644
--- a/app/models/account_deletion.rb
+++ b/app/models/account_deletion.rb
@@ -3,8 +3,7 @@
# the COPYRIGHT file.
class AccountDeletion < ActiveRecord::Base
- include ROXML
- include Diaspora::Webhooks
+ include Diaspora::Federated::Base
belongs_to :person
@@ -15,6 +14,7 @@ class AccountDeletion < ActiveRecord::Base
xml_name :account_deletion
xml_attr :diaspora_handle
+
def person=(person)
self[:diaspora_handle] = person.diaspora_handle
self[:person_id] = person.id
diff --git a/app/models/comment.rb b/app/models/comment.rb
index a19b09cb9..d608ca27f 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -3,9 +3,9 @@
# the COPYRIGHT file.
class Comment < ActiveRecord::Base
- include ROXML
- include Diaspora::Webhooks
+ include Diaspora::Federated::Base
+
include Diaspora::Guid
include Diaspora::Relayable
diff --git a/app/models/conversation.rb b/app/models/conversation.rb
index 437750310..4fc891280 100644
--- a/app/models/conversation.rb
+++ b/app/models/conversation.rb
@@ -1,7 +1,6 @@
class Conversation < ActiveRecord::Base
- include ROXML
+ include Diaspora::Federated::Base
include Diaspora::Guid
- include Diaspora::Webhooks
xml_attr :subject
xml_attr :created_at
diff --git a/app/models/message.rb b/app/models/message.rb
index c8741736a..699bbb934 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -1,9 +1,7 @@
class NotVisibleError < RuntimeError; end
class Message < ActiveRecord::Base
- include ROXML
-
+ include Diaspora::Federated::Base
include Diaspora::Guid
- include Diaspora::Webhooks
include Diaspora::Relayable
xml_attr :text
diff --git a/app/models/photo.rb b/app/models/photo.rb
index c30e4d26e..54b3a9f6b 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -5,10 +5,12 @@
class Photo < ActiveRecord::Base
require 'carrierwave/orm/activerecord'
+ include Diaspora::Federated::Shareable
include Diaspora::Commentable
include Diaspora::Shareable
+
# NOTE API V1 to be extracted
acts_as_api
api_accessible :backbone do |t|
diff --git a/app/models/post.rb b/app/models/post.rb
index f171edd8c..8c5b2753e 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -5,10 +5,13 @@
class Post < ActiveRecord::Base
include ApplicationHelper
+ include Diaspora::Federated::Shareable
+
include Diaspora::Likeable
include Diaspora::Commentable
include Diaspora::Shareable
+
has_many :participations, :dependent => :delete_all, :as => :target
attr_accessor :user_like,
diff --git a/app/models/profile.rb b/app/models/profile.rb
index 9bf2025c4..8cb9bb3b5 100644
--- a/app/models/profile.rb
+++ b/app/models/profile.rb
@@ -3,10 +3,8 @@
# the COPYRIGHT file.
class Profile < ActiveRecord::Base
- require File.join(Rails.root, 'lib/diaspora/webhooks')
- include Diaspora::Webhooks
+ include Diaspora::Federated::Base
include Diaspora::Taggable
- include ROXML
attr_accessor :tag_string
diff --git a/app/models/request.rb b/app/models/request.rb
index 7bed46d73..0b0f446b3 100644
--- a/app/models/request.rb
+++ b/app/models/request.rb
@@ -4,8 +4,7 @@
# the COPYRIGHT file.
class Request
- include ROXML
- include Diaspora::Webhooks
+ include Diaspora::Federated::Base
include ActiveModel::Validations
attr_accessor :sender, :recipient, :aspect
diff --git a/app/models/retraction.rb b/app/models/retraction.rb
index 6c5aa34b1..3a35c28f2 100644
--- a/app/models/retraction.rb
+++ b/app/models/retraction.rb
@@ -3,8 +3,7 @@
# the COPYRIGHT file.
class Retraction
- include ROXML
- include Diaspora::Webhooks
+ include Diaspora::Federated::Base
xml_accessor :post_guid
xml_accessor :diaspora_handle
diff --git a/app/models/signed_retraction.rb b/app/models/signed_retraction.rb
index c515b963f..67a6812c1 100644
--- a/app/models/signed_retraction.rb
+++ b/app/models/signed_retraction.rb
@@ -3,8 +3,8 @@
# the COPYRIGHT file.
class SignedRetraction
- include ROXML
- include Diaspora::Webhooks
+ include Diaspora::Federated::Base
+
include Diaspora::Encryptable
xml_name :signed_retraction
diff --git a/lib/diaspora.rb b/lib/diaspora.rb
index 2a836faaf..18d812247 100644
--- a/lib/diaspora.rb
+++ b/lib/diaspora.rb
@@ -4,5 +4,4 @@
module Diaspora
autoload :Parser
- autoload :Webhooks
end
diff --git a/lib/diaspora/federated/base.rb b/lib/diaspora/federated/base.rb
new file mode 100644
index 000000000..32054cca6
--- /dev/null
+++ b/lib/diaspora/federated/base.rb
@@ -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
+
+ #{to_xml.to_s}
+
+ XML
+ end
+
+ def x(input)
+ input.to_s.to_xs
+ end
+
+ # @abstract
+ # @note this must return [Array]
+ # @return [Array]
+ 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
diff --git a/lib/diaspora/federated/shareable.rb b/lib/diaspora/federated/shareable.rb
new file mode 100644
index 000000000..a2c4ce957
--- /dev/null
+++ b/lib/diaspora/federated/shareable.rb
@@ -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] 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
\ No newline at end of file
diff --git a/lib/diaspora/guid.rb b/lib/diaspora/guid.rb
index aa8ae8d81..3a7b1d54d 100644
--- a/lib/diaspora/guid.rb
+++ b/lib/diaspora/guid.rb
@@ -1,9 +1,13 @@
+#implicitly requires roxml
+
module Diaspora::Guid
# Creates a before_create callback which calls #set_guid and makes the guid serialize in to_xml
def self.included(model)
model.class_eval do
before_create :set_guid
xml_attr :guid
+ validates :guid, :uniqueness => true
+
end
end
diff --git a/lib/diaspora/ostatus_builder.rb b/lib/diaspora/ostatus_builder.rb
deleted file mode 100644
index 56150ee93..000000000
--- a/lib/diaspora/ostatus_builder.rb
+++ /dev/null
@@ -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
-
-
-Diaspora
-#{@user.public_url}.atom
-#{x(@user.name)}'s Public Feed
-Updates from #{x(@user.name)} on Diaspora
-#{@user.person.profile.image_url(:thumb_small)}
-#{Time.now.xmlschema}
- XML
- end
-
- def create_subject
- <<-XML
-
- http://activitystrea.ms/schema/1.0/person
- #{x(@user.name)}
- #{local_or_remote_person_path(@user.person, :absolute => true)}
- #{x(@user.username)}
- #{x(@user.person.name)}
-
- XML
- end
-
- def create_endpoints
- <<-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
-
- XML
- end
- end
-end
diff --git a/lib/diaspora/shareable.rb b/lib/diaspora/shareable.rb
index fb7f3c12e..759020825 100644
--- a/lib/diaspora/shareable.rb
+++ b/lib/diaspora/shareable.rb
@@ -1,15 +1,12 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# 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 Shareable
- include Diaspora::Webhooks
-
def self.included(model)
model.instance_eval do
- include ROXML
- include Diaspora::Guid
has_many :aspect_visibilities, :as => :shareable
has_many :aspects, :through => :aspect_visibilities
@@ -19,7 +16,6 @@ module Diaspora
belongs_to :author, :class_name => 'Person'
- validates :guid, :uniqueness => true
#scopes
scope :all_public, where(:public => true, :pending => false)
@@ -27,9 +23,10 @@ module Diaspora
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'").
joins("LEFT OUTER JOIN contacts ON contacts.id = share_visibilities.contact_id").
- where(Contact.arel_table[:user_id].eq(user.id).or(
- self.arel_table[:public].eq(true).or(
- self.arel_table[:author_id].eq(user.person.id)
+ where(
+ Contact.arel_table[:user_id].eq(user.id).or(
+ self.arel_table[:public].eq(true).or(
+ 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')
where("#{self.table_name}.#{order} < ?", max_time).order("#{self.table_name}.#{order} desc")
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] 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
@@ -103,48 +50,5 @@ module Diaspora
self.class.where(:id => self.id).
update_all(:reshares_count => self.reshares.count)
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
diff --git a/lib/diaspora/webhooks.rb b/lib/diaspora/webhooks.rb
deleted file mode 100644
index 582b4bd21..000000000
--- a/lib/diaspora/webhooks.rb
+++ /dev/null
@@ -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
- <
- #{to_xml.to_s}
-
-XML
- end
-
- def x(input)
- input.to_s.to_xs
- end
-
- # @abstract
- # @note this must return [Array]
- # @return [Array]
- 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
diff --git a/lib/federated/relayable.rb b/lib/federated/relayable.rb
index 618c24820..d852a4dcd 100644
--- a/lib/federated/relayable.rb
+++ b/lib/federated/relayable.rb
@@ -3,9 +3,7 @@ module Federated
self.abstract_class = true
#crazy ordering issues - DEATH TO ROXML
- include ROXML
-
- include Diaspora::Webhooks
+ include Diaspora::Federated::Base
include Diaspora::Guid
#seriously, don't try to move this shit around until you have killed ROXML
diff --git a/lib/postzord/dispatcher.rb b/lib/postzord/dispatcher.rb
index 6e2676bed..6726c39d2 100644
--- a/lib/postzord/dispatcher.rb
+++ b/lib/postzord/dispatcher.rb
@@ -25,7 +25,7 @@ class Postzord::Dispatcher
# @return [Postzord::Dispatcher] Public or private dispatcher depending on the object's intended audience
def self.build(user, object, opts={})
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
if self.object_should_be_processed_as_public?(object)
diff --git a/lib/postzord/presenter.rb b/lib/postzord/presenter.rb
new file mode 100644
index 000000000..5d70da3fb
--- /dev/null
+++ b/lib/postzord/presenter.rb
@@ -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
+
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index 554ccea0e..1911ab109 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -47,12 +47,10 @@ describe UsersController do
end
it 'redirects to a profile page if html is requested' do
- Diaspora::OstatusBuilder.should_not_receive(:new)
get :public, :username => @user.username
response.should be_redirect
end
it 'redirects to a profile page if mobile is requested' do
- Diaspora::OstatusBuilder.should_not_receive(:new)
get :public, :username => @user.username, :format => :mobile
response.should be_redirect
end
diff --git a/spec/lib/diaspora/webhooks_spec.rb b/spec/lib/diaspora/federated_base_spec.rb
similarity index 83%
rename from spec/lib/diaspora/webhooks_spec.rb
rename to spec/lib/diaspora/federated_base_spec.rb
index 30cda1e38..a3fbcbacc 100644
--- a/spec/lib/diaspora/webhooks_spec.rb
+++ b/spec/lib/diaspora/federated_base_spec.rb
@@ -4,11 +4,11 @@
require 'spec_helper'
-describe Diaspora::Webhooks do
+describe Diaspora::Federated::Base do
describe '#subscribers' do
it 'throws an error if the including module does not redefine it' do
class Foo
- include Diaspora::Webhooks
+ include Diaspora::Federated::Base
end
f = Foo.new
diff --git a/spec/lib/postzord/dispatcher_spec.rb b/spec/lib/postzord/dispatcher_spec.rb
index f53229b36..c7f5f915f 100644
--- a/spec/lib/postzord/dispatcher_spec.rb
+++ b/spec/lib/postzord/dispatcher_spec.rb
@@ -42,7 +42,7 @@ describe Postzord::Dispatcher do
it 'raises and gives you a helpful message if the object can not federate' do
expect {
Postzord::Dispatcher.build(alice, [])
- }.should raise_error /Diaspora::Webhooks/
+ }.should raise_error /Diaspora::Federated::Base/
end
end
diff --git a/spec/lib/web_hooks_spec.rb b/spec/lib/web_hooks_spec.rb
deleted file mode 100644
index d50a403fb..000000000
--- a/spec/lib/web_hooks_spec.rb
+++ /dev/null
@@ -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