From 4fd0853e71a3b195478734c316222cf83fb3f0bc Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 8 Sep 2010 18:29:39 -0700 Subject: [PATCH 01/27] Moving to salmon --- app/models/person.rb | 48 ++++++++++++++++++++----- app/models/user.rb | 21 +++++++---- lib/encryptable.rb | 5 +++ lib/encryptor.rb | 61 ++++++++++++++++++++++++++++++++ lib/salmon/salmon.rb | 26 +++++++++----- spec/lib/salmon_salmon_spec.rb | 47 ++++++++++++++++-------- spec/models/post_spec.rb | 16 +++++++-- spec/models/user/receive_spec.rb | 12 +++++++ spec/user_encryption_spec.rb | 11 ++++++ 9 files changed, 204 insertions(+), 43 deletions(-) create mode 100644 lib/encryptor.rb diff --git a/app/models/person.rb b/app/models/person.rb index 7853b9d17..2f90fe727 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -1,6 +1,7 @@ class Person include MongoMapper::Document include ROXML + include Encryptor::Public xml_accessor :_id xml_accessor :email @@ -37,6 +38,13 @@ class Person def real_name "#{profile.first_name.to_s} #{profile.last_name.to_s}" end + def owns?(post) + self.id == post.person.id + end + + def receive_url + "#{self.url}receive/users/#{self.id}/" + end def encryption_key OpenSSL::PKey::RSA.new( serialized_key ) @@ -51,6 +59,10 @@ class Person Base64.encode64 OpenSSL::Digest::SHA256.new(self.exported_key).to_s end + def public_key + encryption_key.public_key + end + def exported_key encryption_key.public_key.export end @@ -60,16 +72,34 @@ class Person @serialized_key = new_key end - def owns?(post) - self.id == post.person.id - end - - def receive_url - "#{self.url}receive/users/#{self.id}/" - end - def self.by_webfinger( identifier ) - Person.first(:email => identifier.gsub('acct:', '')) + local_person = Person.first(:email => identifier.gsub('acct:', '')) + if local_person + local_person + elsif !identifier.include?("localhost") + begin + f = Redfinger.finger(identifier) + rescue SocketError => e + raise "Diaspora server for #{identifier} not found" if e.message =~ /Name or service not known/ + end + #raise "No diaspora user found at #{identifier}" + Person.from_webfinger_profile(identifier, f ) + end + end + + def self.from_webfinger_profile( identifier, profile) + public_key = profile.links.select{|x| x.rel == 'diaspora-public-key'}.first.href + new_person = Person.new + new_person.exported_key = Base64.decode64 public_key + new_person.email = identifier + receive_url = profile.links.select{ |l| l.rel == 'http://joindiaspora.com/seed_location'}.first.href + new_person.url = receive_url.split('receive').first + new_person.profile = Profile.new(:first_name => "Anon", :last_name => "ymous") + if new_person.save! + new_person + else + cry + end end def remote? diff --git a/app/models/user.rb b/app/models/user.rb index 1fbc1a849..c5cfcbdf4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,8 +1,11 @@ require 'lib/diaspora/user/friending.rb' +require 'lib/salmon/salmon' class User include MongoMapper::Document include Diaspora::UserModules::Friending + include Encryptor::Private + devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable key :username, :unique => true @@ -128,6 +131,10 @@ class User post.push_to( target_people ) end + def salmon( post, opts = {} ) + Salmon::SalmonSlap.create(self, post.encrypted_xml_for(opts[:to])) + end + def visible_posts( opts = {} ) if opts[:by_members_of] return raw_visible_posts if opts[:by_members_of] == :all @@ -184,6 +191,13 @@ class User end ###### Receiving ####### + def receive_salmon xml + salmon = Salmon::SalmonSlap.parse xml + if salmon.verified_for_key?(salmon.author.public_key) + self.receive(decrypt(salmon.data)) + end + end + def receive xml object = Diaspora::Parser.from_xml(xml) Rails.logger.debug("Receiving object for #{self.real_name}:\n#{object.inspect}") @@ -316,11 +330,4 @@ class User } end - - protected - - def self.generate_key - OpenSSL::PKey::RSA::generate 1024 - end - end diff --git a/lib/encryptable.rb b/lib/encryptable.rb index 17d8ab0c7..bcc34894a 100644 --- a/lib/encryptable.rb +++ b/lib/encryptable.rb @@ -28,5 +28,10 @@ Rails.logger.debug("Signing #{signable_string}") Base64.encode64(key.sign "SHA", signable_string) end + + def encrypted_xml_for(person) + person.encrypt self.to_diaspora_xml + end + end diff --git a/lib/encryptor.rb b/lib/encryptor.rb new file mode 100644 index 000000000..e8d7cf7de --- /dev/null +++ b/lib/encryptor.rb @@ -0,0 +1,61 @@ +module Encryptor + module Public + def encrypt cleartext + aes_key = gen_aes_key + ciphertext = aes_encrypt(cleartext, aes_key) + encrypted_key = encrypt_aes_key aes_key + cipher_hash = {:aes_key => encrypted_key, :ciphertext => ciphertext} + Base64.encode64( cipher_hash.to_json ) + end + + def gen_aes_key + cipher = OpenSSL::Cipher.new('AES-256-CBC') + key = cipher.random_key + iv = cipher.random_iv + {'key' => Base64.encode64(key), 'iv' => Base64.encode64(iv)} + end + + def aes_encrypt(txt, key) + cipher = OpenSSL::Cipher.new('AES-256-CBC') + cipher.encrypt + cipher.key = Base64.decode64 key['key'] + cipher.iv = Base64.decode64 key['iv'] + ciphertext = '' + ciphertext << cipher.update(txt) + ciphertext << cipher.final + Base64.encode64 ciphertext + end + + def encrypt_aes_key key + Base64.encode64 encryption_key.public_encrypt( key.to_json ) + end + end + + module Private + def decrypt cipher_json + json = JSON.parse(Base64.decode64 cipher_json) + aes_key = get_aes_key json['aes_key'] + aes_decrypt(json['ciphertext'], aes_key) + end + + def get_aes_key encrypted_key + clear_key = encryption_key.private_decrypt( Base64.decode64 encrypted_key ) + JSON::parse(clear_key) + end + + def aes_decrypt(ciphertext, key) + cipher = OpenSSL::Cipher.new('AES-256-CBC') + cipher.decrypt + cipher.key = Base64.decode64 key['key'] + cipher.iv = Base64.decode64 key['iv'] + txt = '' + txt << cipher.update(Base64.decode64 ciphertext) + txt << cipher.final + txt + end + + def self.generate_key + OpenSSL::PKey::RSA::generate 4096 + end + end +end diff --git a/lib/salmon/salmon.rb b/lib/salmon/salmon.rb index a20f35796..d207c00b4 100644 --- a/lib/salmon/salmon.rb +++ b/lib/salmon/salmon.rb @@ -36,7 +36,7 @@ end # Verify documents secured with Magic Signatures module Salmon class SalmonSlap - attr_accessor :magic_sig, :user, :data, :data_type, :sig + attr_accessor :magic_sig, :author, :author_email, :data, :data_type, :sig def self.parse(xml) slap = self.new doc = Nokogiri::XML(xml) @@ -57,15 +57,15 @@ module Salmon raise ArgumentError, "Magic Signature data must be signed with RSA-SHA256, was #{slap.magic_sig.alg}" unless 'RSA-SHA256' == slap.magic_sig.alg + uri = doc.search('uri').text + slap.author_email = uri.split("acct:").last slap end - - def self.create(user, activity) salmon = self.new - salmon.user = user - salmon.magic_sig = MagicSigEnvelope.create(user, activity) + salmon.author = user.person + salmon.magic_sig = MagicSigEnvelope.create(user , activity) salmon end @@ -74,8 +74,8 @@ module Salmon - #{@user.real_name} - acct:#{@user.email} + #{@author.real_name} + acct:#{@author.email} #{@magic_sig.to_xml} @@ -83,6 +83,14 @@ ENTRY end + def author + if @author + @author + else + Person.by_webfinger @author_email + end + end + # Decode URL-safe-Base64. This implements def self.decode64url(str) # remove whitespace @@ -161,7 +169,7 @@ ENTRY end class MagicSigEnvelope - attr_accessor :data, :data_type, :encoding, :alg, :sig, :user + attr_accessor :data, :data_type, :encoding, :alg, :sig, :author def self.parse(doc) env = self.new ns = {'me'=>'http://salmon-protocol.org/ns/magic-env'} @@ -175,7 +183,7 @@ ENTRY def self.create(user, activity) env = MagicSigEnvelope.new - env.user = user + env.author = user.person env.data = Base64.urlsafe_encode64(activity) env.data_type = env.get_data_type env.encoding = env.get_encoding diff --git a/spec/lib/salmon_salmon_spec.rb b/spec/lib/salmon_salmon_spec.rb index 49ffa483d..4fda36884 100644 --- a/spec/lib/salmon_salmon_spec.rb +++ b/spec/lib/salmon_salmon_spec.rb @@ -9,33 +9,50 @@ include Salmon describe Salmon do - it 'should verify the signature on a roundtrip' do + before do + @user = Factory.create :user @post = @user.post :status_message, :message => "hi", :to => @user.group(:name => "sdg").id - x = Salmon::SalmonSlap.create(@user, @post.to_diaspora_xml) - - z = Salmon::SalmonSlap.parse x.to_xml + @sent_salmon = Salmon::SalmonSlap.create(@user, @post.to_diaspora_xml) + @parsed_salmon = Salmon::SalmonSlap.parse @sent_salmon.to_xml + end - x.magic_sig.data.should == z.magic_sig.data + it 'should verify the signature on a roundtrip' do - x.magic_sig.sig.should == z.magic_sig.sig - x.magic_sig.signable_string.should == z.magic_sig.signable_string + @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 - x.verified_for_key?(OpenSSL::PKey::RSA.new(@user.exported_key)).should be true - z.verified_for_key?(OpenSSL::PKey::RSA.new(@user.exported_key)).should be true + @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 - @user = Factory.create :user - @post = @user.post :status_message, :message => "hi", :to => @user.group(:name => "sdg").id - x = Salmon::SalmonSlap.create(@user, @post.to_diaspora_xml) - z = Salmon::SalmonSlap.parse x.to_xml - xml = @post.to_diaspora_xml - z.data.should == xml + @parsed_salmon.data.should == xml end + + it 'should parse out the author email' do + @parsed_salmon.author_email.should == @user.person.email + end + + it 'should reference a local author' do + @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 + end + + it 'should fail to reference a nonexistent remote author' do + @parsed_salmon.author_email = 'idsfug@difgubhpsduh.rgd' + proc {@parsed_salmon.author.real_name}.should raise_error /not found/ + end + end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 608c17ba7..35e85ab21 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -7,10 +7,20 @@ describe Post do end describe 'xml' do - it 'should serialize to xml with its person' do - message = Factory.create(:status_message, :person => @user.person) - message.to_xml.to_s.include?(@user.person.email).should == true + before do + @message = Factory.create(:status_message, :person => @user.person) end + + it 'should serialize to xml with its person' do + @message.to_xml.to_s.include?(@user.person.email).should == true + end + + it 'should serialize to encrypted xml' do + enc_xml = @message.encrypted_xml_for(@user.person) + enc_xml.include?(@message.to_diaspora_xml).should be false + @user.decrypt(enc_xml).include?(@message.to_diaspora_xml).should be true + end + end describe 'deletion' do diff --git a/spec/models/user/receive_spec.rb b/spec/models/user/receive_spec.rb index 74ddfb882..41b619dbb 100644 --- a/spec/models/user/receive_spec.rb +++ b/spec/models/user/receive_spec.rb @@ -165,4 +165,16 @@ describe User do @user3.visible_person_by_id(commenter_id).should_not be_nil end end + + describe 'salmon' do + before do + @post = @user.post :status_message, :message => "hello", :to => @group.id + @salmon = @user.salmon( @post, :to => @user2.person ) + end + + it 'should receive a salmon for a post' do + @user2.receive_salmon( @salmon.to_xml ) + @user2.visible_post_ids.include?(@post.id).should be true + end + end end diff --git a/spec/user_encryption_spec.rb b/spec/user_encryption_spec.rb index 9432ac07b..6efafed4e 100644 --- a/spec/user_encryption_spec.rb +++ b/spec/user_encryption_spec.rb @@ -59,6 +59,17 @@ describe 'user encryption' do end end + describe 'encryption' do + before do + @message = @user.post :status_message, :message => "hi", :to => @group.id + end + it 'should encrypt large messages' do + ciphertext = @user.encrypt @message.to_diaspora_xml + ciphertext.include?(@message.to_diaspora_xml).should be false + @user.decrypt(ciphertext).include?(@message.to_diaspora_xml).should be true + end + end + describe 'signing and verifying' do it 'should sign a message on create' do From 240dda4eab19fce5c2309b826bf78a121cc24d85 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 12:21:36 -0700 Subject: [PATCH 02/27] Salmon for posts is in, old cruft has not been taken out and requests and comments are unfinished --- app/controllers/publics_controller.rb | 8 +++- app/models/user.rb | 28 ++++++++++---- lib/salmon/salmon.rb | 9 +++++ spec/controllers/publics_controller_spec.rb | 19 ++++++---- spec/lib/salmon_salmon_spec.rb | 8 ++++ spec/lib/web_hooks_spec.rb | 15 ++------ spec/models/user/posting_spec.rb | 41 ++++++++++++++++++++- 7 files changed, 98 insertions(+), 30 deletions(-) diff --git a/app/controllers/publics_controller.rb b/app/controllers/publics_controller.rb index e606dfb0e..2840e917f 100644 --- a/app/controllers/publics_controller.rb +++ b/app/controllers/publics_controller.rb @@ -23,13 +23,19 @@ class PublicsController < ApplicationController def receive render :nothing => true + return unless params[:xml] begin @user = Person.first(:id => params[:id]).owner rescue NoMethodError => e Rails.logger.error("Received post #{params[:xml]} for nonexistent person #{params[:id]}") return end - @user.receive params[:xml] if params[:xml] + puts params[:xml] + if params[:xml].include? "xml version='1.0'" + @user.receive_salmon params[:xml] + else + @user.receive params[:xml] + end end end diff --git a/app/models/user.rb b/app/models/user.rb index c5cfcbdf4..45eae6bad 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -86,7 +86,6 @@ class User ######## Posting ######## def post(class_name, options = {}) - options[:person] = self.person if class_name == :photo raise ArgumentError.new("No album_id given") unless options[:album_id] @@ -99,15 +98,20 @@ class User group_ids = [group_ids] if group_ids.is_a? BSON::ObjectId raise ArgumentError.new("You must post to someone.") if group_ids.nil? || group_ids.empty? + post = build_post(class_name, options) + + post.socket_to_uid(id, :group_ids => group_ids) if post.respond_to?(:socket_to_uid) + push_to_groups(post, group_ids) + + post + end + + def build_post( class_name, options = {}) + options[:person] = self.person model_class = class_name.to_s.camelize.constantize post = model_class.instantiate(options) post.creator_signature = post.sign_with_key(encryption_key) post.save - - post.socket_to_uid(id, :group_ids => group_ids) if post.respond_to?(:socket_to_uid) - - push_to_groups(post, group_ids) - self.raw_visible_posts << post self.save post @@ -128,11 +132,19 @@ class User group.save target_people = target_people | group.people } - post.push_to( target_people ) + push_to_people(post, target_people) + end + + def push_to_people(post, people) + people.each{|person| + salmon(post, :to => person) + } end def salmon( post, opts = {} ) - Salmon::SalmonSlap.create(self, post.encrypted_xml_for(opts[:to])) + salmon = Salmon::SalmonSlap.create(self, post.encrypted_xml_for(opts[:to])) + salmon.push_to_url opts[:to].receive_url + salmon end def visible_posts( opts = {} ) diff --git a/lib/salmon/salmon.rb b/lib/salmon/salmon.rb index d207c00b4..f94118e12 100644 --- a/lib/salmon/salmon.rb +++ b/lib/salmon/salmon.rb @@ -35,6 +35,8 @@ end # Verify documents secured with Magic Signatures module Salmon + QUEUE = MessageHandler.new + class SalmonSlap attr_accessor :magic_sig, :author, :author_email, :data, :data_type, :sig def self.parse(xml) @@ -91,6 +93,13 @@ ENTRY end end + def push_to_url(url) + Rails.logger.debug("Adding xml for #{self} to message queue to #{url}") + QUEUE.add_post_request( url, self.to_xml ) + QUEUE.process + end + + # Decode URL-safe-Base64. This implements def self.decode64url(str) # remove whitespace diff --git a/spec/controllers/publics_controller_spec.rb b/spec/controllers/publics_controller_spec.rb index cc6bd85b5..63d615363 100644 --- a/spec/controllers/publics_controller_spec.rb +++ b/spec/controllers/publics_controller_spec.rb @@ -5,7 +5,6 @@ describe PublicsController do before do @user = Factory.create(:user) - @user.person.save sign_in :user, @user end @@ -16,11 +15,17 @@ describe PublicsController do end it 'should accept a post from another node and save the information' do - person = Factory.create(:person) - message = StatusMessage.new(:message => 'foo', :person => person) - StatusMessage.all.count.should be 0 - post :receive, :id => @user.person.id, :xml => message.to_diaspora_xml - StatusMessage.all.count.should be 1 + 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 = user2.salmon(message, :to => @user.person).to_xml + + post :receive, :id => @user.person.id, :xml => xml + + @user.reload + @user.visible_post_ids.include?(message.id).should be true end end @@ -28,11 +33,9 @@ describe PublicsController do describe 'friend requests' do before do @user2 = Factory.create(:user) - @user2.person.save group = @user2.group(:name => 'disciples') @user3 = Factory.create(:user) - @user3.person.save req = @user2.send_friend_request_to(@user.person.url, group.id) diff --git a/spec/lib/salmon_salmon_spec.rb b/spec/lib/salmon_salmon_spec.rb index 4fda36884..f22186cb9 100644 --- a/spec/lib/salmon_salmon_spec.rb +++ b/spec/lib/salmon_salmon_spec.rb @@ -28,7 +28,15 @@ describe Salmon do @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 have an accessible queue' do + Salmon::QUEUE.is_a?(MessageHandler).should be true + end + it 'should push to a url' do + QUEUE.should_receive(:add_post_request) + @sent_salmon.push_to_url("example.com") + end it 'should return the data so it can be "received"' do diff --git a/spec/lib/web_hooks_spec.rb b/spec/lib/web_hooks_spec.rb index fa661049b..43f55b4d7 100644 --- a/spec/lib/web_hooks_spec.rb +++ b/spec/lib/web_hooks_spec.rb @@ -6,8 +6,11 @@ describe Diaspora do describe Webhooks do before do - @user = Factory.create(:user, :email => "bob@aol.com") + @user = Factory.create(:user) @group = @user.group(:name => "losers") + @user2 = Factory.create(:user) + @group2 = @user2.group(:name => "losers") + friend_users(@user, @group, @user2, @group2) end describe "body" do @@ -19,16 +22,6 @@ describe Diaspora do @post.respond_to?(:to_diaspora_xml).should be true end - it "should send an owners post to their people" do - message_queue.should_receive :process - @user.post :status_message, :message => "hi", :to => @group.id - end - - it "should check that it does not send a person's post to an owners people" do - message_queue.should_not_receive(:add_post_request) - Factory.create(:status_message, :person => Factory.create(:person)) - end - end end end diff --git a/spec/models/user/posting_spec.rb b/spec/models/user/posting_spec.rb index 0589de13e..627e8e78e 100644 --- a/spec/models/user/posting_spec.rb +++ b/spec/models/user/posting_spec.rb @@ -2,10 +2,47 @@ require File.dirname(__FILE__) + '/../../spec_helper' describe User do before do - @user = Factory.create(:user) - @group = @user.group(:name => 'heroes') + @user = Factory.create :user + @group = @user.group(:name => 'heroes') + @group1 = @user.group(:name => 'heroes') + + @user2 = Factory.create(:user) + @group2 = @user2.group(:name => 'losers') + + @user3 = Factory.create(:user) + @group3 = @user3.group(:name => 'heroes') + + @user4 = Factory.create(:user) + @group4 = @user4.group(:name => 'heroes') + + friend_users(@user, @group, @user2, @group2) + friend_users(@user, @group, @user3, @group3) + friend_users(@user, @group1, @user4, @group4) end + it 'should not be able to post without a group' do proc {@user.post(:status_message, :message => "heyheyhey")}.should raise_error /You must post to someone/ end + + describe 'dispatching' do + before do + @post = @user.build_post :status_message, :message => "hey" + end + it 'should push a post to a group' do + @user.should_receive(:salmon).twice + @user.push_to_groups(@post, @group.id) + end + + it 'should push a post to all groups' do + @user.should_receive(:salmon).exactly(3).times + @user.push_to_groups(@post, :all) + end + + it 'should push to people' do + @user.should_receive(:salmon).twice + @user.push_to_people(@post, [@user2.person, @user3.person]) + end + + + end end From c6aff4a56263c3bdebad5e87d7127d8fb49f7154 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 13:02:59 -0700 Subject: [PATCH 04/27] making the hcard work --- Gemfile | 1 + Gemfile.lock | 3 +++ app/models/person.rb | 13 ++++++++++--- app/views/publics/webfinger.erb | 4 ++-- config/routes.rb | 2 +- spec/models/person_spec.rb | 6 ++++++ 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index c3d8c3477..35958edae 100644 --- a/Gemfile +++ b/Gemfile @@ -29,6 +29,7 @@ gem 'json' #Standards gem 'pubsubhubbub' gem 'redfinger', :git => 'git://github.com/rsofaer/redfinger.git' +gem 'prism' #EventMachine gem 'em-http-request',:git => 'git://github.com/igrigorik/em-http-request.git', :require => 'em-http' diff --git a/Gemfile.lock b/Gemfile.lock index d34538a54..33e78e39b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -152,6 +152,8 @@ GEM plucky (0.3.5) mongo (~> 1.0.8) polyglot (0.3.1) + prism (0.1.0) + nokogiri pubsubhubbub (0.1.1) em-http-request (>= 0.1.5) eventmachine (>= 0.12.9) @@ -242,6 +244,7 @@ DEPENDENCIES mongo_ext mongo_mapper (= 0.8.4)! nifty-generators + prism pubsubhubbub rails (= 3.0.0) redfinger! diff --git a/app/models/person.rb b/app/models/person.rb index 2f90fe727..541dd03eb 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -88,17 +88,24 @@ class Person end def self.from_webfinger_profile( identifier, profile) - public_key = profile.links.select{|x| x.rel == 'diaspora-public-key'}.first.href new_person = Person.new + + public_key = profile.links.select{|x| x.rel == 'diaspora-public-key'}.first.href new_person.exported_key = Base64.decode64 public_key + new_person.email = identifier + + puts profile.hcard.first[:href] + + hcard = Prism.find profile.hcard.first[:href] + puts hcard.inspect receive_url = profile.links.select{ |l| l.rel == 'http://joindiaspora.com/seed_location'}.first.href new_person.url = receive_url.split('receive').first new_person.profile = Profile.new(:first_name => "Anon", :last_name => "ymous") - if new_person.save! + if new_person.save new_person else - cry + nil end end diff --git a/app/views/publics/webfinger.erb b/app/views/publics/webfinger.erb index adeb2d2db..f05590ea9 100644 --- a/app/views/publics/webfinger.erb +++ b/app/views/publics/webfinger.erb @@ -1,8 +1,8 @@ acct:<%=@person.email%> - "<%= @person.url %>users/#{@user.id}/hcard" - + "<%= @person.url %>" + diff --git a/config/routes.rb b/config/routes.rb index 5e7a6eafc..43149ba57 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,7 +27,7 @@ Diaspora::Application.routes.draw do #public routes # match 'webfinger', :to => 'publics#webfinger' - match 'users/:id/hcard', :to => 'publics#hcard' + match 'hcard/users/:id', :to => 'publics#hcard' match '.well-known/host-meta',:to => 'publics#host_meta' match 'receive/users/:id', :to => 'publics#receive' diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index 319e2b956..d2ce88049 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -144,6 +144,12 @@ describe Person do it 'should search by email exactly' do Person.by_webfinger(@friend_one.email).should == @friend_one end + + it 'should create a stub for a remote user' do + tom = Person.by_webfinger('tom@tom.joindiaspora.com') + puts tom.real_name + tom.real_name.include?("Hamiltom").should be true + end describe 'wall posting' do it 'should be able to post on another persons wall' do From 3e9a36e1f19e48528489a4fcfa9c52ee7155dd7d Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 14:15:20 -0700 Subject: [PATCH 05/27] Layout false on all publics controller routes --- app/controllers/publics_controller.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/controllers/publics_controller.rb b/app/controllers/publics_controller.rb index 2840e917f..d1255f336 100644 --- a/app/controllers/publics_controller.rb +++ b/app/controllers/publics_controller.rb @@ -1,23 +1,24 @@ class PublicsController < ApplicationController require 'lib/diaspora/parser' include Diaspora::Parser + layout false def hcard @person = Person.find_by_id params[:id] - + puts @person unless @person.nil? || @person.owner.nil? render 'hcard' end end def host_meta - render 'host_meta', :layout => false, :content_type => 'application/xrd+xml' + render 'host_meta', :content_type => 'application/xrd+xml' end def webfinger @person = Person.by_webfinger(params[:q]) unless @person.nil? || @person.owner.nil? - render 'webfinger', :layout => false, :content_type => 'application/xrd+xml' + render 'webfinger', :content_type => 'application/xrd+xml' end end From 59006e657fb92d589080d4ece0295b48d8a8373d Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 15:15:37 -0700 Subject: [PATCH 06/27] Hcard done manually --- Gemfile | 1 - Gemfile.lock | 5 +---- app/models/person.rb | 5 +++-- app/views/publics/hcard.erb | 15 +++++++++++++-- spec/lib/salmon_salmon_spec.rb | 10 +--------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Gemfile b/Gemfile index 35958edae..c3d8c3477 100644 --- a/Gemfile +++ b/Gemfile @@ -29,7 +29,6 @@ gem 'json' #Standards gem 'pubsubhubbub' gem 'redfinger', :git => 'git://github.com/rsofaer/redfinger.git' -gem 'prism' #EventMachine gem 'em-http-request',:git => 'git://github.com/igrigorik/em-http-request.git', :require => 'em-http' diff --git a/Gemfile.lock b/Gemfile.lock index 33e78e39b..673818fbe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -148,12 +148,10 @@ GEM net-ssh-gateway (1.0.1) net-ssh (>= 1.99.1) nifty-generators (0.4.0) - nokogiri (1.4.3.1) + nokogiri (1.4.1) plucky (0.3.5) mongo (~> 1.0.8) polyglot (0.3.1) - prism (0.1.0) - nokogiri pubsubhubbub (0.1.1) em-http-request (>= 0.1.5) eventmachine (>= 0.12.9) @@ -244,7 +242,6 @@ DEPENDENCIES mongo_ext mongo_mapper (= 0.8.4)! nifty-generators - prism pubsubhubbub rails (= 3.0.0) redfinger! diff --git a/app/models/person.rb b/app/models/person.rb index 541dd03eb..883db68bc 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -97,8 +97,9 @@ class Person puts profile.hcard.first[:href] - hcard = Prism.find profile.hcard.first[:href] - puts hcard.inspect + hcard = Prism.find profile.hcard.first[:href], :hcard + pp hcard.class + debugger receive_url = profile.links.select{ |l| l.rel == 'http://joindiaspora.com/seed_location'}.first.href new_person.url = receive_url.split('receive').first new_person.profile = Profile.new(:first_name => "Anon", :last_name => "ymous") diff --git a/app/views/publics/hcard.erb b/app/views/publics/hcard.erb index 7cfbe5604..773aa1cc7 100644 --- a/app/views/publics/hcard.erb +++ b/app/views/publics/hcard.erb @@ -9,10 +9,21 @@ <%= @person.real_name%> -
+
Full name
- <%= @person.real_name %> + <%= @person.profile.first_name %> +
+
+
+
Full name
+
+ <%= @person.profile.last_name %> +
+
+
Full name
+
+ <%= @person.real_name %>
diff --git a/spec/lib/salmon_salmon_spec.rb b/spec/lib/salmon_salmon_spec.rb index f22186cb9..f53c9d228 100644 --- a/spec/lib/salmon_salmon_spec.rb +++ b/spec/lib/salmon_salmon_spec.rb @@ -1,13 +1,5 @@ require File.dirname(__FILE__) + '/../spec_helper' - - -require 'lib/salmon/salmon' -include ApplicationHelper -include Salmon - - - describe Salmon do before do @@ -34,7 +26,7 @@ describe Salmon do end it 'should push to a url' do - QUEUE.should_receive(:add_post_request) + Salmon::QUEUE.should_receive(:add_post_request) @sent_salmon.push_to_url("example.com") end From 67f9d9dab5f490713cdae4eda705feaa179ea3b1 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 15:34:20 -0700 Subject: [PATCH 07/27] Add hcard, add id for pod_location --- app/models/person.rb | 14 ++++++++------ app/views/publics/hcard.erb | 5 +++-- lib/hcard.rb | 8 ++++++++ spec/lib/hcard.rb | 13 +++++++++++++ 4 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 lib/hcard.rb create mode 100644 spec/lib/hcard.rb diff --git a/app/models/person.rb b/app/models/person.rb index 883db68bc..82ee82e62 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -1,3 +1,5 @@ +require 'lib/hcard' + class Person include MongoMapper::Document include ROXML @@ -97,13 +99,13 @@ class Person puts profile.hcard.first[:href] - hcard = Prism.find profile.hcard.first[:href], :hcard - pp hcard.class - debugger + hcard = HCard.find profile.hcard.first[:href] + receive_url = profile.links.select{ |l| l.rel == 'http://joindiaspora.com/seed_location'}.first.href - new_person.url = receive_url.split('receive').first - new_person.profile = Profile.new(:first_name => "Anon", :last_name => "ymous") - if new_person.save + new_person.url = hcard[:url] + puts new_person.url + new_person.profile = Profile.new(:first_name => hcard[:given_name], :last_name => hcard[:family_name]) + if new_person.save! new_person else nil diff --git a/app/views/publics/hcard.erb b/app/views/publics/hcard.erb index 773aa1cc7..f8a3fef91 100644 --- a/app/views/publics/hcard.erb +++ b/app/views/publics/hcard.erb @@ -20,7 +20,8 @@
<%= @person.profile.last_name %>
-
+
+
Full name
<%= @person.real_name %> @@ -29,7 +30,7 @@
URL
- <%= @person.url%> + <%= @person.url%>
diff --git a/lib/hcard.rb b/lib/hcard.rb new file mode 100644 index 000000000..e8c1c2110 --- /dev/null +++ b/lib/hcard.rb @@ -0,0 +1,8 @@ +module HCard + def self.find url + doc = Nokogiri::HTML(Net::HTTP.get URI.parse(url)) + {:given_name => doc.css(".given_name").text, + :family_name => doc.css(".family_name").text, + :url => doc.css("#pod_location").text} + end +end diff --git a/spec/lib/hcard.rb b/spec/lib/hcard.rb new file mode 100644 index 000000000..06a237188 --- /dev/null +++ b/spec/lib/hcard.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/../spec_helper' +require File.dirname(__FILE__) + '/../../lib/hcard' + +describe HCard do + it 'should retreive and parse an hcard' do + f = Redfinger.finger('tom@tom.joindiaspora.com') + hcard = HCard.find f.hcard.first[:href] + hcard[:family_name].include?("Hamiltom").should be true + hcard[:given_name].include?("Alex").should be true + pp hcard + (hcard[:url] == "http://tom.joindiaspora.com").should be true + end +end From fd61535e11aca84cfd31fb01163bb2fc9222ad4c Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 15:43:16 -0700 Subject: [PATCH 08/27] Hcards working --- app/models/person.rb | 5 +---- spec/lib/hcard.rb | 3 +-- spec/models/person_spec.rb | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/app/models/person.rb b/app/models/person.rb index 82ee82e62..e3a2dd5da 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -97,15 +97,12 @@ class Person new_person.email = identifier - puts profile.hcard.first[:href] - hcard = HCard.find profile.hcard.first[:href] receive_url = profile.links.select{ |l| l.rel == 'http://joindiaspora.com/seed_location'}.first.href new_person.url = hcard[:url] - puts new_person.url new_person.profile = Profile.new(:first_name => hcard[:given_name], :last_name => hcard[:family_name]) - if new_person.save! + if new_person.save new_person else nil diff --git a/spec/lib/hcard.rb b/spec/lib/hcard.rb index 06a237188..6092e4dab 100644 --- a/spec/lib/hcard.rb +++ b/spec/lib/hcard.rb @@ -7,7 +7,6 @@ describe HCard do hcard = HCard.find f.hcard.first[:href] hcard[:family_name].include?("Hamiltom").should be true hcard[:given_name].include?("Alex").should be true - pp hcard - (hcard[:url] == "http://tom.joindiaspora.com").should be true + hcard[:url].should == "http://tom.joindiaspora.com/" end end diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index d2ce88049..8f0e21ef9 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -147,7 +147,6 @@ describe Person do it 'should create a stub for a remote user' do tom = Person.by_webfinger('tom@tom.joindiaspora.com') - puts tom.real_name tom.real_name.include?("Hamiltom").should be true end From 86d9a41d25b00e9908d97e525c212a7d938d2102 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 16:06:42 -0700 Subject: [PATCH 09/27] send_friend_request_to now takes a person and group, rather than a receive url and a group id --- app/controllers/dev_utilities_controller.rb | 2 +- app/controllers/publics_controller.rb | 1 - app/controllers/requests_controller.rb | 2 +- app/helpers/requests_helper.rb | 15 +++++---------- db/seeds/dev.rb | 2 +- db/seeds/tom.rb | 2 +- lib/diaspora/user/friending.rb | 18 ++++-------------- spec/controllers/publics_controller_spec.rb | 2 +- spec/lib/diaspora_parser_spec.rb | 4 ++-- spec/models/comments_spec.rb | 2 +- spec/models/person_spec.rb | 6 +++--- spec/models/request_spec.rb | 2 +- spec/models/user/user_friending_spec.rb | 6 +++--- spec/spec_helper.rb | 2 +- spec/user_encryption_spec.rb | 4 ++-- 15 files changed, 27 insertions(+), 43 deletions(-) diff --git a/app/controllers/dev_utilities_controller.rb b/app/controllers/dev_utilities_controller.rb index a16c1fd56..e633d4021 100644 --- a/app/controllers/dev_utilities_controller.rb +++ b/app/controllers/dev_utilities_controller.rb @@ -30,7 +30,7 @@ def warzombie backer_email = "#{backer['username']}@#{backer['username']}.joindiaspora.com" rel_hash = relationship_flow(backer_email) logger.info "Zombefriending #{backer['given_name']} #{backer['family_name']}" - current_user.send_request(rel_hash, current_user.groups.first.id) + current_user.send_friend_request_to(rel_hash[:friend], current_user.groups.first.id) end end end diff --git a/app/controllers/publics_controller.rb b/app/controllers/publics_controller.rb index d1255f336..bf9a61e21 100644 --- a/app/controllers/publics_controller.rb +++ b/app/controllers/publics_controller.rb @@ -31,7 +31,6 @@ class PublicsController < ApplicationController Rails.logger.error("Received post #{params[:xml]} for nonexistent person #{params[:id]}") return end - puts params[:xml] if params[:xml].include? "xml version='1.0'" @user.receive_salmon params[:xml] else diff --git a/app/controllers/requests_controller.rb b/app/controllers/requests_controller.rb index b62eb630e..59e58ba3c 100644 --- a/app/controllers/requests_controller.rb +++ b/app/controllers/requests_controller.rb @@ -45,7 +45,7 @@ class RequestsController < ApplicationController Rails.logger.debug("Sending request: #{rel_hash}") begin - @request = current_user.send_request(rel_hash, params[:request][:group_id]) + @request = current_user.send_friend_request_to(rel_hash[:friend], group) rescue Exception => e raise e unless e.message.include? "already friends" message = "You are already friends with #{params[:request][:destination_url]}!" diff --git a/app/helpers/requests_helper.rb b/app/helpers/requests_helper.rb index 37a5485c4..e40f6bde8 100644 --- a/app/helpers/requests_helper.rb +++ b/app/helpers/requests_helper.rb @@ -27,17 +27,12 @@ module RequestsHelper def relationship_flow(identifier) action = :none - url = nil - local_person = Person.by_webfinger identifier - if local_person - action = (local_person == current_user.person ? :none : :friend) - url = local_person.receive_url - elsif !(identifier.include?(request.host) || identifier.include?("localhost")) - f = Redfinger.finger(identifier) - action = subscription_mode(f) - url = subscription_url(action, f) + person = nil + person = Person.by_webfinger identifier + if person + action = (person == current_user.person ? :none : :friend) end - { action => url } + { action => person } end end diff --git a/db/seeds/dev.rb b/db/seeds/dev.rb index c44979057..92653b8d9 100644 --- a/db/seeds/dev.rb +++ b/db/seeds/dev.rb @@ -25,6 +25,6 @@ user2.person.save! # friending users group = user.group(:name => "other dudes") -request = user.send_friend_request_to(user2.receive_url, group.id) +request = user.send_friend_request_to(user2, group) reversed_request = user2.accept_friend_request( request.id, user2.group(:name => "presidents").id ) user.receive reversed_request.to_diaspora_xml diff --git a/db/seeds/tom.rb b/db/seeds/tom.rb index 864caa6f2..7a4a52f3a 100644 --- a/db/seeds/tom.rb +++ b/db/seeds/tom.rb @@ -26,7 +26,7 @@ user2.person.save! # friending users group = user.group(:name => "other dudes") -request = user.send_friend_request_to(user2.receive_url, group.id) +request = user.send_friend_request_to(user2, group) reversed_request = user2.accept_friend_request( request.id, user2.group(:name => "presidents").id ) user.receive reversed_request.to_diaspora_xml user.group(:name => "Presidents") diff --git a/lib/diaspora/user/friending.rb b/lib/diaspora/user/friending.rb index e80ee5aa5..b249347dd 100644 --- a/lib/diaspora/user/friending.rb +++ b/lib/diaspora/user/friending.rb @@ -1,19 +1,17 @@ module Diaspora module UserModules module Friending - def send_friend_request_to(friend_url, group_id) - raise "You are already friends with that person!" if self.friends.detect{ |x| x.receive_url == friend_url} - request = Request.instantiate(:to => friend_url, :from => self.person, :into => group_id) + def send_friend_request_to(friend, group) + raise "You are already friends with that person!" if self.friends.detect{ |x| x.receive_url == friend.receive_url} + request = Request.instantiate(:to => friend.receive_url, :from => self.person, :into => group.id) if request.save self.pending_requests << request self.save - group = self.group_by_id(group_id) - group.requests << request group.save - request.push_to_url friend_url + request.push_to_url friend.receive_url end request end @@ -101,14 +99,6 @@ module Diaspora remove_friend bad_friend end - def send_request(rel_hash, group) - if rel_hash[:friend] - self.send_friend_request_to(rel_hash[:friend], group) - else - raise "you can't do anything to that url" - end - end - def activate_friend(person, group) person.user_refs += 1 group.people << person diff --git a/spec/controllers/publics_controller_spec.rb b/spec/controllers/publics_controller_spec.rb index 63d615363..d574b28f1 100644 --- a/spec/controllers/publics_controller_spec.rb +++ b/spec/controllers/publics_controller_spec.rb @@ -37,7 +37,7 @@ describe PublicsController do @user3 = Factory.create(:user) - req = @user2.send_friend_request_to(@user.person.url, group.id) + req = @user2.send_friend_request_to(@user.person, group) @xml = req.to_diaspora_xml diff --git a/spec/lib/diaspora_parser_spec.rb b/spec/lib/diaspora_parser_spec.rb index 5197080dc..b0b8f6a97 100644 --- a/spec/lib/diaspora_parser_spec.rb +++ b/spec/lib/diaspora_parser_spec.rb @@ -96,7 +96,7 @@ describe Diaspora::Parser do end it "should activate the Person if I initiated a request to that url" do - request = @user.send_friend_request_to( @user2.receive_url, @group.id) + request = @user.send_friend_request_to( @user2.person, @group) request.reverse_for @user2 @@ -118,7 +118,7 @@ describe Diaspora::Parser do it 'should process retraction for a person' do person_count = Person.all.count - request = @user.send_friend_request_to( @user2.receive_url, @group.id) + request = @user.send_friend_request_to( @user2.person, @group) request.reverse_for @user2 xml = request.to_diaspora_xml diff --git a/spec/models/comments_spec.rb b/spec/models/comments_spec.rb index 95d2c977c..bdf85884d 100644 --- a/spec/models/comments_spec.rb +++ b/spec/models/comments_spec.rb @@ -36,7 +36,7 @@ describe Comment do before do - request = @user.send_friend_request_to(@user2.receive_url, @group.id) + request = @user.send_friend_request_to(@user2, @group) reversed_request = @user2.accept_friend_request( request.id, @group2.id ) @user.receive reversed_request.to_diaspora_xml diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index 8f0e21ef9..fc203d593 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -60,7 +60,7 @@ describe Person do describe "unfriending" do it 'should delete an orphaned friend' do - request = @user.send_friend_request_to @person.receive_url, @group.id + request = @user.send_friend_request_to @person, @group @user.activate_friend(@person, @group) @user.reload @@ -74,8 +74,8 @@ describe Person do end it 'should not delete an un-orphaned friend' do - request = @user.send_friend_request_to @person.receive_url, @group.id - request2 = @user2.send_friend_request_to @person.receive_url, @group2.id + request = @user.send_friend_request_to @person, @group + request2 = @user2.send_friend_request_to @person, @group2 @user.activate_friend(@person, @group) @user2.activate_friend(@person, @group2) diff --git a/spec/models/request_spec.rb b/spec/models/request_spec.rb index c5b49cc64..b02d6e682 100644 --- a/spec/models/request_spec.rb +++ b/spec/models/request_spec.rb @@ -15,7 +15,7 @@ describe Request do it 'should generate xml for the User as a Person' do - request = @user.send_friend_request_to "http://www.google.com/", @group.id + request = @user.send_friend_request_to Factory.create(:person), @group xml = request.to_xml.to_s diff --git a/spec/models/user/user_friending_spec.rb b/spec/models/user/user_friending_spec.rb index 6bf4c1117..50e5817fc 100644 --- a/spec/models/user/user_friending_spec.rb +++ b/spec/models/user/user_friending_spec.rb @@ -12,7 +12,7 @@ describe User do group = @user.group(:name => "Dudes") group.requests.size.should == 0 - @user.send_friend_request_to(friend.receive_url, group.id) + @user.send_friend_request_to(friend, group) group.reload group.requests.size.should == 1 @@ -48,7 +48,7 @@ describe User do @user.save - proc {@user.send_friend_request_to( friend.receive_url, @group.id )}.should raise_error + proc {@user.send_friend_request_to( friend, @group)}.should raise_error end @@ -183,7 +183,7 @@ describe User do @user2 = Factory.create :user @group2 = @user2.group(:name => "Gross people") - request = @user.send_friend_request_to( @user2.receive_url, @group.id) + request = @user.send_friend_request_to( @user2, @group) request.reverse_for @user2 @user2.activate_friend(@user.person, @group2) @user.receive request.to_diaspora_xml diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ff5cb46f3..3c5526e0d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -62,7 +62,7 @@ end end def friend_users(user1, group1, user2, group2) - request = user1.send_friend_request_to(user2.receive_url, group1.id) + request = user1.send_friend_request_to(user2.person, group1) reversed_request = user2.accept_friend_request( request.id, group2.id) user1.receive reversed_request.to_diaspora_xml end diff --git a/spec/user_encryption_spec.rb b/spec/user_encryption_spec.rb index 6efafed4e..73b9db0b9 100644 --- a/spec/user_encryption_spec.rb +++ b/spec/user_encryption_spec.rb @@ -32,7 +32,7 @@ describe 'user encryption' do describe 'key exchange on friending' do it 'should send over a public key' do message_queue.stub!(:add_post_request) - request = @user.send_friend_request_to("http://example.com/", @group.id) + request = @user.send_friend_request_to(Factory.create(:person), @group) request.to_diaspora_xml.include?( @user.exported_key).should be true end @@ -44,7 +44,7 @@ describe 'user encryption' do original_key = remote_user.exported_key request = remote_user.send_friend_request_to( - @user.receive_url, remote_user.group(:name => "temp").id) + @user.person, remote_user.group(:name => "temp")) xml = request.to_diaspora_xml From 522450c9d313d52b5ff1cc454a42f8e90fe0ce56 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 16:19:34 -0700 Subject: [PATCH 10/27] RS IZ added a logger statement and a guid in the webfinger profile --- app/models/person.rb | 4 +++- app/models/user.rb | 1 + app/views/publics/webfinger.erb | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/models/person.rb b/app/models/person.rb index e3a2dd5da..3fca21eb2 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -94,12 +94,14 @@ class Person public_key = profile.links.select{|x| x.rel == 'diaspora-public-key'}.first.href new_person.exported_key = Base64.decode64 public_key + + guid = profile.links.select{|x| x.rel == 'diaspora-public-key'}.first.href + new_person.id = guid new_person.email = identifier hcard = HCard.find profile.hcard.first[:href] - receive_url = profile.links.select{ |l| l.rel == 'http://joindiaspora.com/seed_location'}.first.href new_person.url = hcard[:url] new_person.profile = Profile.new(:first_name => hcard[:given_name], :last_name => hcard[:family_name]) if new_person.save diff --git a/app/models/user.rb b/app/models/user.rb index 45eae6bad..d4408674e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -204,6 +204,7 @@ class User ###### Receiving ####### def receive_salmon xml + Rails.logger.info("Received a salmon: #{xml}") salmon = Salmon::SalmonSlap.parse xml if salmon.verified_for_key?(salmon.author.public_key) self.receive(decrypt(salmon.data)) diff --git a/app/views/publics/webfinger.erb b/app/views/publics/webfinger.erb index f05590ea9..75a2e9fe8 100644 --- a/app/views/publics/webfinger.erb +++ b/app/views/publics/webfinger.erb @@ -4,6 +4,7 @@ "<%= @person.url %>" - + + From c73ce3ff99038e744d1de7751667de2cd425ac1c Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 16:20:27 -0700 Subject: [PATCH 11/27] RS IZ added a logger statement and a guid in the webfinger profile --- app/models/person.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/person.rb b/app/models/person.rb index 3fca21eb2..ff1455010 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -95,7 +95,7 @@ class Person public_key = profile.links.select{|x| x.rel == 'diaspora-public-key'}.first.href new_person.exported_key = Base64.decode64 public_key - guid = profile.links.select{|x| x.rel == 'diaspora-public-key'}.first.href + guid = profile.links.select{|x| x.rel == 'http://joindiaspora.com/guid'}.first.href new_person.id = guid new_person.email = identifier From 6b4501c34287aa36d819280fecde56087976d6b5 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 16:23:08 -0700 Subject: [PATCH 12/27] Move generate key back into user --- app/models/user.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index d4408674e..7592dbeee 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -342,5 +342,7 @@ class User } } end - + def self.generate_key + OpenSSL::PKey::RSA::generate 4096 + end end From d03c8e33232e05c037f78c444ed838c1efa2c0ba Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 16:31:10 -0700 Subject: [PATCH 13/27] removed the gen key method from encryptor --- lib/encryptor.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/encryptor.rb b/lib/encryptor.rb index e8d7cf7de..d80aecb15 100644 --- a/lib/encryptor.rb +++ b/lib/encryptor.rb @@ -54,8 +54,6 @@ module Encryptor txt end - def self.generate_key - OpenSSL::PKey::RSA::generate 4096 - end + end end From fcadf7ab9676090344b5bbde38168b9e87ae6a6a Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 16:54:51 -0700 Subject: [PATCH 14/27] Salmon the requests --- lib/diaspora/user/friending.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/diaspora/user/friending.rb b/lib/diaspora/user/friending.rb index b249347dd..781eb756a 100644 --- a/lib/diaspora/user/friending.rb +++ b/lib/diaspora/user/friending.rb @@ -1,9 +1,13 @@ module Diaspora module UserModules module Friending - def send_friend_request_to(friend, group) - raise "You are already friends with that person!" if self.friends.detect{ |x| x.receive_url == friend.receive_url} - request = Request.instantiate(:to => friend.receive_url, :from => self.person, :into => group.id) + def send_friend_request_to(desired_friend, group) + raise "You are already friends with that person!" if self.friends.detect{ + |x| x.receive_url == desired_friend.receive_url} + request = Request.instantiate( + :to => desired_friend.receive_url, + :from => self.person, + :into => group.id) if request.save self.pending_requests << request self.save @@ -11,7 +15,7 @@ module Diaspora group.requests << request group.save - request.push_to_url friend.receive_url + salmon request, :to => desired_friend end request end From a449afca8e7e35e60ffcbd747c6b448f38f5292d Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 17:07:40 -0700 Subject: [PATCH 15/27] RS IZ salmon back friend acceptances --- lib/diaspora/user/friending.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/diaspora/user/friending.rb b/lib/diaspora/user/friending.rb index 781eb756a..37665fcf6 100644 --- a/lib/diaspora/user/friending.rb +++ b/lib/diaspora/user/friending.rb @@ -31,13 +31,15 @@ module Diaspora request end - def dispatch_friend_acceptance(request) - request.push_to_url(request.callback_url) + def dispatch_friend_acceptance(request, requester) + salmon request, :to => requester request.destroy unless request.callback_url.include? url end def accept_and_respond(friend_request_id, group_id) - dispatch_friend_acceptance(accept_friend_request(friend_request_id, group_id)) + requester = Request.find_by_id(friend_request_id).person + reversed_request = accept_friend_request(friend_request_id, group_id) + dispatch_friend_acceptance reversed_request, requester end def ignore_friend_request(friend_request_id) From 87bef90932a1f8afeab3669e03d674f99f3562dc Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 17:28:32 -0700 Subject: [PATCH 16/27] Salmon for retractions and profiles --- app/models/user.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 7592dbeee..575986fdf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -186,7 +186,7 @@ class User post.unsocket_from_uid(self.id) if post.respond_to? :unsocket_from_uid retraction = Retraction.for(post) retraction.creator_signature = retraction.sign_with_key( encryption_key ) - retraction.push_to( self.friends.all ) + push_to_groups retraction, groups_with_post(post).map!{|g| g.id} retraction end @@ -195,7 +195,7 @@ class User params[:profile].delete(:image_url) if params[:profile][:image_url].empty? if self.person.update_attributes(params) - self.profile.push_to( self.friends.all ) + push_to_groups profile, :all true else false From 8b09d8107c0cffa986aaf9589a98b616e8e29437 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 17:43:07 -0700 Subject: [PATCH 17/27] Add encryptable to profiles --- app/models/profile.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/profile.rb b/app/models/profile.rb index 486e99b96..509498037 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -3,6 +3,7 @@ class Profile require 'lib/diaspora/webhooks' include Diaspora::Webhooks include ROXML + include Encryptable xml_reader :person_id xml_accessor :first_name From 2b1724c42ff535bcd5ef9ed07c1bbd11533de92d Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 17:44:33 -0700 Subject: [PATCH 18/27] Pass id to groups_with_post --- app/models/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 575986fdf..035964172 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -186,7 +186,7 @@ class User post.unsocket_from_uid(self.id) if post.respond_to? :unsocket_from_uid retraction = Retraction.for(post) retraction.creator_signature = retraction.sign_with_key( encryption_key ) - push_to_groups retraction, groups_with_post(post).map!{|g| g.id} + push_to_groups retraction, groups_with_post(post.id).map!{|g| g.id} retraction end From e9377a681cd53fe2620be1dfe97800acc40f04f4 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 17:52:35 -0700 Subject: [PATCH 19/27] Don't use push_to_groups for retractions --- app/models/user.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 035964172..0da319889 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -135,6 +135,13 @@ class User push_to_people(post, target_people) end + def people_in_groups groups + people = [] + groups.each{ |group| + people = people | group.people + } + end + def push_to_people(post, people) people.each{|person| salmon(post, :to => person) @@ -186,7 +193,7 @@ class User post.unsocket_from_uid(self.id) if post.respond_to? :unsocket_from_uid retraction = Retraction.for(post) retraction.creator_signature = retraction.sign_with_key( encryption_key ) - push_to_groups retraction, groups_with_post(post.id).map!{|g| g.id} + push_to_people retraction, people_with_groups(groups_with_post(post.id)) retraction end From 222847ca92a2f64f6d466a4842c5661355220be2 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 17:54:33 -0700 Subject: [PATCH 20/27] Using methods that exist can be helpful --- app/models/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 0da319889..4961a0265 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -193,7 +193,7 @@ class User post.unsocket_from_uid(self.id) if post.respond_to? :unsocket_from_uid retraction = Retraction.for(post) retraction.creator_signature = retraction.sign_with_key( encryption_key ) - push_to_people retraction, people_with_groups(groups_with_post(post.id)) + push_to_people retraction, people_in_groups(groups_with_post(post.id)) retraction end From 7448684358dd2e0dc1a730a7d1ee9fceacea9d22 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 17:56:21 -0700 Subject: [PATCH 21/27] Return results of queries --- app/models/user.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/user.rb b/app/models/user.rb index 4961a0265..ea4a7c877 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -140,6 +140,7 @@ class User groups.each{ |group| people = people | group.people } + people end def push_to_people(post, people) From 68dc74e0b7a7a45ba83dc86cd484834f6774652a Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Sep 2010 18:15:30 -0700 Subject: [PATCH 22/27] Tests pass again, use id => in retraction.perform --- app/models/retraction.rb | 2 +- spec/models/retraction_spec.rb | 10 ++++------ spec/models/user_spec.rb | 2 -- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/app/models/retraction.rb b/app/models/retraction.rb index afea944f6..3d97db47b 100644 --- a/app/models/retraction.rb +++ b/app/models/retraction.rb @@ -30,7 +30,7 @@ class Retraction begin return unless signature_valid? Rails.logger.debug("Retracting #{self.type} id: #{self.post_id}") - target = self.type.constantize.first(self.post_id) + target = self.type.constantize.first(:id => self.post_id) target.unsocket_from_uid receiving_user_id if target.respond_to? :unsocket_from_uid target.destroy rescue NameError diff --git a/spec/models/retraction_spec.rb b/spec/models/retraction_spec.rb index bb344a039..9b742fae3 100644 --- a/spec/models/retraction_spec.rb +++ b/spec/models/retraction_spec.rb @@ -3,10 +3,10 @@ require File.dirname(__FILE__) + '/../spec_helper' describe Retraction do before do @user = Factory.create(:user) - @post = @user.post :status_message, :message => "Destroy!", :to => @user.group(:name => "losers").id @person = Factory.create(:person) - @user.friends << @person - @user.save + @group = @user.group(:name => "Bruisers") + @user.activate_friend(@person, @group) + @post = @user.post :status_message, :message => "Destroy!", :to => @group.id end describe 'serialization' do it 'should have a post id after serialization' do @@ -18,10 +18,8 @@ describe Retraction do describe 'dispatching' do it 'should dispatch a message on delete' do Factory.create(:person) - message_queue.should_receive(:add_post_request) + Salmon::QUEUE.should_receive :add_post_request @post.destroy end end - - end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 548966548..54dfe9632 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -12,8 +12,6 @@ describe User do updated_profile = {:profile => {:first_name => 'bob', :last_name => 'billytown', :image_url => "http://clown.com"}} - message_queue.should_receive(:process) - @user.update_profile(updated_profile).should == true @user.profile.image_url.should == "http://clown.com" end From aa1f3c643856c471e7dc1bc09224c7a688c68aa8 Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 10 Sep 2010 10:31:23 -0700 Subject: [PATCH 23/27] Comments now use salmon, the whole salmon is encrypted, user querying moved to lib file --- app/controllers/people_controller.rb | 2 +- app/controllers/publics_controller.rb | 6 +- app/models/user.rb | 74 +++++--------------- lib/diaspora/user/querying.rb | 54 ++++++++++++++ lib/salmon/salmon.rb | 12 +--- spec/controllers/publics_controller_spec.rb | 5 +- spec/controllers/requests_controller_spec.rb | 13 ++-- spec/lib/{hcard.rb => hcard_spec.rb} | 0 spec/lib/salmon_salmon_spec.rb | 9 --- spec/models/retraction_spec.rb | 2 +- spec/models/user/receive_spec.rb | 2 +- 11 files changed, 88 insertions(+), 91 deletions(-) create mode 100644 lib/diaspora/user/querying.rb rename spec/lib/{hcard.rb => hcard_spec.rb} (100%) diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 2f516d5bc..8f1ea9553 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -14,7 +14,7 @@ class PeopleController < ApplicationController @profile = @person.profile @groups_with_person = current_user.groups_with_person(@person) @groups_dropdown_array = current_user.groups.collect{|x| [x.to_s, x.id]} - @posts = current_user.posts_visible_to_me(:from => @person).paginate :page => params[:page], :order => 'created_at DESC' + @posts = current_user.visible_posts_from_others(:from => @person).paginate :page => params[:page], :order => 'created_at DESC' @latest_status_message = current_user.raw_visible_posts.find_all_by__type_and_person_id("StatusMessage", params[:id]).last @post_count = @posts.count respond_with @person diff --git a/app/controllers/publics_controller.rb b/app/controllers/publics_controller.rb index bf9a61e21..da7d8219e 100644 --- a/app/controllers/publics_controller.rb +++ b/app/controllers/publics_controller.rb @@ -31,11 +31,7 @@ class PublicsController < ApplicationController Rails.logger.error("Received post #{params[:xml]} for nonexistent person #{params[:id]}") return end - if params[:xml].include? "xml version='1.0'" - @user.receive_salmon params[:xml] - else - @user.receive params[:xml] - end + @user.receive_salmon params[:xml] end end diff --git a/app/models/user.rb b/app/models/user.rb index ea4a7c877..21054c020 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,10 +1,13 @@ require 'lib/diaspora/user/friending.rb' +require 'lib/diaspora/user/querying.rb' require 'lib/salmon/salmon' class User include MongoMapper::Document include Diaspora::UserModules::Friending + include Diaspora::UserModules::Querying include Encryptor::Private + QUEUE = MessageHandler.new devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable @@ -72,18 +75,6 @@ class User false end -##querying with permissions - def posts_visible_to_me(opts ={}) - if opts[:from].class == Person - Post.where(:person_id => opts[:from].id, :_id.in => self.visible_post_ids) - elsif opts[:from].class == Group - Post.where(:_id.in => opts[:from].post_ids) unless opts[:from].user != self - else - Post.where(:_id.in => self.visible_post_ids) - end - end - - ######## Posting ######## def post(class_name, options = {}) @@ -149,19 +140,20 @@ class User } 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.process + + end + def salmon( post, opts = {} ) - salmon = Salmon::SalmonSlap.create(self, post.encrypted_xml_for(opts[:to])) - salmon.push_to_url opts[:to].receive_url + salmon = Salmon::SalmonSlap.create(self, post.to_diaspora_xml) + push_to_person( opts[:to], salmon.to_xml) salmon end - def visible_posts( opts = {} ) - if opts[:by_members_of] - return raw_visible_posts if opts[:by_members_of] == :all - group = self.groups.find_by_id( opts[:by_members_of].id ) - group.posts - end - end + ######## Commenting ######## def comment(text, options = {}) @@ -211,11 +203,12 @@ class User end ###### Receiving ####### - def receive_salmon xml - Rails.logger.info("Received a salmon: #{xml}") - salmon = Salmon::SalmonSlap.parse xml + def receive_salmon ciphertext + cleartext = decrypt( ciphertext) + Rails.logger.info("Received a salmon: #{cleartext}") + salmon = Salmon::SalmonSlap.parse cleartext if salmon.verified_for_key?(salmon.author.public_key) - self.receive(decrypt(salmon.data)) + self.receive(salmon.data) end end @@ -303,42 +296,13 @@ class User self.password_confirmation = self.password end - def visible_person_by_id( id ) - id = id.to_id - return self.person if id == self.person.id - result = friends.detect{|x| x.id == id } - result = visible_people.detect{|x| x.id == id } unless result - result - end - - def group_by_id( id ) - id = id.to_id - groups.detect{|x| x.id == id } - end - - def album_by_id( id ) - id = id.to_id - albums.detect{|x| x.id == id } - end - - def groups_with_post( id ) - self.groups.find_all_by_post_ids( id.to_id ) - end - - def groups_with_person person - id = person.id.to_id - groups.select { |g| g.person_ids.include? id} - end - def setup_person self.person.serialized_key ||= User.generate_key.export self.person.email ||= email self.person.save! end - def all_group_ids - self.groups.all.collect{|x| x.id} - end + def as_json(opts={}) { diff --git a/lib/diaspora/user/querying.rb b/lib/diaspora/user/querying.rb new file mode 100644 index 000000000..7346a8ab2 --- /dev/null +++ b/lib/diaspora/user/querying.rb @@ -0,0 +1,54 @@ +module Diaspora + module UserModules + module Querying + def visible_posts_from_others(opts ={}) + if opts[:from].class == Person + Post.where(:person_id => opts[:from].id, :_id.in => self.visible_post_ids) + elsif opts[:from].class == Group + Post.where(:_id.in => opts[:from].post_ids) unless opts[:from].user != self + else + Post.where(:_id.in => self.visible_post_ids) + end + end + + def visible_posts( opts = {} ) + if opts[:by_members_of] + return raw_visible_posts if opts[:by_members_of] == :all + group = self.groups.find_by_id( opts[:by_members_of].id ) + group.posts + end + end + + def visible_person_by_id( id ) + id = id.to_id + return self.person if id == self.person.id + result = friends.detect{|x| x.id == id } + result = visible_people.detect{|x| x.id == id } unless result + result + end + + def group_by_id( id ) + id = id.to_id + groups.detect{|x| x.id == id } + end + + def album_by_id( id ) + id = id.to_id + albums.detect{|x| x.id == id } + end + + def groups_with_post( id ) + self.groups.find_all_by_post_ids( id.to_id ) + end + + def groups_with_person person + id = person.id.to_id + groups.select { |g| g.person_ids.include? id} + end + + def all_group_ids + self.groups.all.collect{|x| x.id} + end + end + end +end diff --git a/lib/salmon/salmon.rb b/lib/salmon/salmon.rb index f94118e12..c1e14c021 100644 --- a/lib/salmon/salmon.rb +++ b/lib/salmon/salmon.rb @@ -35,7 +35,6 @@ end # Verify documents secured with Magic Signatures module Salmon - QUEUE = MessageHandler.new class SalmonSlap attr_accessor :magic_sig, :author, :author_email, :data, :data_type, :sig @@ -93,11 +92,7 @@ ENTRY end end - def push_to_url(url) - Rails.logger.debug("Adding xml for #{self} to message queue to #{url}") - QUEUE.add_post_request( url, self.to_xml ) - QUEUE.process - end + # Decode URL-safe-Base64. This implements @@ -170,11 +165,6 @@ ENTRY key end - - - - - end class MagicSigEnvelope diff --git a/spec/controllers/publics_controller_spec.rb b/spec/controllers/publics_controller_spec.rb index d574b28f1..cc9f3064d 100644 --- a/spec/controllers/publics_controller_spec.rb +++ b/spec/controllers/publics_controller_spec.rb @@ -20,7 +20,7 @@ describe PublicsController do @user.reload @user.visible_post_ids.include?(message.id).should be false - xml = user2.salmon(message, :to => @user.person).to_xml + xml = @user.person.encrypt(user2.salmon(message, :to => @user.person).to_xml) post :receive, :id => @user.person.id, :xml => xml @@ -39,7 +39,7 @@ describe PublicsController do req = @user2.send_friend_request_to(@user.person, group) - @xml = req.to_diaspora_xml + @xml = @user.person.encrypt(@user2.salmon(req, :to => @user.person).to_xml) req.delete @user2.reload @@ -54,6 +54,7 @@ describe PublicsController do 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.email).and_return(@user2.person) @user2.person.delete @user2.delete post :receive, :id => @user.person.id, :xml => @xml diff --git a/spec/controllers/requests_controller_spec.rb b/spec/controllers/requests_controller_spec.rb index 579ee620e..f6ddb849a 100644 --- a/spec/controllers/requests_controller_spec.rb +++ b/spec/controllers/requests_controller_spec.rb @@ -2,14 +2,15 @@ require File.dirname(__FILE__) + '/../spec_helper' include ApplicationHelper include RequestsHelper describe RequestsController do - before do + render_views + before do + @user = Factory.create :user @tom = Redfinger.finger('tom@tom.joindiaspora.com') @evan = Redfinger.finger('evan@status.net') @max = Redfinger.finger('mbs348@gmail.com') + sign_in :user, @user + end + it 'should return the correct tag and url for a given address' do + relationship_flow('tom@tom.joindiaspora.com')[:friend].include?("receive/user").should == true end - it 'should return the correct tag and url for a given address' do - relationship_flow('tom@tom.joindiaspora.com')[:friend].include?("receive/user").should == true - end - - end diff --git a/spec/lib/hcard.rb b/spec/lib/hcard_spec.rb similarity index 100% rename from spec/lib/hcard.rb rename to spec/lib/hcard_spec.rb diff --git a/spec/lib/salmon_salmon_spec.rb b/spec/lib/salmon_salmon_spec.rb index f53c9d228..de85fe838 100644 --- a/spec/lib/salmon_salmon_spec.rb +++ b/spec/lib/salmon_salmon_spec.rb @@ -20,15 +20,6 @@ describe Salmon do @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 have an accessible queue' do - Salmon::QUEUE.is_a?(MessageHandler).should be true - end - - it 'should push to a url' do - Salmon::QUEUE.should_receive(:add_post_request) - @sent_salmon.push_to_url("example.com") - end it 'should return the data so it can be "received"' do diff --git a/spec/models/retraction_spec.rb b/spec/models/retraction_spec.rb index 9b742fae3..8b6802ea1 100644 --- a/spec/models/retraction_spec.rb +++ b/spec/models/retraction_spec.rb @@ -18,7 +18,7 @@ describe Retraction do describe 'dispatching' do it 'should dispatch a message on delete' do Factory.create(:person) - Salmon::QUEUE.should_receive :add_post_request + User::QUEUE.should_receive :add_post_request @post.destroy end end diff --git a/spec/models/user/receive_spec.rb b/spec/models/user/receive_spec.rb index 41b619dbb..4d2827545 100644 --- a/spec/models/user/receive_spec.rb +++ b/spec/models/user/receive_spec.rb @@ -173,7 +173,7 @@ describe User do end it 'should receive a salmon for a post' do - @user2.receive_salmon( @salmon.to_xml ) + @user2.receive_salmon( @user2.person.encrypt(@salmon.to_xml) ) @user2.visible_post_ids.include?(@post.id).should be true end end From cab8610beaf7b3b1d12571f47e3beeb77f8962f7 Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 10 Sep 2010 10:38:16 -0700 Subject: [PATCH 24/27] Actually use salmon to push comments --- app/models/comment.rb | 10 ---------- app/models/user.rb | 4 ++-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/app/models/comment.rb b/app/models/comment.rb index 82de5ecdf..1826efd0c 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -22,16 +22,6 @@ class Comment timestamps! - def push_upstream - Rails.logger.info("GOIN UPSTREAM") - push_to([post.person]) - end - - def push_downstream - Rails.logger.info("SWIMMIN DOWNSTREAM") - push_to(post.people_with_permissions) - end - #ENCRYPTION xml_accessor :creator_signature diff --git a/app/models/user.rb b/app/models/user.rb index 21054c020..f1a246d95 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -174,10 +174,10 @@ class User if owns? comment.post comment.post_creator_signature = comment.sign_with_key(encryption_key) comment.save - comment.push_downstream + push_to_people comment, people_in_groups(groups_with_post(comment.post.id)) elsif owns? comment comment.save - comment.push_upstream + salmon comment, :to => comment.post.person end end From a44d40168a7db6582b58b997b7104a3f35b5ef83 Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 10 Sep 2010 16:04:09 -0700 Subject: [PATCH 25/27] Encryption removed from everything other than comments, most irrelevant specs removed --- app/models/post.rb | 17 -------- app/models/profile.rb | 3 -- app/models/request.rb | 24 +--------- app/models/retraction.rb | 28 ------------ app/models/user.rb | 35 +++++++-------- lib/diaspora/user/friending.rb | 3 +- lib/diaspora/user/querying.rb | 8 ++++ lib/encryptable.rb | 4 -- spec/models/comments_spec.rb | 52 +++++++++++++++------- spec/models/post_spec.rb | 6 --- spec/models/user/posting_spec.rb | 6 +++ spec/user_encryption_spec.rb | 75 +------------------------------- 12 files changed, 72 insertions(+), 189 deletions(-) diff --git a/app/models/post.rb b/app/models/post.rb index 6b5688914..a072d1dc3 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -4,7 +4,6 @@ class Post include ApplicationHelper include ROXML include Diaspora::Webhooks - include Encryptable include Diaspora::Socketable xml_accessor :_id @@ -28,22 +27,6 @@ class Post self.create params.to_hash end - #ENCRYPTION - xml_accessor :creator_signature - key :creator_signature, String - - def signable_accessors - accessors = self.class.roxml_attrs.collect{|definition| - definition.accessor} - accessors.delete 'person' - accessors.delete 'creator_signature' - accessors - end - - def signable_string - signable_accessors.collect{|accessor| - (self.send accessor.to_sym).to_s}.join ';' - end def as_json(opts={}) { diff --git a/app/models/profile.rb b/app/models/profile.rb index 509498037..3f8b18a30 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -3,7 +3,6 @@ class Profile require 'lib/diaspora/webhooks' include Diaspora::Webhooks include ROXML - include Encryptable xml_reader :person_id xml_accessor :first_name @@ -24,6 +23,4 @@ class Profile self._parent_document end - ##this needs to go once we move to Salmon - def signature_valid?; true; end end diff --git a/app/models/request.rb b/app/models/request.rb index afc1349eb..a4466ad52 100644 --- a/app/models/request.rb +++ b/app/models/request.rb @@ -3,7 +3,6 @@ class Request include MongoMapper::Document include Diaspora::Webhooks include ROXML - include Encryptable xml_accessor :_id xml_accessor :person, :as => Person @@ -41,28 +40,7 @@ class Request self.save end - #ENCRYPTION - - xml_accessor :creator_signature - key :creator_signature, String - - def signable_accessors - accessors = self.class.roxml_attrs.collect{|definition| - definition.accessor} - - accessors.delete 'person' - accessors.delete 'creator_signature' - accessors - end - - def signable_string - signable_accessors.collect{|accessor| - (self.send accessor.to_sym).to_s}.join ';' - end - - def signature_valid?; true; end - - protected +protected def clean_link if self.destination_url self.destination_url = 'http://' + self.destination_url unless self.destination_url.match('https?://') diff --git a/app/models/retraction.rb b/app/models/retraction.rb index 3d97db47b..67ca5bb92 100644 --- a/app/models/retraction.rb +++ b/app/models/retraction.rb @@ -1,7 +1,6 @@ class Retraction include ROXML include Diaspora::Webhooks - include Encryptable xml_accessor :post_id xml_accessor :person_id @@ -38,16 +37,6 @@ class Retraction end end - def signature_valid? - target = self.type.constantize.find_by_id(self.post_id) - - if target.is_a? Person - verify_signature(@creator_signature, self.type.constantize.find_by_id(self.post_id)) - else - verify_signature(@creator_signature, self.type.constantize.find_by_id(self.post_id).person) - end - end - def self.person_id_from(object) object.is_a?(Person) ? object.id : object.person.id end @@ -56,21 +45,4 @@ class Retraction Person.find_by_id(self.person_id) end - #ENCRYPTION - xml_accessor :creator_signature - - def signable_accessors - accessors = self.class.roxml_attrs.collect{|definition| - definition.accessor} - accessors.delete 'person' - accessors.delete 'creator_signature' - accessors - end - - def signable_string - signable_accessors.collect{|accessor| - (self.send accessor.to_sym).to_s - }.join ';' - end - end diff --git a/app/models/user.rb b/app/models/user.rb index f1a246d95..453e9118d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -101,7 +101,6 @@ class User options[:person] = self.person model_class = class_name.to_s.camelize.constantize post = model_class.instantiate(options) - post.creator_signature = post.sign_with_key(encryption_key) post.save self.raw_visible_posts << post self.save @@ -111,10 +110,11 @@ class User def push_to_groups( post, group_ids ) if group_ids == :all || group_ids == "all" groups = self.groups + elsif group_ids.is_a?(Array) && group_ids.first.class == Group + groups = group_ids else groups = self.groups.find_all_by_id( group_ids ) end - #send to the groups target_people = [] @@ -126,13 +126,7 @@ class User push_to_people(post, target_people) end - def people_in_groups groups - people = [] - groups.each{ |group| - people = people | group.people - } - people - end + def push_to_people(post, people) people.each{|person| @@ -157,19 +151,26 @@ class User ######## Commenting ######## def comment(text, options = {}) + comment = build_comment(text, options) + if comment + dispatch_comment comment + comment.socket_to_uid id + end + comment + end + + def build_comment( text, options = {}) raise "must comment on something!" unless options[:on] comment = Comment.new(:person_id => self.person.id, :text => text, :post => options[:on]) comment.creator_signature = comment.sign_with_key(encryption_key) if comment.save - dispatch_comment comment - comment.socket_to_uid id comment else Rails.logger.warn "this failed to save: #{comment.inspect}" false end end - + def dispatch_comment( comment ) if owns? comment.post comment.post_creator_signature = comment.sign_with_key(encryption_key) @@ -185,7 +186,6 @@ class User def retract( post ) post.unsocket_from_uid(self.id) if post.respond_to? :unsocket_from_uid retraction = Retraction.for(post) - retraction.creator_signature = retraction.sign_with_key( encryption_key ) push_to_people retraction, people_in_groups(groups_with_post(post.id)) retraction end @@ -216,10 +216,9 @@ class User object = Diaspora::Parser.from_xml(xml) Rails.logger.debug("Receiving object for #{self.real_name}:\n#{object.inspect}") Rails.logger.debug("From: #{object.person.inspect}") if object.person - raise "In receive for #{self.real_name}, signature was not valid on: #{object.inspect}" unless object.signature_valid? if object.is_a? Retraction - if object.type == 'Person' && object.signature_valid? + if object.type == 'Person' Rails.logger.info( "the person id is #{object.post_id} the friend found is #{visible_person_by_id(object.post_id).inspect}") unfriended_by visible_person_by_id(object.post_id) @@ -247,14 +246,16 @@ class User elsif object.is_a?(Comment) object.person = Diaspora::Parser.parse_or_find_person_from_xml( xml ).save if object.person.nil? - self.visible_people << object.person + self.visible_people = self.visible_people | [object.person] self.save Rails.logger.debug("The person parsed from comment xml is #{object.person.inspect}") unless object.person.nil? object.person.save Rails.logger.debug("From: #{object.person.inspect}") if object.person raise "In receive for #{self.real_name}, signature was not valid on: #{object.inspect}" unless object.post.person == self.person || object.verify_post_creator_signature object.save - dispatch_comment object unless owns?(object) + unless owns?(object) + dispatch_comment object + end object.socket_to_uid(id) if (object.respond_to?(:socket_to_uid) && !self.owns?(object)) else Rails.logger.debug("Saving object: #{object}") diff --git a/lib/diaspora/user/friending.rb b/lib/diaspora/user/friending.rb index 37665fcf6..3cd483598 100644 --- a/lib/diaspora/user/friending.rb +++ b/lib/diaspora/user/friending.rb @@ -79,7 +79,6 @@ module Diaspora def unfriend(bad_friend) Rails.logger.info("#{self.real_name} is unfriending #{bad_friend.inspect}") retraction = Retraction.for(self) - retraction.creator_signature = retraction.sign_with_key(encryption_key) retraction.push_to_url(bad_friend.receive_url) remove_friend(bad_friend) end @@ -109,9 +108,9 @@ module Diaspora person.user_refs += 1 group.people << person friends << person + save person.save group.save - save end def request_from_me?(request) diff --git a/lib/diaspora/user/querying.rb b/lib/diaspora/user/querying.rb index 7346a8ab2..ed2bcb115 100644 --- a/lib/diaspora/user/querying.rb +++ b/lib/diaspora/user/querying.rb @@ -46,6 +46,14 @@ module Diaspora groups.select { |g| g.person_ids.include? id} end + def people_in_groups groups + people = [] + groups.each{ |group| + people = people | group.people + } + people + end + def all_group_ids self.groups.all.collect{|x| x.id} end diff --git a/lib/encryptable.rb b/lib/encryptable.rb index bcc34894a..4c39a129e 100644 --- a/lib/encryptable.rb +++ b/lib/encryptable.rb @@ -29,9 +29,5 @@ Base64.encode64(key.sign "SHA", signable_string) end - def encrypted_xml_for(person) - person.encrypt self.to_diaspora_xml - end - end diff --git a/spec/models/comments_spec.rb b/spec/models/comments_spec.rb index bdf85884d..d442b22b3 100644 --- a/spec/models/comments_spec.rb +++ b/spec/models/comments_spec.rb @@ -28,56 +28,78 @@ describe Comment do it 'should not send out comments when we have no people' do status = Factory.create(:status_message, :person => @user.person) - message_queue.should_not_receive(:add_post_request) + User::QUEUE.should_not_receive(:add_post_request) @user.comment "sup dog", :on => status end describe 'comment propagation' do before do + friend_users(@user, Group.first(:id => @group.id), @user2, @group2) - - request = @user.send_friend_request_to(@user2, @group) - reversed_request = @user2.accept_friend_request( request.id, @group2.id ) - @user.receive reversed_request.to_diaspora_xml - @person = Factory.create(:person) + @user.activate_friend(@person, Group.first(:id => @group.id)) + @person2 = Factory.create(:person) @person_status = Factory.build(:status_message, :person => @person) - @user_status = Factory.build(:status_message, :person => @user.person) + + @user.reload + @user_status = @user.post :status_message, :message => "hi", :to => @group.id + + @group.reload + @user.reload end + it 'should have the post in the groups post list' do + group = Group.first(:id => @group.id) + group.people.size.should == 2 + group.post_ids.include?(@user_status.id).should be true + end + it "should send a user's comment on a person's post to that person" do - message_queue.should_receive(:add_post_request) + User::QUEUE.should_receive(:add_post_request) @user.comment "yo", :on => @person_status end it 'should send a user comment on his own post to lots of people' do - allowed_urls = @user.friends.map!{ |x| x = x.receive_url } - message_queue.should_receive(:add_post_request).with(allowed_urls, anything) + + User::QUEUE.should_receive(:add_post_request).twice @user.comment "yo", :on => @user_status end it 'should send a comment a person made on your post to all people' do - message_queue.should_receive(:add_post_request) comment = Comment.new(:person_id => @person.id, :text => "balls", :post => @user_status) + User::QUEUE.should_receive(:add_post_request).twice @user.receive(comment.to_diaspora_xml) end - it 'should send a comment a user made on your post to all people' do - message_queue.should_receive(:add_post_request).twice + + it 'should send a comment a user made on your post to all people' do + comment = @user2.comment( "balls", :on => @user_status) + User::QUEUE.should_receive(:add_post_request).twice @user.receive(comment.to_diaspora_xml) end it 'should not send a comment a person made on his own post to anyone' do - message_queue.should_not_receive(:add_post_request) + User::QUEUE.should_not_receive(:add_post_request) comment = Comment.new(:person_id => @person.id, :text => "balls", :post => @person_status) @user.receive(comment.to_diaspora_xml) end + it 'should not send a comment a person made on a person post to anyone' do - message_queue.should_not_receive(:add_post_request) + User::QUEUE.should_not_receive(:add_post_request) comment = Comment.new(:person_id => @person2.id, :text => "balls", :post => @person_status) @user.receive(comment.to_diaspora_xml) end + + it 'should not clear the group post array on receiving a comment' do + @group.post_ids.include?(@user_status.id).should be true + comment = Comment.new(:person_id => @person.id, :text => "balls", :post => @user_status) + + @user.receive(comment.to_diaspora_xml) + + @group.reload + @group.post_ids.include?(@user_status.id).should be true + end end describe 'serialization' do it 'should serialize the commenter' do diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 35e85ab21..a1c391657 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -14,12 +14,6 @@ describe Post do it 'should serialize to xml with its person' do @message.to_xml.to_s.include?(@user.person.email).should == true end - - it 'should serialize to encrypted xml' do - enc_xml = @message.encrypted_xml_for(@user.person) - enc_xml.include?(@message.to_diaspora_xml).should be false - @user.decrypt(enc_xml).include?(@message.to_diaspora_xml).should be true - end end diff --git a/spec/models/user/posting_spec.rb b/spec/models/user/posting_spec.rb index 627e8e78e..2365912da 100644 --- a/spec/models/user/posting_spec.rb +++ b/spec/models/user/posting_spec.rb @@ -24,6 +24,12 @@ describe User do proc {@user.post(:status_message, :message => "heyheyhey")}.should raise_error /You must post to someone/ end + it 'should put the post in the group post array' do + post = @user.post(:status_message, :message => "hey", :to => @group.id) + @group.reload + @group.post_ids.include?(post.id).should be true + end + describe 'dispatching' do before do @post = @user.build_post :status_message, :message => "hey" diff --git a/spec/user_encryption_spec.rb b/spec/user_encryption_spec.rb index 73b9db0b9..99ddcc4ca 100644 --- a/spec/user_encryption_spec.rb +++ b/spec/user_encryption_spec.rb @@ -70,82 +70,9 @@ describe 'user encryption' do end end - describe 'signing and verifying' do - - it 'should sign a message on create' do - message = @user.post :status_message, :message => "hi", :to => @group.id - message.signature_valid?.should be true - end - - it 'should sign a retraction on create' do - - unstub_mocha_stubs - message = @user.post :status_message, :message => "hi", :to => @group.id - - - retraction = @user.retract(message) - retraction.signature_valid?.should be true - - end - - it 'should not be able to verify a message from a person without a key' do - person = Factory.create(:person, :serialized_key => "lskdfhdlfjnh;klsf") - message = Factory.build(:status_message, :person => person) - message.save(:validate => false) - lambda {message.signature_valid?.should be false}.should raise_error - end - - it 'should verify a remote signature' do - message = Factory.build(:status_message, :person => @person) - message.creator_signature = message.send(:sign_with_key,@person.encryption_key) - message.save(:validate => false) - message.signature_valid?.should be true - end - - it 'should know if the signature is from the wrong person' do - message = Factory.build(:status_message, :person => @person) - message.save(:validate => false) - message.creator_signature = message.send(:sign_with_key,@person.encryption_key) - message.person = @user - message.signature_valid?.should be false - end - - it 'should know if the signature is for the wrong text' do - message = Factory.build(:status_message, :person => @person) - message.creator_signature = message.send(:sign_with_key,@person.encryption_key) - message.message = 'I love VENISON' - message.save(:validate => false) - message.signature_valid?.should be false - end - end - - describe 'sending and recieving signatures' do - it 'should contain the signature in the xml' do - message = @user.post :status_message, :message => "hi", :to => @group.id - xml = message.to_xml.to_s - xml.include?(message.creator_signature).should be true - end - - it 'A message with an invalid signature should be rejected' do - @user2 = Factory.create :user - - message = @user2.post :status_message, :message => "hey", :to => @user2.group(:name => "bruisers").id - message.creator_signature = "totally valid" - message.save(:validate => false) - - xml = message.to_diaspora_xml - message.destroy - Post.count.should be 0 - proc {@user.receive xml}.should raise_error /ignature was not valid/ - Post.count.should be 0 - end - - end describe 'comments' do before do - @remote_message = Factory.build(:status_message, :person => @person) - @remote_message.creator_signature = @remote_message.send(:sign_with_key,@person.encryption_key) - @remote_message.save + @remote_message = Factory.create(:status_message, :person => @person) @message = @user.post :status_message, :message => "hi", :to => @group.id end it 'should attach the creator signature if the user is commenting' do From 4922ebd84ca79c48fb01764e468870c8064c307c Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 10 Sep 2010 16:14:37 -0700 Subject: [PATCH 26/27] Finish removing encryption from retractions --- app/models/retraction.rb | 1 - spec/lib/diaspora_parser_spec.rb | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/models/retraction.rb b/app/models/retraction.rb index 67ca5bb92..6fad270c2 100644 --- a/app/models/retraction.rb +++ b/app/models/retraction.rb @@ -27,7 +27,6 @@ class Retraction def perform receiving_user_id Rails.logger.debug "Performing retraction for #{post_id}" begin - return unless signature_valid? Rails.logger.debug("Retracting #{self.type} id: #{self.post_id}") target = self.type.constantize.first(:id => self.post_id) target.unsocket_from_uid receiving_user_id if target.respond_to? :unsocket_from_uid diff --git a/spec/lib/diaspora_parser_spec.rb b/spec/lib/diaspora_parser_spec.rb index b0b8f6a97..3d4dc3727 100644 --- a/spec/lib/diaspora_parser_spec.rb +++ b/spec/lib/diaspora_parser_spec.rb @@ -51,10 +51,10 @@ describe Diaspora::Parser do person = Factory.create(:person) message = Factory.create(:status_message, :person => person) retraction = Retraction.for(message) - request = retraction.to_diaspora_xml + xml = retraction.to_diaspora_xml StatusMessage.count.should == 1 - @user.receive request + @user.receive xml StatusMessage.count.should == 0 end From ab6d631a27d2ba0c669c0faf4191a159169030b2 Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 10 Sep 2010 16:25:19 -0700 Subject: [PATCH 27/27] White space in user file, deleting net/curl as unused --- app/models/retraction.rb | 1 - app/models/user.rb | 4 ---- lib/net/curl.rb | 10 ---------- 3 files changed, 15 deletions(-) delete mode 100644 lib/net/curl.rb diff --git a/app/models/retraction.rb b/app/models/retraction.rb index 6fad270c2..cf52720ed 100644 --- a/app/models/retraction.rb +++ b/app/models/retraction.rb @@ -10,7 +10,6 @@ class Retraction attr_accessor :person_id attr_accessor :type - def self.for(object) retraction = self.new if object.is_a? User diff --git a/app/models/user.rb b/app/models/user.rb index 453e9118d..c767e3b91 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -126,8 +126,6 @@ class User push_to_people(post, target_people) end - - def push_to_people(post, people) people.each{|person| salmon(post, :to => person) @@ -147,8 +145,6 @@ class User salmon end - - ######## Commenting ######## def comment(text, options = {}) comment = build_comment(text, options) diff --git a/lib/net/curl.rb b/lib/net/curl.rb deleted file mode 100644 index 4220a27f7..000000000 --- a/lib/net/curl.rb +++ /dev/null @@ -1,10 +0,0 @@ -class Curl - def self.post(s) - `curl -X POST -d #{s}`;; - end - - def self.get(s) - `curl -X GET #{s}` - end -end -