Merge branch 'salmon-refactor'
This commit is contained in:
commit
bb88a6fb8c
11 changed files with 176 additions and 95 deletions
|
|
@ -166,26 +166,28 @@ class User
|
|||
aspect.save
|
||||
target_people = target_people | aspect.people
|
||||
}
|
||||
|
||||
push_to_people(post, target_people)
|
||||
end
|
||||
|
||||
def push_to_people(post, people)
|
||||
salmon = salmon(post)
|
||||
people.each{|person|
|
||||
salmon(post, :to => person)
|
||||
xml = salmon.xml_for person
|
||||
push_to_person( person, xml)
|
||||
}
|
||||
end
|
||||
|
||||
def push_to_person( person, xml )
|
||||
Rails.logger.debug("Adding xml for #{self} to message queue to #{url}")
|
||||
QUEUE.add_post_request( person.receive_url, person.encrypt(xml) )
|
||||
QUEUE.add_post_request( person.receive_url, xml )
|
||||
QUEUE.process
|
||||
|
||||
end
|
||||
|
||||
def salmon( post, opts = {} )
|
||||
salmon = Salmon::SalmonSlap.create(self, post.to_diaspora_xml)
|
||||
push_to_person( opts[:to], salmon.to_xml)
|
||||
salmon
|
||||
def salmon( post )
|
||||
created_salmon = Salmon::SalmonSlap.create(self, post.to_diaspora_xml)
|
||||
created_salmon
|
||||
end
|
||||
|
||||
######## Commenting ########
|
||||
|
|
@ -217,7 +219,7 @@ class User
|
|||
push_to_people comment, people_in_aspects(aspects_with_post(comment.post.id))
|
||||
elsif owns? comment
|
||||
comment.save
|
||||
salmon comment, :to => comment.post.person
|
||||
push_to_people comment, [comment.post.person]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ cross_server:
|
|||
deploy_to: '/usr/local/app/diaspora'
|
||||
user: 'root'
|
||||
repo: 'git://github.com/diaspora/diaspora.git'
|
||||
branch: 'master'
|
||||
branch: 'salmon_refactor'
|
||||
default_env: 'development'
|
||||
servers:
|
||||
tom:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ module Diaspora
|
|||
aspect.requests << request
|
||||
aspect.save
|
||||
|
||||
salmon request, :to => desired_friend
|
||||
push_to_people request, [desired_friend]
|
||||
end
|
||||
request
|
||||
end
|
||||
|
|
@ -80,7 +80,7 @@ module Diaspora
|
|||
def unfriend(bad_friend)
|
||||
Rails.logger.info("#{self.real_name} is unfriending #{bad_friend.inspect}")
|
||||
retraction = Retraction.for(self)
|
||||
salmon( retraction, :to => bad_friend)
|
||||
push_to_people retraction, [bad_friend]
|
||||
remove_friend(bad_friend)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
module Diaspora
|
||||
module UserModules
|
||||
module Receiving
|
||||
def receive_salmon ciphertext
|
||||
cleartext = decrypt( ciphertext)
|
||||
salmon = Salmon::SalmonSlap.parse cleartext
|
||||
def receive_salmon salmon_xml
|
||||
salmon = Salmon::SalmonSlap.parse salmon_xml, self
|
||||
if salmon.verified_for_key?(salmon.author.public_key)
|
||||
Rails.logger.info("data in salmon: #{salmon.data}")
|
||||
self.receive(salmon.data)
|
||||
Rails.logger.info("data in salmon: #{salmon.parsed_data}")
|
||||
self.receive(salmon.parsed_data)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -41,16 +41,37 @@ end
|
|||
module Salmon
|
||||
|
||||
class SalmonSlap
|
||||
attr_accessor :magic_sig, :author, :author_email, :data, :data_type, :sig
|
||||
def self.parse(xml)
|
||||
attr_accessor :magic_sig, :author, :author_email, :aes_key, :iv, :parsed_data,
|
||||
:data_type, :sig
|
||||
|
||||
def self.create(user, activity)
|
||||
salmon = self.new
|
||||
salmon.author = user.person
|
||||
aes_key_hash = user.person.gen_aes_key
|
||||
salmon.aes_key = aes_key_hash['key']
|
||||
salmon.iv = aes_key_hash['iv']
|
||||
salmon.magic_sig = MagicSigEnvelope.create(user , user.person.aes_encrypt(activity, aes_key_hash))
|
||||
salmon
|
||||
end
|
||||
|
||||
def self.parse(xml, user)
|
||||
slap = self.new
|
||||
doc = Nokogiri::XML(xml)
|
||||
|
||||
sig_doc = doc.search('entry')
|
||||
|
||||
### Header ##
|
||||
decrypted_header = user.decrypt(doc.search('encrypted_header').text)
|
||||
header_doc = Nokogiri::XML(decrypted_header)
|
||||
slap.aes_key = header_doc.search('aes_key').text
|
||||
slap.iv = header_doc.search('iv').text
|
||||
|
||||
slap.magic_sig = MagicSigEnvelope.parse sig_doc
|
||||
|
||||
if 'base64url' == slap.magic_sig.encoding
|
||||
slap.data = decode64url(slap.magic_sig.data)
|
||||
|
||||
key_hash = {'key' => slap.aes_key, 'iv' => slap.iv}
|
||||
slap.parsed_data = user.aes_decrypt(decode64url(slap.magic_sig.data), key_hash)
|
||||
slap.sig = slap.magic_sig.sig
|
||||
else
|
||||
raise ArgumentError, "Magic Signature data must be encoded with base64url, was #{slap.magic_sig.encoding}"
|
||||
|
|
@ -65,17 +86,11 @@ module Salmon
|
|||
slap
|
||||
end
|
||||
|
||||
def self.create(user, activity)
|
||||
salmon = self.new
|
||||
salmon.author = user.person
|
||||
salmon.magic_sig = MagicSigEnvelope.create(user , activity)
|
||||
salmon
|
||||
end
|
||||
|
||||
def to_xml
|
||||
def xml_for person
|
||||
xml =<<ENTRY
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<entry xmlns='http://www.w3.org/2005/Atom'>
|
||||
<encrypted_header>#{person.encrypt(decrypted_header)}</encrypted_header>
|
||||
<author>
|
||||
<name>#{@author.real_name}</name>
|
||||
<uri>acct:#{@author.diaspora_handle}</uri>
|
||||
|
|
@ -86,6 +101,19 @@ ENTRY
|
|||
|
||||
end
|
||||
|
||||
def decrypted_header
|
||||
header =<<HEADER
|
||||
<decrypted_header>
|
||||
<iv>#{iv}</iv>
|
||||
<aes_key>#{aes_key}</aes_key>
|
||||
<author>
|
||||
<name>#{@author.real_name}</name>
|
||||
<uri>acct:#{@author.diaspora_handle}</uri>
|
||||
</author>
|
||||
</decrypted_header>
|
||||
HEADER
|
||||
end
|
||||
|
||||
def author
|
||||
if @author
|
||||
@author
|
||||
|
|
|
|||
|
|
@ -65,4 +65,17 @@ namespace :db do
|
|||
}
|
||||
puts "everything should be peachy"
|
||||
end
|
||||
|
||||
task :move_private_key do
|
||||
User.all.each do |user|
|
||||
if user.private_key.nil?
|
||||
user.private_key = user.person.serialized_key
|
||||
user.save
|
||||
person = user.person
|
||||
person.serialized_key = nil
|
||||
person.serialized_public_key = user.encryption_key.public_key
|
||||
person.save
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ namespace :generate do
|
|||
Rails.application.config.secret_token = '#{secret}'
|
||||
EOF
|
||||
|
||||
puts "YAY!!"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,30 +6,31 @@ require 'spec_helper'
|
|||
|
||||
describe PublicsController do
|
||||
render_views
|
||||
let(:user) {Factory.create :user}
|
||||
let(:user2){Factory.create :user}
|
||||
|
||||
before do
|
||||
@user = Factory.create(:user)
|
||||
sign_in :user, @user
|
||||
sign_in :user, user
|
||||
end
|
||||
|
||||
describe 'receive endpoint' do
|
||||
it 'should have a and endpoint and return a 200 on successful receipt of a request' do
|
||||
post :receive, :id =>@user.person.id
|
||||
post :receive, :id =>user.person.id
|
||||
response.code.should == '200'
|
||||
end
|
||||
|
||||
it 'should accept a post from another node and save the information' do
|
||||
user2 = Factory.create(:user)
|
||||
message = user2.build_post(:status_message, :message => "hi")
|
||||
|
||||
@user.reload
|
||||
@user.visible_post_ids.include?(message.id).should be false
|
||||
xml = @user.person.encrypt(user2.salmon(message, :to => @user.person).to_xml)
|
||||
user.reload
|
||||
user.visible_post_ids.include?(message.id).should be false
|
||||
|
||||
post :receive, :id => @user.person.id, :xml => xml
|
||||
xml = user2.salmon(message).xml_for(user.person)
|
||||
|
||||
@user.reload
|
||||
@user.visible_post_ids.include?(message.id).should be true
|
||||
post :receive, :id => user.person.id, :xml => xml
|
||||
|
||||
user.reload
|
||||
user.visible_post_ids.include?(message.id).should be true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -41,35 +42,29 @@ describe PublicsController do
|
|||
end
|
||||
|
||||
describe 'friend requests' do
|
||||
let(:aspect2) {user2.aspect(:name => 'disciples')}
|
||||
let!(:req) {user2.send_friend_request_to(user.person, aspect2)}
|
||||
let!(:xml) {user2.salmon(req).xml_for(user.person)}
|
||||
before do
|
||||
@user2 = Factory.create(:user)
|
||||
aspect = @user2.aspect(:name => 'disciples')
|
||||
|
||||
@user3 = Factory.create(:user)
|
||||
|
||||
req = @user2.send_friend_request_to(@user.person, aspect)
|
||||
|
||||
@xml = @user.person.encrypt(@user2.salmon(req, :to => @user.person).to_xml)
|
||||
|
||||
req.delete
|
||||
@user2.reload
|
||||
@user2.pending_requests.count.should be 1
|
||||
user2.reload
|
||||
user2.pending_requests.count.should be 1
|
||||
end
|
||||
|
||||
it 'should add the pending request to the right user if the target person exists locally' do
|
||||
@user2.delete
|
||||
post :receive, :id => @user.person.id, :xml => @xml
|
||||
user2.delete
|
||||
post :receive, :id => user.person.id, :xml => xml
|
||||
|
||||
assigns(:user).should eq(@user)
|
||||
assigns(:user).should eq(user)
|
||||
end
|
||||
|
||||
it 'should add the pending request to the right user if the target person does not exist locally' do
|
||||
Person.should_receive(:by_webfinger).with(@user2.person.diaspora_handle).and_return(@user2.person)
|
||||
@user2.person.delete
|
||||
@user2.delete
|
||||
post :receive, :id => @user.person.id, :xml => @xml
|
||||
Person.should_receive(:by_webfinger).with(user2.person.diaspora_handle).and_return(user2.person)
|
||||
user2.person.delete
|
||||
user2.delete
|
||||
post :receive, :id => user.person.id, :xml => xml
|
||||
|
||||
assigns(:user).should eq(@user)
|
||||
assigns(:user).should eq(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,52 +5,97 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Salmon do
|
||||
before do
|
||||
let(:user){Factory.create :user}
|
||||
let(:user2) {Factory.create :user}
|
||||
let(:user3) {Factory.create :user}
|
||||
let(:post){ user.post :status_message, :message => "hi", :to => user.aspect(:name => "sdg").id }
|
||||
|
||||
@user = Factory.create :user
|
||||
@post = @user.post :status_message, :message => "hi", :to => @user.aspect(:name => "sdg").id
|
||||
@sent_salmon = Salmon::SalmonSlap.create(@user, @post.to_diaspora_xml)
|
||||
@parsed_salmon = Salmon::SalmonSlap.parse @sent_salmon.to_xml
|
||||
let!(:created_salmon) {Salmon::SalmonSlap.create(user, post.to_diaspora_xml)}
|
||||
|
||||
describe '#create' do
|
||||
|
||||
it 'has data in the magic envelope' do
|
||||
created_salmon.magic_sig.data.should_not be nil
|
||||
end
|
||||
|
||||
it 'has no parsed_data' do
|
||||
created_salmon.parsed_data.should be nil
|
||||
end
|
||||
|
||||
it 'sets aes and iv key' do
|
||||
created_salmon.aes_key.should_not be nil
|
||||
created_salmon.iv.should_not be nil
|
||||
end
|
||||
|
||||
it 'makes the data in the signature encrypted with that key' do
|
||||
key_hash = {'key' => created_salmon.aes_key, 'iv' => created_salmon.iv}
|
||||
decoded_string = Salmon::SalmonSlap.decode64url(created_salmon.magic_sig.data)
|
||||
user.aes_decrypt(decoded_string, key_hash).should == post.to_diaspora_xml
|
||||
end
|
||||
end
|
||||
|
||||
describe '#xml_for' do
|
||||
let(:xml) {created_salmon.xml_for user2.person}
|
||||
|
||||
it 'has a encrypted header field' do
|
||||
xml.include?("encrypted_header").should be true
|
||||
end
|
||||
|
||||
it 'the encrypted_header field should contain the aes key' do
|
||||
doc = Nokogiri::XML(xml)
|
||||
decrypted_header = user2.decrypt(doc.search('encrypted_header').text)
|
||||
decrypted_header.include?(created_salmon.aes_key).should be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'marshaling' do
|
||||
let(:xml) {created_salmon.xml_for user2.person}
|
||||
let(:parsed_salmon) { Salmon::SalmonSlap.parse(xml, user2)}
|
||||
|
||||
it 'should parse out the aes key' do
|
||||
parsed_salmon.aes_key.should == created_salmon.aes_key
|
||||
end
|
||||
|
||||
it 'should parse out the iv' do
|
||||
parsed_salmon.iv.should == created_salmon.iv
|
||||
end
|
||||
it 'should parse out the authors diaspora_handle' do
|
||||
parsed_salmon.author_email.should == user.person.diaspora_handle
|
||||
|
||||
end
|
||||
|
||||
describe '#author' do
|
||||
before do
|
||||
stub_success("tom@tom.joindiaspora.com")
|
||||
end
|
||||
|
||||
it 'should verify the signature on a roundtrip' do
|
||||
|
||||
@sent_salmon.magic_sig.data.should == @parsed_salmon.magic_sig.data
|
||||
|
||||
@sent_salmon.magic_sig.sig.should == @parsed_salmon.magic_sig.sig
|
||||
@sent_salmon.magic_sig.signable_string.should == @parsed_salmon.magic_sig.signable_string
|
||||
|
||||
@parsed_salmon.verified_for_key?(OpenSSL::PKey::RSA.new(@user.exported_key)).should be true
|
||||
@sent_salmon.verified_for_key?(OpenSSL::PKey::RSA.new(@user.exported_key)).should be true
|
||||
end
|
||||
|
||||
it 'should return the data so it can be "received"' do
|
||||
|
||||
xml = @post.to_diaspora_xml
|
||||
|
||||
@parsed_salmon.data.should == xml
|
||||
end
|
||||
|
||||
it 'should parse out the authors diaspora_handle' do
|
||||
@parsed_salmon.author_email.should == @user.person.diaspora_handle
|
||||
|
||||
end
|
||||
|
||||
it 'should reference a local author' do
|
||||
@parsed_salmon.author.should == @user.person
|
||||
parsed_salmon.author.should == user.person
|
||||
end
|
||||
|
||||
it 'should reference a remote author' do
|
||||
@parsed_salmon.author_email = 'tom@tom.joindiaspora.com'
|
||||
@parsed_salmon.author.public_key.should_not be_nil
|
||||
parsed_salmon.author_email = 'tom@tom.joindiaspora.com'
|
||||
parsed_salmon.author.public_key.should_not be_nil
|
||||
end
|
||||
|
||||
it 'should fail to reference a nonexistent remote author' do
|
||||
@parsed_salmon.author_email = 'idsfug@difgubhpsduh.rgd'
|
||||
parsed_salmon.author_email = 'idsfug@difgubhpsduh.rgd'
|
||||
proc {
|
||||
Redfinger.stub(:finger).and_return(nil) #Redfinger returns nil when there is no profile
|
||||
@parsed_salmon.author.real_name}.should raise_error /No webfinger profile found/
|
||||
parsed_salmon.author.real_name}.should raise_error /No webfinger profile found/
|
||||
end
|
||||
end
|
||||
|
||||
it 'verifies the signature for the sender' do
|
||||
parsed_salmon.verified_for_key?(user.public_key).should be true
|
||||
end
|
||||
|
||||
it 'contains the original data' do
|
||||
parsed_salmon.parsed_data.should == post.to_diaspora_xml
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -71,19 +71,19 @@ describe User do
|
|||
|
||||
describe '#push_to_aspects' do
|
||||
it 'should push a post to a aspect' do
|
||||
user.should_receive(:salmon).twice
|
||||
user.should_receive(:push_to_person).twice
|
||||
user.push_to_aspects(post, aspect.id)
|
||||
end
|
||||
|
||||
it 'should push a post to all aspects' do
|
||||
user.should_receive(:salmon).exactly(3).times
|
||||
user.should_receive(:push_to_person).exactly(3).times
|
||||
user.push_to_aspects(post, :all)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#push_to_people' do
|
||||
it 'should push to people' do
|
||||
user.should_receive(:salmon).twice
|
||||
user.should_receive(:push_to_person).twice
|
||||
user.push_to_people(post, [user2.person, user3.person])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -173,11 +173,11 @@ describe User do
|
|||
describe 'salmon' do
|
||||
before do
|
||||
@post = @user.post :status_message, :message => "hello", :to => @aspect.id
|
||||
@salmon = @user.salmon( @post, :to => @user2.person )
|
||||
@salmon = @user.salmon( @post )
|
||||
end
|
||||
|
||||
it 'should receive a salmon for a post' do
|
||||
@user2.receive_salmon( @user2.person.encrypt(@salmon.to_xml) )
|
||||
@user2.receive_salmon( @salmon.xml_for @user2.person )
|
||||
@user2.visible_post_ids.include?(@post.id).should be true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue