Merge pull request #7436 from SuperTux88/federation-update

Federation gem update
This commit is contained in:
Benjamin Neff 2017-07-14 01:31:32 +02:00
commit 01ca08b86f
No known key found for this signature in database
GPG key ID: 971464C3F1A90194
49 changed files with 591 additions and 632 deletions

View file

@ -13,7 +13,7 @@ gem "unicorn-worker-killer", "0.4.4"
# Federation
gem "diaspora_federation-rails", "0.1.9"
gem "diaspora_federation-rails", "0.2.0"
# API and JSON
@ -293,7 +293,7 @@ group :test do
gem "webmock", "2.3.2", require: false
gem "shoulda-matchers", "3.1.1"
gem "diaspora_federation-test", "0.1.9"
gem "diaspora_federation-test", "0.2.0"
# Coverage
gem 'coveralls', require: false

View file

@ -163,18 +163,18 @@ GEM
devise
rails (>= 3.0.4)
diaspora-prosody-config (0.0.7)
diaspora_federation (0.1.9)
faraday (>= 0.9.0, < 0.12.0)
diaspora_federation (0.2.0)
faraday (>= 0.9.0, < 0.13.0)
faraday_middleware (>= 0.10.0, < 0.12.0)
nokogiri (~> 1.6, >= 1.6.8)
typhoeus (~> 1.0)
valid (~> 1.0)
diaspora_federation-rails (0.1.9)
diaspora_federation (= 0.1.9)
rails (>= 4.2, < 6)
diaspora_federation-test (0.1.9)
diaspora_federation (= 0.1.9)
factory_girl (~> 4.7)
diaspora_federation-rails (0.2.0)
actionpack (>= 4.2, < 6)
diaspora_federation (= 0.2.0)
diaspora_federation-test (0.2.0)
diaspora_federation (= 0.2.0)
fabrication (~> 2.16.0)
uuid (~> 2.3.8)
diff-lcs (1.3)
docile (1.1.5)
@ -198,6 +198,7 @@ GEM
sigar (~> 0.7.3)
state_machines
thor
fabrication (2.16.1)
factory_girl (4.8.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.8.0)
@ -777,8 +778,8 @@ DEPENDENCIES
devise (= 4.2.0)
devise_lastseenable (= 0.0.6)
diaspora-prosody-config (= 0.0.7)
diaspora_federation-rails (= 0.1.9)
diaspora_federation-test (= 0.1.9)
diaspora_federation-rails (= 0.2.0)
diaspora_federation-test (= 0.2.0)
entypo-rails (= 3.0.0)
eye (= 0.9.1)
factory_girl_rails (= 4.8.0)

View file

@ -24,17 +24,6 @@
module Api
module OpenidConnect
class DiscoveryController < ApplicationController
def webfinger
jrd = {
links: [{
rel: OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE,
href: root_url
}]
}
jrd[:subject] = params[:resource] if params[:resource].present?
render json: jrd, content_type: "application/jrd+json"
end
def configuration
render json: OpenIDConnect::Discovery::Provider::Config::Response.new(
issuer: root_url,

View file

@ -18,14 +18,6 @@ class MessagesController < ApplicationController
logger.info "event=create type=message user=#{current_user.diaspora_handle} status=success " \
"message=#{message.id} chars=#{params[:message][:text].length}"
Diaspora::Federation::Dispatcher.defer_dispatch(current_user, message)
# TODO: can be removed when messages are not relayed anymore
conversation_owner = conversation.author.owner
if conversation_owner && conversation_owner != current_user
remote_subs = conversation.participants.remote.ids
opts = {subscriber_ids: remote_subs}
Diaspora::Federation::Dispatcher.defer_dispatch(conversation_owner, message, opts) unless remote_subs.empty?
end
else
flash[:error] = I18n.t('conversations.new_conversation.fail')
end

View file

@ -26,7 +26,6 @@ class PostsController < ApplicationController
render locals: {post: presenter}
end
format.mobile { render locals: {post: post} }
format.xml { render xml: DiasporaFederation::Salmon::XmlPayload.pack(Diaspora::Federation::Entities.post(post)) }
format.json { render json: presenter }
end
end

View file

@ -7,9 +7,6 @@ class Message < ActiveRecord::Base
delegate :name, to: :author, prefix: true
# TODO: can be removed when messages are not relayed anymore
alias_attribute :parent, :conversation
validates :conversation, presence: true
validates :text, presence: true
validate :participant_of_parent_conversation
@ -31,11 +28,7 @@ class Message < ActiveRecord::Base
# @return [Array<Person>]
def subscribers
if author.local?
conversation.participants
else # for relaying, TODO: can be removed when messages are not relayed anymore
conversation.participants.remote
end
conversation.participants
end
private

View file

@ -268,10 +268,6 @@ class User < ActiveRecord::Base
end
end
def salmon(post)
Salmon::EncryptedSlap.create_by_user_and_activity(self, post.to_diaspora_xml)
end
# Check whether the user has liked a post.
# @param [Post] post
def liked?(target)
@ -347,7 +343,7 @@ class User < ActiveRecord::Base
######### Posts and Such ###############
def retract(target)
retraction = Retraction.for(target, self)
retraction = Retraction.for(target)
retraction.defer_dispatch(self)
retraction.perform
end

View file

@ -34,7 +34,7 @@ class User
if contact.person.local?
contact.person.owner.disconnected_by(contact.user.person)
else
Retraction.for(contact).defer_dispatch(self)
ContactRetraction.for(contact).defer_dispatch(self)
end
contact.aspect_memberships.delete_all

View file

@ -6,10 +6,10 @@ module Workers
class DeferredRetraction < Base
sidekiq_options queue: :high
def perform(user_id, retraction_data, recipient_ids, opts)
def perform(user_id, retraction_class, retraction_data, recipient_ids, opts)
user = User.find(user_id)
subscribers = Person.where(id: recipient_ids)
object = Retraction.new(retraction_data.deep_symbolize_keys, subscribers)
object = retraction_class.constantize.new(retraction_data.deep_symbolize_keys, subscribers)
opts = HashWithIndifferentAccess.new(opts)
Diaspora::Federation::Dispatcher.build(user, object, opts).dispatch

View file

@ -8,7 +8,7 @@ module Workers
def filter_errors_for_retry
yield
rescue DiasporaFederation::Entity::ValidationError,
DiasporaFederation::Entity::InvalidRootNode,
DiasporaFederation::Parsers::BaseParser::InvalidRootNode,
DiasporaFederation::Entity::InvalidEntityName,
DiasporaFederation::Entity::UnknownEntity,
DiasporaFederation::Entities::Relayable::SignatureVerificationFailed,

View file

@ -13,16 +13,22 @@ DiasporaFederation.configure do |config|
person = Person.where(diaspora_handle: diaspora_id, closed_account: false).where.not(owner: nil).first
if person
DiasporaFederation::Discovery::WebFinger.new(
acct_uri: "acct:#{person.diaspora_handle}",
alias_url: AppConfig.url_to("/people/#{person.guid}"),
hcard_url: AppConfig.url_to(DiasporaFederation::Engine.routes.url_helpers.hcard_path(person.guid)),
seed_url: AppConfig.pod_uri,
profile_url: person.profile_url,
atom_url: person.atom_url,
salmon_url: person.receive_url,
subscribe_url: AppConfig.url_to("/people?q={uri}"),
guid: person.guid,
public_key: person.serialized_public_key
{
acct_uri: "acct:#{person.diaspora_handle}",
hcard_url: AppConfig.url_to(DiasporaFederation::Engine.routes.url_helpers.hcard_path(person.guid)),
seed_url: AppConfig.pod_uri,
profile_url: person.profile_url,
atom_url: person.atom_url,
salmon_url: person.receive_url,
subscribe_url: AppConfig.url_to("/people?q={uri}")
},
aliases: [AppConfig.url_to("/people/#{person.guid}")],
links: [
{
rel: OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE,
href: Rails.application.routes.url_helpers.root_url
}
]
)
end
end

View file

@ -230,6 +230,5 @@ Diaspora::Application.routes.draw do
end
end
get ".well-known/webfinger", to: "api/openid_connect/discovery#webfinger"
get ".well-known/openid-configuration", to: "api/openid_connect/discovery#configuration"
end

View file

@ -0,0 +1,5 @@
class RemoveMessageSignature < ActiveRecord::Migration
def change
remove_column :messages, :author_signature, :text
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20161107100840) do
ActiveRecord::Schema.define(version: 20170430022507) do
create_table "account_deletions", force: :cascade do |t|
t.string "diaspora_handle", limit: 255
@ -214,13 +214,12 @@ ActiveRecord::Schema.define(version: 20161107100840) do
add_index "mentions", ["person_id"], name: "index_mentions_on_person_id", using: :btree
create_table "messages", force: :cascade do |t|
t.integer "conversation_id", limit: 4, null: false
t.integer "author_id", limit: 4, null: false
t.string "guid", limit: 255, null: false
t.text "text", limit: 65535, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "author_signature", limit: 65535
t.integer "conversation_id", limit: 4, null: false
t.integer "author_id", limit: 4, null: false
t.string "guid", limit: 255, null: false
t.text "text", limit: 65535, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "messages", ["author_id"], name: "index_messages_on_author_id", using: :btree

View file

@ -6,5 +6,6 @@ module Diaspora
module Federated
require "diaspora/federated/base"
require "diaspora/federated/retraction"
require "diaspora/federated/contact_retraction"
end
end

View file

@ -0,0 +1,18 @@
class ContactRetraction < Retraction
def self.entity_class
DiasporaFederation::Entities::Contact
end
def self.retraction_data_for(target)
Diaspora::Federation::Entities.contact(target).to_h
end
def self.for(target)
target.receiving = false
super
end
def public?
false
end
end

View file

@ -14,23 +14,27 @@ class Retraction
@target = target
end
def self.for(target, sender=nil)
federation_retraction = case target
when Diaspora::Relayable
Diaspora::Federation::Entities.relayable_retraction(target, sender)
when Post
Diaspora::Federation::Entities.signed_retraction(target, sender)
else
Diaspora::Federation::Entities.retraction(target)
end
def self.entity_class
DiasporaFederation::Entities::Retraction
end
new(federation_retraction.to_h, target.subscribers.select(&:remote?), target)
def self.retraction_data_for(target)
DiasporaFederation::Entities::Retraction.new(
target_guid: target.guid,
target: Diaspora::Federation::Entities.related_entity(target),
target_type: Diaspora::Federation::Mappings.entity_name_for(target),
author: target.diaspora_handle
).to_h
end
def self.for(target)
federation_retraction_data = retraction_data_for(target)
new(federation_retraction_data, target.subscribers.select(&:remote?), target)
end
def defer_dispatch(user, include_target_author=true)
subscribers = dispatch_subscribers(include_target_author)
sender = dispatch_sender(user)
Workers::DeferredRetraction.perform_async(sender.id, data, subscribers.map(&:id), service_opts(user))
Workers::DeferredRetraction.perform_async(user.id, self.class.to_s, data, subscribers.map(&:id), service_opts(user))
end
def perform
@ -40,8 +44,7 @@ class Retraction
end
def public?
# TODO: backward compatibility for pre 0.6 pods, they don't relay public retractions
data[:target][:public] == "true" && (!data[:target][:parent] || data[:target][:parent][:local] == "true")
data[:target][:public]
end
private
@ -53,11 +56,6 @@ class Retraction
subscribers
end
# @deprecated This is only needed for pre 0.6 pods
def dispatch_sender(user)
target.try(:sender_for_dispatch) || user
end
def service_opts(user)
return {} unless target.is_a?(StatusMessage)

