Merge branch 'salmon' of github.com:diaspora/diaspora
This commit is contained in:
commit
6afaf73c30
42 changed files with 523 additions and 404 deletions
|
|
@ -148,7 +148,7 @@ 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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,35 +1,37 @@
|
|||
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
|
||||
|
||||
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]
|
||||
@user.receive_salmon params[:xml]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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]}!"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
require 'lib/hcard'
|
||||
|
||||
class Person
|
||||
include MongoMapper::Document
|
||||
include ROXML
|
||||
include Encryptor::Public
|
||||
|
||||
xml_accessor :_id
|
||||
xml_accessor :email
|
||||
|
|
@ -37,6 +40,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 +61,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 +74,41 @@ 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)
|
||||
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
|
||||
|
||||
guid = profile.links.select{|x| x.rel == 'http://joindiaspora.com/guid'}.first.href
|
||||
new_person.id = guid
|
||||
|
||||
new_person.email = identifier
|
||||
|
||||
hcard = HCard.find profile.hcard.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
|
||||
new_person
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def remote?
|
||||
|
|
|
|||
|
|
@ -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={})
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,4 @@ class Profile
|
|||
self._parent_document
|
||||
end
|
||||
|
||||
##this needs to go once we move to Salmon
|
||||
def signature_valid?; true; end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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?://')
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
class Retraction
|
||||
include ROXML
|
||||
include Diaspora::Webhooks
|
||||
include Encryptable
|
||||
|
||||
xml_accessor :post_id
|
||||
xml_accessor :person_id
|
||||
|
|
@ -11,7 +10,6 @@ class Retraction
|
|||
attr_accessor :person_id
|
||||
attr_accessor :type
|
||||
|
||||
|
||||
def self.for(object)
|
||||
retraction = self.new
|
||||
if object.is_a? User
|
||||
|
|
@ -28,9 +26,8 @@ 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(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
|
||||
|
|
@ -38,16 +35,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 +43,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
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
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
|
||||
key :username, :unique => true
|
||||
|
|
@ -69,21 +75,8 @@ 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 = {})
|
||||
options[:person] = self.person
|
||||
|
||||
if class_name == :photo
|
||||
raise ArgumentError.new("No album_id given") unless options[:album_id]
|
||||
|
|
@ -96,15 +89,19 @@ 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?
|
||||
|
||||
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 = 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.save
|
||||
self.raw_visible_posts << post
|
||||
self.save
|
||||
post
|
||||
|
|
@ -113,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 = []
|
||||
|
||||
|
|
@ -125,40 +123,58 @@ class User
|
|||
group.save
|
||||
target_people = target_people | group.people
|
||||
}
|
||||
post.push_to( target_people )
|
||||
push_to_people(post, target_people)
|
||||
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
|
||||
def push_to_people(post, people)
|
||||
people.each{|person|
|
||||
salmon(post, :to => person)
|
||||
}
|
||||
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.to_diaspora_xml)
|
||||
push_to_person( opts[:to], salmon.to_xml)
|
||||
salmon
|
||||
end
|
||||
|
||||
######## 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)
|
||||
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
|
||||
|
||||
|
|
@ -166,8 +182,7 @@ 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 )
|
||||
retraction.push_to( self.friends.all )
|
||||
push_to_people retraction, people_in_groups(groups_with_post(post.id))
|
||||
retraction
|
||||
end
|
||||
|
||||
|
|
@ -176,7 +191,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
|
||||
|
|
@ -184,14 +199,22 @@ class User
|
|||
end
|
||||
|
||||
###### Receiving #######
|
||||
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(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}")
|
||||
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)
|
||||
|
|
@ -219,14 +242,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}")
|
||||
|
|
@ -268,42 +293,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={})
|
||||
{
|
||||
|
|
@ -315,12 +311,7 @@ class User
|
|||
}
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
|
||||
def self.generate_key
|
||||
OpenSSL::PKey::RSA::generate 1024
|
||||
end
|
||||
|
||||
def self.generate_key
|
||||
OpenSSL::PKey::RSA::generate 4096
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,16 +9,28 @@
|
|||
<a href="<%=@person.url%>" rel="me" class="nickname url uid"><%= @person.real_name%></a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_fn">
|
||||
<dl class="entity_given_name">
|
||||
<dt>Full name</dt>
|
||||
<dd>
|
||||
<span class="fn"><%= @person.real_name %></span>
|
||||
<span class="given_name" ><%= @person.profile.first_name %></span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_family_name">
|
||||
<dt>Full name</dt>
|
||||
<dd>
|
||||
<span class="family_name" ><%= @person.profile.last_name %></span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_fn">
|
||||
<dt>Full name</dt>
|
||||
<dd>
|
||||
<span class="fn" ><%= @person.real_name %></span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_url">
|
||||
<dt>URL</dt>
|
||||
<dd>
|
||||
<a href="<%= @person.url%>" rel="me" class="url"><%= @person.url%></a>
|
||||
<a href="<%= @person.url%>" rel="me" id="pod_location" class="url"><%= @person.url%></a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="entity_note">
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Subject>acct:<%=@person.email%></Subject>
|
||||
<Alias>"<%= @person.url %>users/#{@user.id}/hcard"</Alias>
|
||||
<Link rel="http://microformats.org/profile/hcard" type="text/html" href="<%=@person.url%>hcard"/>
|
||||
<Alias>"<%= @person.url %>"</Alias>
|
||||
<Link rel="http://microformats.org/profile/hcard" type="text/html" href="<%=@person.url%>/hcard/users/<%=@person.id%>"/>
|
||||
<Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="<%=@person.url%>status_messages.atom"/>
|
||||
<Link rel="http://joindiaspora.com/seed_location" type = 'text/html' href="<%=@person.receive_url%>"/>
|
||||
<Link rel="http://joindiaspora.com/seed_location" type = 'text/html' href="<%=@person.url%>"/>
|
||||
<Link rel="http://joindiaspora.com/guid" type = 'text/html' href="<%=@person.id%>"/>
|
||||
<Link rel="diaspora-public-key" type = 'RSA' href="<%=Base64.encode64(@person.exported_key)%>"/>
|
||||
</XRD>
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
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(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
|
||||
|
||||
group = self.group_by_id(group_id)
|
||||
|
||||
group.requests << request
|
||||
group.save
|
||||
|
||||
request.push_to_url friend_url
|
||||
salmon request, :to => desired_friend
|
||||
end
|
||||
request
|
||||
end
|
||||
|
|
@ -29,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)
|
||||
|
|
@ -75,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
|
||||
|
|
@ -101,21 +104,13 @@ 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
|
||||
friends << person
|
||||
save
|
||||
person.save
|
||||
group.save
|
||||
save
|
||||
end
|
||||
|
||||
def request_from_me?(request)
|
||||
|
|
|
|||
62
lib/diaspora/user/querying.rb
Normal file
62
lib/diaspora/user/querying.rb
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
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 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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -28,5 +28,6 @@
|
|||
Rails.logger.debug("Signing #{signable_string}")
|
||||
Base64.encode64(key.sign "SHA", signable_string)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
59
lib/encryptor.rb
Normal file
59
lib/encryptor.rb
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
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
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
8
lib/hcard.rb
Normal file
8
lib/hcard.rb
Normal file
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -35,8 +35,9 @@ 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 +58,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 +75,8 @@ module Salmon
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<entry xmlns='http://www.w3.org/2005/Atom'>
|
||||
<author>
|
||||
<name>#{@user.real_name}</name>
|
||||
<uri>acct:#{@user.email}</uri>
|
||||
<name>#{@author.real_name}</name>
|
||||
<uri>acct:#{@author.email}</uri>
|
||||
</author>
|
||||
#{@magic_sig.to_xml}
|
||||
</entry>
|
||||
|
|
@ -83,6 +84,17 @@ 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
|
||||
|
|
@ -153,15 +165,10 @@ ENTRY
|
|||
key
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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 +182,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
|
||||
|
|
|
|||
|
|
@ -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 = @user.person.encrypt(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,15 +33,13 @@ 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)
|
||||
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
|
||||
|
|
@ -51,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
12
spec/lib/hcard_spec.rb
Normal file
12
spec/lib/hcard_spec.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
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
|
||||
hcard[:url].should == "http://tom.joindiaspora.com/"
|
||||
end
|
||||
end
|
||||
|
|
@ -1,41 +1,49 @@
|
|||
require File.dirname(__FILE__) + '/../spec_helper'
|
||||
|
||||
|
||||
|
||||
require 'lib/salmon/salmon'
|
||||
include ApplicationHelper
|
||||
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
|
||||
|
||||
x.magic_sig.data.should == z.magic_sig.data
|
||||
|
||||
x.magic_sig.sig.should == z.magic_sig.sig
|
||||
x.magic_sig.signable_string.should == z.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
|
||||
@sent_salmon = Salmon::SalmonSlap.create(@user, @post.to_diaspora_xml)
|
||||
@parsed_salmon = Salmon::SalmonSlap.parse @sent_salmon.to_xml
|
||||
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
|
||||
@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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.receive_url, @group.id)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -144,6 +144,11 @@ 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')
|
||||
tom.real_name.include?("Hamiltom").should be true
|
||||
end
|
||||
|
||||
describe 'wall posting' do
|
||||
it 'should be able to post on another persons wall' do
|
||||
|
|
|
|||
|
|
@ -7,10 +7,14 @@ 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
|
||||
|
||||
end
|
||||
|
||||
describe 'deletion' do
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
User::QUEUE.should_receive :add_post_request
|
||||
@post.destroy
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,10 +2,53 @@ 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
|
||||
|
||||
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"
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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( @user2.person.encrypt(@salmon.to_xml) )
|
||||
@user2.visible_post_ids.include?(@post.id).should be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -59,82 +59,20 @@ 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
|
||||
describe 'encryption' do
|
||||
before do
|
||||
@message = @user.post :status_message, :message => "hi", :to => @group.id
|
||||
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
|
||||
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 '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
|
||||
|
|
|
|||
Loading…
Reference in a new issue