Merge branch 'master' of github.com:diaspora/diaspora

Conflicts:
	spec/models/aspect_spec.rb
This commit is contained in:
ilya 2010-10-20 11:30:06 -07:00
commit 992bd42b55
72 changed files with 1536 additions and 541 deletions

2
.gitignore vendored
View file

@ -13,7 +13,7 @@ public/stylesheets/ui.css
# Uploded files and local files
public/uploads/*
public/source.tar
public/source.tar*
tmp/**/*
db/*.sqlite3

View file

@ -1,6 +1,7 @@
source 'http://rubygems.org'
gem 'rails', '>= 3.0.0'
gem 'bundler', '>= 1.0.0'
#Security
@ -41,6 +42,7 @@ gem 'aws'
group :test, :development do
gem 'factory_girl_rails'
gem 'ruby-debug19' if RUBY_VERSION.include? "1.9"
gem 'ruby-debug' if RUBY_VERSION.include? "1.8"
end

View file

@ -15,9 +15,9 @@ GIT
GIT
remote: git://github.com/dcu/magent.git
revision: 59b8563961b830f491cd6f6592cced67791ce0ef
revision: 90ee5db241abd2e2b7d7de5c80f0d7c5b4b8db2d
specs:
magent (0.5.0)
magent (0.5.1)
em-websocket
mongo
uuidtools
@ -99,7 +99,7 @@ GEM
addressable (2.2.2)
arel (1.0.1)
activesupport (~> 3.0.0)
aws (2.3.21)
aws (2.3.22)
http_connection
uuidtools
xml-simple
@ -120,7 +120,7 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
selenium-webdriver (>= 0.0.3)
childprocess (0.0.7)
childprocess (0.1.3)
ffi (~> 0.6.3)
columnize (0.3.1)
crack (0.1.8)
@ -153,13 +153,13 @@ GEM
rails (>= 3.0.0.beta4)
ffi (0.6.3)
rake (>= 0.8.7)
gherkin (2.2.8)
gherkin (2.2.9)
json (~> 1.4.6)
term-ansicolor (~> 1.0.5)
haml (3.0.21)
haml (3.0.22)
hashie (0.4.0)
highline (1.6.1)
http_connection (1.3.1)
http_connection (1.4.0)
i18n (0.4.1)
json (1.4.6)
json_pure (1.4.6)
@ -213,18 +213,18 @@ GEM
rake (0.8.7)
rest-client (1.6.1)
mime-types (>= 1.16)
rspec (2.0.0)
rspec-core (= 2.0.0)
rspec-expectations (= 2.0.0)
rspec-mocks (= 2.0.0)
rspec-core (2.0.0)
rspec-expectations (2.0.0)
rspec (2.0.1)
rspec-core (~> 2.0.1)
rspec-expectations (~> 2.0.1)
rspec-mocks (~> 2.0.1)
rspec-core (2.0.1)
rspec-expectations (2.0.1)
diff-lcs (>= 1.1.2)
rspec-mocks (2.0.0)
rspec-core (= 2.0.0)
rspec-expectations (= 2.0.0)
rspec-rails (2.0.0)
rspec (= 2.0.0)
rspec-mocks (2.0.1)
rspec-core (~> 2.0.1)
rspec-expectations (~> 2.0.1)
rspec-rails (2.0.1)
rspec (~> 2.0.0)
ruby-debug (0.10.3)
columnize (>= 0.1)
ruby-debug-base (~> 0.10.3.0)

View file

@ -20,10 +20,11 @@ class AspectsController < ApplicationController
@aspect = current_user.aspect(params[:aspect])
if @aspect.valid?
flash[:notice] = I18n.t('aspects.create.success')
respond_with @aspect
else
flash[:error] = I18n.t('aspects.create.failure')
redirect_to aspects_manage_path
end
respond_with @aspect
end
def new

View file

@ -9,20 +9,19 @@ class PeopleController < ApplicationController
respond_to :json, :only => [:index, :show]
def index
@aspects_dropdown_array = current_user.aspects.collect{|x| [x.to_s, x.id]}
@aspect = :all
@aspect = :search
@people = Person.search(params[:q]).paginate :page => params[:page], :per_page => 25, :order => 'created_at DESC'
respond_with @people
end
def show
@aspect = :profile
@person = current_user.visible_person_by_id(params[:id])
unless @person
render :file => "#{Rails.root}/public/404.html", :layout => false, :status => 404
else
@profile = @person.profile
@aspects_with_person = current_user.aspects_with_person(@person)
@aspects_dropdown_array = current_user.aspects.collect{|x| [x.to_s, x.id]}
@posts = current_user.visible_posts(:person_id => @person.id).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

View file

@ -4,17 +4,13 @@
class RegistrationsController < Devise::RegistrationsController
def create
begin
user = User.instantiate!(params[:user])
rescue MongoMapper::DocumentNotValid => e
flash[:error] = e.message
redirect_to new_user_registration_path
end
if user.save
@user = User.build(params[:user])
if @user.save
flash[:notice] = I18n.t 'registrations.create.success'
sign_in_and_redirect(:user, user)
@user.seed_aspects
sign_in_and_redirect(:user, @user)
else
flash[:error] = user.errors.full_messages.join(', ')
flash[:error] = @user.errors.full_messages.join(', ')
redirect_to new_user_registration_path
end
end

View file

@ -35,8 +35,15 @@ class RequestsController < ApplicationController
begin
rel_hash = relationship_flow(params[:request][:destination_url].strip)
rescue Exception => e
raise e unless e.message.include? "not found"
flash[:error] = I18n.t 'requests.create.error'
if e.message.include? "not found"
flash[:error] = I18n.t 'requests.create.error'
elsif e.message.include? "Connection timed out"
flash[:error] = I18n.t 'requests.create.error_server'
elsif e.message == "Identifier is invalid"
flash[:error] = I18n.t 'requests.create.invalid_identity'
else
raise e
end
respond_with :location => aspect
return
end

View file

@ -5,14 +5,16 @@
class UsersController < ApplicationController
require File.join(Rails.root, 'lib/diaspora/ostatus_builder')
require File.join(Rails.root, 'lib/diaspora/exporter')
require File.join(Rails.root, 'lib/diaspora/importer')
require File.join(Rails.root, 'lib/collect_user_photos')
before_filter :authenticate_user!, :except => [:new, :create, :public]
before_filter :authenticate_user!, :except => [:new, :create, :public, :import]
respond_to :html
def edit
@aspect = :user_edit
@user = current_user
@person = @user.person
@profile = @user.person.profile
@ -78,6 +80,31 @@ class UsersController < ApplicationController
send_data( File.open(tar_path).read, :filename => "#{current_user.id}.tar" )
end
def invite
User.invite!(:email => params[:email])
end
def import
xml = params[:upload][:file].read
params[:user][:diaspora_handle] = 'asodij@asodij.asd'
begin
importer = Diaspora::Importer.new(Diaspora::Parsers::XML)
importer.execute(xml, params[:user])
flash[:notice] = "hang on a sec, try logging in!"
rescue Exception => e
flash[:error] = "Derp, something went wrong: #{e.message}"
end
redirect_to new_user_registration_path
#redirect_to user_session_path
end
private
def prep_image_url(params)
url = APP_CONFIG[:pod_url].dup

View file

@ -22,6 +22,13 @@ class Person
key :owner_id, ObjectId
one :profile, :class_name => 'Profile'
validate :profile_is_valid
def profile_is_valid
if profile.present? && !profile.valid?
profile.errors.full_messages.each { |m| errors.add(:base, m) }
end
end
many :albums, :class_name => 'Album', :foreign_key => :person_id
belongs_to :owner, :class_name => 'User'
@ -85,7 +92,11 @@ class Person
end
def self.by_webfinger(identifier, opts = {})
#need to check if this is a valid email structure, maybe should do in JS
# Raise an error if identifier has a port number
raise "Identifier is invalid" if(identifier.strip.match(/\:\d+$/))
# Raise an error if identifier is not a valid email (generous regexp)
raise "Identifier is invalid" if !(identifier =~ /\A.*\@.*\..*\Z/)
query = /#{Regexp.escape(identifier.gsub('acct:', '').to_s)}/i
local_person = Person.first(:diaspora_handle => query)
@ -162,4 +173,5 @@ class Person
def remove_all_traces
Post.all(:person_id => id).each { |p| p.delete }
end
end

View file

@ -14,6 +14,7 @@ class Post
xml_accessor :_id
xml_accessor :person, :as => Person
xml_reader :public
xml_reader :created_at
key :public , Boolean, :default => false

View file

@ -18,6 +18,9 @@ class Profile
key :image_url, String
validates_presence_of :first_name, :last_name
after_validation :strip_names
before_save :strip_names
def person_id
self._parent_document.id
@ -27,4 +30,10 @@ class Profile
self._parent_document
end
protected
def strip_names
self.first_name.strip! if self.first_name
self.last_name.strip! if self.last_name
end
end

View file

@ -48,6 +48,12 @@ class User
validates_with InvitedUserValidator
one :person, :class_name => 'Person', :foreign_key => :owner_id
validate :person_is_valid
def person_is_valid
if person.present? && !person.valid?
person.errors.full_messages.each {|m| errors.add(:base, m)}
end
end
many :inviters, :in => :inviter_ids, :class_name => 'User'
many :friends, :in => :friend_ids, :class_name => 'Person'
@ -56,9 +62,9 @@ class User
many :raw_visible_posts, :in => :visible_post_ids, :class_name => 'Post'
many :aspects, :class_name => 'Aspect'
after_create :seed_aspects
#after_create :seed_aspects
before_destroy :unfriend_everyone, :remove_person, :remove_all_aspects
before_destroy :unfriend_everyone, :remove_person
def strip_username
if username.present?
@ -385,13 +391,15 @@ class User
end
###Helpers############
def self.instantiate!(opts = {})
def self.build(opts = {})
opts[:person][:diaspora_handle] = "#{opts[:username]}@#{APP_CONFIG[:terse_pod_url]}"
opts[:person][:url] = APP_CONFIG[:pod_url]
opts[:serialized_private_key] = generate_key
opts[:person][:serialized_public_key] = opts[:serialized_private_key].public_key
User.create(opts)
u = User.new(opts)
u
end
def seed_aspects
@ -438,8 +446,4 @@ class User
end
}
end
def remove_all_aspects
aspects.destroy_all
end
end

View file

@ -2,12 +2,14 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
%h1=t('.add_a_new_album')
.span-12.last
.modal_title_bar
%h4= t('.add_a_new_album')
= form_for Album.new do |f|
= f.error_messages
%p
= f.label :name
= f.text_field :name
= f.hidden_field :to, :value => aspect
= f.submit t('.create'), :class => 'button'
= form_for Album.new do |f|
= f.error_messages
%p
= f.label :name
= f.text_field :name
= f.hidden_field :to, :value => aspect
= f.submit t('.create'), :class => 'button'

View file

@ -2,10 +2,14 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
%h1=t('.add_a_new_aspect')
= form_for Aspect.new do |aspect|
= aspect.error_messages
%p
= aspect.label :name
= aspect.text_field :name
= aspect.submit t('.create'), :class => 'button'
.span-12.last
.modal_title_bar
%h4= t('.add_a_new_aspect')
= form_for Aspect.new do |aspect|
= aspect.error_messages
%p
= aspect.label :name
= aspect.text_field :name
= aspect.submit t('.create'), :class => 'button'

View file

@ -1,4 +1,51 @@
%p
Welcome #{@resource.email}!
%p You can confirm your account through the link below:
%p= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token)
!!!
%html
%head
%meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}/
:css
body{
width:600px;
font-family:'Arial','Helvetica',sans-serif;
font-size:14px;
color:#333;
}
#container{
margin-bottom:25px
min-height:400px;
padding-left:15px;
}
header{
background-color:#333;
padding: 15px;
margin-bottom: 25px;
}
p{
padding:5px;
}
p.small{
font-size:smaller;
color:#999;
font-style:italic;
}
a{
color:#107FC9;
font-weight:bold;
}
a:hover{
color: #22AAE0;
}
a:active{
color: #005D9C;
}
.large_text{
font-size:21px;
font-family:"Helvetica Neue",Arial,Helvetica,sans-serif;
}
%body
%header
= image_tag '/images/diaspora_white.png'
#container
%p
Welcome #{@resource.email}!
%p You can confirm your account through the link below:
%p= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token), :class => "large_text"

View file

@ -1,16 +1,61 @@
%p
Hello #{@resource.email}!
%p
#{(@resource.inviters.count == 1)? ( @resource.inviters.first.real_name + " has") : (@resource.inviters.map{|inv| inv.real_name}.join(",") + " have")} invited you to #{root_url}, you can accept it through the link below.
- @resource.inviters.each do |inv|
- if @resource.invite_messages[inv.id.to_s]
= "#{inv.real_name}:"
= @resource.invite_messages[inv.id.to_s]
%p
%p= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @resource.invitation_token)
%p
If you don't want to accept the invitation, please ignore this email.
%br/
Your account won't be created until you access the link above and sign up.
!!!
%html
%head
%meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}/
:css
body{
width:600px;
font-family:'Arial','Helvetica',sans-serif;
font-size:14px;
color:#333;
}
#container{
margin-bottom:25px
min-height:400px;
padding-left:15px;
}
header{
background-color:#333;
padding: 15px;
margin-bottom: 25px;
}
p{
padding:5px;
}
p.small{
font-size:smaller;
color:#999;
font-style:italic;
}
a{
color:#107FC9;
font-weight:bold;
}
a:hover{
color: #22AAE0;
}
a:active{
color: #005D9C;
}
.large_text{
font-size:21px;
font-family:"Helvetica Neue",Arial,Helvetica,sans-serif;
}
%body
%header
= image_tag '/images/diaspora_white.png'
#container
%p
Hello #{@resource.email}!
%p
#{(@resource.inviters.count == 1)? ( @resource.inviters.first.real_name + " has") : (@resource.inviters.map{|inv| inv.real_name + " (#{inv.diaspora_handle})"}.join(",") + " have")} invited you to join Diaspora at #{root_url}, you can accept it through the link below.
- @resource.inviters.each do |inv|
- if @resource.invite_messages[inv.id.to_s]
= "#{inv.real_name}:"
= @resource.invite_messages[inv.id.to_s]
%p
%p= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @resource.invitation_token), :class => "large_text"
%p.small
If you don't want to accept the invitation, please ignore this email.
%br/
Your account won't be created until you access the link above and sign up.

View file

@ -1,6 +1,53 @@
%p
Hello #{@resource.email}!
%p Someone has requested a link to change your password, and you can do this through the link below.
%p= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token)
%p If you didn't request this, please ignore this email.
%p Your password won't change until you access the link above and create a new one.
!!!
%html
%head
%meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}/
:css
body{
width:600px;
font-family:'Arial','Helvetica',sans-serif;
font-size:14px;
color:#333;
}
#container{
margin-bottom:25px
min-height:400px;
padding-left:15px;
}
header{
background-color:#333;
padding: 15px;
margin-bottom: 25px;
}
p{
padding:5px;
}
p.small{
font-size:smaller;
color:#999;
font-style:italic;
}
a{
color:#107FC9;
font-weight:bold;
}
a:hover{
color: #22AAE0;
}
a:active{
color: #005D9C;
}
.large_text{
font-size:21px;
font-family:"Helvetica Neue",Arial,Helvetica,sans-serif;
}
%body
%header
= image_tag '/images/diaspora_white.png'
#container
%p
Hello #{@resource.email}!
%p Someone has requested a link to change your password, and you can do this through the link below.
%p= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token), :class => "large_text"
%p Your password won't change until you access the link above and create a new one.
%p.small If you didn't request this, please ignore this email.

View file

@ -1,5 +1,52 @@
%p
Hello #{@resource.email}!
%p Your account has been locked due to an excessive amount of unsuccessful sign in attempts.
%p Click the link below to unlock your account:
%p= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token)
!!!
%html
%head
%meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}/
:css
body{
width:600px;
font-family:'Arial','Helvetica',sans-serif;
font-size:14px;
color:#333;
}
#container{
margin-bottom:25px
min-height:400px;
padding-left:15px;
}
header{
background-color:#333;
padding: 15px;
margin-bottom: 25px;
}
p{
padding:5px;
}
p.small{
font-size:smaller;
color:#999;
font-style:italic;
}
a{
color:#107FC9;
font-weight:bold;
}
a:hover{
color: #22AAE0;
}
a:active{
color: #005D9C;
}
.large_text{
font-size:21px;
font-family:"Helvetica Neue",Arial,Helvetica,sans-serif;
}
%body
%header
= image_tag '/images/diaspora_white.png'
#container
%p
Hello #{@resource.email}!
%p Your account has been locked due to an excessive amount of unsuccessful sign in attempts.
%p Click the link below to unlock your account:
%p= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token), :class => "large_text"

View file

@ -1,15 +1,20 @@
%h2 Send invitation
= form_for User.new, :url => invitation_path(User) do |invite|
%p
= invite.label :email
= invite.text_field :email
To
- unless @aspect.is_a? Aspect
= invite.select(:aspects, @aspects_dropdown_array)
- else
= invite.select(:aspects, @aspects_dropdown_array, :selected => @aspect.id)
Message:
= invite.text_area :invite_messages
.span-12.last
.modal_title_bar
%h4 Invite someone to join Diaspora!
%p= invite.submit "Send an invitation"
%i if they accept, they will be added to the aspect you invited them
= form_for User.new, :url => invitation_path(User) do |invite|
%p
= invite.label :email
= invite.text_field :email
To
- unless @aspect.is_a? Aspect
= invite.select(:aspects, @aspects_dropdown_array)
- else
= invite.select(:aspects, @aspects_dropdown_array, :selected => @aspect.id)
Message:
= invite.text_area :invite_messages, :value => ""
%p= invite.submit "Send an invitation"

View file

@ -12,6 +12,8 @@
= person_image_link(@person)
%ul
-unless @posts.first.nil?
%li
%b.small= @person.diaspora_handle
%li
%i= t(".last_seen",:how_long_ago => how_long_ago(@posts.first))
- if @person != current_user.person && current_user.friends.include?(@person)

View file

@ -24,3 +24,27 @@
= pr.text_field :last_name
= f.submit t('.sign_up')
= render :partial => "devise/shared/links"
%br
%br
%h2 or, upload yourself
= form_tag '/users/import', :multipart => true do
%p
= label_tag 'user[email]'
= text_field_tag 'user[email]'
%p
= label_tag 'user[password]'
= password_field_tag 'user[password]'
%p
= label_tag 'user[password_confirmation]'
= password_field_tag 'user[password_confirmation]'
%label Select File
= file_field 'upload', 'file'
= submit_tag "Upload"

View file

@ -2,20 +2,22 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
%h1
=t('.add_a_new_friend_to')
%i= aspect.name
.span-12.last
.modal_title_bar
%h4
=t('.add_a_new_friend_to')
%i= aspect.name
= form_for Request.new do |fr_request|
= fr_request.error_messages
= form_for Request.new do |fr_request|
= fr_request.error_messages
=t('.enter_a_diaspora_username')
%br
%i= t '.your_diaspora_username_is', :diaspora_handle => current_user.diaspora_handle
=t('.enter_a_diaspora_username')
%br
%i= t '.your_diaspora_username_is', :diaspora_handle => current_user.diaspora_handle
%p
= fr_request.label :destination_url, t(".friends_username")
= fr_request.text_field :destination_url
= fr_request.hidden_field :aspect_id, :value => aspect.id
= fr_request.submit
%p
= fr_request.label :destination_url, t(".friends_username")
= fr_request.text_field :destination_url
= fr_request.hidden_field :aspect_id, :value => aspect.id
= fr_request.submit

View file

@ -1,8 +1,7 @@
- unless @aspect == :all
%h4 Invites
= link_to "Invite a friend", "#invite_user_pane", :class => "invite_user_button", :title => "Invite a friend"
= "(#{invites} left)"
%br
.yo{ :style => "display:none;"}
#invite_user_pane
= render "invitations/new"
%h4 Invites
= link_to "Invite a friend", "#invite_user_pane", :class => "invite_user_button", :title => "Invite a friend"
= "(#{invites} left)"
%br
.yo{ :style => "display:none;"}
#invite_user_pane
= render "invitations/new"

View file

@ -1,12 +1,18 @@
%h3 You are about to post a public message!
%p
Public messages will be available for others outside of Diaspora to see.
%br
%br
- if @logged_in
= connected_fb_as(@access_token)
- else
= link_to "Connect to Facebook", @fb_access_url
%br
%br
= link_to "OK", '#', :class => "button", :onClick => '$.fancybox.close();'
-# Copyright (c) 2010, Diaspora Inc. This file is
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
.span-12.last
.modal_title_bar
%h4 You are about to post a public message!
%p
Public messages will be available for others outside of Diaspora to see.
%br
%br
- if @logged_in
= connected_fb_as(@access_token)
- else
= link_to "Connect to Facebook", @fb_access_url
%br
%br
= link_to "OK", '#', :class => "button", :onClick => '$.fancybox.close();'

View file

@ -2,16 +2,6 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
:javascript
$(".reshare_button").toggle(function(e){
e.preventDefault();
$(this).parent(".reshare_pane").children(".reshare_box").fadeIn(200);
}, function(e) {
e.preventDefault();
$(this).parent(".reshare_pane").children(".reshare_box").fadeOut(200);
});
- unless current_user.aspects.size == current_user.aspects_with_post(post.id).size
.reshare_pane
%span.reshare_button

View file

@ -7,7 +7,6 @@ default:
debug: false
socket_debug : false
socket_host: 0.0.0.0
socket_pidfile: log/diaspora-wsd.pid
socket_port: 8080
socket_collection_name: 'websocket'
pubsub_server: 'https://pubsubhubbub.appspot.com/'

View file

@ -229,6 +229,8 @@ en:
ignore: "Ignored friend request."
create:
error: "No diaspora seed found with this email!"
invalid_identity: "This identity is not properly formatted"
error_server: "Problem with other server. Maybe it doesn't exist?"
yourself: "You cannot befriend yourself!"
already_friends: "You are already friends with %{destination_url}!"
success: "A friend request was sent to %{destination_url}."

View file

@ -16,6 +16,7 @@ Diaspora::Application.routes.draw do
# added public route to user
match 'public/:username', :to => 'users#public'
match 'users/export', :to => 'users#export'
match 'users/import', :to => 'users#import'
match 'users/export_photos', :to => 'users#export_photos'
resources :users, :except => [:create, :new, :show]

View file

@ -25,14 +25,14 @@ def create
require File.join(File.dirname(__FILE__), "..", "..", "config", "initializers", "_load_app_config.rb")
# Create seed user
user = User.instantiate!(:email => "#{username}@#{username}.joindiaspora.com",
user = User.build(:email => "#{username}@#{username}.joindiaspora.com",
:username => username,
:password => "#{username+backer_info[backer_number]['pin'].to_s}",
:password_confirmation => "#{username+backer_info[backer_number]['pin'].to_s}",
:person => Person.new(
:profile => Profile.new( :first_name => backer_info[backer_number]['given_name'], :last_name => backer_info[backer_number]['family_name'],
:image_url => "http://#{username}.joindiaspora.com/images/user/#{username}.jpg")
))
)).save
user.person.save!
user.aspect(:name => "Presidents")

View file

@ -18,23 +18,25 @@ username = "tom"
set_app_config username
# Create seed user
user = User.instantiate!( :email => "tom@tom.joindiaspora.com",
user = User.build( :email => "tom@tom.joindiaspora.com",
:username => "tom",
:password => "evankorth",
:password_confirmation => "evankorth",
:person => Person.new(
:profile => Profile.new( :first_name => "Alexander", :last_name => "Hamiltom" ))
)
).save
user.person.save!
user.seed_aspects
user2 = User.instantiate!( :email => "korth@tom.joindiaspora.com",
user2 = User.build( :email => "korth@tom.joindiaspora.com",
:username => "korth",
:password => "evankorth",
:password_confirmation => "evankorth",
:person => Person.new(
:profile => Profile.new( :first_name => "Evan", :last_name => "Korth")))
:profile => Profile.new( :first_name => "Evan", :last_name => "Korth"))).save
user2.person.save!
user2.seed_aspects
# friending users
aspect = user.aspect(:name => "other dudes")

View file

@ -18,23 +18,24 @@ set_app_config "tom"
require 'config/initializers/_load_app_config.rb'
# Create seed user
user = User.instantiate!( :email => "tom@tom.joindiaspora.com",
user = User.build( :email => "tom@tom.joindiaspora.com",
:username => "tom",
:password => "evankorth",
:password_confirmation => "evankorth",
:person => {
:profile => { :first_name => "Alexander", :last_name => "Hamiltom",
:image_url => "http://tom.joindiaspora.com/images/user/tom.jpg"}}
)
).save!
user.seed_aspects
user.person.save!
user2 = User.instantiate!( :email => "korth@tom.joindiaspora.com",
user2 = User.build( :email => "korth@tom.joindiaspora.com",
:password => "evankorth",
:password_confirmation => "evankorth",
:username => "korth",
:person => {:profile => { :first_name => "Evan", :last_name => "Korth",
:image_url => "http://tom.joindiaspora.com/images/user/korth.jpg"}})
user2.seed_aspects
user2.person.save!
# friending users

View file

@ -12,12 +12,10 @@ Feature: User creates an aspect
Scenario: success
Given I fill in "Name" with "Dorm Mates" in the modal window
When I press "Create" in the modal window
Then I should see "Manage aspects"
And I should see "Dorm Mates" in the header
And I should see "Dorm Mates" in the aspect list
Then I should see "Dorm Mates" in the header
And I should see "Your aspect 'Dorm Mates' is empty."
Scenario: I omit the name
Given I fill in "Name" with "" in the modal window
When I press "Create" in the modal window
Then I should see "Manage aspects"
And I should see "Aspect creation failed."
Then I should see "Aspect creation failed."

View file

@ -14,36 +14,51 @@ module Diaspora
module XML
def execute(user)
builder = Nokogiri::XML::Builder.new do |xml|
xml.user {
xml.username user.username
xml.parent << user.person.to_xml
xml.serialized_private_key user.serialized_private_key
user_person_id = user.person.id
xml.export {
xml.user {
xml.username user.username
xml.serialized_private_key user.serialized_private_key
xml.parent << user.person.to_xml
}
xml.aspects {
user.aspects.each do |aspect|
xml.aspect {
xml.id_ aspect.id
xml.name aspect.name
xml.people {
aspect.people.each do |person|
xml.person person.to_xml
xml.person_ids {
aspect.person_ids.each do |id|
xml.person_id id
end
}
xml.posts {
aspect.posts.find_all_by_person_id(user.person.id).each do |post|
post_doc = post.to_xml
post.comments.each do |comment|
post_doc << comment.to_xml
end
xml.post post_doc
xml.post_ids {
aspect.posts.find_all_by_person_id(user_person_id).each do |post|
xml.post_id post.id
end
}
}
end
}
xml.people {
user.friends.each do |friend|
xml.parent << friend.to_xml
end
}
xml.posts {
user.raw_visible_posts.find_all_by_person_id(user_person_id).each do |post|
#post_doc = post.to_xml
#post.comments.each do |comment|
# post_doc << comment.to_xml
#end
xml.parent << post.to_xml
end
}
}
end

179
lib/diaspora/importer.rb Normal file
View file

@ -0,0 +1,179 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
module Diaspora
class Importer
def initialize(strategy)
self.class.send(:include, strategy)
end
def commit(user, person, aspects, people, posts, opts = {})
filter = verify_and_clean(user, person, people, aspects, posts)
#assume data is good
# to go
user.email = opts[:email]
user.password= opts[:password]
user.password_confirmation = opts[:pasword_confirmation]
user.person = person
user.person.diaspora_handle = opts[:diaspora_handle]
user.visible_post_ids = filter[:whitelist].keys
user.friend_ids = people.collect{ |x| x.id }
user.visible_person_ids = user.friend_ids
user.save!
user.person.save!
posts.each do |post|
post.save! if filter[:unknown].include? post.id
end
aspects.each do |aspect|
user.aspects << aspect
end
people.each do |p|
p.save! if filter[:people].include? p.id.to_s
end
end
### verification (to be module) ################
def verify_and_clean(user, person, people, aspects, posts)
verify_user(user)
verify_person_for_user(user, person)
filters = filter_posts(posts, person)
clean_aspects(aspects, filters[:whitelist])
filters[:people] = filter_people(people)
filters
end
def verify_user(user)
User.find_by_id(user.id).nil? ? true : raise("User already exists!")
end
def verify_person_for_user(user, person)
local_person = Person.find_by_id(person.id)
if local_person
unless user.encryption_key.public_key.to_s == local_person.public_key.to_s
raise "local person found with different owner"
end
end
true
end
def filter_people(people)
person_ids = people.collect{|x| x.id}
people_from_db = Person.find_all_by_id(person_ids) #this query should be limited to only return person_id
person_ids = person_ids - people_from_db.collect{ |x| x.id }
person_hash = {}
person_ids.each{|x| person_hash[x.to_s] = true }
person_hash
end
def filter_posts(posts, person)
post_ids = posts.collect{|x| x.id}
posts_from_db = Post.find_all_by_id(post_ids) #this query should be limited to only return post id and owner id
unknown_posts = post_ids - posts_from_db.collect{|x| x.id}
posts_from_db.delete_if{|x| x.person_id == person.id}
unauthorized_post_ids = posts_from_db.collect{|x| x.id}
post_whitelist = post_ids - unauthorized_post_ids
unknown = {}
unknown_posts.each{|x| unknown[x.to_s] = true }
whitelist = {}
post_whitelist.each{|x| whitelist[x.to_s] = true }
return {
:unknown => unknown,
:whitelist => whitelist }
end
def clean_aspects(aspects, whitelist)
aspects.each do |aspect|
aspect.post_ids.delete_if{ |x| !whitelist.include? x.to_s }
end
end
end
module Parsers
module XML
def execute(xml, opts = {})
doc = Nokogiri::XML.parse(xml)
user, person = parse_user_and_person(doc)
aspects = parse_aspects(doc)
people = parse_people(doc)
posts = parse_posts(doc)
user
commit(user, person, aspects, people, posts, opts)
end
def parse_user_and_person(doc)
user = User.new
user_doc = doc.xpath('/export/user')
user.username = user_doc.xpath('//user/username').text
user.serialized_private_key= user_doc.xpath('//user/serialized_private_key').text
person = Person.from_xml(user_doc.xpath('//user/person').to_s)
[user, person]
end
def parse_aspects(doc)
aspects = []
aspect_doc = doc.xpath('/export/aspects/aspect')
aspect_doc.each do |x|
a = Nokogiri::XML.parse(x.to_s)
aspect = Aspect.new
aspect.name = a.xpath('/aspect/name').text
aspect.post_ids = a.xpath('/aspect/post_ids/post_id').collect{ |x| x.text.to_id }
aspect.person_ids = a.xpath('/aspect/person_ids/person_id').collect{ |x| x.text.to_id }
aspects << aspect
end
aspects
end
def parse_people(doc)
people_doc = doc.xpath('/export/people/person')
people_doc.inject([]) do |people,curr|
people << Person.from_xml(curr.to_s)
end
end
def parse_posts(doc)
post_doc = doc.xpath('/export/posts/status_message')
post_doc.inject([]) do |posts,curr|
posts << StatusMessage.from_xml(curr.to_s)
end
end
end
end
end

View file

@ -89,7 +89,10 @@ module Diaspora
def remove_friend(bad_friend)
raise "Friend not deleted" unless self.friend_ids.delete( bad_friend.id )
aspects.each{|aspect|
aspect.person_ids.delete( bad_friend.id )}
if aspect.person_ids.delete( bad_friend.id )
aspect.posts.delete_if { |post|
post.person_id == bad_friend.id}
end}
self.save
self.raw_visible_posts.find_all_by_person_id( bad_friend.id ).each{|post|

View file

@ -11,7 +11,7 @@ module HCard
{:given_name => doc.css(".given_name").text,
:family_name => doc.css(".family_name").text,
:url => doc.css("#pod_location").text,
:photo => doc.css(".photo[src]").text}
:photo => doc.css(".photo[src]").attribute('src').text }
end
def self.find url

View file

@ -12,11 +12,11 @@ aimed for packaging purposes.
Prerequisites:
- ruby-1.8, rubygem, git and rake as described in
[RPM installation Fedora](http://github.com/diaspora/diaspora/wiki/Rpm-installation-on-fedora)
or [Installing-on-CentOS-Fedora](http://github.com/diaspora/diaspora/wiki/Installing-on-CentOS-Fedora)
http://github.com/diaspora/diaspora/wiki/Rpm-installation-on-fedora
or http://github.com/diaspora/diaspora/wiki/Installing-on-CentOS-Fedora
- A personal environment to build RPM:s, also described in
[RPM installation Fedora](http://github.com/diaspora/diaspora/wiki/Rpm-installation-on-fedora)
http://github.com/diaspora/diaspora/wiki/Rpm-installation-on-fedora
Install g++ (possibly unnnecessary?):
% yum install gcc-c++
@ -46,7 +46,7 @@ Start development server:
cd /usr/share/diaspora/master
./script/server
See [Using Apache](http://github.com/diaspora/diaspora/wiki/Using-apache) for
See http://github.com/diaspora/diaspora/wiki/Using-apache for
apache/passenger setup. After configuration, start with:
/sbin/service diaspora-wsd start
/sbin/service httpd restart
@ -120,8 +120,7 @@ directory, copy-paste previous version nr. It will be updated.
This has been confirmed to start up and provide basic functionality both using
the thin webserver and apache passenger, on 32/64 bit systems and in the
mock build environment. Irregular nightly builds are available form time to time
at [ftp://mumin.dnsalias.net/pub/leamas/diaspora/builds](ftp://mumin.dnsalias.net/pub/leamas/diaspora/builds)
mock build environment.
#### Implementation

View file

@ -39,20 +39,18 @@ else
exit 1
fi
# %attr(0777, diaspora, diaspora) doesn't work in specfile due to umask 022.
chmod 777 /var/lib/diaspora/uploads
chown -R diaspora /var/log/diaspora
sed -i '/socket_pidfile:/s|:.*|: /var/run/diaspora/diaspora-wsd.pid|' \
config/app_config.yml
hostname=$( awk '/pod_url:/ { print $2; exit }' <config/app_config.yml)
if [ -n "$arg_hostname" ]; then
sed -i "/pod_url:/s/$hostname/$arg_hostname/g" config/app_config.yml &&
sed -i "/pod_url:/s|$hostname|$arg_hostname|g" config/app_config.yml &&
echo "config/app_config.yml updated."
exit 0
fi
hostname=$( awk '/pod_url:/ { print $2; exit }' <config/app_config.yml)
while : ; do
echo "Current hostname is \"$hostname\""
echo -n "Enter new hostname [$hostname] :"
@ -60,7 +58,7 @@ while : ; do
echo -n "Use hostname \"$new_hostname\" as pod_url (Yes/No) [Yes]? :"
read yesno garbage
test "${yesno:0:1}" = 'y' -o "${yesno:0:1}" = 'Y' -o -z "$yesno" && {
sed -i "/pod_url:/s/$hostname/$new_hostname/g" config/app_config.yml &&
sed -i "/pod_url:/s|$hostname|$new_hostname|g" config/app_config.yml &&
echo "config/app_config.yml updated."
break
}

View file

@ -33,9 +33,9 @@ cd /usr/share/diaspora
RETVAL=0
prog="Diaspora websocket server"
exec="script/websocket_server.rb"
pidfile="/var/run/diaspora/diaspora-wsd"
pidfile="/var/run/diaspora-wsd"
lockfile="/var/lock/subsys/diaspora-wsd"
logfile="/var/log/diaspora/diaspora-wsd.log"
logfile=/var/log/diaspora-wsd.log
[ -n "$OPTIONS" ] && OPTIONS=" $OPTIONS"
ruby_cmd="ruby -C $PWD $exec$OPTIONS"

View file

@ -77,7 +77,6 @@ mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib/diaspora/tmp
cp %SOURCE2 $RPM_BUILD_ROOT/%{_datadir}/diaspora
mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/log/diaspora
mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run/diaspora
mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib/diaspora/uploads
mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib/diaspora/tmp
@ -95,8 +94,6 @@ find -L $RPM_BUILD_ROOT/%{_datadir}/diaspora -type f \
cat files >> dirs && mv -f dirs files
sed -i -e '\|.*/master/config.ru"$|d' \
-e '\|.*/master/config/environment.rb"$|d' \
-e '\|.*/run/diaspora"$|d' \
-e '\|.*/pkg/fedora/dist"$|d' \
-e 's|%{buildroot}||' -e 's|//|/|' -e '/""/d' \
files
@ -104,7 +101,6 @@ sed -i -e '\|.*/master/config.ru"$|d' \
%post wsd
/sbin/chkconfig --add diaspora-wsd || :
%preun wsd
if [ $1 -eq 0 ] ; then
service diaspora-wsd stop &>/dev/null || :
@ -121,11 +117,9 @@ rm -fr $RPM_BUILD_ROOT
%doc AUTHORS README.md GNU-AGPL-3.0 COPYRIGHT README-Fedora.md
%attr(-, diaspora, diaspora) %{_datadir}/diaspora/master/config.ru
%attr(-, diaspora, diaspora) %{_datadir}/diaspora/master/config/environment.rb
%attr(-, diaspora, diaspora) %{_datadir}/diaspora/master/pkg/fedora/dist
%attr(-, diaspora, diaspora) %{_localstatedir}/log/diaspora
%attr(-, diaspora, diaspora) %{_localstatedir}/lib/diaspora/uploads
%attr(-, diaspora, diaspora) %{_localstatedir}/lib/diaspora/tmp
%attr(-, diaspora, diaspora) %{_localstatedir}/run/diaspora
%{_datadir}/diaspora/master/tmp
%{_datadir}/diaspora/master/public/uploads