View file

@ -31,6 +31,16 @@ module Diaspora
attr_reader :sender, :object, :opts
def entity
@entity ||= Entities.build(object)
end
def magic_envelope
@magic_envelope ||= DiasporaFederation::Salmon::MagicEnvelope.new(
entity, sender.diaspora_handle
).envelop(sender.encryption_key)
end
def deliver_to_services
deliver_to_user_services if opts[:service_types]
end

View file

@ -7,22 +7,17 @@ module Diaspora
def deliver_to_remote(people)
return if people.empty?
entity = Entities.build(object)
Workers::SendPrivate.perform_async(sender.id, entity.to_s, targets(people, salmon_slap(entity)))
Workers::SendPrivate.perform_async(sender.id, entity.to_s, targets(people))
end
def targets(people, salmon_slap)
def targets(people)
active, inactive = people.partition {|person| person.pod.active? }
logger.info "ignoring inactive pods: #{inactive.map(&:diaspora_handle).join(', ')}" if inactive.any?
active.map {|person| [person.receive_url, salmon_slap.generate_xml(person.public_key)] }.to_h
active.map {|person| [person.receive_url, encrypted_magic_envelope(person)] }.to_h
end
def salmon_slap(entity)
DiasporaFederation::Salmon::EncryptedSlap.prepare(
sender.diaspora_handle,
sender.encryption_key,
entity
)
def encrypted_magic_envelope(person)
DiasporaFederation::Salmon::EncryptedMagicEnvelope.encrypt(magic_envelope, person.public_key)
end
end
end

View file

@ -14,8 +14,7 @@ module Diaspora
return if targets.empty?
entity = Entities.build(object)
Workers::SendPublic.perform_async(sender.id, entity.to_s, targets, salmon_xml(entity))
Workers::SendPublic.perform_async(sender.id, entity.to_s, targets, magic_envelope.to_xml)
end
def target_urls(people)
@ -29,14 +28,6 @@ module Diaspora
[AppConfig.relay.outbound.url]
end
def salmon_xml(entity)
DiasporaFederation::Salmon::Slap.generate_xml(
sender.diaspora_handle,
sender.encryption_key,
entity
)
end
def deliver_to_hub
logger.debug "deliver to pubsubhubbub sender: #{sender.diaspora_handle}"
Workers::PublishToHub.perform_async(sender.atom_url)

View file

@ -5,17 +5,6 @@ module Diaspora
public_send(Mappings.builder_for(entity.class), entity)
end
def self.build_retraction(retraction)
case retraction.data[:target_type]
when "Comment", "Like", "PollParticipation"
DiasporaFederation::Entities::RelayableRetraction.new(retraction.data)
when "Post"
DiasporaFederation::Entities::SignedRetraction.new(retraction.data)
else
DiasporaFederation::Entities::Retraction.new(retraction.data)
end
end
def self.post(post)
case post
when StatusMessage
@ -50,10 +39,11 @@ module Diaspora
end
def self.contact(contact)
# TODO: use DiasporaFederation::Entities::Contact
DiasporaFederation::Entities::Request.new(
DiasporaFederation::Entities::Contact.new(
author: contact.user.diaspora_handle,
recipient: contact.person.diaspora_handle
recipient: contact.person.diaspora_handle,
sharing: contact.receiving,
following: contact.receiving
)
end
@ -98,10 +88,7 @@ module Diaspora
guid: message.guid,
text: message.text,
created_at: message.created_at,
parent_guid: message.conversation.guid,
conversation_guid: message.conversation.guid,
author_signature: message.author_signature,
parent: related_entity(message.conversation)
conversation_guid: message.conversation.guid
)
end
@ -110,8 +97,7 @@ module Diaspora
author: participation.diaspora_handle,
guid: participation.guid,
parent_guid: participation.target.guid,
parent_type: Mappings.entity_name_for(participation.target),
parent: related_entity(participation.target)
parent_type: Mappings.entity_name_for(participation.target)
)
end
@ -178,16 +164,6 @@ module Diaspora
)
end
# @deprecated
def self.relayable_retraction(target, sender)
DiasporaFederation::Entities::RelayableRetraction.new(
target_guid: target.guid,
target_type: Mappings.entity_name_for(target),
target: related_entity(target),
author: sender.diaspora_handle
)
end
def self.reshare(reshare)
DiasporaFederation::Entities::Reshare.new(
root_author: reshare.root_diaspora_id,
@ -200,35 +176,8 @@ module Diaspora
)
end
def self.retraction(target)
case target
when Contact
# TODO: deprecated
author = target.user.diaspora_handle
DiasporaFederation::Entities::Retraction.new(
target_guid: target.user.guid,
target_type: "Person",
target: DiasporaFederation::Entities::RelatedEntity.new(author: author, local: true),
author: author
)
else
DiasporaFederation::Entities::Retraction.new(
target_guid: target.guid,
target_type: Mappings.entity_name_for(target),
target: related_entity(target),
author: target.diaspora_handle
)
end
end
# @deprecated
def self.signed_retraction(target, sender)
DiasporaFederation::Entities::SignedRetraction.new(
target_guid: target.guid,
target_type: Mappings.entity_name_for(target),
target: related_entity(target),
author: sender.diaspora_handle
)
def self.retraction(retraction)
retraction.class.entity_class.new(retraction.data)
end
def self.status_message(status_message)

View file

@ -49,7 +49,8 @@ module Diaspora
PollParticipation => :poll_participation,
Profile => :profile,
Reshare => :reshare,
Retraction => :build_retraction,
Retraction => :retraction,
ContactRetraction => :retraction,
StatusMessage => :status_message
}.freeze

View file

@ -25,7 +25,7 @@ module Diaspora
def self.contact(entity)
recipient = Person.find_by(diaspora_handle: entity.recipient).owner
if entity.sharing.to_s == "true"
if entity.sharing
Contact.create_or_update_sharing_contact(recipient, author_of(entity))
else
recipient.disconnected_by(author_of(entity))
@ -59,7 +59,9 @@ module Diaspora
end
def self.message(entity)
save_message(entity).tap {|message| relay_relayable(message) if message }
ignore_existing_guid(Message, entity.guid, author_of(entity)) do
build_message(entity).tap(&:save!)
end
end
def self.participation(entity)
@ -149,7 +151,7 @@ module Diaspora
when Diaspora::Relayable
if object.parent.author.local?
parent_author = object.parent.author.owner
retraction = Retraction.for(object, parent_author)
retraction = Retraction.for(object)
retraction.defer_dispatch(parent_author, false)
retraction.perform
else
@ -215,15 +217,6 @@ module Diaspora
end
end
private_class_method def self.save_message(entity)
ignore_existing_guid(Message, entity.guid, author_of(entity)) do
build_message(entity).tap do |message|
message.author_signature = entity.author_signature if message.conversation.author.local?
message.save!
end
end
end
private_class_method def self.save_photo(entity)
Photo.create!(
author: author_of(entity),
@ -263,8 +256,8 @@ module Diaspora
private_class_method def self.build_signature(klass, entity)
klass.reflect_on_association(:signature).klass.new(
author_signature: entity.author_signature,
additional_data: entity.additional_xml_elements,
signature_order: SignatureOrder.find_or_create_by!(order: entity.xml_order.join(" "))
additional_data: entity.additional_data,
signature_order: SignatureOrder.find_or_create_by!(order: entity.signature_order.join(" "))
)
end
@ -272,7 +265,7 @@ module Diaspora
parent_author = relayable.parent.author.owner
return unless parent_author && parent_author.ignored_people.include?(relayable.author)
retraction = Retraction.for(relayable, parent_author)
retraction = Retraction.for(relayable)
Diaspora::Federation::Dispatcher.build(parent_author, retraction, subscribers: [relayable.author]).dispatch
raise Diaspora::Federation::AuthorIgnored

View file

@ -36,7 +36,6 @@ module Diaspora
end
end
# @deprecated This is only needed for pre 0.6 pods
def sender_for_dispatch
parent.author.owner if parent.author.local?
end

View file

@ -1,20 +1,4 @@
describe Api::OpenidConnect::DiscoveryController, type: :controller do
describe "#webfinger" do
before do
get :webfinger, resource: "http://example.com/bob"
end
it "should return a url to the openid-configuration" do
json_body = JSON.parse(response.body)
expect(json_body["links"].first["href"]).to eq(root_url)
end
it "should return the resource in the subject" do
json_body = JSON.parse(response.body)
expect(json_body["subject"]).to eq("http://example.com/bob")
end
end
describe "#configuration" do
before do
get :configuration

View file

@ -102,19 +102,6 @@ describe MessagesController, :type => :controller do
expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Message))
post :create, @message_params
end
it "dispatches the message twice if the conversation author is local and it has remote users" do
@conversation_params[:participant_ids] = [bob.person.id, alice.person.id, remote_raphael.id]
conversation = Conversation.create!(@conversation_params)
@message_params[:conversation_id] = conversation.id
expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(alice, instance_of(Message))
expect(Diaspora::Federation::Dispatcher).to receive(:defer_dispatch).with(
bob, instance_of(Message), subscriber_ids: [remote_raphael.id]
)
post :create, @message_params
end
end
context 'on a post from a stranger' do

View file

