From efdbe1f3b1d425c4ca7bf11114e192630dc37661 Mon Sep 17 00:00:00 2001 From: George Babey <gbabey@edx.org> Date: Thu, 30 Jan 2020 13:32:25 -0500 Subject: [PATCH] Adds management command for bulk updating email addresses This PR adds a management command that will update the email address of the given accounts provided through a CSV file. This is necessary internally at edX to update a number of internal accounts which are using sibling email addresses and would be locked out after we enforce SSO. --- .../management/commands/bulk_update_email.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 common/djangoapps/student/management/commands/bulk_update_email.py diff --git a/common/djangoapps/student/management/commands/bulk_update_email.py b/common/djangoapps/student/management/commands/bulk_update_email.py new file mode 100644 index 00000000000..1f53ea0efd5 --- /dev/null +++ b/common/djangoapps/student/management/commands/bulk_update_email.py @@ -0,0 +1,76 @@ +""" +Management command to bulk update many user's email addresses +""" + + +import csv +import logging +from os import path + +from django.core.management.base import BaseCommand, CommandError + +from django.contrib.auth import get_user_model + +logger = logging.getLogger('student.management.commands.bulk_update_email') + + +class Command(BaseCommand): + """ + Management command to bulk update many user's email addresses + """ + + help = """ + Change the email address of each user specified in the csv file + + csv file is expected to have one row per user with the format: + current_email_address, new_email_address + + Example: + $ ... bulk_update_email csv_file_path + """ + + def add_arguments(self, parser): + """ Add argument to the command parser. """ + parser.add_argument( + '--csv_file_path', + required=True, + help='Csv file path' + ) + + def handle(self, *args, **options): + """ Main handler for the command.""" + file_path = options['csv_file_path'] + + if not path.isfile(file_path): + raise CommandError('File not found.') + + with open(file_path, 'r') as csv_file: + csv_reader = csv.reader(csv_file) + + email_mappings = [ + (current_email, new_email) + for (current_email, new_email) + in csv_reader + ] + + successful_updates = [] + failed_updates = [] + + for (current_email, new_email) in email_mappings: + try: + user = get_user_model().objects.get(email=current_email) + user.email = new_email + user.save() + successful_updates.append(new_email) + except Exception: # pylint: disable=broad-except + logger.exception('Unable to update account %s', current_email) + failed_updates.append(current_email) + + logger.info( + 'Successfully updated %s accounts. Failed to update %s accounts', + len(successful_updates), + len(failed_updates) + ) + + if (failed_updates): + exit(-1) -- GitLab