View file

View file

@ -126,7 +126,8 @@ function checkout()
git clone --quiet $GIT_REPO;
(
cd diaspora;
git remote add upstream $GIT_REPO
git remote add upstream \
git://github.com/diaspora/diaspora.git
for p in ../../*.patch; do
git apply --whitespace=fix $p > /dev/null
done &> /dev/null || :
@ -180,6 +181,7 @@ function make_bundle()
# Usage: make_bundle [ commit, defaults to HEAD]
#
{
set -x
checkout ${1:-'HEAD'} >/dev/null
bundle_id=$( git_id dist/diaspora/Gemfile)
bundle_name="diaspora-bundle-$VERSION-$bundle_id"

View file

@ -5,7 +5,6 @@ work as a first step towards packaging, but should be usable as is.
### Synopsis
Bootstrap the distribution from git:
% sudo apt-get install git-core
% git clone git://github.com/diaspora/diaspora.git
@ -80,11 +79,19 @@ dependencies lives in the application - nothing is installed by user or
on system level.
This has been tested on a Ubuntu 32-bit 10.10 , clean server and on 10.04
Lucid desktop, also clean installation. Irregular nightly builds are
available from time to time at
[ftp://mumin.dnsalias.net/pub/leamas/diaspora/builds](ftp://mumin.dnsalias.net/pub/leamas/diaspora/builds)
Lucid desktop, also clean installation.
mongodb is having problems occasionally. Sometimes the dependencies are not
installed, and mongod refuses to start. invoke */usr/bin/mongod -f
/etc/mongodb.conf* to test. The lockfile /var/lib/mongodb/mongod.conf is
also a potential problem. Remove to make it start again.
The diaspora-wsd is just placeholder FTM, it does **not** work.

View file

@ -30,7 +30,7 @@ sed -i '/BUNDLE_PATH/s|:.*|: /usr/lib/diaspora-bundle/bundle|' \
cp master/GNU-AGPL-3.0 master/COPYRIGHT master/README.md master/AUTHORS .
cp master/config/app_config.yml.example ./app_config.yml
cp master/pkg/ubuntu/diaspora-wsd.conf /etc/init
cp master/pkg/ubuntu/diaspora-wsd /etc/init.d
sed -i '/^cd /s|.*|cd /usr/share/diaspora/master|' /etc/init.d/diaspora-wsd
@ -41,8 +41,8 @@ cp master/pkg/ubuntu/diaspora-setup .
mkdir -p /var/log/diaspora
mkdir -p /var/lib/diaspora/uploads
mkdir -p /var/lib/diaspora/tmp
mkdir -p /var/run/diaspora
mkdir -p /etc/diaspora
mkdir -p /usr/share/diaspora/master/pkg/ubuntu/dist
ln -sf /var/log/diaspora ./master/log
cp master/config/app_config.yml.example /etc/diaspora/app_config.yml
@ -65,6 +65,5 @@ chown diaspora:diaspora /var/log/diaspora
chown diaspora:diaspora /var/lib/diaspora/uploads
chown diaspora:diaspora /var/lib/diaspora/tmp
chown diaspora:diaspora /var/lib/diaspora
chown diaspora:diaspora /var/run/diaspora
chown diaspora:diaspora /usr/share/diaspora/master/pkg/ubuntu/dist

View file

@ -43,11 +43,9 @@ else
exit 1
fi
chmod 777 /var/lib/diaspora/uploads
chown -R diaspora /var/log/diaspora
sed -i '/socket_pidfile:/s|:.*|: /var/run/diaspora/diaspora-wsd.pid|' \
config/app_config.yml
hostname=$( awk '/pod_url:/ { print $2; exit }' <config/app_config.yml)
if [ -n "$arg_hostname" ]; then
@ -63,7 +61,7 @@ while : ; do
echo -n "Use hostname \"$new_hostname\" as pod_url (Yes/No) [Yes]? :"
read yesno garbage
test "${yesno:0:1}" = 'y' -o "${yesno:0:1}" = 'Y' -o -z "$yesno" && {
sed -i "/pod_url:/s/$hostname/$new_hostname/g" config/app_config.yml &&
sed -i "/pod_url:/s|$hostname|$new_hostname|g" config/app_config.yml &&
echo "config/app_config.yml updated."
break
}

102
pkg/ubuntu/diaspora-wsd Executable file
View file

@ -0,0 +1,102 @@
#!/bin/bash
#
# /etc/rc.d/init.d/diaspora-wsd
#
# SHOULD start the diaspora websocket daemon, but it doesn't. No way.
#
# chkconfig: - 80 80
# description: Diaspora websocket daemon
### BEGIN INIT INFO
# Provides: diaspora-wsd
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Should-Start: $remote_fs
# Should-Stop: $remote_fs
# Default-Start:
# Default-Stop: 0 1 2 3 4 5 6
# Short-Description: start and stop Diaspora websocket server
# Description: The websocket server provides websocket services for
# diaspora.
### END INIT INFO
# Source function library.
. /etc/init.d/functions
if [ -f /etc/sysconfig/diaspora-wsd -a $UID -eq 0 ]; then
. /etc/sysconfig/diaspora-wsd
fi
# Note: this line is patched by installation scripts.
cd /usr/share/diaspora
RETVAL=0
prog="Diaspora websocket server"
exec="script/websocket_server.rb"
pidfile="/var/run/diaspora-wsd"
lockfile="/var/lock/subsys/diaspora-wsd"
logfile=/var/log/diaspora-wsd.log
[ -n "$OPTIONS" ] && OPTIONS=" $OPTIONS"
ruby_cmd="ruby -C $PWD $exec$OPTIONS"
start() {
[ $UID -eq 0 ] || exit 4
[ -f $exec ] || exit 5
echo -n $"Starting $prog: "
daemon --pidfile $pidfile "$ruby_cmd >>$logfile 2>&1 &"
RETVAL=$?
echo
if test $RETVAL = 0; then
touch $lockfile
pgrep -f "$ruby_cmd" > $pidfile || {
echo "Warning: cannot find running diaspora-webserver"
exit 7
}
fi
}
stop() {
[ $UID -eq 0 ] || exit 4
echo -n $"Stopping $prog: "
killproc -p $pidfile $exec
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f $lockfile
echo
}
#
# See how we were called.
#
case "$1" in
start)
start
;;
stop)
stop
;;
force-reload|restart)
stop
sleep 1
start
RETVAL=$?
;;
condrestart|try-restart)
if [ -f $lockfile ]; then
stop
sleep 3
start
fi
;;
status)
status -p $pidfile $exec
RETVAL=$?
;;
*)
echo $"Usage: $0 {condrestart|try-restart|start|stop|restart|force-reload|status}"
RETVAL=2
[ "$1" = 'usage' ] && RETVAL=0
esac
exit $RETVAL