@ -76,12 +76,6 @@ describe PostsController, type: :controller do
expect(response.body).to match "hello"
end
it "responds with diaspora xml if format is xml" do
get :show, id: public.guid, format: :xml
expected_xml = DiasporaFederation::Salmon::XmlPayload.pack(Diaspora::Federation::Entities.post(public)).to_xml
expect(response.body).to eq(expected_xml)
end
it "includes the correct uniques meta tags" do
presenter = PostPresenter.new(public)
methods_properties = {

View file

@ -10,8 +10,7 @@ def r_str
SecureRandom.hex(3)
end
require "diaspora_federation/test"
DiasporaFederation::Test::Factories.federation_factories
require "diaspora_federation/test/factories"
FactoryGirl.define do
factory :profile do
@ -246,10 +245,9 @@ FactoryGirl.define do
association(:post, factory: :status_message)
end
factory(:notification) do
factory(:notification, class: Notifications::AlsoCommented) do
association :recipient, :factory => :user
association :target, :factory => :comment
type 'Notifications::AlsoCommented'
after(:build) do |note|
note.actors << FactoryGirl.build(:person)

View file

@ -6,15 +6,20 @@ describe "diaspora federation callbacks" do
person = alice.person
wf = DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, alice.diaspora_handle)
expect(wf.acct_uri).to eq("acct:#{person.diaspora_handle}")
expect(wf.alias_url).to eq(AppConfig.url_to("/people/#{person.guid}"))
expect(wf.hcard_url).to eq(AppConfig.url_to("/hcard/users/#{person.guid}"))
expect(wf.seed_url).to eq(AppConfig.pod_uri)
expect(wf.profile_url).to eq(person.profile_url)
expect(wf.atom_url).to eq(person.atom_url)
expect(wf.salmon_url).to eq(person.receive_url)
expect(wf.subscribe_url).to eq(AppConfig.url_to("/people?q={uri}"))
expect(wf.guid).to eq(person.guid)
expect(wf.public_key).to eq(person.serialized_public_key)
end
it "contains the OpenID issuer" do
wf = DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, alice.diaspora_handle)
links = wf.additional_data[:links]
openid_issuer = links.find {|l| l[:rel] == OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE }
expect(openid_issuer).not_to be_nil
expect(openid_issuer[:href]).to eq(Rails.application.routes.url_helpers.root_url)
end
it "returns nil if the person was not found" do
@ -203,7 +208,7 @@ describe "diaspora federation callbacks" do
it "returns nil for an unknown id" do
expect(
DiasporaFederation.callbacks.trigger(:fetch_private_key, FactoryGirl.generate(:diaspora_id))
DiasporaFederation.callbacks.trigger(:fetch_private_key, Fabricate.sequence(:diaspora_id))
).to be_nil
end
end
@ -225,7 +230,7 @@ describe "diaspora federation callbacks" do
end
it "returns nil for an unknown person" do
diaspora_id = FactoryGirl.generate(:diaspora_id)
diaspora_id = Fabricate.sequence(:diaspora_id)
expect(Person).to receive(:find_or_fetch_by_identifier).with(diaspora_id)
.and_raise(DiasporaFederation::Discovery::DiscoveryError)
@ -295,7 +300,7 @@ describe "diaspora federation callbacks" do
it "returns nil for a non-existing guid" do
expect(
DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Post", FactoryGirl.generate(:guid))
DiasporaFederation.callbacks.trigger(:fetch_related_entity, "Post", Fabricate.sequence(:guid))
).to be_nil
end
end
@ -337,7 +342,7 @@ describe "diaspora federation callbacks" do
describe ":receive_entity" do
it "receives an AccountDeletion" do
account_deletion = FactoryGirl.build(:account_deletion_entity, author: remote_person.diaspora_handle)
account_deletion = Fabricate(:account_deletion_entity, author: remote_person.diaspora_handle)
expect(Diaspora::Federation::Receive).to receive(:account_deletion).with(account_deletion)
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
@ -346,7 +351,7 @@ describe "diaspora federation callbacks" do
end
it "receives a Retraction" do
retraction = FactoryGirl.build(:retraction_entity, author: remote_person.diaspora_handle)
retraction = Fabricate(:retraction_entity, author: remote_person.diaspora_handle)
expect(Diaspora::Federation::Receive).to receive(:retraction).with(retraction, 42)
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
@ -355,7 +360,7 @@ describe "diaspora federation callbacks" do
end
it "receives a entity" do
received = FactoryGirl.build(:status_message_entity, author: remote_person.diaspora_handle)
received = Fabricate(:status_message_entity, author: remote_person.diaspora_handle)
persisted = FactoryGirl.create(:status_message)
expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(persisted)
@ -365,7 +370,7 @@ describe "diaspora federation callbacks" do
end
it "calls schedule_check_if_needed on the senders pod" do
received = FactoryGirl.build(:status_message_entity, author: remote_person.diaspora_handle)
received = Fabricate(:status_message_entity, author: remote_person.diaspora_handle)
persisted = FactoryGirl.create(:status_message)
expect(Person).to receive(:by_account_identifier).with(received.author).and_return(remote_person)
@ -377,7 +382,7 @@ describe "diaspora federation callbacks" do
end
it "receives a entity for a recipient" do
received = FactoryGirl.build(:status_message_entity, author: remote_person.diaspora_handle)
received = Fabricate(:status_message_entity, author: remote_person.diaspora_handle)
persisted = FactoryGirl.create(:status_message)
expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(persisted)
@ -387,7 +392,7 @@ describe "diaspora federation callbacks" do
end
it "does not trigger a ReceiveLocal job if Receive.perform returned nil" do
received = FactoryGirl.build(:status_message_entity, author: remote_person.diaspora_handle)
received = Fabricate(:status_message_entity, author: remote_person.diaspora_handle)
expect(Diaspora::Federation::Receive).to receive(:perform).with(received).and_return(nil)
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
@ -460,7 +465,7 @@ describe "diaspora federation callbacks" do
end
it "forwards the DiscoveryError" do
diaspora_id = FactoryGirl.generate(:diaspora_id)
diaspora_id = Fabricate.sequence(:diaspora_id)
expect(Person).to receive(:find_or_fetch_by_identifier).with(diaspora_id)
.and_raise(DiasporaFederation::Discovery::DiscoveryError)

View file

@ -51,11 +51,11 @@ module HelperMethods
}.join(" ")
end
def build_relayable_federation_entity(type, data={}, additional_xml_elements={})
attributes = FactoryGirl.attributes_for("#{type}_entity".to_sym, data)
entity_class = "DiasporaFederation::Entities::#{type.capitalize}".constantize
signable_fields = attributes.keys - [:author_signature]
def build_relayable_federation_entity(type, data={}, additional_data={})
attributes = Fabricate.attributes_for("#{type}_entity".to_sym, data)
entity_class = "DiasporaFederation::Entities::#{type.to_s.camelize}".constantize
signable_fields = attributes.keys - %i[author_signature parent]
entity_class.new(attributes, [*signable_fields, *additional_xml_elements.keys], additional_xml_elements)
entity_class.new(attributes, [*signable_fields, *additional_data.keys], additional_data)
end
end

View file

@ -23,7 +23,7 @@ describe "attack vectors", type: :request do
alice.share_with(eve.person, alices_aspect)
post_message(generate_xml(Diaspora::Federation::Entities.post(original_message), bob, alice), alice)
post_message(generate_payload(Diaspora::Federation::Entities.post(original_message), bob, alice), alice)
# alice still should not see eves original post, even though bob sent it to her
expect(alice.reload.visible_shareables(Post).where(guid: original_message.guid)).to be_blank
@ -34,7 +34,7 @@ describe "attack vectors", type: :request do
profile = eve.profile.clone
profile.first_name = "Not BOB"
post_message(generate_xml(Diaspora::Federation::Entities.profile(profile), alice, bob), bob)
post_message(generate_payload(Diaspora::Federation::Entities.profile(profile), alice, bob), bob)
expect(eve.profile(true).first_name).not_to eq("Not BOB")
end
@ -42,16 +42,17 @@ describe "attack vectors", type: :request do
it "public post should not be spoofed from another author" do
post = FactoryGirl.build(:status_message, public: true, author: eve.person)
post_message(generate_xml(Diaspora::Federation::Entities.post(post), alice))
post_message(generate_payload(Diaspora::Federation::Entities.post(post), alice))
expect(StatusMessage.exists?(guid: post.guid)).to be_falsey
end
it "should not receive retractions where the retractor and the salmon author do not match" do
original_message = eve.post(:status_message, text: "store this!", to: eves_aspect.id)
retraction = Retraction.for(original_message)
expect {
post_message(generate_xml(Diaspora::Federation::Entities.retraction(original_message), alice, bob), bob)
post_message(generate_payload(Diaspora::Federation::Entities.retraction(retraction), alice, bob), bob)
}.to_not change { bob.visible_shareables(Post).count(:all) }
end
@ -61,7 +62,9 @@ describe "attack vectors", type: :request do
contact = bob.contacts(true).find_by(person_id: eve.person.id)
expect(contact).to be_sharing
post_message(generate_xml(Diaspora::Federation::Entities.retraction(contact), alice, bob), bob)
post_message(
generate_payload(Diaspora::Federation::Entities.retraction(ContactRetraction.for(contact)), alice, bob), bob
)
expect(bob.contacts(true).find_by(person_id: eve.person.id)).to be_sharing
end
@ -79,7 +82,7 @@ describe "attack vectors", type: :request do
author: alice.person
)
post_message(generate_xml(Diaspora::Federation::Entities.post(malicious_message), alice, bob), bob)
post_message(generate_payload(Diaspora::Federation::Entities.post(malicious_message), alice, bob), bob)
expect(original_message.reload.author_id).to eq(eve.person.id)
end
@ -92,7 +95,7 @@ describe "attack vectors", type: :request do
# eve tries to send me another message with the same ID
malicious_message = FactoryGirl.build(:status_message, id: original_message.id, text: "BAD!!!", author: eve.person)
post_message(generate_xml(Diaspora::Federation::Entities.post(malicious_message), eve, bob), bob)
post_message(generate_payload(Diaspora::Federation::Entities.post(malicious_message), eve, bob), bob)
expect(original_message.reload.text).to eq("store this!")
end
@ -108,7 +111,7 @@ describe "attack vectors", type: :request do
)
expect {
post_message(generate_xml(retraction, alice, bob), bob)
post_message(generate_payload(retraction, alice, bob), bob)
}.to_not change(StatusMessage, :count)
end
@ -121,7 +124,7 @@ describe "attack vectors", type: :request do
new_message.height = 23
new_message.width = 42
post_message(generate_xml(Diaspora::Federation::Entities.photo(new_message), alice, bob), bob)
post_message(generate_payload(Diaspora::Federation::Entities.photo(new_message), alice, bob), bob)
expect(original_message.reload.text).to eq("store this!")
end

View file

@ -35,41 +35,38 @@ def create_relayable_entity(entity_name, parent, diaspora_id)
:fetch_private_key, alice.diaspora_handle
).at_least(1).times.and_return(nil) if parent == local_parent
parent_guid = parent.guid
FactoryGirl.build(
Fabricate(
entity_name,
conversation_guid: parent_guid,
parent_guid: parent_guid,
author: diaspora_id,
poll_answer_guid: parent.respond_to?(:poll_answers) ? parent.poll_answers.first.guid : nil,
parent: Diaspora::Federation::Entities.related_entity(parent)
parent_guid: parent.guid,
author: diaspora_id,
poll_answer_guid: parent.respond_to?(:poll_answers) ? parent.poll_answers.first.guid : nil,
parent: Diaspora::Federation::Entities.related_entity(parent)
)
end
def generate_xml(entity, remote_user, recipient=nil)
def generate_payload(entity, remote_user, recipient=nil)
magic_env = DiasporaFederation::Salmon::MagicEnvelope.new(
entity,
remote_user.diaspora_handle
).envelop(remote_user.encryption_key)
if recipient
DiasporaFederation::Salmon::EncryptedSlap.prepare(
remote_user.diaspora_handle,
remote_user.encryption_key,
entity
).generate_xml(recipient.encryption_key)
DiasporaFederation::Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient.encryption_key)
else
DiasporaFederation::Salmon::Slap.generate_xml(
remote_user.diaspora_handle,
remote_user.encryption_key,
entity
)
magic_env.to_xml
end
end
def post_message(xml, recipient=nil)
def post_message(payload, recipient=nil)
if recipient
inlined_jobs do
post "/receive/users/#{recipient.guid}", guid: recipient.guid, xml: xml
headers = {"CONTENT_TYPE" => "application/json"}
post "/receive/users/#{recipient.guid}", payload, headers
end
else
inlined_jobs do
post "/receive/public", xml: xml
headers = {"CONTENT_TYPE" => "application/magic-envelope+xml"}
post "/receive/public", payload, headers
end
end
end

