diff --git a/Gemfile b/Gemfile index aefce44377cd52f165be89ab0ec848263a554c60..83cb3ea087b1b5e93837ab2856bf568c985d6882 100644 --- a/Gemfile +++ b/Gemfile @@ -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 diff --git a/Gemfile.lock b/Gemfile.lock index 14e3f10efbbbe11897938d21f4e111ea5fe0c61f..91fca33496e9a7bc12f7bc4941ad663f58f7e428 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,6 +97,7 @@ GEM activesupport (= 3.0.1) activesupport (3.0.1) addressable (2.2.2) + archive-tar-minitar (0.5.2) arel (1.0.1) activesupport (~> 3.0.0) aws (2.3.21) @@ -163,7 +164,8 @@ GEM i18n (0.4.1) json (1.4.6) json_pure (1.4.6) - linecache (0.43) + linecache19 (0.5.11) + ruby_core_source (>= 0.1.4) mail (2.2.7) activesupport (>= 2.3.6) mime-types @@ -225,11 +227,16 @@ GEM rspec-expectations (= 2.0.0) rspec-rails (2.0.0) rspec (= 2.0.0) - ruby-debug (0.10.3) - columnize (>= 0.1) - ruby-debug-base (~> 0.10.3.0) - ruby-debug-base (0.10.3) - linecache (>= 0.3) + ruby-debug-base19 (0.11.24) + columnize (>= 0.3.1) + linecache19 (>= 0.5.11) + ruby_core_source (>= 0.1.4) + ruby-debug19 (0.11.6) + columnize (>= 0.3.1) + linecache19 (>= 0.5.11) + ruby-debug-base19 (>= 0.11.19) + ruby_core_source (0.1.4) + archive-tar-minitar (>= 0.5.2) rubyzip (0.9.4) selenium-webdriver (0.0.29) childprocess (>= 0.0.7) @@ -287,7 +294,7 @@ DEPENDENCIES roxml! rspec (>= 2.0.0) rspec-rails (>= 2.0.0) - ruby-debug + ruby-debug19 sprinkle! thin webmock diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index ec9bd7f1beb768554e5df915d0784f9717d7d57d..970bdca5bf8ccd481cbc2b4bbf848b0f063bc07a 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -19,7 +19,7 @@ class RegistrationsController < Devise::RegistrationsController end end - def update + def update super end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 0a2c2b0ad8ad6ad4d5baa056b695e842eee258a6..b9bd53ab5555c63150f071eaa6159ceb13c0d075 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -5,10 +5,11 @@ 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 @@ -78,6 +79,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 diff --git a/app/models/post.rb b/app/models/post.rb index aa68dc897ca06920f6034816f180cb7cd138c2e6..0e1fc1959a114ca07bd757a9da0cc39c309360a2 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -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 diff --git a/app/models/user.rb b/app/models/user.rb index 1593ee29cbbcba3cb5fd7cb5b234a104dad8d5ac..5152acbdf95ece1c77278b4522d5b89134355714 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -56,7 +56,7 @@ class User many :raw_visible_posts, :in => :visible_post_ids, :class_name => 'Post' many :aspects, :class_name => 'Aspect', :dependent => :destroy - after_create :seed_aspects + #after_create :seed_aspects before_destroy :unfriend_everyone, :remove_person, :remove_all_aspects @@ -379,7 +379,11 @@ class User 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.seed_aspects + u.save! + u end def seed_aspects diff --git a/app/views/registrations/new.html.haml b/app/views/registrations/new.html.haml index 7e74a215708839f36e96282e23fa79713d610e5f..cea31ff78e0f076f9c7f2d45c80c033775451328 100644 --- a/app/views/registrations/new.html.haml +++ b/app/views/registrations/new.html.haml @@ -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" + diff --git a/config/routes.rb b/config/routes.rb index 8fbd132a870e2a136e3ac78457001a200f1287cf..47e73807ba1c7c1f004e20d974c7630435af5556 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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] diff --git a/lib/diaspora/exporter.rb b/lib/diaspora/exporter.rb index b560f729c1f08b27404b41938621a77681ade6a6..5f40322fbf5e3c28c5d4b01315bcc23a1f0a1b90 100644 --- a/lib/diaspora/exporter.rb +++ b/lib/diaspora/exporter.rb @@ -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 diff --git a/lib/diaspora/importer.rb b/lib/diaspora/importer.rb new file mode 100644 index 0000000000000000000000000000000000000000..e1e8ad97f9bd6e0db3f81144c8b54865fa9bd050 --- /dev/null +++ b/lib/diaspora/importer.rb @@ -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 diff --git a/spec/lib/exporter_spec.rb b/spec/lib/exporter_spec.rb index fb3e6d29fe3a5201f3f5d49fc3ec07f9823899e2..0c177ef4509bd667311deb0fb1f82db6cdf9e91b 100644 --- a/spec/lib/exporter_spec.rb +++ b/spec/lib/exporter_spec.rb @@ -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) + doc.xpath('//posts').to_s.should include status_message1.created_at.to_s + 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 diff --git a/spec/lib/importer_spec.rb b/spec/lib/importer_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..268b0f5e19018f6d8186450ac45fbb96ac10963a --- /dev/null +++ b/spec/lib/importer_spec.rb @@ -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 + diff --git a/spec/lib/verify_spec.rb b/spec/lib/verify_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..b0b8a0de65ed3debcd03b647499236a3c9c6b1a3 --- /dev/null +++ b/spec/lib/verify_spec.rb @@ -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 diff --git a/spec/models/aspect_spec.rb b/spec/models/aspect_spec.rb index e91d4a258e01f2d5c403c18be26afac488d47db8..d5c281a3b1905da448cd54f45cf5f8f5c78889da 100644 --- a/spec/models/aspect_spec.rb +++ b/spec/models/aspect_spec.rb @@ -65,7 +65,7 @@ describe Aspect do it 'belong to a user' do @aspect.user.id.should == @user.id - @user.aspects.size.should == 3 + @user.aspects.size.should == 1 end it 'should have people' do