Skip to content
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

Merge users through the console #3327

Merged
merged 22 commits into from
Feb 1, 2022
Merged

Conversation

jorg-vr
Copy link
Contributor

@jorg-vr jorg-vr commented Jan 24, 2022

This pull request adds a function merge_into to the user model. This function can be used to merge two user from the command line.

Also added an error if the two users don't have the same permissions. This error can be circumvented by using force, in which case the highest permissions will be kept for the new user.

For overlapping unique properties, such as right_requests, read_states and identities the values of other are kept.
For overlapping course memberships, the highest permission is kept.

I have added a rake task to run this from a command line interface: (Without rails console)
example input: invalid, swap, yes
image

  • Tests were added

Closes #2668 .

@jorg-vr jorg-vr self-assigned this Jan 24, 2022
@jorg-vr jorg-vr marked this pull request as ready for review January 26, 2022 09:58
@jorg-vr jorg-vr requested a review from a team as a code owner January 26, 2022 09:58
@jorg-vr jorg-vr requested review from bmesuere and niknetniko and removed request for a team January 26, 2022 09:58
@jorg-vr jorg-vr added the feature New feature or request label Jan 26, 2022
Copy link
Member

@bmesuere bmesuere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 This will certainly be useful. I have added a few remarks below.

Comment on lines 299 to 304
other.permission = permission if (permission == 'staff' && other.permission == 'student') \
|| (permission == 'zeus' && other.permission != 'zeus')

other.institution_id = institution_id if other.institution_id.nil?

rights_request.update(user: other) if !rights_request.nil? && other.permission == 'student' && other.rights_request.nil?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these "if modifiers" enforced by rubocop? If they are more complex like the first and third one, a classical if seems more appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are indeed enforced by rubocop

Comment on lines 306 to 312
submissions.each { |s| s.update(user: other) }
api_tokens.each { |at| at.update(user: other) }
events.each { |e| e.update(user: other) }
exports.each { |e| e.update(user: other) }
notifications.each { |n| n.update(user: other) }
annotations.each { |a| a.update(user: other, last_updated_by_id: other.id) }
questions.each { |q| q.update(user: other) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these updates and the ones below cover most aspects of our users. Some open thoughts:

  • How do we handle grading?
  • Calling update on each of these will generate a huge number of queries, especially for submissions. Using update_all will do this in a single query, but will skip all validations and callbacks. It might be worth checking if update_all can be used for submissions and read states.
  • Somewhat linked with the previous point: the necessary caches should be invalidated (e.g. the number of users that solved an exercise within a course). This might happen automatically using the callbacks/validations but it should be double checked.
  • You of course added some tests, but I was curious if you checked the order of the updates. For example, validations (or cache recalculations) that might fail if a users has submissions in a course which he is at that moment not a member off (the membership is updated last).

Copy link
Contributor Author

@jorg-vr jorg-vr Jan 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I indeed seem to have forgotten about grading (As it was not mentioned as a relationship at the top of the model) Will add code for evaluations

Will explore the update_all statements

I have not yet checked any cached values, will do this now :)

Order of updates has not caused me any trouble in my manual testing. But I see this is not explicitly tested in the test cases, so I will expand upon this to make sure this does not cause any errors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Grading:
I have added a merge of evaluation users. When two users appear in the same evaluation I keep the evaluation of other.
I am hesitating to just block the merge of users in this case, because removing the grades of a user without manually checking which grade is most applicable can led to real world issues. It also should not happen very often, so it is acceptable to break here, and force this merge to be done manually.

On update_all:
This indeed forgoes validations, which breaks caching. I am weary to combine an update all statement with a custom rewrite of the applicable validations, as this code will diverge over time from the actual validations that need to happen .

On caching:
I have added tests to validate some cached parameters. These broke when testing the update_all statements for example

On order:
In general it seems possible to have submissions linked to a course which you are not a member of. So i was unable to produce failing tests. Yet I did update the order a bit to be more logical in case later validations are written that break this. (Although there will always be inconsistencies while the merge is in progress)

lib/tasks/merge_users.rake Show resolved Hide resolved
Copy link
Member

@chvp chvp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I don't have any comments other than what was already mentioned by Bart or Niko.

Copy link
Member

@bmesuere bmesuere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok for me, but I would like approval from @niknetniko before merging.

Copy link
Member

@niknetniko niknetniko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 👍

@jorg-vr jorg-vr merged commit fb47c52 into develop Feb 1, 2022
@jorg-vr jorg-vr deleted the feature/2668-merge-users-console branch February 1, 2022 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Merge users through the console
4 participants