View file

@ -15,14 +15,14 @@ describe "Receive federation messages feature" do
let(:recipient) { nil }
it "receives account deletion correctly" do
post_message(generate_xml(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: sender_id), sender))
post_message(generate_payload(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: sender_id), sender))
expect(AccountDeletion.exists?(diaspora_handle: sender_id)).to be_truthy
end
it "rejects account deletion with wrong diaspora_id" do
delete_id = FactoryGirl.generate(:diaspora_id)
post_message(generate_xml(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: delete_id), sender))
delete_id = Fabricate.sequence(:diaspora_id)
post_message(generate_payload(DiasporaFederation::Entities::AccountDeletion.new(diaspora_id: delete_id), sender))
expect(AccountDeletion.exists?(diaspora_handle: delete_id)).to be_falsey
expect(AccountDeletion.exists?(diaspora_handle: sender_id)).to be_falsey
@ -31,14 +31,14 @@ describe "Receive federation messages feature" do
context "reshare" do
it "reshare of public post passes" do
post = FactoryGirl.create(:status_message, author: alice.person, public: true)
reshare = FactoryGirl.build(
reshare = Fabricate(
:reshare_entity, root_author: alice.diaspora_handle, root_guid: post.guid, author: sender_id)
expect(Participation::Generator).to receive(:new).with(
alice, instance_of(Reshare)
).and_return(double(create!: true))
post_message(generate_xml(reshare, sender))
post_message(generate_payload(reshare, sender))
expect(Reshare.exists?(root_guid: post.guid)).to be_truthy
expect(Reshare.where(root_guid: post.guid).last.diaspora_handle).to eq(sender_id)
@ -46,10 +46,10 @@ describe "Receive federation messages feature" do
it "reshare of private post fails" do
post = FactoryGirl.create(:status_message, author: alice.person, public: false)
reshare = FactoryGirl.build(
reshare = Fabricate(
:reshare_entity, root_author: alice.diaspora_handle, root_guid: post.guid, author: sender_id)
expect {
post_message(generate_xml(reshare, sender))
post_message(generate_payload(reshare, sender))
}.to raise_error ActiveRecord::RecordInvalid, "Validation failed: Only posts which are public may be reshared."
expect(Reshare.exists?(root_guid: post.guid)).to be_falsey
@ -73,12 +73,12 @@ describe "Receive federation messages feature" do
context "with private receive" do
let(:recipient) { alice }
it "treats sharing request recive correctly" do
entity = FactoryGirl.build(:request_entity, author: sender_id, recipient: alice.diaspora_handle)
it "treats sharing request receive correctly" do
entity = Fabricate(:contact_entity, author: sender_id, recipient: alice.diaspora_handle)
expect(Workers::ReceiveLocal).to receive(:perform_async).and_call_original
post_message(generate_xml(entity, sender, alice), alice)
post_message(generate_payload(entity, sender, alice), alice)
expect(alice.contacts.count).to eq(2)
new_contact = alice.contacts.find {|c| c.person.diaspora_handle == sender_id }
@ -105,8 +105,8 @@ describe "Receive federation messages feature" do
it_behaves_like "messages which can't be send without sharing"
it "treats profile receive correctly" do
entity = FactoryGirl.build(:profile_entity, author: sender_id)
post_message(generate_xml(entity, sender, alice), alice)
entity = Fabricate(:profile_entity, author: sender_id)
post_message(generate_payload(entity, sender, alice), alice)
received_profile = sender.profile.reload
@ -115,35 +115,70 @@ describe "Receive federation messages feature" do
end
it "receives conversation correctly" do
entity = FactoryGirl.build(
entity = Fabricate(
:conversation_entity,
author: sender_id,
participants: "#{sender_id};#{alice.diaspora_handle}"
)
post_message(generate_xml(entity, sender, alice), alice)
post_message(generate_payload(entity, sender, alice), alice)
expect(Conversation.exists?(guid: entity.guid)).to be_truthy
end
context "with message" do
let(:local_parent) {
FactoryGirl.build(:conversation, author: alice.person).tap do |target|
target.participants << remote_user_on_pod_b.person
target.participants << remote_user_on_pod_c.person
target.save
end
}
let(:remote_parent) {
FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person).tap do |target|
target.participants << alice.person
target.participants << remote_user_on_pod_c.person
target.save
end
}
let(:entity_name) { :message_entity }
let(:klass) { Message }
context "local" do
let(:parent) {
FactoryGirl.build(:conversation, author: alice.person).tap do |target|
target.participants << remote_user_on_pod_b.person
target.participants << remote_user_on_pod_c.person
target.save
end
}
let(:message) {
Fabricate(
:message_entity,
conversation_guid: parent.guid,
author: sender_id,
parent: Diaspora::Federation::Entities.related_entity(parent)
)
}
it_behaves_like "it deals correctly with a relayable"
it "receives the message correctly" do
expect(Workers::ReceiveLocal).to receive(:perform_async)
post_message(generate_payload(message, sender, recipient), recipient)
received_message = Message.find_by(guid: message.guid)
expect(received_message).not_to be_nil
expect(received_message.author.diaspora_handle).to eq(sender_id)
end
end
context "remote" do
let(:parent) {
FactoryGirl.build(:conversation, author: remote_user_on_pod_b.person).tap do |target|
target.participants << alice.person
target.participants << remote_user_on_pod_c.person
target.save
end
}
let(:message) {
Fabricate(
:message_entity,
conversation_guid: parent.guid,
author: remote_user_on_pod_c.diaspora_handle,
parent: Diaspora::Federation::Entities.related_entity(parent)
)
}
it "receives the message correctly" do
expect(Workers::ReceiveLocal).to receive(:perform_async)
post_message(generate_payload(message, remote_user_on_pod_c, recipient), recipient)
received_message = Message.find_by(guid: message.guid)
expect(received_message).not_to be_nil
expect(received_message.author.diaspora_handle).to eq(remote_user_on_pod_c.diaspora_handle)
end
end
end
end
end

View file

@ -4,7 +4,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "treats upstream receive correctly" do
expect(Workers::ReceiveLocal).to receive(:perform_async)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
received_entity = klass.find_by(guid: entity.guid)
expect(received_entity).not_to be_nil
@ -15,7 +15,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "rejects an upstream entity with a malformed author signature" do
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
allow(remote_user_on_pod_b).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(klass.exists?(guid: entity.guid)).to be_falsey
end
@ -28,7 +28,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "treats downstream receive correctly" do
expect(Workers::ReceiveLocal).to receive(:perform_async)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
received_entity = klass.find_by(guid: entity.guid)
expect(received_entity).not_to be_nil
@ -40,7 +40,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "rejects a downstream entity with a malformed author signature" do
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
allow(remote_user_on_pod_c).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(klass.exists?(guid: entity.guid)).to be_falsey
end
@ -50,7 +50,7 @@ shared_examples_for "it deals correctly with a relayable" do
it "declines downstream receive when sender signed with a wrong key" do
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(klass.exists?(guid: entity.guid)).to be_falsey
end

View file

@ -1,6 +1,6 @@
def retraction_entity(entity_name, target_object, sender)
FactoryGirl.build(
entity_name,
def retraction_entity(target_object, sender)
Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: target_object.guid,
target_type: target_object.class.to_s,
@ -10,23 +10,23 @@ end
shared_examples_for "it retracts non-relayable object" do
it "retracts object by a correct retraction message" do
entity = retraction_entity(entity_name, target_object, sender)
post_message(generate_xml(entity, sender, recipient), recipient)
entity = retraction_entity(target_object, sender)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_falsey
end
it "doesn't retract object when retraction has wrong signatures" do
allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
entity = retraction_entity(entity_name, target_object, sender)
post_message(generate_xml(entity, sender, recipient), recipient)
entity = retraction_entity(target_object, sender)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy
end
it "doesn't retract object when sender is different from target object" do
entity = retraction_entity(entity_name, target_object, remote_user_on_pod_c)
post_message(generate_xml(entity, remote_user_on_pod_c, recipient), recipient)
entity = retraction_entity(target_object, remote_user_on_pod_c)
post_message(generate_payload(entity, remote_user_on_pod_c, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy
end
@ -34,16 +34,16 @@ end
shared_examples_for "it retracts relayable object" do
it "retracts object by a correct message" do
entity = retraction_entity(entity_name, target_object, sender)
post_message(generate_xml(entity, sender, recipient), recipient)
entity = retraction_entity(target_object, sender)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_falsey
end
it "doesn't retract object when retraction has wrong signatures" do
allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
entity = retraction_entity(entity_name, target_object, sender)
post_message(generate_xml(entity, sender, recipient), recipient)
entity = retraction_entity(target_object, sender)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(target_object.class.exists?(guid: target_object.guid)).to be_truthy
end

View file

@ -4,18 +4,18 @@ shared_examples_for "messages which are indifferent about sharing fact" do
let(:public) { recipient.nil? }
it "treats status message receive correctly" do
entity = FactoryGirl.build(:status_message_entity, author: sender_id, public: public)
entity = Fabricate(:status_message_entity, author: sender_id, public: public)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(StatusMessage.exists?(guid: entity.guid)).to be_truthy
end
it "doesn't accept status message with wrong signature" do
allow(sender).to receive(:encryption_key).and_return(OpenSSL::PKey::RSA.new(1024))
entity = FactoryGirl.build(:status_message_entity, author: sender_id, public: public)
entity = Fabricate(:status_message_entity, author: sender_id, public: public)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(StatusMessage.exists?(guid: entity.guid)).to be_falsey
end
@ -27,7 +27,7 @@ shared_examples_for "messages which are indifferent about sharing fact" do
describe "notifications are sent where required" do
it "for comment on local post" do
entity = create_relayable_entity(:comment_entity, local_parent, remote_user_on_pod_b.diaspora_handle)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(
Notifications::CommentOnPost.exists?(
@ -40,7 +40,7 @@ shared_examples_for "messages which are indifferent about sharing fact" do
it "for like on local post" do
entity = create_relayable_entity(:like_entity, local_parent, remote_user_on_pod_b.diaspora_handle)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(
Notifications::Liked.exists?(
@ -62,11 +62,18 @@ shared_examples_for "messages which are indifferent about sharing fact" do
end
context "with participations" do
let(:entity) { create_relayable_entity(:participation_entity, local_parent, sender_id) }
let(:entity) {
Fabricate(
:participation_entity,
author: sender_id,
parent_guid: local_parent.guid,
parent: Diaspora::Federation::Entities.related_entity(local_parent)
)
}
it "treats participation receive correctly" do
expect(Workers::ReceiveLocal).to receive(:perform_async)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
received_entity = Participation.find_by(guid: entity.guid)
expect(received_entity).not_to be_nil
@ -77,7 +84,7 @@ shared_examples_for "messages which are indifferent about sharing fact" do
expect(Workers::ReceiveLocal).not_to receive(:perform_async)
entity = create_relayable_entity(:participation_entity, remote_parent, sender_id)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(Participation.exists?(guid: entity.guid)).to be_falsey
end
@ -107,17 +114,11 @@ end
shared_examples_for "messages which can't be send without sharing" do
# retractions shouldn't depend on sharing fact
describe "retractions for non-relayable objects" do
%w(retraction signed_retraction).each do |retraction_entity_name|
context "with #{retraction_entity_name}" do
let(:entity_name) { "#{retraction_entity_name}_entity".to_sym }
%w[status_message photo].each do |target|
context "with #{target}" do
let(:target_object) { FactoryGirl.create(target.to_sym, author: remote_user_on_pod_b.person) }
%w(status_message photo).each do |target|
context "with #{target}" do
let(:target_object) { FactoryGirl.create(target.to_sym, author: remote_user_on_pod_b.person) }
it_behaves_like "it retracts non-relayable object"
end
end
it_behaves_like "it retracts non-relayable object"
end
end
end
@ -133,7 +134,7 @@ shared_examples_for "messages which can't be send without sharing" do
alice.participate!(remote_parent)
author_id = remote_user_on_pod_c.diaspora_handle
entity = create_relayable_entity(:comment_entity, remote_parent, author_id)
post_message(generate_xml(entity, sender, recipient), recipient)
post_message(generate_payload(entity, sender, recipient), recipient)
expect(
Notifications::AlsoCommented.exists?(
@ -146,47 +147,41 @@ shared_examples_for "messages which can't be send without sharing" do
end
describe "retractions for relayable objects" do
%w(retraction signed_retraction relayable_retraction).each do |retraction_entity_name|
context "with #{retraction_entity_name}" do
let(:entity_name) { "#{retraction_entity_name}_entity".to_sym }
before do
allow(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_private_key, alice.diaspora_handle
) { alice.encryption_key }
end
before do
allow(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_private_key, alice.diaspora_handle
) { alice.encryption_key }
end
context "with comment" do
it_behaves_like "it retracts relayable object" do
# case for to-upstream federation
let(:target_object) {
FactoryGirl.create(:comment, author: remote_user_on_pod_b.person, post: local_parent)
}
end
context "with comment" do
it_behaves_like "it retracts relayable object" do
# case for to-upstream federation
let(:target_object) {
FactoryGirl.create(:comment, author: remote_user_on_pod_b.person, post: local_parent)
}
end
it_behaves_like "it retracts relayable object" do
# case for to-downsteam federation
let(:target_object) {
FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: remote_parent)
}
end
end
it_behaves_like "it retracts relayable object" do
# case for to-downsteam federation
let(:target_object) {
FactoryGirl.create(:comment, author: remote_user_on_pod_c.person, post: remote_parent)
}
end
end
context "with like" do
it_behaves_like "it retracts relayable object" do
# case for to-upstream federation
let(:target_object) {
FactoryGirl.create(:like, author: remote_user_on_pod_b.person, target: local_parent)
}
end
context "with like" do
it_behaves_like "it retracts relayable object" do
# case for to-upstream federation
let(:target_object) {
FactoryGirl.create(:like, author: remote_user_on_pod_b.person, target: local_parent)
}
end
it_behaves_like "it retracts relayable object" do
# case for to-downsteam federation
let(:target_object) {
FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: remote_parent)
}
end
end
it_behaves_like "it retracts relayable object" do
# case for to-downsteam federation
let(:target_object) {
FactoryGirl.create(:like, author: remote_user_on_pod_c.person, target: remote_parent)
}
end
end
end

View file

@ -73,7 +73,7 @@ module MentioningSpecHelpers
end
def receive_status_message_via_federation(text, *recipients)
entity = FactoryGirl.build(
entity = Fabricate(
:status_message_entity,
author: remote_raphael.diaspora_handle,
text: text,

View file

@ -0,0 +1,66 @@
describe ContactRetraction do
let(:contact) { FactoryGirl.build(:contact, sharing: true, receiving: true) }
let(:retraction) { ContactRetraction.for(contact) }
describe "#subscribers" do
it "contains the contact person" do
expect(retraction.subscribers).to eq([contact.person])
end
end
describe "#data" do
it "contains the hash with all data from the federation-retraction" do
federation_retraction_data = Diaspora::Federation::Entities.contact(contact).to_h
federation_retraction_data[:sharing] = false
federation_retraction_data[:following] = false
expect(retraction.data).to eq(federation_retraction_data)
end
end
describe ".retraction_data_for" do
it "creates a retraction for a contact" do
contact = FactoryGirl.build(:contact, sharing: false, receiving: false)
expect(Diaspora::Federation::Entities).to receive(:contact).with(contact).and_call_original
data = ContactRetraction.retraction_data_for(contact)
expect(data[:author]).to eq(contact.user.diaspora_handle)
expect(data[:recipient]).to eq(contact.person.diaspora_handle)
expect(data[:sharing]).to be_falsey
expect(data[:following]).to be_falsey
end
end
describe ".for" do
it "creates a retraction for a contact" do
expect(ContactRetraction).to receive(:retraction_data_for).with(contact)
ContactRetraction.for(contact)
end
it "create contact entity with 'sharing' and 'following' set to false" do
data = ContactRetraction.for(contact).data
expect(data[:sharing]).to be_falsey
expect(data[:following]).to be_falsey
end
end
describe ".defer_dispatch" do
it "queues a job to send the retraction later" do
contact = FactoryGirl.build(:contact, user: local_luke, person: remote_raphael)
retraction = ContactRetraction.for(contact)
federation_retraction_data = Diaspora::Federation::Entities.contact(contact).to_h
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
local_luke.id, "ContactRetraction", federation_retraction_data, [remote_raphael.id], {}
)
retraction.defer_dispatch(local_luke)
end
end
describe "#public?" do
it "returns false for a contact retraction" do
expect(retraction.public?).to be_falsey
end
end
end

View file

@ -4,13 +4,13 @@
describe Retraction do
let(:post) { alice.post(:status_message, text: "destroy!", public: true) }
let(:retraction) { Retraction.for(post, alice) }
let(:retraction) { Retraction.for(post) }
describe "#subscribers" do
it "contains all remote-subscribers of target object" do
post = local_luke.post(:status_message, text: "destroy!", public: true)
retraction = Retraction.for(post, local_luke)
retraction = Retraction.for(post)
expect(retraction.subscribers).to eq([remote_raphael])
end
@ -18,46 +18,60 @@ describe Retraction do
describe "#data" do
it "contains the hash with all data from the federation-retraction" do
federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice)
expect(retraction.data[:target_guid]).to eq(post.guid)
expect(retraction.data[:target]).to eq(Diaspora::Federation::Entities.related_entity(post).to_h)
expect(retraction.data[:target_type]).to eq("Post")
expect(retraction.data[:author]).to eq(alice.diaspora_handle)
end
end
expect(retraction.data).to eq(federation_retraction.to_h)
describe ".retraction_data_for" do
it "creates the retraction data for a post" do
data = Retraction.retraction_data_for(post)
expect(data[:target_guid]).to eq(post.guid)
expect(data[:target]).to eq(Diaspora::Federation::Entities.related_entity(post).to_h)
expect(data[:target_type]).to eq("Post")
expect(data[:author]).to eq(alice.diaspora_handle)
end
it "creates the retraction data for a relayable" do
comment = FactoryGirl.create(:comment, author: alice.person, post: post)
data = Retraction.retraction_data_for(comment)
expect(data[:target_guid]).to eq(comment.guid)
expect(data[:target]).to eq(Diaspora::Federation::Entities.related_entity(comment).to_h)
expect(data[:target_type]).to eq("Comment")
expect(data[:author]).to eq(alice.diaspora_handle)
end
end
describe ".for" do
it "creates a retraction for a post" do
expect(Diaspora::Federation::Entities).to receive(:signed_retraction).with(post, alice)
expect(Retraction).to receive(:retraction_data_for).with(post)
Retraction.for(post, alice)
Retraction.for(post)
end
it "creates a retraction for a relayable" do
comment = FactoryGirl.create(:comment, author: alice.person, post: post)
expect(Diaspora::Federation::Entities).to receive(:relayable_retraction).with(comment, alice)
expect(Retraction).to receive(:retraction_data_for).with(comment)
Retraction.for(comment, alice)
end
it "creates a retraction for a contact" do
contact = FactoryGirl.create(:contact)
expect(Diaspora::Federation::Entities).to receive(:retraction).with(contact)
Retraction.for(contact, contact.user)
Retraction.for(comment)
end
end
describe ".defer_dispatch" do
it "queues a job to send the retraction later" do
post = local_luke.post(:status_message, text: "destroy!", public: true)
federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, local_luke)
retraction = Retraction.for(post)
federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
local_luke.id, federation_retraction.to_h, [remote_raphael.id], service_types: []
local_luke.id, "Retraction", federation_retraction.to_h, [remote_raphael.id], service_types: []
)
Retraction.for(post, local_luke).defer_dispatch(local_luke)
retraction.defer_dispatch(local_luke)
end
it "adds service metadata to queued job for deletion" do
@ -66,47 +80,38 @@ describe Retraction do
facebook = Services::Facebook.new(access_token: "facebook")
alice.services << twitter << facebook
federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice)
retraction = Retraction.for(post)
federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
alice.id, federation_retraction.to_h, [], service_types: ["Services::Twitter"], tweet_id: "123"
alice.id, "Retraction", federation_retraction.to_h, [], service_types: ["Services::Twitter"], tweet_id: "123"
)
Retraction.for(post, alice).defer_dispatch(alice)
retraction.defer_dispatch(alice)
end
it "queues also a job if subscribers is empty" do
federation_retraction = Diaspora::Federation::Entities.signed_retraction(post, alice)
retraction = Retraction.for(post)
federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
alice.id, federation_retraction.to_h, [], service_types: []
alice.id, "Retraction", federation_retraction.to_h, [], service_types: []
)
Retraction.for(post, alice).defer_dispatch(alice)
retraction.defer_dispatch(alice)
end
it "queues a job with empty opts for non-StatusMessage" do
post = local_luke.post(:status_message, text: "hello", public: true)
comment = local_luke.comment!(post, "destroy!")
federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke)
retraction = Retraction.for(comment)
federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
local_luke.id, federation_retraction.to_h, [remote_raphael.id], {}
local_luke.id, "Retraction", federation_retraction.to_h, [remote_raphael.id], {}
)
Retraction.for(comment, local_luke).defer_dispatch(local_luke)
end
it "uses the author of the target parent as sender for a comment-retraction if the parent is local" do
post = local_luke.post(:status_message, text: "hello", public: true)
comment = local_leia.comment!(post, "destroy!")
federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_leia)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
local_luke.id, federation_retraction.to_h, [remote_raphael.id], {}
)
Retraction.for(comment, local_leia).defer_dispatch(local_leia)
retraction.defer_dispatch(local_luke)
end
context "relayable" do
@ -114,23 +119,25 @@ describe Retraction do
let(:comment) { FactoryGirl.create(:comment, post: post, author: remote_raphael) }
it "sends retraction to target author if deleted by parent author" do
federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke)
retraction = Retraction.for(comment)
federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
local_luke.id, federation_retraction.to_h, [remote_raphael.id], {}
local_luke.id, "Retraction", federation_retraction.to_h, [remote_raphael.id], {}
)
Retraction.for(comment, local_luke).defer_dispatch(local_luke)
retraction.defer_dispatch(local_luke)
end
it "don't sends retraction back to target author if relayed by parent author" do
federation_retraction = Diaspora::Federation::Entities.relayable_retraction(comment, local_luke)
retraction = Retraction.for(comment)
federation_retraction = Diaspora::Federation::Entities.retraction(retraction)
expect(Workers::DeferredRetraction).to receive(:perform_async).with(
local_luke.id, federation_retraction.to_h, [], {}
local_luke.id, "Retraction", federation_retraction.to_h, [], {}
)
Retraction.for(comment, local_luke).defer_dispatch(local_luke, false)
retraction.defer_dispatch(local_luke, false)
end
end
end
@ -138,29 +145,29 @@ describe Retraction do
describe "#perform" do
it "destroys the target object" do
expect(post).to receive(:destroy!)
Retraction.for(post, alice).perform
Retraction.for(post).perform
end
end
describe "#public?" do
it "returns true for a public post" do
expect(Retraction.for(post, alice).public?).to be_truthy
expect(Retraction.for(post).public?).to be_truthy
end
it "returns true for a public comment if parent post is local" do
comment = bob.comment!(post, "destroy!")
expect(Retraction.for(comment, bob).public?).to be_truthy
expect(Retraction.for(comment).public?).to be_truthy
end
it "returns false for a public comment if parent post is not local" do
remote_post = FactoryGirl.create(:status_message, author: remote_raphael)
it "returns true for a public comment if parent post is not local" do
remote_post = FactoryGirl.create(:status_message, author: remote_raphael, public: true)
comment = alice.comment!(remote_post, "destroy!")
expect(Retraction.for(comment, alice).public?).to be_falsey
expect(Retraction.for(comment).public?).to be_truthy
end
it "returns false for a private target" do
private_post = alice.post(:status_message, text: "destroy!", to: alice.aspects.first.id)
expect(Retraction.for(private_post, alice).public?).to be_falsey
expect(Retraction.for(private_post).public?).to be_falsey
end
end
end

