REMOVED IMPORTER

This commit is contained in:
danielvincent 2010-11-02 11:17:47 -07:00
parent 0b8425cbde
commit a3ce5f1cd7
7 changed files with 2 additions and 648 deletions

View file

@ -5,11 +5,9 @@
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, :import]
before_filter :authenticate_user!, :except => [:new, :create, :public]
respond_to :html
@ -101,23 +99,4 @@ class UsersController < ApplicationController
User.invite!(:email => params[:email])
end
def import
xml = params[:upload][:file].read
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] = "Something went wrong: #{e.message}"
end
redirect_to new_user_registration_path
#redirect_to user_session_path
end
end

View file

@ -4,8 +4,7 @@
class Contact
include MongoMapper::Document
attr_accessor :aspect_names #this is only used in the importer
belongs_to :user
validates_presence_of :user

View file

@ -19,24 +19,3 @@
= f.submit t('.sign_up')
.floating
%h3
= t('.upload_existing_account')
= 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 t('.upload')

View file

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

View file

@ -1,222 +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.
module Diaspora
class Importer
def initialize(strategy)
self.class.send(:include, strategy)
end
def commit(user, person, aspects, people, posts, contacts, opts = {})
filter = verify_and_clean(user, person, people, aspects, posts, contacts)
#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 =
user.visible_person_ids = people.collect{ |x| x.id }
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
contacts.each do |contact|
contact.user = user
user.friends << contact
contact.save!
end
puts user.persisted?
puts user.inspect
user.save(:validate => false)
end
def assign_aspect_ids(contacts, aspects)
a_hash = {}
aspects.each{|x| a_hash[x.name]=x.id}
contacts.each do |contact|
contact.aspect_names.each do |x|
contact.aspect_ids << a_hash[x]
end
contact.aspect_names = nil
end
end
### verification (to be module) ################
def verify_and_clean(user, person, people, aspects, posts, contacts)
verify_user(user)
verify_person_for_user(user, person)
filters = filter_posts(posts, person)
clean_aspects(aspects, filters[:whitelist])
filters[:all_person_ids] = people.collect{ |x| x.id.to_id }
raise "incorrect number of contacts" unless verify_contacts(contacts, filters[:all_person_ids])
assign_aspect_ids(contacts, aspects)
filters[:people] = filter_people(people)
filters
end
def verify_contacts(contacts, person_ids)
return false if contacts.count != person_ids.count
contacts.all?{|x| person_ids.include?(x.person_id)}
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)
contacts = parse_contacts(doc)
people = parse_people(doc)
posts = parse_posts(doc)
user
commit(user, person, aspects, people, posts, contacts, 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 }
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_contacts(doc)
contacts = []
contact_doc = doc.xpath('/export/contacts/contact')
contact_doc.each do |x|
contact = Contact.new
contact.person_id = x.xpath("person_id").text.to_id
contact.aspect_names = x.xpath('aspects/aspect/name').collect{ |x| x.text}
contacts << contact
end
contacts
end
def parse_posts(doc)
post_doc = doc.xpath('/export/posts/status_message')
post_doc.inject([]) do |posts,curr|
posts << StatusMessage.from_xml(curr.to_s)
end
end
end
end
end

View file

@ -1,254 +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'
require File.join(Rails.root, 'lib/diaspora/exporter')
require File.join(Rails.root, 'lib/diaspora/importer')
describe Diaspora::Importer do
def setup_for_exporting
# Five users on pod
@user1 = make_user
@user2 = make_user
@user3 = make_user
@user4 = make_user
@user5 = make_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.aspects.create(:name => "Dudes")
@aspect2 = @user1.aspects.create(:name => "Girls")
@aspect3 = @user1.aspects.create(:name => "Bros")
@aspect4 = @user1.aspects.create(:name => "People")
@aspect5 = @user2.aspects.create(:name => "Abe Lincolns")
@aspect6 = @user3.aspects.create(:name => "Cats")
@aspect7 = @user4.aspects.create(:name => "Dogs")
@aspect8 = @user5.aspects.create(:name => "Hamsters")
@aspect9 = @user5.aspects.create(:name => "Gophers")
@aspect10 = @user1.aspects.create(:name => "Work")
@aspect11 = @user1.aspects.create(: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
before(:all) do
DatabaseCleaner.clean
UserFixer.load_user_fixtures
setup_for_exporting
# 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
end
it 'should gut check this test' do
setup_for_exporting
@user1.friends.count.should be 4
@user1.contact_for(@user2.person).should_not be_nil
@user1.contact_for(@user3.person).should_not be_nil
@user1.contact_for(@user4.person).should_not be_nil
@user1.contact_for(@user5.person).should_not be_nil
# User is generated with two pre-populated aspects
@user1.aspects.count.should be 6
@user1.aspects.find_by_name("Dudes").people.find_by_person_id(@user2.person.id).should_not be_nil
@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
@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
end
describe '#parse_contacts' do
let(:contacts) { @importer.parse_contacts(@doc) }
it 'should return an array' do
contacts.count.should == 4
end
it 'should should have post ids' do
contacts.all?{|x| x.aspect_names.count > 0}.should be true
end
it 'should should have a person id' do
contacts.all?{|x| x.person_id.nil? || x.person_id == ""}.should be false
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)
@username =@user1.username
# Remove user1 from the server
@user1.aspects.each( &:delete )
@user1.friends.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 needs love
the test passes when the validations are set to false when saving the user in the importer"
User.delete_all
Person.delete_all
Post.delete_all
StatusMessage.delete_all
Aspect.delete_all
Contact.delete_all
User.count.should == 0
Person.count.should == 0
@importer.execute(@xml,
:email => "bob@bob.com",
:password => "bobbybob",
:password => "bobbybob",
:diaspora_handle => "#{@username}@#{APP_CONFIG[:terse_pod_url]}")
User.count.should == 1
n = User.first
Post.count.should == 4
n.aspects.count.should == 6
Person.count.should be == 5
Contact.count.should be == 4
# need to check this
#User.first.person.diaspora_handle.should == User.first.diaspora_handle
User.first.diaspora_handle.should == "#{@username}@#{APP_CONFIG[:terse_pod_url]}"
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

View file

@ -1,126 +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'
require File.join(Rails.root, 'lib/diaspora/importer')
describe Diaspora::Importer do
let!(:user1) { make_user }
let!(:user2) { make_user }
let!(:user3) { make_user }
let(:aspect1) { user1.aspects.create(:name => "Work") }
let(:aspect2) { user2.aspects.create(:name => "Family") }
let(:aspect3) { user3.aspects.create(: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 = make_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 'verify contacts' do
let(:contact1) {Contact.new(:user => user1, :person => user2.person, :aspects => [aspect1])}
let(:contact2) {Contact.new(:user => user1, :person => user3.person, :aspects => [aspect2])}
let(:contact3) {Contact.new(:user => user1, :person => user3.person, :aspects => [aspect3])}
let(:less_contacts) {[contact1]}
let(:same_contacts) {[contact1, contact2]}
let(:more_contacts) {[contact1, contact2, contact3]}
let(:person_ids) {[user2.person.id, user3.person.id]}
it 'should be false if the number of the number of contacts is not equal to the number of imported people' do
importer.verify_contacts(less_contacts, person_ids).should be false
importer.verify_contacts(same_contacts, person_ids).should be true
importer.verify_contacts(more_contacts, person_ids).should be false
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