Merge remote branch 'upstream/master'

This commit is contained in:
Alec Leamas 2010-10-23 05:14:10 +02:00
commit 1a49f3fb7d
50 changed files with 917 additions and 524 deletions

View file

@ -57,11 +57,15 @@ module ApplicationHelper
end
def person_image_tag(person)
image_tag image_or_default(person), :class => "avatar", :alt => person.real_name, :title => person.real_name, "data-person_id" => person.id
end
def image_or_default(person)
image_location = person.profile.image_url
image_location ||= "/images/user/default.png"
image_tag image_location, :class => "avatar", :alt => person.real_name, :title => person.real_name, "data-person_id" => person.id
image_location
end
def person_image_link(person)
link_to person_image_tag(person), object_path(person)

22
app/mailers/notifier.rb Normal file
View file

@ -0,0 +1,22 @@
class Notifier < ActionMailer::Base
default :from => "no-reply@joindiaspora.com"
ATTACHMENT = File.read("#{Rails.root}/public/images/diaspora_caps.png")
def new_request(recipient, sender)
@receiver = recipient
@sender = sender
attachments["diaspora_white.png"] = ATTACHMENT
mail(:to => "#{recipient.real_name} <#{recipient.email}>",
:subject => "new Diaspora* friend request from #{@sender.real_name}", :host => APP_CONFIG[:terse_pod_url])
end
def request_accepted(recipient, sender, aspect)
@receiver = recipient
@sender = sender
@aspect = aspect
attachments["diaspora_white.png"] = ATTACHMENT
mail(:to => "#{recipient.real_name} <#{recipient.email}>",
:subject => "#{@sender.real_name} has accepted your friend request on Diaspora*", :host => APP_CONFIG[:terse_pod_url])
end
end

View file

@ -97,9 +97,9 @@ class Person
# 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
query = /\A^#{Regexp.escape(identifier.gsub('acct:', '').to_s)}\z/i
local_person = Person.first(:diaspora_handle => query)
if local_person
Rails.logger.info("Do not need to webfinger, found a local person #{local_person.real_name}")
local_person

View file

@ -3,7 +3,8 @@
# the COPYRIGHT file.
class StatusMessage < Post
validates_length_of :message, :maximum => 1000, :message => "please make your status messages less than 1000 characters"
xml_name :status_message
xml_accessor :message

View file

@ -43,8 +43,7 @@ class User
before_validation :strip_username, :on => :create
validates_presence_of :username
validates_uniqueness_of :username, :case_sensitive => false
validates_format_of :username, :without => /\s/
validates_format_of :username, :with => /\A[A-Za-z0-9_.]+\z/
validates_with InvitedUserValidator
one :person, :class_name => 'Person', :foreign_key => :owner_id

View file

@ -2,14 +2,11 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
.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 |album|
= album.error_messages
%p
= album.label :name
= album.hidden_field :to, :value => aspect
= album.text_field :name
= album.submit t('.create'), :class => 'button'

View file

@ -8,22 +8,11 @@
$("#add_album_button").fancybox();
});
%h2
= @aspect
.friend_pictures.horizontal
= owner_image_link
- for friend in @friends
= person_image_link(friend)
.span-4.append-1.last
= render "shared/aspect_friends"
.span-24.last
%h3
= @aspect
Albums
= link_to t('.new_album'), '#new_album_pane', {:class => "button", :id => "add_album_button"}
.fancybox_content
#new_album_pane
= render "albums/new_album", :aspect => params[:aspect]
.span-15.last
= render "shared/publisher", :type => :album, :aspect => @aspect.id
%div
- for album in @albums

View file

@ -9,15 +9,12 @@
});
});
%h2
= @aspect
.friend_pictures.horizontal
= owner_image_link
- for friend in @friends
= person_image_link(friend)
%h3
= link_to "#{@aspect} Albums", albums_path(:aspect => @aspect)
= render 'shared/author_info', :post => @album
%ul#breadcrumb
%li= link_to "#{@album.person.profile.first_name}'s Photos", '#'
%li= @album.name
.span-19.appends-1.last

View file

@ -7,7 +7,7 @@
.span-15.last
= render 'aspects/no_friends_message'
= render 'shared/publisher'
= render 'shared/publisher', :type => :status_message, :aspect => @aspect
= render 'aspects/no_posts_message'
%ul#stream
- for post in @posts

View file

@ -10,7 +10,7 @@
%h2
Manage aspects
.right
= link_to(t('.add_a_new_aspect'), "#add_aspect_pane", :class => "new_aspect add_aspect_button button", :title => t('.add_a_new_aspect'))
= link_to("+ #{t('.add_a_new_aspect')}", "#add_aspect_pane", :class => "new_aspect add_aspect_button button", :title => t('.add_a_new_aspect'))
.span-4.append-1.last
%h3=t('.requests')
@ -18,54 +18,50 @@
.requests
%ul.dropzone
- if @remote_requests.size < 1
%li.grey No new requests
%li No new requests
- else
- for request in @remote_requests
%li.requested_person{:id => request.person.id, :request_id => request.id}
%li.person.request{:data=>{:guid=>request.id, :person_id=>request.person.id}}
= person_image_tag(request.person)
.name
= request.person.real_name
%h3 Remove from Aspect
.aspect_remove
%ul.dropzone
%li.grey Drag to remove person from aspect
%h3=t('.ignore_remove')
.remove
%ul.dropzone
%li.grey Drag to ignore/remove
.draggable_info
Drag to remove person from aspect
= render 'shared/invitations', :invites => @invites
.span-19.last
%ul#aspect_list
- for aspect in @aspects
%li.aspect
%li.aspect{:data=>{:guid=>aspect.id}}
.aspect_name
%span.edit_name_field
%h3{:contenteditable => true}= aspect.name
%h3{:contenteditable=>true}
= aspect.name
%span.tip click to edit
%ul.tools
%li= link_to t('.add_a_new_friend'), "#add_request_pane_#{aspect.id}", :class => 'add_request_button'
%li!= remove_link(aspect)
%ul.dropzone{:id => aspect.id}
%ul.dropzone{:data=>{:aspect_id=>aspect.id}}
-for person in aspect.people
%li.person{:data=>{:guid=>person.id, :aspect_id=>aspect.id}}
.delete
.x
X
.circle
= person_image_tag(person)
.draggable_info
Drag to add people
-if aspect.people.size < 1
%li.grey Drag to add people
-else
-for person in aspect.people
%li.person{:id => person.id, :class => person.id, :from_aspect_id => aspect.id}
= person_image_tag(person)
.name
= link_to person.real_name, person
.fancybox_content
%div{:id => "add_request_pane_#{aspect.id}"}
= render "requests/new_request", :aspect => aspect

