diaspora/lib/diaspora/importer.rb
2010-10-14 19:15:32 -07:00

179 lines
4.7 KiB
Ruby

# 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