View file

@ -28,18 +28,29 @@ describe Diaspora::Federation::Dispatcher::Private do
end
context "deliver to remote user" do
let(:xml) { "<diaspora/>" }
let(:encryption_key) { double }
let(:magic_env) { double }
let(:magic_env_xml) { double }
let(:json) { "{\"aes_key\": \"...\", \"encrypted_magic_envelope\": \"...\"}" }
it "queues a private send job" do
expect(Workers::SendPrivate).to receive(:perform_async) do |user_id, _entity_string, targets|
expect(user_id).to eq(alice.id)
expect(targets.size).to eq(1)
expect(targets).to have_key(remote_raphael.receive_url)
expect(targets[remote_raphael.receive_url]).to eq(xml)
expect(targets[remote_raphael.receive_url]).to eq(json)
end
salmon = double
expect(DiasporaFederation::Salmon::EncryptedSlap).to receive(:prepare).and_return(salmon)
expect(salmon).to receive(:generate_xml).and_return(xml)
expect(alice).to receive(:encryption_key).and_return(encryption_key)
expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
).and_return(magic_env)
expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
expect(DiasporaFederation::Salmon::EncryptedMagicEnvelope).to receive(:encrypt) do |magic_env, public_key|
expect(magic_env).to eq(magic_env_xml)
expect(public_key.to_s).to eq(remote_raphael.public_key.to_s)
json
end
Diaspora::Federation::Dispatcher.build(alice, post).dispatch
end
@ -60,12 +71,19 @@ describe Diaspora::Federation::Dispatcher::Private do
expect(user_id).to eq(alice.id)
expect(targets.size).to eq(1)
expect(targets).to have_key(remote_person.receive_url)
expect(targets[remote_person.receive_url]).to eq(xml)
expect(targets[remote_person.receive_url]).to eq(json)
end
salmon = double
expect(DiasporaFederation::Salmon::EncryptedSlap).to receive(:prepare).and_return(salmon)
expect(salmon).to receive(:generate_xml).and_return(xml)
expect(alice).to receive(:encryption_key).and_return(encryption_key)
expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
).and_return(magic_env)
expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
expect(DiasporaFederation::Salmon::EncryptedMagicEnvelope).to receive(:encrypt) do |magic_env, public_key|
expect(magic_env).to eq(magic_env_xml)
expect(public_key.to_s).to eq(remote_raphael.public_key.to_s)
json
end
Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_person]).dispatch
end
@ -79,12 +97,19 @@ describe Diaspora::Federation::Dispatcher::Private do
expect(user_id).to eq(alice.id)
expect(targets.size).to eq(1)
expect(targets).to have_key(remote_person.receive_url)
expect(targets[remote_person.receive_url]).to eq(xml)
expect(targets[remote_person.receive_url]).to eq(json)
end
salmon = double
expect(DiasporaFederation::Salmon::EncryptedSlap).to receive(:prepare).and_return(salmon)
expect(salmon).to receive(:generate_xml).and_return(xml)
expect(alice).to receive(:encryption_key).and_return(encryption_key)
expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
).and_return(magic_env)
expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
expect(DiasporaFederation::Salmon::EncryptedMagicEnvelope).to receive(:encrypt) do |magic_env, public_key|
expect(magic_env).to eq(magic_env_xml)
expect(public_key.to_s).to eq(remote_raphael.public_key.to_s)
json
end
Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_person, offline_person]).dispatch
end