View file

@ -1,19 +0,0 @@
# Ubuntu upstart file at /etc/init/diaspora-wsd.conf
start on runlevel [5]
stop on runlevel [06]
export fork
script
if [ -f /etc/default/diaspora ]; then
. /etc/default/diaspora;
fi;
cd /usr/share/diaspora/master;
start-stop-daemon --start \
--chuid diaspora:diaspora \
--chdir $PWD \
--exec "/usr/local/bin/bundle" \
-- exec ruby -C $PWD script/websocket_server.rb;
end script

View file

View file

@ -29,7 +29,7 @@ $(".show_post_comments").live('click', function(event) {
$(this).toggleClass( "visible" );
});
$(".comment_box").live('focus', function(evt){
$(".comment_box").toggle(function(evt){
var $this = $(this);
$this.attr("rows", 2);
$this.parents("p").parents("form").children("p").children(".comment_submit").fadeIn(200);
@ -47,3 +47,10 @@ $(".comment_submit").live('click', function(evt){
$(this).closest("form").children("p .comment_box").attr("rows", 1);
});
$(".reshare_button").live("click", function(e){
e.preventDefault();
var button = $(this);
button.parent(".reshare_pane").children(".reshare_box").show();
button.addClass("active");
});

View file

@ -53,6 +53,21 @@ $(document).ready(function(){
}
});
$("#user_menu").click( function(){
$(this).toggleClass("active");
});
$('body').click( function(event){
if(!$(event.target).closest('#user_menu').length){
$("#user_menu").removeClass("active");
};
if(!$(event.target).closest('.reshare_box').length){
$(".reshare_button").removeClass("active");
$(".reshare_box").hide();
};
});
});//end document ready

View file

@ -22,7 +22,7 @@ a
:color #22AAE0
&:active
:color #005D9C
h1, h2, h3, h4
:color #444
@ -48,14 +48,14 @@ h3
:width 100%
:padding 1em
:box-shadow 0 1px 2px #333
:-moz-box-shadow 0 1px 2px #333
:-webkit-box-shadow 0 1px 2px #333
:font
:weight bold
#flash_notice
:background
:color rgba(127,255,36,0.85)
@ -128,9 +128,9 @@ header
a
:text-shadow 0 1px 0 #000
:width 100px
:z-index 10
:font
:size 14px
:padding 5px 10px
:left 40px
:margin 0
@ -152,11 +152,7 @@ header
a
:display block
&:hover
li
:display block
&:hover
&.active
:margin
:top -3px
:right -6px
@ -168,11 +164,14 @@ header
:-webkit-box-shadow 0 1px 2px #333
:-moz-box-shadow 0 1px 2px #333
li
:display block
.avatar
:height 20px
:width 20px
:position absolute
:left 5px
:left 5px
:display block
@ -275,7 +274,7 @@ li.message
:weight bold
:margin
:right 5px
&:hover
div.info, .time
a
@ -293,6 +292,16 @@ li.message
:decoration none
:cursor default
.right .reshare_pane .reshare_button
:padding 5px
&.active
:background
:color #333
:border-radius 5px 5px 0 0
a
:color #fff
:text-shadow none
.right .reshare_pane
:margin
:left 5px
@ -300,13 +309,14 @@ li.message
:display inline
:position relative
ul.reshare_box
:width 150px
:display none
:z-index 10
:position absolute
:margin
:top 5px
:top 0
:padding 0
:background
@ -315,9 +325,7 @@ li.message
:list
:style none
:border 5px solid #666
:-webkit-box-shadow 0 0 5px #666
:-moz-box-shadow 0 0 5px #666
:border 5px solid #333
:text-shadow 0 2px #fff
:color #000
@ -340,6 +348,7 @@ li.message
:display block
:height 100%
:padding 2px 5px
:cursor default
&:hover
:background
@ -407,7 +416,7 @@ form
> li
:background none
:border none
#stream div.comments
:display none
@ -798,8 +807,8 @@ h1.big_text
:margin 0
a
:-webkit-border-radius 5px 5px 0 0
:-moz-border-radius 5px 5px 0 0
:-webkit-border-radius 5px 5px 0 0
:-moz-border-radius 5px 5px 0 0
:text-shadow 0 1px 0 #444
:line
@ -927,7 +936,7 @@ h1.big_text
:color #333
:border-radius 5px
a
:color #ccc

View file

@ -5,26 +5,6 @@
require File.dirname(__FILE__) + '/../config/environment'
require File.dirname(__FILE__) + '/../lib/diaspora/websocket'
at_exit do
begin
File.delete(PID_FILE)
rescue
puts 'Cannot remove pidfile: ' + (PID_FILE ? PID_FILE : "NIL")
end
end
def write_pidfile
begin
f = File.open(PID_FILE, "w")
f.write(Process.pid)
f.close
rescue => e
puts "Can't write to pidfile!"
puts e.inspect
puts e.backtrace
end
end
CHANNEL = Magent::GenericChannel.new('websocket')
def process_message
if CHANNEL.queue_count > 0
@ -57,8 +37,6 @@ begin
}
end
PID_FILE = APP_CONFIG[:socket_pidfile]
write_pidfile
puts "Websocket server started."
process_message
}