View file

@ -7,7 +7,7 @@
.span-15.last
= render 'aspects/no_friends_message'
= render 'shared/publisher'
= render 'shared/publisher', :type => :status_message, :aspect => @aspect
= render 'aspects/no_posts_message'
%ul#stream
- for post in @posts

View file

@ -0,0 +1,59 @@
!!!
%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 'diaspora_white.png'
#container
%p
Hello #{@receiver.profile.first_name}!
%p
= "#{@sender.real_name} (#{@sender.diaspora_handle})"
just sent you a friend request on Diaspora*
You should really think about checking it out.
%br
= link_to "sign in here", new_user_session_url
%br
love,
%br
the diaspora email robot

View file

@ -0,0 +1,9 @@
= "hey #{@receiver.profile.first_name},"
= "#{@sender.real_name} (#{@sender.diaspora_handle})"
just sent you a friend request on Diaspora*
You should really think about checking it out.
= "sign in here: #{new_user_session_url}"
love,
the diaspora email robot

View file

@ -0,0 +1,59 @@
!!!
%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 'diaspora_white.png'
#container
%p
Hello #{@receiver.profile.first_name}!
%p
= "#{@sender.real_name} (#{@sender.diaspora_handle})"
has accepted your friend request. They are now in your
= link_to @aspect.name, aspect_url(@aspect)
aspect.
%br
love,
%br
the diaspora email robot

View file

@ -0,0 +1,9 @@
= "hey #{@receiver.profile.first_name},"
= "#{@sender.real_name} (#{@sender.diaspora_handle})"
has accepted your friend request. They are now in your
= "#{@aspect.name} asepct.\n"
= "#{aspect_url(@aspect)}"
love, \n
the diaspora email robot

View file

@ -55,15 +55,12 @@
});//end document ready
%h2
= @aspect
.friend_pictures.horizontal
= owner_image_link
- for friend in @friends
= person_image_link(friend)
= render 'shared/author_info', :post => @photo
%h3
= link_to @photo.album.name, @photo.album
%ul#breadcrumb
%li= link_to "#{@album.person.profile.first_name}'s Photos", '#'
%li= link_to @album.name, album_path(@album)
%li= @photo.caption
= link_to "<< #{t('.prev')}", url_to_prev(@photo, @album), :rel => 'prefetch'
|

View file

@ -36,13 +36,9 @@
<dl class="entity_photo">
<dt>Photo</dt>
<dd>
<img class="photo avatar" src="<%= @person.profile.image_url%>" width="100" height="100"/>
<img class="photo avatar" src="<%= image_or_default(@person)%>" width="100" height="100"/>
</dd>
</dl>
<dl class="entity_note">
<dt>Note</dt>
<dd class="note">Diaspora is awesome! vi is better than emacs!</dd>
</dl>
</div>
</div>
</div>

View file

@ -0,0 +1,15 @@
#author_info
= owner_image_link
.from
%h2
= post.person.real_name
.aspect
%ul
- if post.public?
the world
- else
- for aspect in current_user.aspects_with_post( post.id )
%li= link_to aspect.name, aspect
= link_to "view profile", person_path(post.person)

View file