View file

@ -48,7 +48,9 @@ describe Diaspora::Federation::Dispatcher::Public do
end
context "deliver to remote user" do
let(:salmon_xml) { "<diaspora/>" }
let(:encryption_key) { double }
let(:magic_env) { double }
let(:magic_env_xml) { double(to_xml: "<diaspora/>") }
it "queues a public send job" do
alice.share_with(remote_raphael, alice.aspects.first)
@ -57,10 +59,14 @@ describe Diaspora::Federation::Dispatcher::Public do
expect(user_id).to eq(alice.id)
expect(urls.size).to eq(1)
expect(urls[0]).to eq(remote_raphael.pod.url_to("/receive/public"))
expect(xml).to eq(salmon_xml)
expect(xml).to eq(magic_env_xml.to_xml)
end
expect(DiasporaFederation::Salmon::Slap).to receive(:generate_xml).and_return(salmon_xml)
expect(alice).to receive(:encryption_key).and_return(encryption_key)
expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
).and_return(magic_env)
expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
Diaspora::Federation::Dispatcher.build(alice, post).dispatch
end
@ -76,11 +82,14 @@ describe Diaspora::Federation::Dispatcher::Public do
expect(user_id).to eq(alice.id)
expect(urls.size).to eq(1)
expect(urls[0]).to eq(remote_raphael.pod.url_to("/receive/public"))
expect(xml).to eq(salmon_xml)
expect(xml).to eq(magic_env_xml.to_xml)
end
expect(DiasporaFederation::Salmon::Slap).to receive(:generate_xml).and_return(salmon_xml)
expect(alice).to receive(:encryption_key).and_return(encryption_key)
expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
).and_return(magic_env)
expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_raphael]).dispatch
end
@ -92,10 +101,14 @@ describe Diaspora::Federation::Dispatcher::Public do
expect(user_id).to eq(alice.id)
expect(urls.size).to eq(1)
expect(urls[0]).to eq(remote_raphael.pod.url_to("/receive/public"))
expect(xml).to eq(salmon_xml)
expect(xml).to eq(magic_env_xml.to_xml)
end
expect(DiasporaFederation::Salmon::Slap).to receive(:generate_xml).and_return(salmon_xml)
expect(alice).to receive(:encryption_key).and_return(encryption_key)
expect(DiasporaFederation::Salmon::MagicEnvelope).to receive(:new).with(
instance_of(DiasporaFederation::Entities::StatusMessage), alice.diaspora_handle
).and_return(magic_env)
expect(magic_env).to receive(:envelop).with(encryption_key).and_return(magic_env_xml)
Diaspora::Federation::Dispatcher.build(alice, post, subscribers: [remote_raphael, offline_person]).dispatch
end

View file