View file

@ -5,7 +5,8 @@
require 'spec_helper'
describe AspectsController do
render_views
render_views
before do
@user = Factory.create(:user)
@user.aspect(:name => "lame-os")
@ -13,11 +14,36 @@ describe AspectsController do
sign_in :user, @user
end
it "on index sets a variable containing all a user's friends when a user is signed in" do
sign_in :user, @user
Factory.create :person
get :index
assigns[:friends].should == @user.friends
describe "#index" do
it "assigns @friends to all the user's friends" do
Factory.create :person
get :index
assigns[:friends].should == @user.friends
end
end
describe "#create" do
describe "with valid params" do
it "creates an aspect" do
@user.aspects.count.should == 1
post :create, "aspect" => {"name" => "new aspect"}
@user.reload.aspects.count.should == 2
end
it "redirects to the aspect page" do
post :create, "aspect" => {"name" => "new aspect"}
response.should redirect_to(aspect_path(Aspect.find_by_name("new aspect")))
end
end
describe "with invalid params" do
it "does not create an aspect" do
@user.aspects.count.should == 1
post :create, "aspect" => {"name" => ""}
@user.reload.aspects.count.should == 1
end
it "goes back to manage aspects" do
post :create, "aspect" => {"name" => ""}
response.should redirect_to(aspects_manage_path)
end
end
end
end