@ -9,7 +9,7 @@
};
});
$("#publisher textarea").live("focus", function(evt){
$("#publisher textarea, #publisher input").live("focus", function(evt){
$("#publisher .options_and_submit").fadeIn(50);
});
@ -20,28 +20,41 @@
#publisher
= owner_image_tag
= form_for StatusMessage.new, :remote => true do |status|
= status.error_messages
%p
= status.label :message, "Post a message to #{@aspect}"
= status.text_area :message, :rows => 2, :value => params[:prefill]
- if( !defined?(type) || type == :status_message )
= form_for StatusMessage.new, :remote => true do |status|
= status.error_messages
%p
= status.label :message, "Post a message to #{aspect}"
= status.text_area :message, :rows => 2, :value => params[:prefill]
= status.hidden_field :to, :value => (@aspect == :all ? @aspect : @aspect.id)
= status.hidden_field :to, :value => (aspect == :all ? aspect : aspect.id)
.options_and_submit
- if @aspect == :all
.public_toggle
= status.check_box( :public, :value => false )
make public
= link_to '(?)', "#question_mark_pane", :class => 'question_mark'
.options_and_submit
- if aspect == :all
.public_toggle
= status.check_box( :public, :value => false )
make public
= link_to '(?)', "#question_mark_pane", :class => 'question_mark'
.fancybox_content
#question_mark_pane
= render 'shared/public_explain'
.fancybox_content
#question_mark_pane
= render 'shared/public_explain'
- if @aspect == :all
= status.submit t('.share'), :title => "Share with all aspects"
- else
= status.submit t('.share'), :title => "Share with #{@aspect}"
- if aspect == :all
= status.submit t('.share'), :title => "Share with all aspects"
- else
= status.submit t('.share'), :title => "Share with #{aspect}"
- else
= form_for Album.new do |album|
= album.error_messages
%p
= album.label :name
= album.text_field :name
= album.hidden_field :to, :value => aspect
.options_and_submit
= album.submit "Create", :class => 'button'

View file

@ -1,20 +0,0 @@
#aspect_header
.container
.span-4.last
- if @person
%h2
= @person.real_name
- else
%h2
- if @aspect == :all
= link_to "Everyone", root_path
- elsif @aspect == :manage
= link_to t('.manage_aspects'), root_path
- else
= link_to @aspect.name, @aspect
.page_title
= yield :page_title
.span-15.last{ :style => "position:relative;" }
= yield :publish

View file

@ -3,17 +3,11 @@
-# the COPYRIGHT file.
%h2
= @aspect
.friend_pictures.horizontal
- for friend in @friends
= person_image_link(friend)
= render 'shared/author_info', :post => @status_message
.span-14.append-1.last
#stream
%h1.show_text
= person_image_link(@status_message.person)
= link_to @status_message.person.real_name, @status_message.person
= make_links(@status_message.message)
= "Posted #{how_long_ago(@status_message)} to"

View file

@ -3,15 +3,17 @@
# the COPYRIGHT file.
Diaspora::Application.configure do
config.action_mailer.delivery_method = :smtp
config.action_mailer.default_url_options = {:host => APP_CONFIG[:terse_pod_url]}
config.action_mailer.smtp_settings = {
:address => APP_CONFIG[:smtp_address],
:port => APP_CONFIG[:smtp_port],
:domain => APP_CONFIG[:smtp_domain],
:authentication => APP_CONFIG[:smtp_authentication],
:user_name => APP_CONFIG[:smtp_username],
:password => APP_CONFIG[:smtp_password],
:enable_starttls_auto => true
}
unless Rails.env == 'test'
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => APP_CONFIG[:smtp_address],
:port => APP_CONFIG[:smtp_port],
:domain => APP_CONFIG[:smtp_domain],
:authentication => APP_CONFIG[:smtp_authentication],
:user_name => APP_CONFIG[:smtp_username],
:password => APP_CONFIG[:smtp_password],
:enable_starttls_auto => true
}
end
end

View file

@ -0,0 +1,2 @@
# if you wish to intercept emails to go to a particuar email address
#ActionMailer::Base.register_interceptor(DevelopmentMailInterceptor) if Rails.env.development?

View file

@ -13,7 +13,8 @@ def create
#set pod url
username = backer_info[backer_number]['username'].gsub(/ /,'').downcase
set_app_config username
set_app_config username unless File.exists?(Rails.root.join('config', 'app_config.yml'))
require File.join(File.dirname(__FILE__), "..", "..", "config", "initializers", "_load_app_config.rb")
# Create seed user

View file

@ -15,7 +15,9 @@ def set_app_config username
end
username = "tom"
set_app_config username
set_app_config username unless File.exists?(Rails.root.join('config', 'app_config.yml'))
require Rails.root.join('config', "initializers", "_load_app_config.rb")
# Create seed user
user = User.build( :email => "tom@tom.joindiaspora.com",

View file

@ -14,7 +14,8 @@ def set_app_config username
file.close
end
set_app_config "tom"
set_app_config "tom" unless File.exists?(Rails.root.join('config', 'app_config.yml'))
require 'config/initializers/_load_app_config.rb'
# Create seed user

View file

@ -0,0 +1,7 @@
class DevelopmentMailInterceptor
def self.delivering_email(message)
message.subject = "[#{message.to}] #{message.subject}"
message.to = "email@joindiaspora.com"
end
end

View file

@ -63,19 +63,23 @@ module Diaspora
def receive_friend_request(friend_request)
Rails.logger.info("receiving friend request #{friend_request.to_json}")
#response from a friend request you sent
if request_from_me?(friend_request) && self.aspect_by_id(friend_request.aspect_id)
aspect = self.aspect_by_id(friend_request.aspect_id)
activate_friend(friend_request.person, aspect)
Rails.logger.info("#{self.real_name}'s friend request has been accepted")
friend_request.destroy
Notifier.request_accepted(self, friend_request.person, aspect).deliver
#this is a new friend request
else
self.pending_requests << friend_request
self.save
Rails.logger.info("#{self.real_name} has received a friend request")
friend_request.save
Notifier.new_request(self, friend_request.person).deliver
end
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -4,9 +4,9 @@
*/
function decrementRequestsCounter() {
var $new_requests = $(".new_requests"),
request_html = $new_requests.html(),
old_request_count = request_html.match(/\d+/);
var $new_requests = $(".new_requests");
var request_html = $new_requests.html();
var old_request_count = request_html.match(/\d+/);
if( old_request_count == 1 ) {
$new_requests.html(
@ -19,133 +19,142 @@ function decrementRequestsCounter() {
}
}
// Dragging person between aspects
$(function() {
// Multiple classes here won't work
$("ul .person").draggable({
revert: true
revert: true,
start: function(event,ui){
$(this).children("img").animate({'height':80, 'width':80, 'opacity':0.8},200);
$(".draggable_info").fadeIn(100);
},
stop: function(event,ui){
$(this).children("img").animate({'height':70, 'width':70, 'opacity':1},200);
$(".draggable_info").fadeOut(100);
}
});
$("ul .requested_person").draggable({
revert: true
});
$(".aspect ul").droppable({
$(".aspect ul.dropzone").droppable({
hoverClass: 'active',
drop: function(event, ui) {
if ($(ui.draggable[0]).hasClass('requested_person')){
var dropzone = $(this);
var person = ui.draggable;
if( person.hasClass('request') ){
$.ajax({
type: "DELETE",
url: "/requests/" + ui.draggable[0].getAttribute('request_id') ,
data: {"accept" : true , "aspect_id" : $(this)[0].id },
url: "/requests/" + person.attr('data-guid'),
data: {"accept" : true, "aspect_id" : dropzone.attr('data-aspect_id') },
success: function(data){
decrementRequestsCounter();
}
});
};
var dropzone = $(this)[0];
if ($(this)[0].id == ui.draggable[0].getAttribute('from_aspect_id')){
ui.draggable.css('background-color','#333');
} else {
ui.draggable.css('background-color','orange');
$.ajax({
url: "/aspects/move_friend/",
data: {"friend_id" : ui.draggable[0].id,
"from" : ui.draggable[0].getAttribute('from_aspect_id'),
"to" : { "to" : dropzone.id }},
success: function(data){
ui.draggable.attr('from_aspect_id', dropzone.id);
ui.draggable.css('background-color','#333');
}});
if( dropzone.attr('data-aspect_id') != person.attr('data-aspect_id' )){
$.ajax({
url: "/aspects/move_friend/",
data: {"friend_id" : person.attr('data-guid'),
"from" : person.attr('data-aspect_id'),
"to" : { "to" : dropzone.attr('data-aspect_id') }},
success: function(data){
person.attr('data-aspect_id', dropzone.attr('data-aspect_id'));
}});
}
$(this).closest("ul").append(ui.draggable);
$(this).closest("ul").append(person);
}
});
$(".remove ul").droppable({
hoverClass: 'active',
drop: function(event, ui) {
if ($(ui.draggable[0]).hasClass('requested_person')){
$.ajax({
type: "DELETE",
url: "/requests/" + ui.draggable.attr('request_id'),
success: function () {
decrementRequestsCounter();
}
});
} else {
$.ajax({
type: "DELETE",
url: "/people/" + ui.draggable.attr('id'),
success: function () {
alert("Removed Friend, proably want an undo countdown.")
}
});
}
$(ui.draggable[0]).fadeOut('slow');
$(ui.draggable[0]).remove();
}
});
$(".aspect_remove ul").droppable({
hoverClass: 'active',
drop: function(event, ui) {
if ($( "." + ui.draggable[0].id).length == 1) {
var person = ui.draggable;
if ( person.attr('data-guid').length == 1 ) {
alert("You can not remove the person from the last aspect");
} else {
if (!$(ui.draggable[0]).hasClass('requested_person')){
var aspect = ui.draggable[0].getAttribute('from_aspect_id')
var person_id = ui.draggable[0].id
if( !person.hasClass('request') ){
$.ajax({
type: "POST",
url: "/aspects/remove_from_aspect",
data:{
'friend_id' : person_id,
'aspect_id' : aspect
}
'friend_id' : person.attr('data-guid'),
'aspect_id' : person.attr('data-aspect_id') }
});
}
$(ui.draggable[0]).fadeOut('slow');
$(ui.draggable[0]).remove();
person.fadeOut('slow', $(this).remove());
}
}
});
$(".aspect h3").live( 'focus', function() {
});
var $this = $(this),
id = $this.closest("li").children("ul").attr("id"),
link = "/aspects/"+ id;
$this.keypress(function(e) {
if (e.which == 13) {
e.preventDefault();
$this.blur();
// Person deletion
$(".delete").live("click", function() {
//save changes
$.ajax({
type: "PUT",
url: link,
data: {"aspect" : {"name" : $this.text() }}
});
}
//update all other aspect links
$this.keyup(function(e) {
$("#aspect_nav a[href='"+link+"']").text($this.text());
var person = $(this).closest("li.person");
if (person.hasClass('request')){
if( confirm("Ignore request?") ){
var request_id = person.attr("data-guid");
$.ajax({
type: "DELETE",
url: "/requests/" + request_id,
success: function () {
decrementRequestsCounter();
}
});
}
} else {
if( confirm("Remove this person from all aspects?") ){
var person_id = $(this).closest("li.person").attr('data-guid');
$.ajax({
type: "DELETE",
url: "/people/" + person_id,
success: function() {
person.fadeOut(200);
}
});
}
}
});
// Editing aspect name
$(".aspect h3").live('focus', function() {
var $this = $(this);
var id = $this.closest("li.aspect").attr("data-guid");
var link = "/aspects/"+ id;
$this.keypress(function(e) {
if (e.which == 13) {
e.preventDefault();
$this.blur();
//save changes
$.ajax({
type: "PUT",
url: link,
data: {"aspect" : {"name" : $this.text() }}
});
}
//update all other aspect links
$this.keyup(function(e) {
$("#aspect_nav a[href='"+link+"']").text($this.text());
});
});
});

View file

@ -30,6 +30,7 @@ $(document).ready(function(){
$("#add_request_button").fancybox({ 'titleShow': false , 'hideOnOverlayClick' : false });
$(".invite_user_button").fancybox({ 'titleShow': false , 'hideOnOverlayClick' : false });
$(".add_request_button").fancybox({ 'titleShow': false , 'hideOnOverlayClick' : false });
$(".remove_person_button").fancybox({ 'titleShow': false , 'hideOnOverlayClick' : false });
$(".question_mark").fancybox({ 'titleShow': false , 'hideOnOverlayClick' : false });
$("input[type='submit']").addClass("button");

View file

@ -202,6 +202,71 @@ header
.avatar
:border-radius 5px
.from
:font
:family 'Helvetica neue', Arial, Helvetica, sans-serif
:text
:shadow 0 1px #fff
.aspect
:cursor default
:display inline
:color #bbb
:font
:size 85%
a
:font
:weight normal
:color #bbb
&:hover
:text
:decoration underline
&:active
:color #999
ul
:display inline
:margin 0
:padding 0
:list
:style none
li
:display inline
&:after
:content ","
&:last-child:after
:content ""
a
:font
:weight bold
#author_info
:position relative
:padding
:left 65px
:height 70px
img
:position absolute
:top 8px
:left 0
h2
:margin
:bottom -2px
a
:font
:weight normal
.from
:font
:size 14px
.avatar
:border-radius 5px
li.message
:position relative
:line-height 19px
@ -220,44 +285,6 @@ li.message
:padding
:left 65px
.from
:font
:family 'Helvetica neue', Arial, Helvetica, sans-serif
:text
:shadow 0 1px #fff
.aspect
:cursor default
:display inline
:color #bbb
:font
:size 12px
a
:font
:weight normal
:color #bbb
&:hover
:text
:decoration underline
&:active
:color #999
ul
:display inline
:margin 0
:padding 0
:list
:style none
li
:display inline
&:after
:content ","
&:last-child:after
:content ""
a
:font
:weight bold
:color #444
:font
@ -639,8 +666,11 @@ label
:position relative
textarea
:width 515px
:height 42px
input[type='text'],
textarea
:width 515px
:margin 0
.options_and_submit
@ -873,13 +903,7 @@ h1.big_text
:padding 2px
.aspect,
.requests,
.remove,
.aspect_remove
:list
:style none
.aspect
h3
:display inline-block
@ -914,63 +938,115 @@ h1.big_text
&:last-child
:margin
:right 0
.grey
:color #999
:cursor default
:text-shadow 0 1px #fff
.aspect,
.requests,
.aspect_remove
:list
:style none
:color #999
:cursor default
:text-shadow 0 1px #fff
ul.dropzone
:position relative
:min-height 20px
:margin 0
:bottom 25px
:background
:color #efefef
:border 1px solid #ccc
:-webkit-border-radius 10px
:-moz-border-radius 10px
:border-radius 10px
:list
:style none
:padding 15px
:border 2px dashed #ccc
&.active
:background
:color #fafafa
:color rgba(255,252,127,0.2)
.person,
.requested_person
.draggable_info
:position absolute
:display none
:right 15px
:bottom 10px
:font
:style italic
:size 14px
:color #aaa
.person
:display inline-block
:padding 5px
:cursor move
:margin 5px
:z-index 10
:position relative
:padding 0
:margin 5px
:width 110px
:background
:color #333
:border-radius 5px
:color #ccc
a
:color #ccc
:color #eee
img
:height 40px
:width 40px
:display inline
:height 70px
:width 70px
:border-radius 5px
:-webkit-box-shadow 0 1px 2px #999
.name
:display inline
:top 0
:margin
:left 5px
&:hover
.delete
:display inline
&:active
:z-index 20
:color #666
:-webkit-box-shadow 0 1px 3px #000
:-moz-box-shadow 0 2px 4px #000
:opacity 0.9
img
:-webkit-box-shadow 0 1px 3px #000
:-moz-box-shadow 0 2px 4px #000
.delete
:display none
.delete
:display none
:position absolute
:top -8px
:left -8px
.circle
:z-index 1
:position absolute
:background
:color #333
:width 20px
:max-width 20px
:height 20px
:max-height 20px
:border 1px solid #fff
:-webkit-border-radius 20px
:-moz-border-radius 20px
:border-radius 20px
:-webkit-box-shadow 0 1px 3px #000
.x
:z-index 2
:position absolute
:top 2px
:left 7px
&:hover
:cursor default
.circle
:background
:color rgba(208,49,43,1)
.requests
ul.dropzone
:border 2px solid #ccc
ul#settings_nav
:display inline
@ -1090,6 +1166,10 @@ header
h2
:display inline
.right
:margin
:top 10px
.modal_title_bar
:width 100%
@ -1136,3 +1216,27 @@ header
.controls
:display inline
ul#breadcrumb
:list
:style none
:margin 0
:padding 0
:font
:size 14px
:weight bold
:line
:height 3em
a
:font
:weight bold
> li
:display inline
&:after
:content ' '
&:last-child
&:after
:content ''

View file

@ -6,10 +6,10 @@ require 'spec_helper'
describe PublicsController do
render_views
let(:user) {Factory.create :user}
let(:user2){Factory.create :user}
let(:aspect1){user.aspect(:name => "foo")}
let(:aspect2){user2.aspect(:name => "far")}
let(:user) { Factory.create :user }
let(:user2) { Factory.create :user }
let(:aspect1) { user.aspect(:name => "foo") }
let(:aspect2) { user2.aspect(:name => "far") }
before do
sign_in :user, user
end
@ -23,7 +23,7 @@ describe PublicsController do
it 'should accept a post from another node and save the information' do
message = user2.build_post(:status_message, :message => "hi")
friend_users(user, aspect1, user2, aspect2)
user.reload
user.visible_post_ids.include?(message.id).should be false
@ -77,10 +77,13 @@ describe PublicsController do
end
describe 'friend requests' do
let(:aspect2) {user2.aspect(:name => 'disciples')}
let!(:req) {user2.send_friend_request_to(user.person, aspect2)}
let!(:xml) {user2.salmon(req).xml_for(user.person)}
let(:aspect2) { user2.aspect(:name => 'disciples') }
let!(:req) { user2.send_friend_request_to(user.person, aspect2) }
let!(:xml) { user2.salmon(req).xml_for(user.person) }
before do
deliverable = Object.new
deliverable.stub!(:deliver)
Notifier.stub!(:new_request).and_return(deliverable)
req.delete
user2.reload
user2.pending_requests.count.should be 1

View file

@ -8,14 +8,15 @@
#This inclsion, because gpg-agent(not needed) is never run and hence never sets any env. variables on a MAC
Factory.define :profile do |p|
p.first_name "Robert"
p.last_name "Grimm"
p.sequence(:first_name){|n| "Robert#{n}"}
p.sequence(:last_name){|n| "Grimm#{n}"}
end
Factory.define :person do |p|
p.sequence(:diaspora_handle) {|n| "bob-person-#{n}@aol.com"}
p.sequence(:url) {|n| "http://google-#{n}.com/"}
p.profile Factory.create(:profile)
p.profile Factory.create(:profile, :first_name => "eugene", :last_name => "weinstien")
p.serialized_public_key OpenSSL::PKey::RSA.generate(1024).public_key.export
end
@ -32,7 +33,7 @@ Factory.define :user do |u|
u.password_confirmation "bluepin7"
u.serialized_private_key OpenSSL::PKey::RSA.generate(1024).export
u.after_build do |user|
user.person = Factory.build(:person, :owner_id => user._id,
user.person = Factory.build(:person, :profile => Factory.create(:profile), :owner_id => user._id,
:serialized_public_key => user.encryption_key.public_key.export,
:diaspora_handle => "#{user.username}@#{APP_CONFIG[:pod_url].gsub(/(https?:|www\.)\/\//, '').chop!}")
end

View file

@ -5,15 +5,15 @@
require 'spec_helper'
describe Diaspora::Parser do
let(:user) {Factory.create(:user)}
let(:aspect) {user.aspect(:name => 'spies')}
let(:user2) {Factory.create(:user)}
let(:aspect2){user2.aspect(:name => "pandas")}
let(:user3) {Factory.create :user}
let(:person) {user3.person}
let(:user) { Factory.create(:user) }
let(:aspect) { user.aspect(:name => 'spies') }
let(:user2) { Factory.create(:user) }
let(:aspect2) { user2.aspect(:name => "pandas") }
let(:user3) { Factory.create :user }
let(:person) { user3.person }
describe "parsing compliant XML object" do
it 'should be able to correctly handle comments with person in db' do
it 'should be able to correctly handle comments with person in db' do
post = user.post :status_message, :message => "hello", :to => aspect.id
comment = Factory.build(:comment, :post => post, :person => @person, :text => "Freedom!")
xml = comment.to_diaspora_xml
@ -25,7 +25,7 @@ describe Diaspora::Parser do
end
it 'should be able to correctly handle person on a comment with person not in db' do
friend_users(user, aspect, user2, aspect2)
friend_users(user, aspect, user2, aspect2)
post = user.post :status_message, :message => "hello", :to => aspect.id
comment = user2.comment "Fool!", :on => post
@ -40,42 +40,50 @@ describe Diaspora::Parser do
end
it 'should accept retractions' do
friend_users(user, aspect, user2, aspect2)
friend_users(user, aspect, user2, aspect2)
message = Factory.create(:status_message, :person => user2.person)
retraction = Retraction.for(message)
xml = retraction.to_diaspora_xml
proc {user.receive xml, user2.person}.should change(StatusMessage, :count).by(-1)
proc { user.receive xml, user2.person }.should change(StatusMessage, :count).by(-1)
end
it "should create a new person upon getting a person request" do
request = Request.instantiate(:to =>"http://www.google.com/", :from => person)
context "friending" do
before do
deliverable = Object.new
deliverable.stub!(:deliver)
Notifier.stub!(:new_request).and_return(deliverable)
end
xml = request.to_diaspora_xml
it "should create a new person upon getting a person request" do
request = Request.instantiate(:to =>"http://www.google.com/", :from => person)
user3.destroy
person.destroy
user
lambda {user.receive xml, person}.should change(Person, :count).by(1)
end
xml = request.to_diaspora_xml
it "should not create a new person if the person is already here" do
request = Request.instantiate(:to =>"http://www.google.com/", :from => user2.person)
original_person_id = user2.person.id
xml = request.to_diaspora_xml
user
lambda {user.receive xml, user2.person}.should_not change(Person, :count)
user3.destroy
person.destroy
user
lambda { user.receive xml, person }.should change(Person, :count).by(1)
end
user2.reload
user2.person.reload
user2.serialized_private_key.include?("PRIVATE").should be true
it "should not create a new person if the person is already here" do
request = Request.instantiate(:to =>"http://www.google.com/", :from => user2.person)
original_person_id = user2.person.id
xml = request.to_diaspora_xml
user
lambda { user.receive xml, user2.person }.should_not change(Person, :count)
url = "http://" + request.callback_url.split("/")[2] + "/"
Person.where(:url => url).first.id.should == original_person_id
user2.reload
user2.person.reload
user2.serialized_private_key.include?("PRIVATE").should be true
url = "http://" + request.callback_url.split("/")[2] + "/"
Person.where(:url => url).first.id.should == original_person_id
end
end
it "should activate the Person if I initiated a request to that url" do
request = user.send_friend_request_to( user3.person, aspect)
request = user.send_friend_request_to(user3.person, aspect)
user.reload
request.reverse_for user3
@ -95,16 +103,16 @@ describe Diaspora::Parser do
end
it 'should process retraction for a person' do
friend_users(user, aspect, user2, aspect2)
friend_users(user, aspect, user2, aspect2)
retraction = Retraction.for(user2)
retraction_xml = retraction.to_diaspora_xml
lambda {user.receive retraction_xml, user2.person}.should change{
aspect.reload.people.size}.by(-1)
lambda { user.receive retraction_xml, user2.person }.should change {
aspect.reload.people.size }.by(-1)
end
it 'should marshal a profile for a person' do
friend_users(user, aspect, user2, aspect2)
friend_users(user, aspect, user2, aspect2)
#Create person
person = user2.person
id = person.id
@ -132,9 +140,9 @@ describe Diaspora::Parser do
person = Person.first(:id => person.id)
person.profile.should_not be nil
person.profile.first_name.should == old_profile.first_name
person.profile.last_name.should == old_profile.last_name
person.profile.image_url.should == old_profile.image_url
end
person.profile.last_name.should == old_profile.last_name
person.profile.image_url.should == old_profile.image_url
end
end
end

View file

@ -0,0 +1,54 @@
# 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'
describe 'user encryption' do
before do
@user = Factory.create(:user)
@aspect = @user.aspect(:name => 'dudes')
end
describe 'key exchange on friending' do
it 'should receive and marshal a public key from a request' do
remote_user = Factory.build(:user)
remote_user.encryption_key.nil?.should== false
deliverable = Object.new
deliverable.stub!(:deliver)
Notifier.stub!(:new_request).and_return(deliverable)
Person.should_receive(:by_webfinger).and_return(remote_user.person)
#should move this to friend request, but i found it here
id = remote_user.person.id
original_key = remote_user.exported_key
request = remote_user.send_friend_request_to(
@user.person, remote_user.aspect(:name => "temp"))
xml = remote_user.salmon(request).xml_for(@user)
remote_user.person.delete
remote_user.delete
person_count = Person.all.count
@user.receive_salmon xml
Person.all.count.should == person_count + 1
new_person = Person.first(:id => id)
new_person.exported_key.should == original_key
end
end
describe 'encryption' do
before do
@string = File.open(File.dirname(__FILE__) + '/../fixtures/fb_status').read
end
it 'should encrypt a string' do
ciphertext = @user.encrypt @string
ciphertext.include?(@string).should be false
@user.decrypt(ciphertext).should == @string
end
end
end

View file

@ -0,0 +1,46 @@
require 'spec_helper'
describe Notifier do
let!(:user) {Factory.create :user}
let!(:aspect) {user.aspect(:name => "science")}
let!(:person) {Factory.create :person}
let!(:request_mail) {Notifier.new_request(user, person)}
let!(:request_accepted_mail) {Notifier.request_accepted(user, person, aspect)}
describe "#new_request" do
it 'goes to the right person' do
request_mail.to.should == [user.email]
end
it 'has the receivers name in the body' do
request_mail.body.encoded.include?(user.person.profile.first_name).should be true
end
it 'has the name of person sending the request' do
request_mail.body.encoded.include?(person.real_name).should be true
end
end
describe "#request_accpeted" do
it 'goes to the right person' do
request_accepted_mail.to.should == [user.email]
end
it 'has the receivers name in the body' do
request_accepted_mail.body.encoded.include?(user.person.profile.first_name).should be true
end
it 'has the name of person sending the request' do
request_accepted_mail.body.encoded.include?(person.real_name).should be true
end
it 'has the name of the aspect in the body' do
request_accepted_mail.body.encoded.include?(aspect.name).should be true
end
end
end

View file

@ -97,6 +97,10 @@ describe Comment do
user.receive comment.to_diaspora_xml, user2.person
end
context 'posts from a remote person' do
before(:all) do
stub_comment_signature_verification
end
it 'should not send a comment a person made on his own post to anyone' do
User::QUEUE.should_not_receive(:add_post_request)
comment = Comment.new(:person_id => @person.id, :text => "balls", :post => @person_status)
@ -108,6 +112,10 @@ describe Comment do
comment = Comment.new(:person_id => @person2.id, :text => "balls", :post => @person_status)
user.receive comment.to_diaspora_xml, @person
end
after(:all) do
unstub_mocha_stubs
end
end
it 'should not clear the aspect post array on receiving a comment' do
aspect.post_ids.include?(@user_status.id).should be true
@ -130,4 +138,50 @@ describe Comment do
comment.to_diaspora_xml.include?(commenter.person.id.to_s).should be true
end
end
describe 'comments' do
before do
friend_users(user, aspect, user2, aspect2)
@remote_message = user2.post :status_message, :message => "hello", :to => aspect2.id
@message = user.post :status_message, :message => "hi", :to => aspect.id
end
it 'should attach the creator signature if the user is commenting' do
user.comment "Yeah, it was great", :on => @remote_message
@remote_message.comments.first.signature_valid?.should be true
end
it 'should sign the comment if the user is the post creator' do
message = user.post :status_message, :message => "hi", :to => aspect.id
user.comment "Yeah, it was great", :on => message
message.comments.first.signature_valid?.should be true
message.comments.first.verify_post_creator_signature.should be true
end
it 'should verify a comment made on a remote post by a different friend' do
comment = Comment.new(:person => user2.person, :text => "cats", :post => @remote_message)
comment.creator_signature = comment.send(:sign_with_key,user2.encryption_key)
comment.signature_valid?.should be true
comment.verify_post_creator_signature.should be false
comment.post_creator_signature = comment.send(:sign_with_key,user.encryption_key)
comment.verify_post_creator_signature.should be true
end
it 'should reject comments on a remote post with only a creator sig' do
comment = Comment.new(:person => user2.person, :text => "cats", :post => @remote_message)
comment.creator_signature = comment.send(:sign_with_key,user2.encryption_key)
comment.signature_valid?.should be true
comment.verify_post_creator_signature.should be false
end
it 'should receive remote comments on a user post with a creator sig' do
comment = Comment.new(:person => user2.person, :text => "cats", :post => @message)
comment.creator_signature = comment.send(:sign_with_key,user2.encryption_key)
comment.signature_valid?.should be true
comment.verify_post_creator_signature.should be false
end
end
end

View file

@ -187,6 +187,25 @@ describe Person do
end
end
it 'should only find people who are exact matches' do
user = Factory(:user, :username => "SaMaNtHa")
person = Factory(:person, :diaspora_handle => "tomtom@tom.joindiaspora.com")
user.person.diaspora_handle = "tom@tom.joindiaspora.com"
user.person.save
Person.by_webfinger("tom@tom.joindiaspora.com").diaspora_handle.should == "tom@tom.joindiaspora.com"
end
it 'should return nil if there is not an exact match' do
Redfinger.stub!(:finger).and_return(nil)
person = Factory(:person, :diaspora_handle => "tomtom@tom.joindiaspora.com")
person1 = Factory(:person, :diaspora_handle => "tom@tom.joindiaspora.comm")
#Person.by_webfinger("tom@tom.joindiaspora.com").should_be false
proc{ Person.by_webfinger("tom@tom.joindiaspora.com")}.should raise_error
end
it 'identifier should be a valid email' do
stub_success("joe.valid+email@my-address.com")
Proc.new {

View file

@ -28,6 +28,7 @@ describe Request do
xml.should include user.person.url
xml.should include user.profile.first_name
xml.should include user.profile.last_name
xml.should include user.exported_key
end
it 'should allow me to see only friend requests sent to me' do
@ -56,6 +57,10 @@ describe Request do
end
it 'recognized when a request is not from me' do
deliverable = Object.new
deliverable.stub!(:deliver)
Notifier.stub!(:new_request).and_return(deliverable)
user2.receive_salmon(user.salmon(request).xml_for(user2.person))
user2.reload
user2.request_from_me?(request).should == false
@ -64,6 +69,10 @@ describe Request do
context 'quering request through user' do
it 'finds requests for that user' do
deliverable = Object.new
deliverable.stub!(:deliver)
Notifier.stub!(:new_request).and_return(deliverable)
user2.receive_salmon(user.salmon(request).xml_for(user2.person))
user2.reload
user2.requests_for_me.include?(request).should == true

View file

@ -21,6 +21,15 @@ describe StatusMessage do
status = @user.post(:status_message, :message => "Users do things", :to => @aspect.id)
end
it 'should require status messages to be less than 1000 characters' do
message = ''
1001.times do message = message +'1';end
status = Factory.build(:status_message, :message => message)
status.should_not be_valid
end
describe "XML" do
it 'should serialize to XML' do
message = Factory.create(:status_message, :message => "I hate WALRUSES!", :person => @user.person)

View file

@ -4,7 +4,7 @@
require 'spec_helper'
describe User do
describe "attack vectors" do
let(:user) { Factory(:user) }
let(:aspect) { user.aspect(:name => 'heroes') }
@ -73,10 +73,11 @@ describe User do
profile.first_name = "Not BOB"
user2.reload
user2.profile.first_name.should == "Robert"
first_name = user2.profile.first_name
proc{user.receive_salmon(user3.salmon(profile).xml_for(user.person))}.should raise_error /Malicious Post/
user2.reload
user2.profile.first_name.should == "Robert"
user2.profile.first_name.should == first_name
end
it 'should not overwrite another persons profile through comment' do

View file

@ -115,6 +115,7 @@ describe User do
comment_id = comment.id
comment.delete
comment.post_creator_signature = comment.sign_with_key(user.encryption_key)
user3.receive comment.to_diaspora_xml, user.person
user3.reload

View file

@ -1,20 +1,28 @@
# 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'
describe User do
let(:user) {Factory.create :user}
let(:aspect) {user.aspect(:name => 'heroes')}
let(:aspect1) {user.aspect(:name => 'other')}
describe Diaspora::UserModules::Friending do
let(:user) { Factory.create :user }
let(:aspect) { user.aspect(:name => 'heroes') }
let(:aspect1) { user.aspect(:name => 'other') }
let(:friend) { Factory.create(:person) }
let(:person_one) {Factory.create :person}
let(:person_two) {Factory.create :person}
let(:user2) { Factory.create :user}
let(:aspect2) { user2.aspect(:name => "aspect two")}
let(:person_one) { Factory.create :person }
let(:person_two) { Factory.create :person }
let(:user2) { Factory.create :user }
let(:aspect2) { user2.aspect(:name => "aspect two") }
before do
deliverable = Object.new
deliverable.stub!(:deliver)
Notifier.stub!(:new_request).and_return(deliverable)
Notifier.stub!(:request_accepted).and_return(deliverable)
end
context 'friend requesting' do
it "should assign a request to a aspect" do
@ -29,9 +37,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
proc {user.accept_friend_request(r.id, aspect.id)}.should change{
Request.for_user(user).all.count}.by(-1)
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,8 +47,8 @@ describe User do
r = Request.instantiate(:to => user.receive_url, :from => friend)
r.save
proc{user.ignore_friend_request(r.id)}.should change{
Request.for_user(user).count}.by(-1)
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
@ -54,6 +62,13 @@ describe User do
proc { user.send_friend_request_to(nil, aspect) }.should raise_error(RuntimeError, /befriend yourself/)
end
it 'should send an email on acceptance if a friend request' do
Notifier.should_receive(:request_accepted)
request = user.send_friend_request_to(user2.person, aspect)
request.reverse_for(user2)
user.receive_friend_request(request)
end
describe 'multiple users accepting/rejecting the same person' do
@ -81,40 +96,52 @@ describe User do
user2.receive @req_three_xml, user.person
end
it 'should befriend the user other user on the same pod' do
proc{
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{
proc {
user2.ignore_friend_request @request_three.id
}.should_not change(Person, :count)
user2.friends.include?(user.person).should be false
end
it 'sends an email to the receiving user' do
mail_obj = mock("mailer")
mail_obj.should_receive(:deliver)
Notifier.should_receive(:new_request).and_return(mail_obj)
user.receive @req_xml, person_one
end
end
context 'Two users receiving requests from one person' do
before do
user.receive @req_xml, person_one
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
user2.accept_friend_request @request_two.id, aspect2.id
user2.friends.include?(person_one).should be true
describe '#accept_friend_request' do
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
user2.accept_friend_request @request_two.id, aspect2.id
user2.friends.include?(person_one).should be true
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
user2.ignore_friend_request @request_two.id
user2.friends.include?(person_one).should be false
end
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
user2.ignore_friend_request @request_two.id
user2.friends.include?(person_one).should be false
end
it 'should keep the person around if the users ignores them' do
user.ignore_friend_request user.pending_requests.first.id
@ -124,6 +151,8 @@ describe User do
user2.friends.include?(person_one).should be false
end
end
end
describe 'a user accepting rejecting multiple people' do
@ -160,25 +189,25 @@ describe User do
describe 'unfriending' do
before do
friend_users(user,aspect, user2, aspect2)
friend_users(user, aspect, user2, aspect2)
end
it 'should unfriend the other user on the same seed' do
lambda {user2.unfriend user.person}.should change{
user2.friends.count}.by(-1)
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)
lambda { user.unfriended_by user2.person }.should change {
user.friends.count }.by(-1)
aspect.reload.people.count.should == 0
end
it 'should remove the friend from all aspects they are in' do
user.add_person_to_aspect(user2.person.id, aspect1.id)
lambda {user.unfriended_by user2.person}.should change{
user.friends.count}.by(-1)
lambda { user.unfriended_by user2.person }.should change {
user.friends.count }.by(-1)
aspect.reload.people.count.should == 0
aspect1.reload.people.count.should == 0
end
@ -186,9 +215,9 @@ describe User do
context 'with a post' do
before do
@message = user.post(:status_message, :message => "hi", :to => aspect.id)
user2.receive @message.to_diaspora_xml.to_s, user.person
user2.unfriend user.person
user.unfriended_by user2.person
user2.receive @message.to_diaspora_xml.to_s, user.person
user2.unfriend user.person
user.unfriended_by user2.person
end
it "deletes the unfriended user's posts from visible_posts" do
user.reload.raw_visible_posts.include?(@message.id).should be_false

View file

@ -10,6 +10,10 @@ describe User do
let(:user2) { Factory(:user) }
let(:aspect2) { user2.aspect(:name => 'stuff') }
it 'should have a key' do
user.encryption_key.should_not be nil
end
describe "validation" do
describe "of associated person" do
it "fails if person is not valid" do
@ -69,6 +73,11 @@ describe User do
user = Factory.build(:user, :username => "bobby tables")
user.should_not be_valid
end
it 'can not contain non url safe characters' do
user = Factory.build(:user, :username => "kittens;")
user.should_not be_valid
end
end
describe "of email" do

View file

@ -25,10 +25,6 @@ RSpec.configure do |config|
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.orm = "mongo_mapper"
config.before(:suite) do
stub_signature_verification
end
config.before(:each) do
stub_sockets
DatabaseCleaner.clean
@ -49,10 +45,8 @@ ImageUploader.enable_processing = false
Diaspora::WebSocket.unstub!(:unsubscribe)
end
def stub_signature_verification
(get_models.map{|model| model.camelize.constantize} - [User]).each do |model|
model.any_instance.stubs(:verify_signature).returns(true)
end
def stub_comment_signature_verification
Comment.any_instance.stubs(:verify_signature).returns(true)
end
def unstub_mocha_stubs
@ -82,11 +76,11 @@ ImageUploader.enable_processing = false
aspect2.reload
end
def stub_success(address = 'abc@example.com')
def stub_success(address = 'abc@example.com', opts = {})
host = address.split('@')[1]
stub_request(:get, "https://#{host}/.well-known/host-meta").to_return(:status => 200, :body => host_xrd)
stub_request(:get, "http://#{host}/.well-known/host-meta").to_return(:status => 200, :body => host_xrd)
if host.include?("joindiaspora.com")
if opts[:diaspora] || host.include?("diaspora")
stub_request(:get, /webfinger\/\?q=#{address}/).to_return(:status => 200, :body => finger_xrd)
stub_request(:get, "http://#{host}/hcard/users/4c8eccce34b7da59ff000002").to_return(:status => 200, :body => hcard_response)
else

View file

@ -1,113 +0,0 @@
# 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'
describe 'user encryption' do
before do
unstub_mocha_stubs
@user = Factory.create(:user)
@aspect = @user.aspect(:name => 'dudes')
@user2 = Factory.create(:user)
@aspect2 = @user2.aspect(:name => 'dudes')
end
after do
stub_signature_verification
#gpgdir = File.expand_path("../../db/gpg-#{Rails.env}", __FILE__)
#ctx = GPGME::Ctx.new
#keys = ctx.keys
#keys.each{|k| ctx.delete_key(k, true)}
end
it 'should have a key' do
@user.encryption_key.should_not be nil
end
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(Factory.create(:person), @aspect)
request.to_diaspora_xml.include?( @user.exported_key).should be true
end
it 'should receive and marshal a public key from a request' do
remote_user = Factory.build(:user)
remote_user.encryption_key.nil?.should== false
#should move this to friend request, but i found it here
id = remote_user.person.id
original_key = remote_user.exported_key
request = remote_user.send_friend_request_to(
@user.person, remote_user.aspect(:name => "temp"))
xml = request.to_diaspora_xml
remote_user.person.delete
remote_user.delete
person_count = Person.all.count
@user.receive xml, remote_user.person
Person.all.count.should == person_count + 1
new_person = Person.first(:id => id)
new_person.exported_key.should == original_key
end
end
describe 'encryption' do
before do
@message = @user.post :status_message, :message => "hi", :to => @aspect.id
end
it 'should encrypt large messages' do
ciphertext = @user.encrypt @message.to_diaspora_xml
ciphertext.include?(@message.to_diaspora_xml).should be false
@user.decrypt(ciphertext).include?(@message.to_diaspora_xml).should be true
end
end
describe 'comments' do
before do
friend_users(@user, @aspect, @user2, @aspect2)
@remote_message = @user2.post :status_message, :message => "hello", :to => @aspect2.id
@message = @user.post :status_message, :message => "hi", :to => @aspect.id
end
it 'should attach the creator signature if the user is commenting' do
@user.comment "Yeah, it was great", :on => @remote_message
@remote_message.comments.first.signature_valid?.should be true
end
it 'should sign the comment if the user is the post creator' do
message = @user.post :status_message, :message => "hi", :to => @aspect.id
@user.comment "Yeah, it was great", :on => message
message.comments.first.signature_valid?.should be true
message.comments.first.verify_post_creator_signature.should be true
end
it 'should verify a comment made on a remote post by a different friend' do
comment = Comment.new(:person => @user2.person, :text => "cats", :post => @remote_message)
comment.creator_signature = comment.send(:sign_with_key,@user2.encryption_key)
comment.signature_valid?.should be true
comment.verify_post_creator_signature.should be false
comment.post_creator_signature = comment.send(:sign_with_key,@user.encryption_key)
comment.verify_post_creator_signature.should be true
end
it 'should reject comments on a remote post with only a creator sig' do
comment = Comment.new(:person => @user2.person, :text => "cats", :post => @remote_message)
comment.creator_signature = comment.send(:sign_with_key,@user2.encryption_key)
comment.signature_valid?.should be true
comment.verify_post_creator_signature.should be false
end
it 'should receive remote comments on a user post with a creator sig' do
comment = Comment.new(:person => @user2.person, :text => "cats", :post => @message)
comment.creator_signature = comment.send(:sign_with_key,@user2.encryption_key)
comment.signature_valid?.should be true
comment.verify_post_creator_signature.should be false
end
end
end