@ -18,8 +18,7 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.post.guid)
expect(federation_entity.text).to eq(diaspora_entity.text)
expect(federation_entity.author_signature).to be_nil
expect(federation_entity.xml_order).to be_nil
expect(federation_entity.additional_xml_elements).to be_empty
expect(federation_entity.additional_data).to be_empty
end
it "builds a comment with signature" do
@ -32,17 +31,19 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.post.guid)
expect(federation_entity.text).to eq(diaspora_entity.text)
expect(federation_entity.author_signature).to eq(diaspora_entity.signature.author_signature)
expect(federation_entity.xml_order).to eq(diaspora_entity.signature.signature_order.order.split)
expect(federation_entity.additional_xml_elements).to eq(diaspora_entity.signature.additional_data)
expect(federation_entity.signature_order.map(&:to_s)).to eq(diaspora_entity.signature.signature_order.order.split)
expect(federation_entity.additional_data).to eq(diaspora_entity.signature.additional_data)
end
it "builds a contact (request)" do
diaspora_entity = FactoryGirl.build(:contact)
it "builds a contact" do
diaspora_entity = FactoryGirl.build(:contact, receiving: true)
federation_entity = described_class.build(diaspora_entity)
expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Request)
expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Contact)
expect(federation_entity.author).to eq(diaspora_entity.user.diaspora_handle)
expect(federation_entity.recipient).to eq(diaspora_entity.person.diaspora_handle)
expect(federation_entity.sharing).to be_truthy
expect(federation_entity.following).to be_truthy
end
context "Conversation" do
@ -85,8 +86,7 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.target.guid)
expect(federation_entity.positive).to eq(diaspora_entity.positive)
expect(federation_entity.author_signature).to be_nil
expect(federation_entity.xml_order).to be_nil
expect(federation_entity.additional_xml_elements).to be_empty
expect(federation_entity.additional_data).to be_empty
end
it "builds a like with signature" do
@ -99,12 +99,12 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.target.guid)
expect(federation_entity.positive).to eq(diaspora_entity.positive)
expect(federation_entity.author_signature).to eq(diaspora_entity.signature.author_signature)
expect(federation_entity.xml_order).to eq(diaspora_entity.signature.signature_order.order.split)
expect(federation_entity.additional_xml_elements).to eq(diaspora_entity.signature.additional_data)
expect(federation_entity.signature_order.map(&:to_s)).to eq(diaspora_entity.signature.signature_order.order.split)
expect(federation_entity.additional_data).to eq(diaspora_entity.signature.additional_data)
end
it "builds a message" do
diaspora_entity = FactoryGirl.create(:message, author_signature: "abc")
diaspora_entity = FactoryGirl.create(:message)
federation_entity = described_class.build(diaspora_entity)
expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Message)
@ -113,7 +113,6 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.conversation_guid).to eq(diaspora_entity.conversation.guid)
expect(federation_entity.text).to eq(diaspora_entity.text)
expect(federation_entity.created_at).to eq(diaspora_entity.created_at)
expect(federation_entity.author_signature).to eq(diaspora_entity.author_signature)
end
it "builds a participation" do
@ -153,8 +152,7 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.poll_answer.poll.guid)
expect(federation_entity.poll_answer_guid).to eq(diaspora_entity.poll_answer.guid)
expect(federation_entity.author_signature).to be_nil
expect(federation_entity.xml_order).to be_nil
expect(federation_entity.additional_xml_elements).to be_empty
expect(federation_entity.additional_data).to be_empty
end
it "builds a poll participation with signature" do
@ -168,8 +166,8 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.parent_guid).to eq(diaspora_entity.poll_answer.poll.guid)
expect(federation_entity.poll_answer_guid).to eq(diaspora_entity.poll_answer.guid)
expect(federation_entity.author_signature).to eq(signature.author_signature)
expect(federation_entity.xml_order).to eq(signature.signature_order.order.split)
expect(federation_entity.additional_xml_elements).to eq(signature.additional_data)
expect(federation_entity.signature_order.map(&:to_s)).to eq(signature.signature_order.order.split)
expect(federation_entity.additional_data).to eq(signature.additional_data)
end
it "builds a profile" do
@ -206,6 +204,31 @@ describe Diaspora::Federation::Entities do
expect(federation_entity.provider_display_name).to eq(diaspora_entity.provider_display_name)
end
context "Retraction" do
it "builds a Retraction entity for a Photo retraction" do
target = FactoryGirl.create(:photo, author: alice.person)
retraction = Retraction.for(target)
federation_entity = described_class.build(retraction)
expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Retraction)
expect(federation_entity.author).to eq(target.author.diaspora_handle)
expect(federation_entity.target_guid).to eq(target.guid)
expect(federation_entity.target_type).to eq("Photo")
end
it "builds a Contact for a Contact retraction" do
target = FactoryGirl.create(:contact, receiving: false)
retraction = ContactRetraction.for(target)
federation_entity = described_class.build(retraction)
expect(federation_entity).to be_instance_of(DiasporaFederation::Entities::Contact)
expect(federation_entity.author).to eq(target.user.diaspora_handle)
expect(federation_entity.recipient).to eq(target.person.diaspora_handle)
expect(federation_entity.sharing).to be_falsey
expect(federation_entity.following).to be_falsey
end
end
context "StatusMessage" do
it "builds a status message" do
diaspora_entity = FactoryGirl.create(:status_message)
@ -274,89 +297,4 @@ describe Diaspora::Federation::Entities do
end
end
end
describe ".build_retraction" do
context "Retraction" do
it "builds a Retraction for a Photo" do
target = FactoryGirl.create(:photo, author: alice.person)
retraction = Retraction.for(target, alice)
federation_retraction = described_class.build_retraction(retraction)
expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::Retraction)
expect(federation_retraction.author).to eq(target.author.diaspora_handle)
expect(federation_retraction.target_guid).to eq(target.guid)
expect(federation_retraction.target_type).to eq("Photo")
end
it "builds a Retraction for a Contact" do
target = FactoryGirl.create(:contact)
retraction = Retraction.for(target, target.user)
federation_retraction = described_class.build_retraction(retraction)
expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::Retraction)
expect(federation_retraction.author).to eq(target.user.diaspora_handle)
expect(federation_retraction.target_guid).to eq(target.user.guid)
expect(federation_retraction.target_type).to eq("Person")
end
end
context "SignedRetraction" do
it "builds a SignedRetraction for a StatusMessage" do
target = FactoryGirl.create(:status_message, author: alice.person)
retraction = Retraction.for(target, alice)
federation_retraction = described_class.build_retraction(retraction)
expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::SignedRetraction)
expect(federation_retraction.author).to eq(target.author.diaspora_handle)
expect(federation_retraction.target_guid).to eq(target.guid)
expect(federation_retraction.target_type).to eq("Post")
end
it "builds a SignedRetraction for a Reshare" do
target = FactoryGirl.create(:reshare, author: alice.person)
retraction = Retraction.for(target, alice)
federation_retraction = described_class.build_retraction(retraction)
expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::SignedRetraction)
expect(federation_retraction.author).to eq(target.author.diaspora_handle)
expect(federation_retraction.target_guid).to eq(target.guid)
expect(federation_retraction.target_type).to eq("Post")
end
end
context "RelayableRetraction" do
it "builds a RelayableRetraction for a Comment" do
target = FactoryGirl.create(:comment, author: alice.person)
retraction = Retraction.for(target, alice)
federation_retraction = described_class.build_retraction(retraction)
expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction)
expect(federation_retraction.author).to eq(alice.diaspora_handle)
expect(federation_retraction.target_guid).to eq(target.guid)
expect(federation_retraction.target_type).to eq("Comment")
end
it "builds a RelayableRetraction for a Like" do
target = FactoryGirl.create(:like, author: alice.person)
retraction = Retraction.for(target, alice)
federation_retraction = described_class.build_retraction(retraction)
expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction)
expect(federation_retraction.author).to eq(alice.diaspora_handle)
expect(federation_retraction.target_guid).to eq(target.guid)
expect(federation_retraction.target_type).to eq("Like")
end
it "builds a RelayableRetraction for a PollParticipation" do
target = FactoryGirl.create(:poll_participation, author: alice.person)
retraction = Retraction.for(target, alice)
federation_retraction = described_class.build_retraction(retraction)
expect(federation_retraction).to be_instance_of(DiasporaFederation::Entities::RelayableRetraction)
expect(federation_retraction.author).to eq(alice.diaspora_handle)
expect(federation_retraction.target_guid).to eq(target.guid)
expect(federation_retraction.target_type).to eq("PollParticipation")
end
end
end
end

View file