View file

@ -26,6 +26,10 @@ describe RegistrationsController do
it "creates a user" do
lambda { get :create, @valid_params }.should change(User, :count).by(1)
end
it "assigns @user" do
get :create, @valid_params
assigns(:user).should_not be_nil
end
it "sets the flash" do
get :create, @valid_params
flash[:notice].should_not be_empty
@ -37,19 +41,23 @@ describe RegistrationsController do
end
context "with invalid parameters" do
before do
@valid_params["user"].delete("username")
@valid_params["user"]["person"]["profile"].delete("first_name")
@invalid_params = @valid_params
end
it "does not create a user" do
lambda { get :create, @invalid_params }.should_not change(User, :count)
end
it "assigns @user" do
get :create, @valid_params
assigns(:user).should_not be_nil
end
it "sets the flash error" do
get :create, @invalid_params
flash[:error].should_not be_blank
end
it "goes back to the form" do
get :create, @invalid_params
response.should redirect_to new_user_registration_path
response.should be_redirect
end
end
end

View file

@ -22,4 +22,34 @@ describe RequestsController do
response.should redirect_to aspect_path(@user.aspects[0].id.to_s)
end
it "should not error out when requesting an invalid identity" do
put("create", "request" => {
"destination_url" => "not_a_@valid_email",
"aspect_id" => @user.aspects[0].id
}
)
response.should redirect_to aspect_path(@user.aspects[0].id.to_s)
end
it "should not error out when requesting an invalid identity with a port number" do
put("create", "request" => {
"destination_url" => "johndoe@email.com:3000",
"aspect_id" => @user.aspects[0].id
}
)
response.should redirect_to aspect_path(@user.aspects[0].id.to_s)
end
it "should not error out when requesting an identity from an invalid server" do
stub_request(:get, /notadiasporaserver\.com/).to_raise(Errno::ETIMEDOUT)
put("create", "request" => {
"destination_url" => "johndoe@notadiasporaserver.com",
"aspect_id" => @user.aspects[0].id
}
)
response.should redirect_to aspect_path(@user.aspects[0].id.to_s)
end
end

View file

@ -6,7 +6,7 @@ require 'spec_helper'
describe Diaspora::Parser do
before do
@user = Factory.create(:user, :email => "bob@aol.com")
@user = Factory.create(:user)
@aspect = @user.aspect(:name => 'spies')
@user3 = Factory.create :user
@ -22,7 +22,7 @@ describe Diaspora::Parser do
end
it 'should be able to correctly handle comments with person in db' do
person = Factory.create(:person, :diaspora_handle => "test@testing.com")
person = Factory.create(:person)
post = Factory.create(:status_message, :person => @user.person)
comment = Factory.build(:comment, :post => post, :person => person, :text => "Freedom!")
xml = comment.to_diaspora_xml
@ -56,9 +56,7 @@ describe Diaspora::Parser do
retraction = Retraction.for(message)
xml = retraction.to_diaspora_xml
StatusMessage.count.should == 1
@user.receive xml, person
StatusMessage.count.should == 0
proc {@user.receive xml, person}.should change(StatusMessage, :count).by(-1)
end
it "should create a new person upon getting a person request" do
@ -155,7 +153,7 @@ describe Diaspora::Parser do
person.save
#Cache profile for checking against marshaled profile
old_profile = person.profile
old_profile = person.profile.dup
old_profile.first_name.should == 'bob'
#Build xml for profile, clear profile

View file

