Allow to choose to overwrite settings and profile data
This commit is contained in:
parent
96493b4a5c
commit
34528521f2
5 changed files with 179 additions and 53 deletions
|
|
@ -3,14 +3,14 @@
|
||||||
class ImportService
|
class ImportService
|
||||||
include Diaspora::Logging
|
include Diaspora::Logging
|
||||||
|
|
||||||
def import_by_user(user)
|
def import_by_user(user, opts={})
|
||||||
import_by_files(user.export.current_path, user.exported_photos_file.current_path, user.username)
|
import_by_files(user.export.current_path, user.exported_photos_file.current_path, user.username, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def import_by_files(path_to_profile, path_to_photos, username)
|
def import_by_files(path_to_profile, path_to_photos, username, opts={})
|
||||||
if path_to_profile.present?
|
if path_to_profile.present?
|
||||||
logger.info "Import for profile #{username} at path #{path_to_profile} requested"
|
logger.info "Import for profile #{username} at path #{path_to_profile} requested"
|
||||||
import_user_profile(path_to_profile, username)
|
import_user_profile(path_to_profile, username, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
user = User.find_by(username: username)
|
user = User.find_by(username: username)
|
||||||
|
|
@ -25,10 +25,10 @@ class ImportService
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def import_user_profile(path_to_profile, username)
|
def import_user_profile(path_to_profile, username, opts)
|
||||||
raise ArgumentError, "Profile file not found at path: #{path_to_profile}" unless File.exist?(path_to_profile)
|
raise ArgumentError, "Profile file not found at path: #{path_to_profile}" unless File.exist?(path_to_profile)
|
||||||
|
|
||||||
service = MigrationService.new(path_to_profile, username)
|
service = MigrationService.new(path_to_profile, username, opts)
|
||||||
logger.info "Start validating user profile #{username}"
|
logger.info "Start validating user profile #{username}"
|
||||||
service.validate
|
service.validate
|
||||||
logger.info "Start importing user profile for '#{username}'"
|
logger.info "Start importing user profile for '#{username}'"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class MigrationService
|
class MigrationService
|
||||||
attr_reader :archive_path, :new_user_name
|
attr_reader :archive_path, :new_user_name, :opts
|
||||||
|
|
||||||
delegate :errors, :warnings, to: :archive_validator
|
delegate :errors, :warnings, to: :archive_validator
|
||||||
|
|
||||||
def initialize(archive_path, new_user_name)
|
def initialize(archive_path, new_user_name, opts={})
|
||||||
@archive_path = archive_path
|
@archive_path = archive_path
|
||||||
@new_user_name = new_user_name
|
@new_user_name = new_user_name
|
||||||
|
@opts = opts
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate
|
def validate
|
||||||
|
|
@ -40,12 +42,11 @@ class MigrationService
|
||||||
private
|
private
|
||||||
|
|
||||||
def find_or_create_user
|
def find_or_create_user
|
||||||
archive_importer.user = User.find_by(username: new_user_name)
|
archive_importer.find_or_create_user(username: new_user_name, password: SecureRandom.hex)
|
||||||
archive_importer.create_user(username: new_user_name, password: SecureRandom.hex) if archive_importer.user.nil?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def import_archive
|
def import_archive
|
||||||
archive_importer.import
|
archive_importer.import(opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_migration
|
def run_migration
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ class ArchiveImporter
|
||||||
@archive_hash = archive_hash
|
@archive_hash = archive_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
def import
|
def import(opts={})
|
||||||
import_tag_followings
|
import_tag_followings
|
||||||
import_aspects
|
import_aspects
|
||||||
import_contacts
|
import_contacts
|
||||||
|
|
@ -19,12 +19,12 @@ class ArchiveImporter
|
||||||
import_subscriptions
|
import_subscriptions
|
||||||
import_others_relayables
|
import_others_relayables
|
||||||
import_blocks
|
import_blocks
|
||||||
|
import_settings if opts.fetch(:import_settings, true)
|
||||||
|
import_profile if opts.fetch(:import_profile, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_user(attr)
|
def find_or_create_user(attr)
|
||||||
allowed_keys = %w[
|
allowed_keys = %w[email language]
|
||||||
email strip_exif show_community_spotlight_in_stream language disable_mail auto_follow_back
|
|
||||||
]
|
|
||||||
data = convert_keys(archive_hash["user"], allowed_keys)
|
data = convert_keys(archive_hash["user"], allowed_keys)
|
||||||
# setting getting_started to false as the user doesn't need to see the getting started wizard
|
# setting getting_started to false as the user doesn't need to see the getting started wizard
|
||||||
data.merge!(
|
data.merge!(
|
||||||
|
|
@ -36,8 +36,6 @@ class ArchiveImporter
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.user = User.find_or_build(data)
|
self.user = User.find_or_build(data)
|
||||||
user.show_community_spotlight_in_stream = data.fetch(:show_community_spotlight_in_stream, true)
|
|
||||||
user.strip_exif = data.fetch(:strip_exif, true)
|
|
||||||
user.getting_started = false
|
user.getting_started = false
|
||||||
user.save!
|
user.save!
|
||||||
end
|
end
|
||||||
|
|
@ -63,7 +61,7 @@ class ArchiveImporter
|
||||||
return if name.nil?
|
return if name.nil?
|
||||||
|
|
||||||
aspect = user.aspects.find_by(name: name)
|
aspect = user.aspects.find_by(name: name)
|
||||||
user.update(auto_follow_back_aspect: aspect) if aspect
|
user.update(auto_follow_back: true, auto_follow_back_aspect: aspect) if aspect
|
||||||
end
|
end
|
||||||
|
|
||||||
def import_aspects
|
def import_aspects
|
||||||
|
|
@ -74,7 +72,6 @@ class ArchiveImporter
|
||||||
logger.warn "#{self}: #{e}"
|
logger.warn "#{self}: #{e}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
set_auto_follow_back_aspect
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def import_posts
|
def import_posts
|
||||||
|
|
@ -125,6 +122,21 @@ class ArchiveImporter
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def import_settings
|
||||||
|
allowed_keys = %w[language show_community_spotlight_in_stream strip_exif]
|
||||||
|
convert_keys(archive_hash["user"], allowed_keys).each do |key, value|
|
||||||
|
user.update(key => value) unless value.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
set_auto_follow_back_aspect if archive_hash.fetch("user").fetch("auto_follow_back", false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def import_profile
|
||||||
|
profile_attributes.each do |key, value|
|
||||||
|
user.person.profile.update(key => value) unless value.nil?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def convert_keys(hash, allowed_keys)
|
def convert_keys(hash, allowed_keys)
|
||||||
hash
|
hash
|
||||||
.slice(*allowed_keys)
|
.slice(*allowed_keys)
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,16 @@
|
||||||
|
|
||||||
namespace :accounts do
|
namespace :accounts do
|
||||||
desc "Perform migration"
|
desc "Perform migration"
|
||||||
task :migration, %i[archive_path photos_path new_user_name] => :environment do |_t, args|
|
task :migration,
|
||||||
puts "Account migration is requested. You can import a profile or a photos archive or booth."
|
%i[archive_path photos_path new_user_name import_settings import_profile] => :environment do |_t, args|
|
||||||
args = %i[archive_path photos_path new_user_name].map {|name| [name, args[name]] }.to_h
|
puts "Account migration is requested. You can import a profile or a photos archive or both."
|
||||||
|
args = %i[archive_path photos_path new_user_name import_settings import_profile]
|
||||||
|
.map {|name| [name, args[name]] }.to_h
|
||||||
process_arguments(args)
|
process_arguments(args)
|
||||||
start_time = Time.now.getlocal
|
start_time = Time.now.getlocal
|
||||||
if args[:new_user_name].present? && (args[:archive_path].present? || args[:photos_path].present?)
|
if args[:new_user_name].present? && (args[:archive_path].present? || args[:photos_path].present?)
|
||||||
ImportService.new.import_by_files(args[:archive_path], args[:photos_path], args[:new_user_name])
|
ImportService.new.import_by_files(args[:archive_path], args[:photos_path], args[:new_user_name],
|
||||||
|
args.slice(:import_settings, :import_profile))
|
||||||
puts "\n Migration completed in #{Time.now.getlocal - start_time} seconds. (Photos might still be processed in)"
|
puts "\n Migration completed in #{Time.now.getlocal - start_time} seconds. (Photos might still be processed in)"
|
||||||
else
|
else
|
||||||
puts "Must set a user name and a archive file path or photos file path"
|
puts "Must set a user name and a archive file path or photos file path"
|
||||||
|
|
@ -19,16 +22,31 @@ namespace :accounts do
|
||||||
args[:archive_path] = request_parameter(args[:archive_path], "Enter the archive (.json, .gz, .zip) path: ")
|
args[:archive_path] = request_parameter(args[:archive_path], "Enter the archive (.json, .gz, .zip) path: ")
|
||||||
args[:photos_path] = request_parameter(args[:photos_path], "Enter the photos (.zip) path: ")
|
args[:photos_path] = request_parameter(args[:photos_path], "Enter the photos (.zip) path: ")
|
||||||
args[:new_user_name] = request_parameter(args[:new_user_name], "Enter the new user name: ")
|
args[:new_user_name] = request_parameter(args[:new_user_name], "Enter the new user name: ")
|
||||||
|
args[:import_settings] = request_boolean_parameter(args[:import_settings], "Import and overwrite settings [Y/n]: ")
|
||||||
|
args[:import_profile] = request_boolean_parameter(args[:import_profile], "Import and overwrite profile [Y/n]: ")
|
||||||
|
|
||||||
puts "Archive path: #{args[:archive_path]}"
|
puts "Archive path: #{args[:archive_path]}"
|
||||||
puts "Photos path: #{args[:photos_path]}"
|
puts "Photos path: #{args[:photos_path]}"
|
||||||
puts "New username: #{args[:new_user_name]}"
|
puts "New username: #{args[:new_user_name]}"
|
||||||
|
puts "Import settings: #{args[:import_settings]}"
|
||||||
|
puts "Import profile: #{args[:import_profile]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_parameter(arg, text)
|
||||||
|
return arg unless arg.nil?
|
||||||
|
|
||||||
|
print text
|
||||||
|
$stdin.gets.strip
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_boolean_parameter(arg, text, default: true)
|
||||||
|
return arg == "true" unless arg.nil?
|
||||||
|
|
||||||
|
print text
|
||||||
|
response = $stdin.gets.strip.downcase
|
||||||
|
|
||||||
|
return default if response == ""
|
||||||
|
|
||||||
|
response[0] == "y"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_parameter(arg, text)
|
|
||||||
return arg unless arg.nil?
|
|
||||||
|
|
||||||
print text
|
|
||||||
$stdin.gets.strip
|
|
||||||
end
|
|
||||||
|
|
|
||||||
|
|
@ -56,17 +56,13 @@ describe ArchiveImporter do
|
||||||
let(:archive_hash) {
|
let(:archive_hash) {
|
||||||
{
|
{
|
||||||
"user" => {
|
"user" => {
|
||||||
"auto_follow_back_aspect" => "Friends",
|
"profile" => {
|
||||||
"profile" => {
|
|
||||||
"entity_data" => {
|
"entity_data" => {
|
||||||
"author" => "old_id@old_pod.nowhere"
|
"author" => "old_id@old_pod.nowhere"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contact_groups" => [{
|
"followed_tags" => [target.tag_followings.first.tag.name],
|
||||||
"name" => "Friends"
|
"post_subscriptions" => [target.participations.first.target.guid]
|
||||||
}],
|
|
||||||
"followed_tags" => [target.tag_followings.first.tag.name],
|
|
||||||
"post_subscriptions" => [target.participations.first.target.guid]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,14 +105,122 @@ describe ArchiveImporter do
|
||||||
}.not_to raise_error
|
}.not_to raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "with settings" do
|
||||||
|
let(:archive_hash) {
|
||||||
|
{
|
||||||
|
"user" => {
|
||||||
|
"profile" => {
|
||||||
|
"entity_data" => {
|
||||||
|
"author" => "old_id@old_pod.nowhere"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact_groups" => [{
|
||||||
|
"name" => "Follow"
|
||||||
|
}],
|
||||||
|
"strip_exif" => false,
|
||||||
|
"show_community_spotlight_in_stream" => false,
|
||||||
|
"language" => "ru",
|
||||||
|
"auto_follow_back" => true,
|
||||||
|
"auto_follow_back_aspect" => "Follow"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it "imports the settings" do
|
||||||
|
expect {
|
||||||
|
archive_importer.import
|
||||||
|
}.not_to raise_error
|
||||||
|
|
||||||
|
expect(archive_importer.user.strip_exif).to eq(false)
|
||||||
|
expect(archive_importer.user.show_community_spotlight_in_stream).to eq(false)
|
||||||
|
expect(archive_importer.user.language).to eq("ru")
|
||||||
|
expect(archive_importer.user.auto_follow_back).to eq(true)
|
||||||
|
expect(archive_importer.user.auto_follow_back_aspect.name).to eq("Follow")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not overwrite settings if import_settings is disabled" do
|
||||||
|
expect {
|
||||||
|
archive_importer.import(import_settings: false)
|
||||||
|
}.not_to raise_error
|
||||||
|
|
||||||
|
expect(archive_importer.user.strip_exif).to eq(true)
|
||||||
|
expect(archive_importer.user.show_community_spotlight_in_stream).to eq(true)
|
||||||
|
expect(archive_importer.user.language).to eq("en")
|
||||||
|
expect(archive_importer.user.auto_follow_back).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with profile" do
|
||||||
|
let(:archive_hash) {
|
||||||
|
{
|
||||||
|
"user" => {
|
||||||
|
"profile" => {
|
||||||
|
"entity_data" => {
|
||||||
|
"author" => "old_id@old_pod.nowhere",
|
||||||
|
"first_name" => "First",
|
||||||
|
"last_name" => "Last",
|
||||||
|
"full_name" => "Full Name",
|
||||||
|
"image_url" => "https://example.com/my_avatar.png",
|
||||||
|
"bio" => "I'm just a test account",
|
||||||
|
"gender" => "Robot",
|
||||||
|
"birthday" => "2006-01-01",
|
||||||
|
"location" => "diaspora* specs",
|
||||||
|
"searchable" => false,
|
||||||
|
"public" => true,
|
||||||
|
"nsfw" => true,
|
||||||
|
"tag_string" => "#diaspora #linux #partying"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it "imports the profile data" do
|
||||||
|
expect {
|
||||||
|
archive_importer.import
|
||||||
|
}.not_to raise_error
|
||||||
|
|
||||||
|
expect(archive_importer.user.profile.first_name).to eq("First")
|
||||||
|
expect(archive_importer.user.profile.last_name).to eq("Last")
|
||||||
|
expect(archive_importer.user.profile.image_url).to eq("https://example.com/my_avatar.png")
|
||||||
|
expect(archive_importer.user.profile.bio).to eq("I'm just a test account")
|
||||||
|
expect(archive_importer.user.profile.gender).to eq("Robot")
|
||||||
|
expect(archive_importer.user.profile.birthday).to eq(Date.new(2006, 1, 1))
|
||||||
|
expect(archive_importer.user.profile.location).to eq("diaspora* specs")
|
||||||
|
expect(archive_importer.user.profile.searchable).to eq(false)
|
||||||
|
expect(archive_importer.user.profile.public_details).to eq(true)
|
||||||
|
expect(archive_importer.user.profile.nsfw).to eq(true)
|
||||||
|
expect(archive_importer.user.profile.tag_string).to eq("#diaspora #linux #partying")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not overwrite profile if import_profile is disabled" do
|
||||||
|
original_profile = target.profile.dup
|
||||||
|
|
||||||
|
expect {
|
||||||
|
archive_importer.import(import_profile: false)
|
||||||
|
}.not_to raise_error
|
||||||
|
|
||||||
|
expect(archive_importer.user.profile.first_name).to eq(original_profile.first_name)
|
||||||
|
expect(archive_importer.user.profile.last_name).to eq(original_profile.last_name)
|
||||||
|
expect(archive_importer.user.profile.image_url).to eq(original_profile.image_url)
|
||||||
|
expect(archive_importer.user.profile.bio).to eq(original_profile.bio)
|
||||||
|
expect(archive_importer.user.profile.gender).to eq(original_profile.gender)
|
||||||
|
expect(archive_importer.user.profile.birthday).to eq(original_profile.birthday)
|
||||||
|
expect(archive_importer.user.profile.location).to eq(original_profile.location)
|
||||||
|
expect(archive_importer.user.profile.searchable).to eq(original_profile.searchable)
|
||||||
|
expect(archive_importer.user.profile.public_details).to eq(original_profile.public_details)
|
||||||
|
expect(archive_importer.user.profile.nsfw).to eq(original_profile.nsfw)
|
||||||
|
expect(archive_importer.user.profile.tag_string).to eq(original_profile.tag_string)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#create_user" do
|
describe "#find_or_create_user" do
|
||||||
let(:archive_importer) { ArchiveImporter.new(archive_hash) }
|
|
||||||
let(:archive_hash) {
|
let(:archive_hash) {
|
||||||
{
|
{
|
||||||
"user" => {
|
"user" => {
|
||||||
"profile" => {
|
"profile" => {
|
||||||
"entity_data" => {
|
"entity_data" => {
|
||||||
"author" => "old_id@old_pod.nowhere",
|
"author" => "old_id@old_pod.nowhere",
|
||||||
"first_name" => "First",
|
"first_name" => "First",
|
||||||
|
|
@ -133,26 +237,17 @@ describe ArchiveImporter do
|
||||||
"tag_string" => "#diaspora #linux #partying"
|
"tag_string" => "#diaspora #linux #partying"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"email" => "user@example.com",
|
"email" => "user@example.com"
|
||||||
"strip_exif" => false,
|
|
||||||
"show_community_spotlight_in_stream" => false,
|
|
||||||
"language" => "ru",
|
|
||||||
"disable_mail" => false,
|
|
||||||
"auto_follow_back" => true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let(:archive_importer) { ArchiveImporter.new(archive_hash) }
|
||||||
|
|
||||||
it "creates user" do
|
it "creates user" do
|
||||||
expect {
|
expect {
|
||||||
archive_importer.create_user(username: "new_name", password: "123456")
|
archive_importer.find_or_create_user(username: "new_name", password: "123456")
|
||||||
}.to change(User, :count).by(1)
|
}.to change(User, :count).by(1)
|
||||||
expect(archive_importer.user.email).to eq("user@example.com")
|
expect(archive_importer.user.email).to eq("user@example.com")
|
||||||
expect(archive_importer.user.strip_exif).to eq(false)
|
|
||||||
expect(archive_importer.user.show_community_spotlight_in_stream).to eq(false)
|
|
||||||
expect(archive_importer.user.language).to eq("ru")
|
|
||||||
expect(archive_importer.user.disable_mail).to eq(false)
|
|
||||||
expect(archive_importer.user.auto_follow_back).to eq(true)
|
|
||||||
expect(archive_importer.user.getting_started).to be_falsey
|
expect(archive_importer.user.getting_started).to be_falsey
|
||||||
|
|
||||||
expect(archive_importer.user.profile.first_name).to eq("First")
|
expect(archive_importer.user.profile.first_name).to eq("First")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue