diff --git a/.rspec b/.rspec index b36b4b596..4e1e0d2f7 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1 @@ --color ---format nested \ No newline at end of file diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index f3da1ec8a..b3e826077 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -2,7 +2,7 @@ class GroupsController < ApplicationController before_filter :authenticate_user! def index - @posts = Post.paginate :page => params[:page], :order => 'created_at DESC' + @posts = current_user.posts.paginate :page => params[:page], :order => 'created_at DESC' end def create diff --git a/app/models/post.rb b/app/models/post.rb index 7725d712b..e1821d615 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -11,6 +11,7 @@ class Post xml_accessor :person, :as => Person key :person_id, ObjectId + key :user_refs, Integer, :default => 0 many :comments, :class_name => 'Comment', :foreign_key => :post_id belongs_to :person, :class_name => 'Person' @@ -29,10 +30,6 @@ class Post end #Querying - def self.stream - Post.sort(:created_at.desc).all - end - def self.newest_for(person) self.first(:person_id => person.id, :order => '_id desc') end diff --git a/app/models/request.rb b/app/models/request.rb index 99625ad13..af57a9187 100644 --- a/app/models/request.rb +++ b/app/models/request.rb @@ -20,38 +20,27 @@ class Request belongs_to :person validates_presence_of :destination_url, :callback_url - - #validates_format_of :destination_url, :with => - #/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/ix - before_validation :clean_link - scope :for_user, lambda{ |user| where(:destination_url => user.receive_url) } + scope :for_user, lambda{ |user| where(:destination_url => user.receive_url) } scope :from_user, lambda{ |user| where(:destination_url.ne => user.receive_url) } def self.instantiate(options = {}) person = options[:from] self.new(:destination_url => options[:to], - :callback_url => person.receive_url, - :person => person, - :exported_key => person.export_key, - :group_id => options[:into]) + :callback_url => person.receive_url, + :person => person, + :exported_key => person.export_key, + :group_id => options[:into]) end - def reverse accepting_user - self.person = accepting_user.person - self.exported_key = accepting_user.export_key + def reverse_for accepting_user + self.person = accepting_user.person + self.exported_key = accepting_user.export_key self.destination_url = self.callback_url - save + self.save end - def set_pending_friend - p = Person.first(:id => self.person.id) - - self.person.save #save pending friend - - end - #ENCRYPTION #before_validation :sign_if_mine #validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature} @@ -61,7 +50,8 @@ class Request def signable_accessors accessors = self.class.roxml_attrs.collect{|definition| - definition.accessor} + definition.accessor} + accessors.delete 'person' accessors.delete 'creator_signature' accessors @@ -69,7 +59,7 @@ class Request def signable_string signable_accessors.collect{|accessor| - (self.send accessor.to_sym).to_s}.join ';' + (self.send accessor.to_sym).to_s}.join ';' end protected diff --git a/app/models/retraction.rb b/app/models/retraction.rb index 123a27a4e..e1f911d2d 100644 --- a/app/models/retraction.rb +++ b/app/models/retraction.rb @@ -38,24 +38,21 @@ class Retraction end def signature_valid? - target = self.type.constantize.first(:id => self.post_id) + target = self.type.constantize.find_by_id(self.post_id) + if target.is_a? Person - verify_signature(@creator_signature, self.type.constantize.first(:id => self.post_id)) + verify_signature(@creator_signature, self.type.constantize.find_by_id(self.post_id)) else - verify_signature(@creator_signature, self.type.constantize.first(:id => self.post_id).person) + verify_signature(@creator_signature, self.type.constantize.find_by_id(self.post_id).person) end end def self.person_id_from(object) - if object.is_a? Person - object.id - else - object.person.id - end + object.is_a?(Person) ? object.id : object.person.id end def person - Person.first(:id => self.person_id) + Person.find_by_id(self.person_id) end #ENCRYPTION diff --git a/app/models/user.rb b/app/models/user.rb index f9deca04e..a9b4a0b30 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -6,11 +6,13 @@ class User key :friend_ids, Array key :pending_request_ids, Array + key :post_ids, Array one :person, :class_name => 'Person', :foreign_key => :owner_id many :friends, :in => :friend_ids, :class_name => 'Person' many :pending_requests, :in => :pending_request_ids, :class_name => 'Request' + many :posts, :in => :post_ids, :class_name => 'Post' many :groups, :class_name => 'Group' @@ -18,7 +20,6 @@ class User before_validation :do_bad_things ######## Making things work ######## - key :email, String def method_missing(method, *args) @@ -31,20 +32,19 @@ class User end ######### Groups ###################### - def group( opts = {} ) opts[:user] = self Group.create(opts) end ######### Posts and Such ############### - def retract( post ) retraction = Retraction.for(post) retraction.creator_signature = retraction.sign_with_key( encryption_key ) retraction.notify_people retraction end + ######### Friend Requesting ########### def send_friend_request_to(friend_url, group_id) unless self.friends.detect{ |x| x.receive_url == friend_url} @@ -65,12 +65,12 @@ class User end def accept_friend_request(friend_request_id, group_id) - request = Request.where(:id => friend_request_id).first - n = pending_requests.delete(request) + request = Request.find_by_id(friend_request_id) + pending_requests.delete(request) activate_friend(request.person, group_by_id(group_id)) - request.reverse self + request.reverse_for(self) request end @@ -84,28 +84,34 @@ class User end def ignore_friend_request(friend_request_id) - request = Request.first(:id => friend_request_id) - person = request.person + request = Request.find_by_id(friend_request_id) + person = request.person + person.user_refs -= 1 - pending_requests.delete(request) - save + + self.pending_requests.delete(request) + self.save + (person.user_refs > 0 || person.owner.nil? == false) ? person.save : person.destroy request.destroy end def receive_friend_request(friend_request) Rails.logger.info("receiving friend request #{friend_request.to_json}") + if request_from_me?(friend_request) group = self.group_by_id(friend_request.group_id) activate_friend(friend_request.person, group) Rails.logger.info("#{self.real_name}'s friend request has been accepted") + friend_request.destroy else + friend_request.person.user_refs += 1 friend_request.person.save - pending_requests << friend_request - save + self.pending_requests << friend_request + self.save Rails.logger.info("#{self.real_name} has received a friend request") friend_request.save end @@ -123,6 +129,14 @@ class User raise "Friend not deleted" unless self.friend_ids.delete( bad_friend.id ) groups.each{|g| g.person_ids.delete( bad_friend.id )} self.save + + self.posts.find_all_by_person_id( bad_friend.id ).each{|post| + self.post_ids.delete( post.id ) + post.user_refs -= 1 + (post.user_refs > 0 || post.person.owner.nil? == false) ? post.save : post.destroy + } + self.save + bad_friend.user_refs -= 1 (bad_friend.user_refs > 0 || bad_friend.owner.nil? == false) ? bad_friend.save : bad_friend.destroy end @@ -179,17 +193,28 @@ class User person = Diaspora::Parser.owner_id_from_xml xml person.profile = object person.save + + elsif object.is_a?(Post) && object.verify_creator_signature == true + Rails.logger.debug("Saving post: #{object}") + + object.user_refs += 1 + object.save + + self.posts << object + self.save + object.socket_to_uid(id) if (object.respond_to?(:socket_to_uid) && !self.owns?(object)) + dispatch_comment object if object.is_a?(Comment) && !owns?(object) + elsif object.is_a?(Comment) && object.verify_post_creator_signature if object.verify_creator_signature || object.person.nil? dispatch_comment object unless owns?(object) - end elsif object.verify_creator_signature == true Rails.logger.debug("Saving object: #{object}") object.save - object.socket_to_uid( id) if (object.respond_to?(:socket_to_uid) && !self.owns?(object)) + object.socket_to_uid(id) if (object.respond_to?(:socket_to_uid) && !self.owns?(object)) end end diff --git a/app/views/groups/index.html.haml b/app/views/groups/index.html.haml index b3b4d2acb..e4d1ecca2 100644 --- a/app/views/groups/index.html.haml +++ b/app/views/groups/index.html.haml @@ -3,6 +3,7 @@ = current_user.profile.first_name = render "shared/publisher" + %ul#stream - for post in @posts = render type_partial(post), :post => post diff --git a/lib/diaspora/parser.rb b/lib/diaspora/parser.rb index 8835bd83b..650c4a4e4 100644 --- a/lib/diaspora/parser.rb +++ b/lib/diaspora/parser.rb @@ -20,7 +20,15 @@ module Diaspora return unless body = doc.xpath("/XML/post").children.first begin - body.name.camelize.constantize.from_xml body.to_s + new_object = body.name.camelize.constantize.from_xml body.to_s + + if new_object.is_a? Post + existing_object = new_object.class.find_by_id(new_object.id) + existing_object ? (return existing_object) : (return new_object) + end + + new_object + rescue NameError => e if e.message.include? 'wrong constant name' Rails.logger.info "Not a real type: #{object.to_s}" diff --git a/spec/lib/diaspora_parser_spec.rb b/spec/lib/diaspora_parser_spec.rb index d0065cfb8..38be7104d 100644 --- a/spec/lib/diaspora_parser_spec.rb +++ b/spec/lib/diaspora_parser_spec.rb @@ -110,7 +110,7 @@ describe Diaspora::Parser do it "should activate the Person if I initiated a request to that url" do request = @user.send_friend_request_to( @user2.receive_url, @group.id) - request.reverse @user2 + request.reverse_for @user2 xml = request.to_diaspora_xml @@ -131,7 +131,7 @@ describe Diaspora::Parser do it 'should process retraction for a person' do person_count = Person.all.count request = @user.send_friend_request_to( @user2.receive_url, @group.id) - request.reverse @user2 + request.reverse_for @user2 xml = request.to_diaspora_xml retraction = Retraction.for(@user2) diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index a20ffb504..12c84ccfe 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -41,16 +41,6 @@ describe Post do Factory.create(:bookmark, :title => "Google", :link => "http://google.com", :created_at => Time.now+5, :person => @person_two) end - it "should list child types in reverse chronological order" do - stream = Post.stream - stream.count.should == 5 - stream[0].class.should == Bookmark - stream[1].class.should == Blog - stream[2].class.should == StatusMessage - stream[3].class.should == Bookmark - stream[4].class.should == StatusMessage - end - it "should get all posts for a specified user" do person_posts = @person_one.posts person_posts.count.should == 1 diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index eb77b1f05..e0d2415c7 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -56,8 +56,7 @@ describe User do Request.count.should == 0 end - it 'should not be able to friend request an existing friend' do - friend = Factory.create(:person) + it 'should not be able to friend request an existing friend' do friend = Factory.create(:person) @user.friends << friend @user.save @@ -239,7 +238,7 @@ describe User do @group2 = @user2.group(:name => "Gross people") request = @user.send_friend_request_to( @user2.receive_url, @group.id) - request.reverse @user2 + request.reverse_for @user2 @user2.activate_friend(@user.person, @group2) @user.receive request.to_diaspora_xml end @@ -272,4 +271,100 @@ describe User do @group2.people.count.should == 0 end end + + describe 'post refs' do + before do + @user2 = Factory.create(:user) + @user.activate_friend( @user2.person, @group) + + @user3 = Factory.create(:user) + @group3 = @user3.group(:name => 'heroes') + + + @user.posts.count.should == 0 + end + + it 'should be removed on unfriending' do + status_message = @user2.post :status_message, :message => "hi" + @user.receive status_message.to_diaspora_xml + @user.reload + + @user.posts.count.should == 1 + + @user.unfriend(@user2.person) + + @user.reload + @user.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" + @user.receive status_message.to_diaspora_xml + @user.reload + + @user.posts.count.should == 1 + + person = @user2.person + @user2.destroy + @user.unfriend(person) + + @user.reload + @user.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" + @user.receive status_message.to_diaspora_xml + @user.reload + + @user.posts.count.should == 1 + + status_message.reload + status_message.user_refs.should == 1 + + @user.unfriend(@user2.person) + status_message.reload + + @user.reload + @user.posts.count.should == 0 + + status_message.reload + status_message.user_refs.should == 0 + + Post.count.should be 1 + end + + it 'should not override userrefs on receive by another person' do + @user3 = Factory.create :user + @user3.activate_friend(@user2, @group3) + + status_message = @user2.post :status_message, :message => "hi" + @user.receive status_message.to_diaspora_xml + @user3.receive status_message.to_diaspora_xml + @user.reload + @user3.reload + + @user.posts.count.should == 1 + + status_message.reload + status_message.user_refs.should == 2 + + @user.unfriend(@user2.person) + status_message.reload + + @user.reload + @user.posts.count.should == 0 + + status_message.reload + status_message.user_refs.should == 1 + + Post.count.should be 1 + end + + + end end