@ -9,25 +9,57 @@ describe Diaspora::Exporter do
let!(:user1) { Factory(:user) }
let!(:user2) { Factory(:user) }
let!(:user3) { Factory(:user) }
let(:aspect1) { user1.aspect(:name => "Work") }
let(:aspect2) { user2.aspect(:name => "Family") }
let(:aspect3) { user3.aspect(:name => "Pivots") }
let!(:status_message1) { user1.post(:status_message, :message => "One", :public => true, :to => aspect1.id) }
let!(:status_message2) { user1.post(:status_message, :message => "Two", :public => true, :to => aspect1.id) }
let!(:status_message3) { user2.post(:status_message, :message => "Three", :public => false, :to => aspect2.id) }
let!(:exported) { Diaspora::Exporter.new(Diaspora::Exporters::XML).execute(user1) }
let(:exported) { Diaspora::Exporter.new(Diaspora::Exporters::XML).execute(user1) }
it 'should include a users posts' do
exported.should include status_message1.to_xml.to_s
exported.should include status_message2.to_xml.to_s
exported.should_not include status_message3.to_xml.to_s
exported.should include status_message1.message
exported.should include status_message2.message
exported.should_not include status_message3.message
end
it 'should include a users private key' do
exported.should include user1.serialized_private_key
end
end
it 'should include post_ids' do
doc = Nokogiri::XML::parse(exported)
doc.xpath('//aspects').to_s.should include status_message1.id.to_s
doc.xpath('//aspects').to_s.should include status_message2.id.to_s
doc.xpath('//posts').to_s.should include status_message1.id.to_s
end
it 'should include post created at time' do
doc = Nokogiri::XML::parse(exported)
Time.parse(doc.xpath('//posts/status_message/created_at').first.text).should == status_message1.created_at
end
it 'should include a list of users posts' do
doc = Nokogiri::XML::parse(exported)
posts = doc.xpath('//posts').to_s
posts.should include(status_message1.message)
end
it 'should serialize a users friends' do
friend_users(user1, aspect1, user3, aspect3)
doc = Nokogiri::XML::parse(exported)
doc.xpath('/export/people').to_s.should include user3.person.id.to_s
end
it 'should serialize only a users posts within his aspects' do
message = Factory(:status_message, :message => "Shouldn't be here", :person => user3.person)
aspect1.posts << message
doc = Nokogiri::XML::parse(exported)
doc.xpath('/export/aspects').to_s.should_not include message.message
end
end

234
spec/lib/importer_spec.rb Normal file
View file

@ -0,0 +1,234 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
require 'spec_helper'
require File.join(Rails.root, 'lib/diaspora/exporter')
require File.join(Rails.root, 'lib/diaspora/importer')
describe Diaspora::Importer do
before(:each) do
# Five users on pod
@user1 = Factory(:user)
@user2 = Factory(:user)
@user3 = Factory(:user)
@user4 = Factory(:user)
@user5 = Factory(:user)
# Two external people referenced on pod
@person1 = Factory(:person)
@person2 = Factory(:person)
# User1 has four aspects(1-4), each following user has one aspect
@aspect1 = @user1.aspect(:name => "Dudes")
@aspect2 = @user1.aspect(:name => "Girls")
@aspect3 = @user1.aspect(:name => "Bros")
@aspect4 = @user1.aspect(:name => "People")
@aspect5 = @user2.aspect(:name => "Abe Lincolns")
@aspect6 = @user3.aspect(:name => "Cats")
@aspect7 = @user4.aspect(:name => "Dogs")
@aspect8 = @user5.aspect(:name => "Hamsters")
@aspect9 = @user5.aspect(:name => "Gophers")
@aspect10 = @user1.aspect(:name => "Work")
@aspect11 = @user1.aspect(:name => "Family")
# User1 posts one status messages to aspects (1-4), two other users post message to one aspect
@status_message1 = @user1.post(:status_message, :message => "One", :public => false, :to => @aspect1.id)
@status_message2 = @user1.post(:status_message, :message => "Two", :public => false, :to => @aspect2.id)
@status_message3 = @user1.post(:status_message, :message => "Three", :public => false, :to => @aspect3.id)
@status_message4 = @user1.post(:status_message, :message => "Four", :public => false, :to => @aspect4.id)
@status_message5 = @user2.post(:status_message, :message => "Five", :public => false, :to => @aspect5.id)
@status_message6 = @user3.post(:status_message, :message => "Six", :public => false, :to => @aspect6.id)
@status_message7 = @user5.post(:status_message, :message => "Seven", :public => false, :to => @aspect9.id)
@aspect1.posts << @status_message1
@aspect2.posts << @status_message2
@aspect3.posts << @status_message3
@aspect4.posts << @status_message4
# Friend users with user1
friend_users( @user1, @aspect1, @user2, @aspect5 )
friend_users( @user1, @aspect2, @user3, @aspect6 )
friend_users( @user1, @aspect3, @user4, @aspect7 )
friend_users( @user1, @aspect4, @user5, @aspect8 )
# Friend users 4 and 5
friend_users( @user5, @aspect9, @user4, @aspect7 )
# Generate status messages and receive for user1
@user2.receive @status_message1.to_diaspora_xml, @user1.person
@user3.receive @status_message2.to_diaspora_xml, @user1.person
@user4.receive @status_message3.to_diaspora_xml, @user1.person
@user5.receive @status_message4.to_diaspora_xml, @user1.person
@user1.receive @status_message5.to_diaspora_xml, @user2.person
@user1.receive @status_message6.to_diaspora_xml, @user3.person
# Generate status message and recieve between user4 and user5
@user4.receive @status_message7.to_diaspora_xml, @user5.person
end
it 'should gut check this test' do
@user1.friends.count.should be 4
@user1.friends.should include @user2.person
@user1.friends.should include @user3.person
@user1.friends.should include @user4.person
@user1.friends.should include @user5.person
# User is generated with two pre-populated aspects
@user1.aspects.count.should be 6
@user1.aspects.find_by_name("Dudes").people.should include @user2.person
@user1.aspects.find_by_name("Dudes").posts.should include @status_message5
@user1.raw_visible_posts.count.should be 6
@user1.raw_visible_posts.find_all_by_person_id(@user1.person.id).count.should be 4
@user1.raw_visible_posts.find_all_by_person_id(@user1.person.id).should_not include @status_message7
end
context 'parsing a user' do
before(:each) do
# Generate exported XML for user1
exporter = Diaspora::Exporter.new(Diaspora::Exporters::XML)
@user1.aspects.reload
@xml = exporter.execute(@user1)
@old_user = @user1
# Remove user1 from the server
@user1.aspects.each( &:delete )
@user1.raw_visible_posts.find_all_by_person_id(@user1.person.id).each( &:delete )
@user1.delete
@importer = Diaspora::Importer.new(Diaspora::Parsers::XML)
@doc = Nokogiri::XML::parse(@xml)
end
describe '#parse_user_and_person' do
before(:each) do
@user, @person = @importer.parse_user_and_person(@doc)
end
it 'should set username' do
@user.username.should == @old_user.username
end
it 'should set private key' do
@user.serialized_private_key.should_not be nil
@user.serialized_private_key.should == @old_user.serialized_private_key
end
end
describe '#parse_aspects' do
let(:aspects) { @importer.parse_aspects(@doc) }
it 'should return valid aspects' do
aspects.all?(&:valid?).should be true
end
it 'should return an array' do
aspects.count.should == 6
end
it 'should should have post ids' do
aspects.any?{|x| x.post_ids.count > 0}.should be true
end
it 'should have person ids' do
aspects.any?{|x| x.person_ids.count > 0}.should be true
end
end
describe '#parse_people' do
let(:people) { @importer.parse_people(@doc) }
it 'should return an array' do
people.count.should == 4
end
end
describe '#parse_posts' do
let(:posts) { @importer.parse_posts(@doc) }
it 'should return an array' do
posts.count.should == 4
end
it 'should return vaild posts' do
posts.all?(&:valid?).should be true
end
end
end
describe 'importing a user' do
context '#execute' do
before(:each) do
# Generate exported XML for user1
exporter = Diaspora::Exporter.new(Diaspora::Exporters::XML)
@xml = exporter.execute(@user1)
# Remove user1 from the server
@user1.aspects.each( &:delete )
@user1.raw_visible_posts.find_all_by_person_id(@user1.person.id).each( &:delete )
@user1.delete
@importer = Diaspora::Importer.new(Diaspora::Parsers::XML)
end
it 'should import' do
pending "there is some weirdness with diaspora handle we need to look into... and this test is terrible"
User.delete_all
Person.delete_all
Post.delete_all
StatusMessage.delete_all
Aspect.delete_all
User.count.should == 0
Person.count.should == 0
@importer.execute(@xml,
:email => "bob@bob.com",
:password => "bobbybob",
:password => "bobbybob",
:diaspora_handle => "bob@diaspora.com")
User.count.should == 1
n = User.first
Post.count.should == 4
n.aspects.count.should == 6
Person.count.should be == 5
User.first.person.diaspora_handle.should == User.first.diaspora_handle
Person.find_by_id( @user1.person.id ).nil?.should == false
Person.find_by_id( @user2.person.id ).nil?.should == false
n.aspects.count.should == 6
people_count = 0
n.aspects.each{|x| people_count += x.people.count }
people_count.should == 4
post_count = 0
n.aspects.reload
n.aspects.each{ |x| post_count += x.post_ids.count }
post_count.should == 4
n.friends.count.should be 4
end
end
end
end

109
spec/lib/verify_spec.rb Normal file
View file

@ -0,0 +1,109 @@
# Copyright (c) 2010, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
require 'spec_helper'
require File.join(Rails.root, 'lib/diaspora/importer')
describe Diaspora::Importer do
let!(:user1) { Factory(:user) }
let!(:user2) { Factory(:user) }
let!(:user3) { Factory(:user) }
let(:aspect1) { user1.aspect(:name => "Work") }
let(:aspect2) { user2.aspect(:name => "Family") }
let(:aspect3) { user3.aspect(:name => "Pivots") }
let!(:status_message1) { user1.post(:status_message, :message => "One", :public => true, :to => aspect1.id) }
let!(:status_message2) { user1.post(:status_message, :message => "Two", :public => true, :to => aspect1.id) }
let!(:status_message3) { user2.post(:status_message, :message => "Three", :public => false, :to => aspect2.id) }
let(:importer) { Diaspora::Importer.new(Diaspora::Parsers::XML) }
context 'serialized user' do
describe '#verify_user' do
it 'should return true for a new valid user' do
new_user = Factory(:user)
new_user.delete
importer.verify_user(new_user).should be true
end
it 'should return false if vaild user already exists' do
u = User.first
lambda{ importer.verify_user(user1) }.should raise_error
end
end
describe '#verify_person_for_user' do
it 'should pass if keys match' do
importer.verify_person_for_user(user1, user1.person).should be true
end
it 'should fail if private and public keys do not match' do
person = Factory(:person)
lambda{ importer.verify_person_for_user(user1, person) }.should raise_error
end
it 'should pass if the person does not exist' do
user = Factory.build(:user)
importer.verify_person_for_user(user, user.person)
end
end
describe '#filter_posts' do
it 'should make sure all found posts are owned by the user' do
posts = [status_message1, status_message2]
whitelist = importer.filter_posts(posts, user1.person)[:whitelist]
whitelist.should have(2).posts
whitelist.should include status_message1.id.to_s
whitelist.should include status_message2.id.to_s
end
it 'should remove posts not owned by the user' do
posts = [status_message1, status_message2, status_message3]
whitelist = importer.filter_posts(posts, user1.person)[:whitelist]
whitelist.should have(2).posts
whitelist.should_not include status_message3.id
end
it 'should return a list of unknown posts' do
posts = [status_message1, status_message2, Factory.build(:status_message)]
unknown = importer.filter_posts(posts, user1.person)[:unknown]
unknown.should have(1).post
end
it 'should generate a whitelist, unknown posts inclusive' do
posts = [status_message1, status_message2, Factory.build(:status_message)]
filters = importer.filter_posts(posts, user1.person)
filters[:whitelist].should include filters[:unknown].keys.first
end
end
describe '#clean_aspects' do
it 'should purge posts not in whitelist that are present in aspects' do
whitelist = {status_message1.id.to_s => true, status_message2.id.to_s => true}
aspect1.reload
aspect1.post_ids << status_message3.id.to_s
proc{ importer.clean_aspects([aspect1], whitelist) }.should change(aspect1.post_ids, :count).by(-1)
aspect1.post_ids.should_not include status_message3.id
end
end
describe '#filter_people' do
it 'should filter people who already exist in the database' do
new_peep = Factory.build(:person)
people = [user1.person, user2.person, new_peep]
importer.filter_people(people).keys.should == [new_peep.id.to_s]
end
end
end
end

