-
Notifications
You must be signed in to change notification settings - Fork 52
Merge accounts #1683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Merge accounts #1683
Changes from all commits
7533775
92fc04a
beb336d
8a5f37c
c58e87b
7a90b11
525d8f1
c43cdae
a34e8c0
1daacd7
f0b8dbf
4802091
5e1f0c9
7a34d00
9f7ce4c
ec4c515
003c0ce
ebb6463
40fcf76
8d64fe9
8938b7a
35536fa
f19cc32
122eb02
84926ca
a436c70
6e2b09b
e7b8efc
4cbc593
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
module Seek | ||
module Merging | ||
module PersonMerge | ||
def merge(other_person) | ||
Person.transaction do | ||
merge_simple_attributes(other_person) | ||
merge_annotations(other_person) | ||
# Roles have to be merged before group_memberships | ||
merge_associations(other_person, 'roles', %i[scope_type scope_id role_type_id], { person_id: id }) | ||
# Merging group_memberships deals with work_groups, programmes, institutions and projects | ||
merge_associations(other_person, 'group_memberships', [:work_group_id], { person_id: id }) | ||
merge_associations(other_person, 'subscriptions', [:subscribable_id], { person_id: id }) | ||
merge_associations(other_person, 'dependent_permissions', [:policy_id], { contributor_id: id }) | ||
merge_resources(other_person) | ||
merge_user(other_person) | ||
|
||
save! | ||
other_person.reload # To prevent destruction of unlinked roles | ||
other_person.destroy! | ||
ActivityLog.create!(action: 'MERGE-person', | ||
data: "Person with id #{other_person.id} was merged into person with id #{id}.") | ||
end | ||
end | ||
|
||
private | ||
|
||
def merge_simple_attributes(other_person) | ||
# This attributes are directly copied from other_person if they are empty in the person to which its merging. | ||
# first_letter is also updated | ||
simple_attributes = %i[first_name last_name email phone skype_name web_page description avatar_id orcid] | ||
simple_attributes.each do |attribute| | ||
send("#{attribute}=", other_person.send(attribute)) if send(attribute).nil? | ||
end | ||
update_first_letter | ||
end | ||
|
||
def merge_annotations(other_person) | ||
annotation_types = %w[expertise tools] | ||
annotation_types.each do |annotation_type| | ||
add_annotations(send(annotation_type) + other_person.send(annotation_type), annotation_type.singularize, self) | ||
end | ||
|
||
# Update annotations by other_user | ||
return unless user && other_person.user | ||
|
||
merge_user_associations(other_person, 'annotations_by', | ||
%i[annotatable_type annotatable_id value_id], | ||
{ source_id: user.id }) | ||
end | ||
|
||
def merge_resources(other_person) | ||
# Contributed | ||
Person::RELATED_RESOURCE_TYPES.each do |resource_type| | ||
other_person.send("contributed_#{resource_type.underscore.pluralize}").in_batches.update_all(contributor_id: id) | ||
end | ||
# Created | ||
duplicated = other_person.created_items.pluck(:id) & created_items.pluck(:id) | ||
AssetsCreator.where(creator_id: other_person.id, asset_id: duplicated).in_batches.destroy_all | ||
AssetsCreator.where(creator_id: other_person.id).in_batches.update_all(creator_id: id) | ||
end | ||
|
||
def merge_associations(other_person, assoc, duplicates_match, update_hash) | ||
other_items = other_person.send(assoc).pluck(*duplicates_match) | ||
self_items = send(assoc).pluck(*duplicates_match) | ||
duplicated = other_items & self_items | ||
duplicated = duplicated.map { |item| [item] } if duplicates_match.length == 1 | ||
|
||
duplicated_hash = Hash[duplicates_match.zip(duplicated.transpose)] | ||
other_person.send(assoc).where(duplicated_hash).in_batches.destroy_all | ||
|
||
other_person.send(assoc).in_batches.update_all(update_hash) | ||
end | ||
|
||
def merge_user(other_person) | ||
return unless user && other_person.user | ||
|
||
merge_user_associations(other_person, 'identities', | ||
%i[provider uid], { user_id: user.id }) | ||
merge_user_associations(other_person, 'oauth_applications', | ||
%i[redirect_uri scopes], { owner_id: user.id }) | ||
merge_user_associations(other_person, 'access_tokens', | ||
%i[application_id scopes], { resource_owner_id: user.id }) | ||
merge_user_associations(other_person, 'access_grants', | ||
%i[application_id redirect_uri scopes], { resource_owner_id: user.id }) | ||
end | ||
Comment on lines
+74
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the auth lookup table should update automatically. rows will be removed when the user is destroyed (another case where we can enhance the delete_all). After it's merged I also plan to check what jobs get created, or whether it just needs a job firing at the end |
||
|
||
def merge_user_associations(other_person, assoc, duplicates_match, update_hash) | ||
other_items = other_person.user.send(assoc).pluck(*duplicates_match) | ||
self_items = user.send(assoc).pluck(*duplicates_match) | ||
duplicated = other_items & self_items | ||
duplicated = duplicated.map { |item| [item] } if duplicates_match.length == 1 | ||
|
||
duplicated_hash = Hash[duplicates_match.zip(duplicated.transpose)] | ||
other_person.user.send(assoc).where(duplicated_hash).in_batches.destroy_all | ||
|
||
other_person.user.send(assoc).in_batches.update_all(update_hash) | ||
end | ||
|
||
end | ||
end | ||
end |
Uh oh!
There was an error while loading. Please reload this page.