Skip to content

Commit

Permalink
Add JSON exporter for user profile download
Browse files Browse the repository at this point in the history
  • Loading branch information
gdpelican committed Dec 15, 2014
1 parent e25a48c commit 4ba9a64
Show file tree
Hide file tree
Showing 18 changed files with 153 additions and 176 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Expand Up @@ -124,6 +124,8 @@ This is disabled by default since it requires the installation of additional pac
* Truncate too long OpenGraph descriptions [#5387](https://github.com/diaspora/diaspora/pull/5387)
* Make the source code URL configurable [#5410](https://github.com/diaspora/diaspora/pull/5410)
* Prefill publisher on the tag pages [#5442](https://github.com/diaspora/diaspora/pull/5442)
* Allows users to export their data in JSON format from their user settings page [#5354](https://github.com/diaspora/diaspora/pull/5354)


# 0.4.1.2

Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Expand Up @@ -162,6 +162,8 @@ gem 'zip-zip'
# https://github.com/discourse/discourse/pull/238
gem 'minitest'

# Serializers
gem 'active_model_serializers'

# Windows and OSX have an execjs compatible runtime built-in, Linux users should
# install Node.js or use 'therubyracer'.
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Expand Up @@ -22,6 +22,8 @@ GEM
erubis (~> 2.7.0)
activemodel (4.1.8)
activesupport (= 4.1.8)
active_model_serializers (0.9.0)
activemodel (>= 3.2)
builder (~> 3.1)
activerecord (4.1.8)
activemodel (= 4.1.8)
Expand Down Expand Up @@ -606,6 +608,7 @@ DEPENDENCIES
actionpack-action_caching
actionpack-page_caching
activerecord-import (= 0.6.0)
active_model_serializers
acts-as-taggable-on (= 3.4.2)
acts_as_api (= 0.4.2)
addressable (= 2.3.6)
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/application_controller.rb
Expand Up @@ -28,6 +28,10 @@ class ApplicationController < ActionController::Base

private

def default_serializer_options
{root: false}
end

def ensure_http_referer_is_set
request.env['HTTP_REFERER'] ||= '/'
end
Expand Down
7 changes: 5 additions & 2 deletions app/controllers/users_controller.rb
Expand Up @@ -136,8 +136,11 @@ def getting_started_completed
end

def export
exporter = Diaspora::Exporter.new(Diaspora::Exporters::XML)
send_data exporter.execute(current_user), :filename => "#{current_user.username}_diaspora_data.xml", :type => :xml
if export = Diaspora::Exporter.new(current_user).execute
send_data export, filename: "#{current_user.username}_diaspora_data.json", type: :json
else
head :not_acceptable
end
end

def export_photos
Expand Down
2 changes: 2 additions & 0 deletions app/models/user.rb
Expand Up @@ -37,6 +37,8 @@ class User < ActiveRecord::Base
serialize :hidden_shareables, Hash

has_one :person, :foreign_key => :owner_id
has_one :profile, through: :person

delegate :guid, :public_key, :posts, :photos, :owns?, :image_url,
:diaspora_handle, :name, :public_url, :profile, :url,
:first_name, :last_name, :gender, :participations, to: :person
Expand Down
7 changes: 7 additions & 0 deletions app/serializers/export/aspect_serializer.rb
@@ -0,0 +1,7 @@
module Export
class AspectSerializer < ActiveModel::Serializer
attributes :name,
:contacts_visible,
:chat_enabled
end
end
12 changes: 12 additions & 0 deletions app/serializers/export/contact_serializer.rb
@@ -0,0 +1,12 @@
module Export
class ContactSerializer < ActiveModel::Serializer
attributes :sharing,
:receiving,
:person_guid,
:person_name,
:person_first_name,
:person_diaspora_handle

has_many :aspects, each_serializer: Export::AspectSerializer
end
end
14 changes: 14 additions & 0 deletions app/serializers/export/profile_serializer.rb
@@ -0,0 +1,14 @@
module Export
class ProfileSerializer < ActiveModel::Serializer
attributes :first_name,
:last_name,
:gender,
:bio,
:birthday,
:location,
:image_url,
:diaspora_handle,
:searchable,
:nsfw
end
end
16 changes: 16 additions & 0 deletions app/serializers/export/user_serializer.rb
@@ -0,0 +1,16 @@
module Export
class UserSerializer < ActiveModel::Serializer
attributes :name,
:email,
:language,
:username,
:disable_mail,
:show_community_spotlight_in_stream,
:auto_follow_back,
:auto_follow_back_aspect
has_one :profile, serializer: Export::ProfileSerializer
has_many :aspects, each_serializer: Export::AspectSerializer
has_many :contacts, each_serializer: Export::ContactSerializer

end
end
3 changes: 2 additions & 1 deletion app/views/users/edit.html.haml
Expand Up @@ -180,7 +180,8 @@
#account_data.span6
%h3
= t('.export_data')
= link_to t('.download_xml'), export_user_path, :class => "button"
.small-horizontal-spacer
= link_to t('.download_profile'), export_user_path(format: :json), :class => "button"
.small-horizontal-spacer
= link_to t('.download_photos'), "#", :class => "button", :id => "photo-export-button", :title => t('.photo_export_unavailable')

Expand Down
2 changes: 1 addition & 1 deletion config/locales/diaspora/en.yml
Expand Up @@ -1266,7 +1266,7 @@ en:
current_password: "Current password"
current_password_expl: "the one you sign in with..."
character_minimum_expl: "must be at least six characters"
download_xml: "download my xml"
download_profile: "download my profile"
download_photos: "download my photos"
your_handle: "Your diaspora* ID"
your_email: "Your email"
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Expand Up @@ -101,7 +101,7 @@

resource :user, :only => [:edit, :update, :destroy], :shallow => true do
get :getting_started_completed
get :export
get :export, format: :json
get :export_photos
end

Expand Down
2 changes: 1 addition & 1 deletion lib/account_deleter.rb
Expand Up @@ -50,7 +50,7 @@ def normal_ar_user_associates_to_delete
end

def special_ar_user_associations
[:invitations_from_me, :person, :contacts, :auto_follow_back_aspect]
[:invitations_from_me, :person, :profile, :contacts, :auto_follow_back_aspect]
end

def ignored_ar_user_associations
Expand Down
86 changes: 11 additions & 75 deletions lib/diaspora/exporter.rb
Expand Up @@ -5,87 +5,23 @@
module Diaspora

class Exporter
def initialize(strategy)
self.class.send(:include, strategy)
end
end

module Exporters
module XML
def execute(user)
builder = Nokogiri::XML::Builder.new do |xml|
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.name aspect.name

# xml.person_ids {
#aspect.person_ids.each do |id|
#xml.person_id id
#end
#}
SERIALIZED_VERSION = '1.0'

xml.post_ids {
aspect.posts.where(author_id: user_person_id).each do |post|
xml.post_id post.id
end
}
}
end
}

xml.contacts {
user.contacts.each do |contact|
xml.contact {
xml.user_id contact.user_id
xml.person_id contact.person_id
xml.person_guid contact.person_guid

xml.aspects {
contact.aspects.each do |aspect|
xml.aspect {
xml.name aspect.name
}
end
}
}
end
}

xml.posts {
user.visible_shareables(Post).where(author_id: user_person_id).each do |post|
#post.comments.each do |comment|
# post_doc << comment.to_xml
#end

xml.parent << post.to_xml
end
}
def initialize(user)
@user = user
end

xml.people {
user.contacts.each do |contact|
person = contact.person
xml.parent << person.to_xml
def execute
@export ||= JSON.generate serialized_user.merge(version: SERIALIZED_VERSION)
end

end
}
}
end
private

builder.to_xml.to_s
end
def serialized_user
@serialized_user ||= Export::UserSerializer.new(@user).as_json
end

end

end
6 changes: 3 additions & 3 deletions spec/controllers/users_controller_spec.rb
Expand Up @@ -12,9 +12,9 @@
end

describe '#export' do
it 'returns an xml file' do
get :export
expect(response.header["Content-Type"]).to include "application/xml"
it 'can return a json file' do
get :export, format: :json
expect(response.header["Content-Type"]).to include "application/json"
end
end

Expand Down
15 changes: 15 additions & 0 deletions spec/lib/account_deleter_spec.rb
Expand Up @@ -43,6 +43,21 @@
end
end

context "profile deletion" do
before do
@profile_deletion = AccountDeleter.new(remote_raphael.diaspora_handle)
@profile = remote_raphael.profile
end

it "nulls out fields in the profile" do
@profile_deletion.perform!
expect(@profile.reload.first_name).to be_blank
expect(@profile.reload.last_name).to be_blank
expect(@profile.reload.searchable).to be_falsey
end

end

context "person deletion" do
before do
@person_deletion = AccountDeleter.new(remote_raphael.diaspora_handle)
Expand Down

0 comments on commit 4ba9a64

Please sign in to comment.