View file

@ -5,34 +5,13 @@
require 'spec_helper'
describe 'making sure the spec runner works' do
it 'should not delete the database mid-spec' do
User.count.should == 0
Factory.create(:user)
User.count.should == 1
end
it 'should make sure the last user no longer exsists' do
User.count.should == 0
end
it 'should factory create a user with a person saved' do
user = Factory.create(:user)
loaded_user = User.first(:id => user.id)
loaded_user.person.owner_id.should == user.id
end
describe 'testing a before do block' do
before do
Factory.create(:user)
end
it 'should have cleaned before the before do block runs' do
User.count.should == 1
end
end
describe '#friend_users' do
describe '#friend_users' do
before do
@user1 = Factory.create(:user)
@aspect1 = @user1.aspect(:name => "losers")

View file

@ -69,8 +69,13 @@ describe Aspect do
end
it 'belong to a user' do
<<<<<<< HEAD
@aspect.user.id.should == user.id
user.aspects.size.should == 3
=======
@aspect.user.id.should == @user.id
@user.aspects.size.should == 1
>>>>>>> 961510a8ed06590109a8090686355ffdcde71180
end
it 'should have people' do

View file

@ -18,7 +18,7 @@ describe Comment do
status.comments.should == []
@user.comment "Yeah, it was great", :on => status
StatusMessage.first.comments.first.text.should == "Yeah, it was great"
status.reload.comments.first.text.should == "Yeah, it was great"
end
it "should be able to comment on a person's status" do
@ -26,8 +26,8 @@ describe Comment do
status = Factory.create(:status_message, :person => person)
@user.comment "sup dog", :on => status
StatusMessage.first.comments.first.text.should == "sup dog"
StatusMessage.first.comments.first.person.should == @user.person
status.reload.comments.first.text.should == "sup dog"
status.reload.comments.first.person.should == @user.person
end
it 'should not send out comments when we have no people' do

View file

@ -13,6 +13,22 @@ describe Person do
@aspect2 = @user2.aspect(:name => "Abscence of Babes")
end
describe "validation" do
describe "of associated profile" do
it "fails if the profile isn't valid" do
person = Factory.build(:person)
person.should be_valid
person.profile.update_attribute(:first_name, nil)
person.profile.should_not be_valid
person.should_not be_valid
person.errors.count.should == 1
person.errors.full_messages.first.should =~ /first name/i
end
end
end
describe '#diaspora_handle' do
context 'local people' do
it 'uses the pod config url to set the diaspora_handle' do
@ -61,64 +77,38 @@ describe Person do
person_two.owns?(person_message).should be false
end
it 'should delete all of user posts except comments upon user deletion' do
it "deletes all of a person's posts upon person deletion" do
person = Factory.create(:person)
Factory.create(:status_message, :person => person)
Factory.create(:status_message, :person => person)
Factory.create(:status_message, :person => person)
Factory.create(:status_message, :person => person)
status = Factory.create(:status_message, :person => person)
Factory.create(:status_message, :person => @person)
lambda {person.destroy}.should change(Post, :count).by(-1)
end
it "does not delete a person's comments on person deletion" do
person = Factory.create(:person)
status_message = Factory.create(:status_message, :person => @person)
Factory.create(:comment, :person_id => person.id, :text => "yes i do", :post => status_message)
Factory.create(:comment, :person_id => person.id, :text => "i love you", :post => status_message)
Factory.create(:comment, :person_id => person.id, :text => "hello", :post => status_message)
Factory.create(:comment, :person_id => @person.id, :text => "you are creepy", :post => status_message)
person.destroy
Post.count.should == 1
Comment.all.count.should == 4
status_message.comments.count.should == 4
lambda {person.destroy}.should_not change(Comment, :count)
end
describe "unfriending" do
it 'should not delete an orphaned friend' do
request = @user.send_friend_request_to @person, @aspect
@user.activate_friend(@person, @aspect)
@user.reload
Person.all.count.should == 3
@user.friends.count.should == 1
@user.unfriend(@person)
@user.reload
@user.friends.count.should == 0
Person.all.count.should == 3
lambda {@user.unfriend(@person)}.should_not change(Person, :count)
end
it 'should not delete an un-orphaned friend' do
request = @user.send_friend_request_to @person, @aspect
request2 = @user2.send_friend_request_to @person, @aspect2
@user.activate_friend(@person, @aspect)
@user2.activate_friend(@person, @aspect2)
@user.reload
@user2.reload
Person.all.count.should == 3
@user.friends.count.should == 1
@user2.friends.count.should == 1
@user.unfriend(@person)
@user.reload
@user2.reload
@user.friends.count.should == 0
@user2.friends.count.should == 1
Person.all.count.should == 3
lambda {@user.unfriend(@person)}.should_not change(Person, :count)
end
end
@ -197,6 +187,26 @@ describe Person do
end
end
it 'identifier should be a valid email' do
stub_success("joe.valid+email@my-address.com")
Proc.new {
Person.by_webfinger("joe.valid+email@my-address.com")
}.should_not raise_error(RuntimeError, "Identifier is invalid")
stub_success("not_a_@valid_email")
Proc.new {
Person.by_webfinger("not_a_@valid_email")
}.should raise_error(RuntimeError, "Identifier is invalid")
end
it 'should not accept a port number' do
stub_success("eviljoe@diaspora.local:3000")
Proc.new {
Person.by_webfinger('eviljoe@diaspora.local:3000')
}.should raise_error(RuntimeError, "Identifier is invalid")
end
it 'creates a stub for a remote user' do
stub_success("tom@tom.joindiaspora.com")
tom = Person.by_webfinger('tom@tom.joindiaspora.com')

View file

@ -51,8 +51,7 @@ describe Photo do
it 'should have a caption' do
@photo.image.store! File.open(@fixture_name)
@photo.caption = "cool story, bro"
@photo.save
Photo.first.caption.should == "cool story, bro"
@photo.save.should be_true
end
it 'should remove its reference in user profile if it is referred' do
@ -63,9 +62,9 @@ describe Photo do
@user.save
@user.person.save
User.first.profile.image_url.should == @photo.image.url(:thumb_medium)
@user.profile.image_url.should == @photo.image.url(:thumb_medium)
@photo.destroy
User.first.profile.image_url.should be nil
@user.reload.profile.image_url.should be nil
end
it 'should not use the imported filename as the url' do

View file

@ -6,8 +6,7 @@ require 'spec_helper'
describe Post do
before do
@user = Factory.create(:user, :email => "bob@aol.com")
@user.person.save
@user = Factory.create(:user)
end
describe 'xml' do

View file

@ -5,25 +5,40 @@
require 'spec_helper'
describe Profile do
before do
@person = Factory.build(:person)
end
describe 'requirements' do
it "should include a first name" do
@person.profile = Factory.build(:profile,:first_name => nil)
@person.profile.valid?.should be false
@person.profile.first_name = "Bob"
@person.profile.valid?.should be true
describe 'validation' do
describe "of first_name" do
it "requires first name" do
profile = Factory.build(:profile, :first_name => nil)
profile.should_not be_valid
profile.first_name = "Hortense"
profile.should be_valid
end
it "requires non-empty first name" do
profile = Factory.build(:profile, :first_name => " ")
profile.should_not be_valid
end
it "strips leading and trailing whitespace" do
profile = Factory.build(:profile, :first_name => " Shelly ")
profile.should be_valid
profile.first_name.should == "Shelly"
end
end
it "should include a last name" do
@person.profile = Factory.build(:profile, :last_name => nil)
@person.profile.valid?.should be false
@person.profile.last_name = "Smith"
@person.profile.valid?.should be true
describe "of last_name" do
it "requires a last name" do
profile = Factory.build(:profile, :last_name => nil)
profile.should_not be_valid
profile.last_name = "Shankar"
profile.should be_valid
end
it "requires non-empty last name" do
profile = Factory.build(:profile, :last_name => " ")
profile.should_not be_valid
end
it "strips leading and trailing whitespace" do
profile = Factory.build(:profile, :last_name => " Ohba ")
profile.should be_valid
profile.last_name.should == "Ohba"
end
end
end
end

View file

@ -6,7 +6,7 @@ require 'spec_helper'
describe StatusMessage do
before do
@user = Factory.create(:user, :email => "bob@aol.com")
@user = Factory.create(:user)
@aspect = @user.aspect(:name => "losers")
end

View file

@ -8,6 +8,8 @@ describe User do
let(:user) { Factory(:user) }
let(:aspect) { user.aspect(:name => 'heroes') }
let(:bad_user) { Factory(:user)}
let(:user2) { Factory(:user) }
let(:aspect2) { user2.aspect(:name => 'losers') }
@ -21,7 +23,7 @@ describe User do
end
context 'non-friend valid user' do
it 'raises if receives post by non-friend' do
post_from_non_friend = bad_user.build_post( :status_message, :message => 'hi')
xml = bad_user.salmon(post_from_non_friend).xml_for(user.person)
@ -40,7 +42,7 @@ describe User do
end
context 'malicious friend attack vector' do
it 'overwrites messages with a different user' do
it 'overwrites messages with a different user' do
original_message = user2.post :status_message, :message => 'store this!', :to => aspect2.id
user.receive_salmon(user2.salmon(original_message).xml_for(user.person))
@ -52,8 +54,8 @@ describe User do
user.raw_visible_posts.count.should be 1
user.raw_visible_posts.first.message.should == "store this!"
end
it 'overwrites messages which apear to be from the same user' do
it 'overwrites messages which apear to be from the same user' do
original_message = user2.post :status_message, :message => 'store this!', :to => aspect2.id
user.receive_salmon(user2.salmon(original_message).xml_for(user.person))
user.raw_visible_posts.count.should be 1
@ -76,12 +78,12 @@ describe User do
user2.reload
user2.profile.first_name.should == "Robert"
end
it 'should not overwrite another persons profile through comment' do
pending
user_status = user.post(:status_message, :message => "hi", :to => 'all')
comment = Comment.new(:person_id => user3.person.id, :text => "hey", :post => user_status)
comment.creator_signature = comment.sign_with_key(user3.encryption_key)
comment.post_creator_signature = comment.sign_with_key(user.encryption_key)
@ -89,14 +91,14 @@ describe User do
original_url = person.url
original_id = person.id
puts original_url
comment.person.url = "http://bad.com/"
user3.delete
person.delete
comment.to_diaspora_xml.include?("bad.com").should be true
user2.receive_salmon(user.salmon(comment).xml_for(user2.person))
comment.person.url.should == original_url
Person.first(:id => original_id).url.should == original_url
end