@ -3,7 +3,7 @@ describe Diaspora::Federation::Receive do
let(:post) { FactoryGirl.create(:status_message, text: "hello", public: true, author: alice.person) }
describe ".account_deletion" do
let(:account_deletion_entity) { FactoryGirl.build(:account_deletion_entity, author: sender.diaspora_handle) }
let(:account_deletion_entity) { Fabricate(:account_deletion_entity, author: sender.diaspora_handle) }
it "saves the account deletion" do
Diaspora::Federation::Receive.account_deletion(account_deletion_entity)
@ -55,7 +55,7 @@ describe Diaspora::Federation::Receive do
expect(comment.signature).not_to be_nil
expect(comment.signature.author_signature).to eq("aa")
expect(comment.signature.additional_data).to eq("new_property" => "data")
expect(comment.signature.order).to eq(comment_entity.xml_order.map(&:to_s))
expect(comment.signature.order).to eq(comment_entity.signature_order.map(&:to_s))
end
let(:entity) { comment_entity }
@ -66,7 +66,7 @@ describe Diaspora::Federation::Receive do
describe ".contact" do
let(:contact_entity) {
FactoryGirl.build(:contact_entity, author: sender.diaspora_handle, recipient: alice.diaspora_handle)
Fabricate(:contact_entity, author: sender.diaspora_handle, recipient: alice.diaspora_handle)
}
it "creates the contact if it doesn't exist" do
@ -99,11 +99,11 @@ describe Diaspora::Federation::Receive do
context "sharing=false" do
let(:unshare_contact_entity) {
FactoryGirl.build(
Fabricate(
:contact_entity,
author: sender.diaspora_handle,
recipient: alice.diaspora_handle,
sharing: "false"
sharing: false
)
}
@ -128,9 +128,9 @@ describe Diaspora::Federation::Receive do
end
describe ".conversation" do
let(:conv_guid) { FactoryGirl.generate(:guid) }
let(:conv_guid) { Fabricate.sequence(:guid) }
let(:message_entity) {
FactoryGirl.build(
Fabricate(
:message_entity,
author: alice.diaspora_handle,
parent_guid: conv_guid,
@ -138,7 +138,7 @@ describe Diaspora::Federation::Receive do
)
}
let(:conversation_entity) {
FactoryGirl.build(
Fabricate(
:conversation_entity,
guid: conv_guid,
author: alice.diaspora_handle,
@ -183,17 +183,15 @@ describe Diaspora::Federation::Receive do
end
describe ".like" do
let(:like_data) {
FactoryGirl.attributes_for(
:like_entity,
author: sender.diaspora_handle,
parent_guid: post.guid,
author_signature: "aa"
)
}
let(:like_entity) {
DiasporaFederation::Entities::Like.new(
like_data, [:author, :guid, :parent_guid, :parent_type, :positive, "new_property"], "new_property" => "data"
build_relayable_federation_entity(
:like,
{
author: sender.diaspora_handle,
parent_guid: post.guid,
author_signature: "aa"
},
"new_property" => "data"
)
}
@ -224,7 +222,7 @@ describe Diaspora::Federation::Receive do
expect(like.signature).not_to be_nil
expect(like.signature.author_signature).to eq("aa")
expect(like.signature.additional_data).to eq("new_property" => "data")
expect(like.signature.order).to eq(%w(author guid parent_guid parent_type positive new_property))
expect(like.signature.order).to eq(like_entity.signature_order.map(&:to_s))
end
let(:entity) { like_entity }
@ -241,7 +239,7 @@ describe Diaspora::Federation::Receive do
end
}
let(:message_entity) {
FactoryGirl.build(
Fabricate(
:message_entity,
author: sender.diaspora_handle,
parent_guid: conversation.guid,
@ -271,12 +269,11 @@ describe Diaspora::Federation::Receive do
let(:entity) { message_entity }
it_behaves_like "it ignores existing object received twice", Message
it_behaves_like "it relays relayables", Message
end
describe ".participation" do
let(:participation_entity) {
FactoryGirl.build(:participation_entity, author: sender.diaspora_handle, parent_guid: post.guid)
Fabricate(:participation_entity, author: sender.diaspora_handle, parent_guid: post.guid)
}
it "saves the participation" do
@ -303,7 +300,7 @@ describe Diaspora::Federation::Receive do
end
describe ".photo" do
let(:photo_entity) { FactoryGirl.build(:photo_entity, author: sender.diaspora_handle) }
let(:photo_entity) { Fabricate(:photo_entity, author: sender.diaspora_handle) }
it "saves the photo if it does not already exist" do
received = Diaspora::Federation::Receive.perform(photo_entity)
@ -352,19 +349,15 @@ describe Diaspora::Federation::Receive do
describe ".poll_participation" do
let(:post_with_poll) { FactoryGirl.create(:status_message_with_poll, author: alice.person) }
let(:poll_participation_data) {
FactoryGirl.attributes_for(
:poll_participation_entity,
author: sender.diaspora_handle,
parent_guid: post_with_poll.poll.guid,
poll_answer_guid: post_with_poll.poll.poll_answers.first.guid,
author_signature: "aa"
)
}
let(:poll_participation_entity) {
DiasporaFederation::Entities::PollParticipation.new(
poll_participation_data,
[:author, :guid, :parent_guid, :poll_answer_guid, "new_property"],
build_relayable_federation_entity(
:poll_participation,
{
author: sender.diaspora_handle,
parent_guid: post_with_poll.poll.guid,
poll_answer_guid: post_with_poll.poll.poll_answers.first.guid,
author_signature: "aa"
},
"new_property" => "data"
)
}
@ -396,7 +389,7 @@ describe Diaspora::Federation::Receive do
expect(poll_participation.signature).not_to be_nil
expect(poll_participation.signature.author_signature).to eq("aa")
expect(poll_participation.signature.additional_data).to eq("new_property" => "data")
expect(poll_participation.signature.order).to eq(%w(author guid parent_guid poll_answer_guid new_property))
expect(poll_participation.signature.order).to eq(poll_participation_entity.signature_order.map(&:to_s))
end
let(:entity) { poll_participation_entity }
@ -406,7 +399,7 @@ describe Diaspora::Federation::Receive do
end
describe ".profile" do
let(:profile_entity) { FactoryGirl.build(:profile_entity, author: sender.diaspora_handle) }
let(:profile_entity) { Fabricate(:profile_entity, author: sender.diaspora_handle) }
it "updates the profile of the person" do
received = Diaspora::Federation::Receive.perform(profile_entity)
@ -426,7 +419,7 @@ describe Diaspora::Federation::Receive do
end
describe ".reshare" do
let(:reshare_entity) { FactoryGirl.build(:reshare_entity, author: sender.diaspora_handle, root_guid: post.guid) }
let(:reshare_entity) { Fabricate(:reshare_entity, author: sender.diaspora_handle, root_guid: post.guid) }
it "saves the reshare" do
received = Diaspora::Federation::Receive.perform(reshare_entity)
@ -456,7 +449,7 @@ describe Diaspora::Federation::Receive do
it "destroys the post" do
remote_post = FactoryGirl.create(:status_message, author: sender, public: true)
retraction = FactoryGirl.build(
retraction = Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: remote_post.guid,
@ -471,12 +464,7 @@ describe Diaspora::Federation::Receive do
end
it "raises when the post does not exist" do
retraction = FactoryGirl.build(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: FactoryGirl.generate(:guid),
target_type: "Post"
)
retraction = Fabricate(:retraction_entity, author: sender.diaspora_handle, target_type: "Post")
expect {
Diaspora::Federation::Receive.retraction(retraction, nil)
@ -486,7 +474,7 @@ describe Diaspora::Federation::Receive do
it "disconnects on Person-Retraction" do
alice.contacts.find_or_initialize_by(person_id: sender.id, receiving: true, sharing: true).save!
retraction = FactoryGirl.build(
retraction = Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: sender.guid,
@ -506,16 +494,16 @@ describe Diaspora::Federation::Receive do
local_post = FactoryGirl.create(:status_message, author: alice.person, public: true)
remote_comment = FactoryGirl.create(:comment, author: sender, post: local_post)
retraction = FactoryGirl.build(
retraction = Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: remote_comment.guid,
target_type: "Comment"
)
comment_retraction = Retraction.for(remote_comment, alice)
comment_retraction = Retraction.for(remote_comment)
expect(Retraction).to receive(:for).with(instance_of(Comment), alice).and_return(comment_retraction)
expect(Retraction).to receive(:for).with(instance_of(Comment)).and_return(comment_retraction)
expect(comment_retraction).to receive(:defer_dispatch).with(alice, false)
expect(comment_retraction).to receive(:perform).and_call_original
expect_any_instance_of(Comment).to receive(:destroy!).and_call_original
@ -529,7 +517,7 @@ describe Diaspora::Federation::Receive do
remote_post = FactoryGirl.create(:status_message, author: sender, public: true)
remote_comment = FactoryGirl.create(:comment, author: sender, post: remote_post)
retraction = FactoryGirl.build(
retraction = Fabricate(
:retraction_entity,
author: sender.diaspora_handle,
target_guid: remote_comment.guid,
@ -547,7 +535,7 @@ describe Diaspora::Federation::Receive do
describe ".status_message" do
context "basic status message" do
let(:status_message_entity) { FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle) }
let(:status_message_entity) { Fabricate(:status_message_entity, author: sender.diaspora_handle) }
it "saves the status message" do
received = Diaspora::Federation::Receive.perform(status_message_entity)
@ -583,7 +571,7 @@ describe Diaspora::Federation::Receive do
end
it "finds the correct author if the author is not lowercase" do
status_message_entity = FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle.upcase)
status_message_entity = Fabricate(:status_message_entity, author: sender.diaspora_handle.upcase)
received = Diaspora::Federation::Receive.perform(status_message_entity)
@ -595,9 +583,9 @@ describe Diaspora::Federation::Receive do
end
context "with poll" do
let(:poll_entity) { FactoryGirl.build(:poll_entity) }
let(:poll_entity) { Fabricate(:poll_entity) }
let(:status_message_entity) {
FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle, poll: poll_entity)
Fabricate(:status_message_entity, author: sender.diaspora_handle, poll: poll_entity)
}
it "saves the status message" do
@ -616,9 +604,9 @@ describe Diaspora::Federation::Receive do
end
context "with location" do
let(:location_entity) { FactoryGirl.build(:location_entity) }
let(:location_entity) { Fabricate(:location_entity) }
let(:status_message_entity) {
FactoryGirl.build(:status_message_entity, author: sender.diaspora_handle, location: location_entity)
Fabricate(:status_message_entity, author: sender.diaspora_handle, location: location_entity)
}
it "saves the status message" do
@ -636,15 +624,15 @@ describe Diaspora::Federation::Receive do
end
context "with photos" do
let(:status_message_guid) { FactoryGirl.generate(:guid) }
let(:status_message_guid) { Fabricate.sequence(:guid) }
let(:photo1) {
FactoryGirl.build(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid)
Fabricate(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid)
}
let(:photo2) {
FactoryGirl.build(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid)
Fabricate(:photo_entity, author: sender.diaspora_handle, status_message_guid: status_message_guid)
}
let(:status_message_entity) {
FactoryGirl.build(
Fabricate(
:status_message_entity,
author: sender.diaspora_handle,
guid: status_message_guid,

View file

@ -7,19 +7,13 @@ describe Api::OpenidConnect::IdToken, type: :model do
let(:decoded_hash) {
JSON::JWT.decode(id_token.to_jwt, Api::OpenidConnect::IdTokenConfig::PRIVATE_KEY)
}
let(:discovery_controller) {
Api::OpenidConnect::DiscoveryController.new.tap {|controller|
controller.request = ActionController::TestRequest.new
controller.request.host = AppConfig.pod_uri.authority
controller.response = ActionController::TestResponse.new
}
}
let(:openid_webfinger) {
JSON.parse(discovery_controller.webfinger[0])
let(:webfinger) {
DiasporaFederation.callbacks.trigger(:fetch_person_for_webfinger, alice.diaspora_handle).to_json
}
it "issuer value must much the one we provided in OpenID discovery routine" do
expect(decoded_hash["iss"]).to eq(openid_webfinger["links"][0]["href"])
openid_issuer = webfinger[:links].find {|l| l[:rel] == OpenIDConnect::Discovery::Provider::Issuer::REL_VALUE }
expect(decoded_hash["iss"]).to eq(openid_issuer[:href])
end
end
end

View file

@ -39,11 +39,6 @@ describe Message, type: :model do
message = Message.create(author: local_luke.person, text: "yo", conversation: remote_conv)
expect(message.subscribers).to match_array([local_luke.person, local_leia.person, remote_raphael])
end
it "returns only remote participants, if the conversation is local, but the author is remote" do
message = Message.create(author: remote_raphael, text: "yo", conversation: local_conv)
expect(message.subscribers).to match_array([remote_raphael])
end
end
describe "#increase_unread" do

View file

@ -4,7 +4,7 @@
describe Notifications::PrivateMessage, type: :model do
let(:conversation) {
conv_guid = FactoryGirl.generate(:guid)
conv_guid = Fabricate.sequence(:guid)
Conversation.create(
guid: conv_guid,

View file

@ -87,6 +87,7 @@ describe User::Connecting, type: :model do
contact = local_leia.contact_for(remote_raphael)
retraction = double
expect(contact).to receive(:receiving=).with(false)
expect(Retraction).to receive(:for).with(contact).and_return(retraction)
expect(retraction).to receive(:defer_dispatch).with(local_leia)

View file

@ -778,7 +778,7 @@ describe User, :type => :model do
context "posts" do
it "sends a retraction" do
expect(Retraction).to receive(:for).with(post, bob).and_return(retraction)
expect(Retraction).to receive(:for).with(post).and_return(retraction)
expect(retraction).to receive(:defer_dispatch).with(bob)
expect(retraction).to receive(:perform)

View file

@ -17,7 +17,7 @@ shared_examples "a dispatcher" do
opts = {service_types: "Services::Twitter", tweet_id: "123"}
expect(Workers::DeletePostFromService).to receive(:perform_async).with(twitter.id, opts)
retraction = Retraction.for(post, alice)
retraction = Retraction.for(post)
Diaspora::Federation::Dispatcher.build(alice, retraction, opts).dispatch
end
@ -35,7 +35,7 @@ shared_examples "a dispatcher" do
it "does not deliver a Retraction of a Comment to services" do
expect(Workers::DeletePostFromService).not_to receive(:perform_async)
retraction = Retraction.for(comment, alice)
retraction = Retraction.for(comment)
Diaspora::Federation::Dispatcher.build(alice, retraction).dispatch
end
end