View file

@ -22,16 +22,13 @@ describe User do
it 'should be able to parse and store a status message from xml' do
status_message = user2.post :status_message, :message => 'store this!', :to => aspect2.id
person = user2.person
xml = status_message.to_diaspora_xml
user2.destroy
status_message.destroy
StatusMessage.all.size.should == 0
user.receive xml , user2.person
Post.all(:person_id => person.id).first.message.should == 'store this!'
StatusMessage.all.size.should == 1
user
lambda {user.receive xml , user2.person}.should change (Post,:count).by(1)
end
it 'should not create new aspects on message receive' do
@ -47,96 +44,52 @@ describe User do
end
describe 'post refs' do
it "should add a received post to the aspect and visible_posts array" do
status_message = user.post :status_message, :message => "hi", :to =>aspect.id
before do
@status_message = user2.post :status_message, :message => "hi", :to =>aspect2.id
user.receive @status_message.to_diaspora_xml, user2.person
user.reload
salmon = user.salmon(status_message).xml_for user2.person
user2.receive_salmon salmon
user2.reload
user2.raw_visible_posts.include?(status_message).should be true
aspect2.reload
aspect2.posts.include?(status_message).should be_true
end
it "should add a received post to the aspect and visible_posts array" do
user.raw_visible_posts.include?(@status_message).should be true
aspect.reload
aspect.posts.include?(@status_message).should be_true
end
it 'should be removed on unfriending' do
status_message = user2.post :status_message, :message => "hi", :to => aspect2.id
user.receive status_message.to_diaspora_xml, user2.person
user.reload
user.raw_visible_posts.count.should == 1
user.unfriend(user2.person)
user.reload
user.raw_visible_posts.count.should == 0
Post.count.should be 1
end
it 'should be remove a post if the noone links to it' do
status_message = user2.post :status_message, :message => "hi", :to => aspect2.id
user.receive status_message.to_diaspora_xml, user2.person
user.reload
user.raw_visible_posts.count.should == 1
person = user2.person
user2.delete
user.unfriend(person)
lambda {user.unfriend(person)}.should change(Post, :count).by(-1)
user.reload
user.raw_visible_posts.count.should == 0
Post.count.should be 0
end
it 'should keep track of user references for one person ' do
status_message = user2.post :status_message, :message => "hi", :to => aspect2.id
user.receive status_message.to_diaspora_xml, user2.person
user.reload
user.raw_visible_posts.count.should == 1
status_message.reload
status_message.user_refs.should == 1
@status_message.reload
@status_message.user_refs.should == 1
user.unfriend(user2.person)
status_message.reload
user.reload
user.raw_visible_posts.count.should == 0
status_message.reload
status_message.user_refs.should == 0
Post.count.should be 1
@status_message.reload
@status_message.user_refs.should == 0
end
it 'should not override userrefs on receive by another person' do
user3.activate_friend(user2.person, aspect3)
user3.receive @status_message.to_diaspora_xml, user2.person
status_message = user2.post :status_message, :message => "hi", :to => aspect2.id
user.receive status_message.to_diaspora_xml, user2.person
user3.receive status_message.to_diaspora_xml, user2.person
user.reload
user3.reload
user.raw_visible_posts.count.should == 1
status_message.reload
status_message.user_refs.should == 2
@status_message.reload
@status_message.user_refs.should == 2
user.unfriend(user2.person)
status_message.reload
user.reload
user.raw_visible_posts.count.should == 0
status_message.reload
status_message.user_refs.should == 1
Post.count.should be 1
@status_message.reload
@status_message.user_refs.should == 1
end
end

View file

@ -28,10 +28,9 @@ describe User do
it "should be able to accept a pending friend request" do
r = Request.instantiate(:to => user.receive_url, :from => friend)
r.save
Person.all.count.should == 2
Request.for_user(user).all.count.should == 1
user.accept_friend_request(r.id, aspect.id)
Request.for_user(user).all.count.should == 0
proc {user.accept_friend_request(r.id, aspect.id)}.should change{
Request.for_user(user).all.count}.by(-1)
end
it 'should be able to ignore a pending friend request' do
@ -39,12 +38,8 @@ describe User do
r = Request.instantiate(:to => user.receive_url, :from => friend)
r.save
Person.count.should == 2
user.ignore_friend_request(r.id)
Person.count.should == 2
Request.count.should == 0
proc{user.ignore_friend_request(r.id)}.should change{
Request.for_user(user).count}.by(-1)
end
it 'should not be able to friend request an existing friend' do
@ -80,59 +75,53 @@ describe User do
@request_three.destroy
end
it 'should befriend the user other user on the same pod' do
user2.receive @req_three_xml, user.person
user2.pending_requests.size.should be 1
user2.accept_friend_request @request_three.id, aspect2.id
user2.friends.include?(user.person).should be true
Person.all.count.should be 3
context 'request from one remote person to one local user' do
before do
user2.receive @req_three_xml, user.person
end
it 'should befriend the user other user on the same pod' do
proc{
user2.accept_friend_request @request_three.id, aspect2.id
}.should_not change(Person, :count)
user2.friends.include?(user.person).should be true
end
it 'should not delete the ignored user on the same pod' do
proc{
user2.ignore_friend_request @request_three.id
}.should_not change(Person, :count)
user2.friends.include?(user.person).should be false
end
end
context 'Two users receiving requests from one person' do
before do
user.receive @req_xml, person_one
it 'should not delete the ignored user on the same pod' do
user2.receive @req_three_xml, user.person
user2.pending_requests.size.should be 1
user2.ignore_friend_request @request_three.id
user2.friends.include?(user.person).should be false
Person.all.count.should be 3
end
user2.receive @req_two_xml, person_one
end
it 'should both users should befriend the same person' do
user.accept_friend_request @request.id, aspect.id
user.friends.include?(person_one).should be true
it 'should both users should befriend the same person' do
user.receive @req_xml, person_one
user.pending_requests.size.should be 1
user.accept_friend_request @request.id, aspect.id
user.friends.include?(person_one).should be true
user2.accept_friend_request @request_two.id, aspect2.id
user2.friends.include?(person_one).should be true
end
user2.receive @req_two_xml, person_one
user2.pending_requests.size.should be 1
user2.accept_friend_request @request_two.id, aspect2.id
user2.friends.include?(person_one).should be true
Person.all.count.should be 3
end
it 'should keep the person around if one of the users rejects him' do
user.accept_friend_request @request.id, aspect.id
user.friends.include?(person_one).should be true
it 'should keep the person around if one of the users rejects him' do
user.receive @req_xml, person_one
user.pending_requests.size.should be 1
user.accept_friend_request @request.id, aspect.id
user.friends.include?(person_one).should be true
user2.ignore_friend_request @request_two.id
user2.friends.include?(person_one).should be false
end
user2.receive @req_two_xml, person_one
user2.pending_requests.size.should be 1
user2.ignore_friend_request @request_two.id
user2.friends.include?(person_one).should be false
Person.all.count.should be 3
end
it 'should keep the person around if the users ignores them' do
user.ignore_friend_request user.pending_requests.first.id
user.friends.include?(person_one).should be false
it 'should keep the person around if the users ignores them' do
user.receive @req_xml, person_one
user.pending_requests.size.should be 1
user.ignore_friend_request user.pending_requests.first.id
user.friends.include?(person_one).should be false
user2.receive @req_two_xml, person_one
user2.pending_requests.size.should be 1
user2.ignore_friend_request user2.pending_requests.first.id #@request_two.id
user2.friends.include?(person_one).should be false
Person.all.count.should be 3
user2.ignore_friend_request user2.pending_requests.first.id #@request_two.id
user2.friends.include?(person_one).should be false
end
end
end
@ -171,24 +160,20 @@ describe User do
describe 'unfriending' do
before do
friend_users(user,aspect, user2, aspect2)
user.reload
user2.reload
end
it 'should unfriend the other user on the same seed' do
user.friends.count.should == 1
user2.friends.count.should == 1
user2.unfriend user.person
user2.reload
user2.friends.count.should == 0
user.unfriended_by user2.person
aspect.reload.people.count.should == 0
lambda {user2.unfriend user.person}.should change{
user2.friends.count}.by(-1)
aspect2.reload.people.count.should == 0
end
it 'is unfriended by another user' do
lambda {user.unfriended_by user2.person}.should change{
user.friends.count}.by(-1)
aspect.reload.people.count.should == 0
end
context 'with a post' do
before do
@message = user.post(:status_message, :message => "hi", :to => aspect.id)

View file

@ -13,6 +13,20 @@ describe User do
let(:aspect3) { user3.aspect(:name => 'stuff') }
describe "validation" do
describe "of associated person" do
it "fails if person is not valid" do
user = Factory.build(:user)
user.should be_valid
user.person.update_attribute(:serialized_public_key, nil)
user.person.should_not be_valid
user.should_not be_valid
user.errors.full_messages.count.should == 1
user.errors.full_messages.first.should =~ /serialized public key/i
end
end
describe "of passwords" do
it "fails if password doesn't match confirmation" do
user = Factory.build(:user, :password => "password", :password_confirmation => "nope")
@ -72,6 +86,48 @@ describe User do
end
end
describe ".build" do
context 'with valid params' do
before do
params = {:username => "ohai",
:email => "ohai@example.com",
:password => "password",
:password_confirmation => "password",
:person =>
{:profile =>
{:first_name => "O",
:last_name => "Hai"}
}
}
@user = User.build(params)
end
it "makes a valid user" do
@user.should be_valid
User.find_by_username("ohai").should be_nil
end
it 'saves successfully' do
@user.save.should be_true
User.find_by_username("ohai").should == @user
end
end
describe "with invalid params" do
before do
@invalid_params = {
:username => "ohai",
:email => "ohai@example.com",
:password => "password",
:password_confirmation => "password",
:person => {:profile => {:first_name => "", :last_name => ""}}}
end
it "raises no error" do
lambda { User.build(@invalid_params) }.should_not raise_error
end
it "does not save" do
User.build(@invalid_params).save.should be_false
end
end
end
describe ".find_for_authentication" do
it "preserves case" do
User.find_for_authentication(:username => user.username).should == user
@ -98,7 +154,6 @@ describe User do
end
context 'aspects' do
it 'should delete an empty aspect' do
user.drop_aspect(aspect)
user.aspects.include?(aspect).should == false
@ -128,7 +183,6 @@ describe User do
user.destroy
end
it 'should remove all aspects' do
aspects = user.aspects
aspects.count.should > 0
@ -137,7 +191,6 @@ describe User do
aspects.count.should == 0
end
describe '#remove_person' do
it 'should remove the person object' do
person = user.person
@ -155,7 +208,6 @@ describe User do
end
describe '#unfriend_everyone' do
before do
user3.delete
end
@ -173,5 +225,4 @@ describe User do
end
end
end
end

View file

@ -26,18 +26,11 @@ RSpec.configure do |config|
DatabaseCleaner.orm = "mongo_mapper"
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
stub_signature_verification
end
config.before(:each) do
DatabaseCleaner.start
stub_sockets
User.stub!(:allowed_email?).and_return(:true)
end
config.after(:each) do
DatabaseCleaner.clean
end
end