diff --git a/opentech/apply/users/management/__init__.py b/opentech/apply/users/management/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/opentech/apply/users/management/commands/__init__.py b/opentech/apply/users/management/commands/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/opentech/apply/users/management/commands/migrate_users.py b/opentech/apply/users/management/commands/migrate_users.py new file mode 100644 index 0000000000000000000000000000000000000000..f77444311de91d7fe1fbd37862104ffbccdda83d --- /dev/null +++ b/opentech/apply/users/management/commands/migrate_users.py @@ -0,0 +1,80 @@ +import argparse +import json + +from django.conf import settings +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group +from django.core.management.base import BaseCommand +from django.db import transaction + +from opentech.apply.users.groups import STAFF_GROUP_NAME + + +class Command(BaseCommand): + help = "User migration script. Requires a source JSON file." + groups = Group.objects.all() + + def add_arguments(self, parser): + parser.add_argument('source', type=argparse.FileType('r'), help='Migration source JSON file') + + @transaction.atomic + def handle(self, *args, **options): + with options['source'] as json_data: + User = get_user_model() + users = json.load(json_data) + + for uid in users: + user = users[uid] + + full_name = self.get_full_name(user) + user_object, created = User.objects.get_or_create( + email=user['mail'], + defaults={ + 'full_name': full_name, + 'drupal_id': uid, + } + ) + + operation = "Imported" if created else "Processed" + + groups = self.get_user_groups(user) + user_object.groups.set(groups) + + # Ensure uid is set + user_object.drupal_id = uid + user_object.save() + + self.stdout.write(f"{operation} user {uid} ({full_name})") + + def get_full_name(self, user): + full_name = user.get('field_otf_real_name', None) + try: + # The Drupal data structure includes a language reference. + # The default is 'und' (undefined). + full_name = full_name['und'][0]['safe_value'] + except (KeyError, TypeError): + full_name = user['name'] + + return full_name + + def get_user_groups(self, user): + groups = [] + role_map = { + 'proposer': 'Applicant', + 'council': 'Advisor', + 'administrator': 'Administrator', + 'dev': 'Administrator', + } + + _, email_domain = user.get('mail').split('@') + if email_domain in settings.STAFF_EMAIL_DOMAINS: + groups.append(self.groups.filter(name=STAFF_GROUP_NAME).first()) + + roles = [role for role in user.get('roles').values() if role != "authenticated user"] + + for role in roles: + group_name = role_map.get(role) + if group_name: + groups.append(self.groups.filter(name=group_name).first()) + + return groups diff --git a/opentech/apply/users/migrations/0005_user_drupal_id.py b/opentech/apply/users/migrations/0005_user_drupal_id.py new file mode 100644 index 0000000000000000000000000000000000000000..662c55217d96a415dcca24a8a5c7564c788a9534 --- /dev/null +++ b/opentech/apply/users/migrations/0005_user_drupal_id.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-02-28 15:21 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0004_drop_first_last_names'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='drupal_id', + field=models.IntegerField(blank=True, editable=False, null=True), + ), + ] diff --git a/opentech/apply/users/models.py b/opentech/apply/users/models.py index 9e867ab9b60c9d430a1e0f79825514b20d043249..f4d22666087e3159ec7d4266bb9513d6b4f591ef 100644 --- a/opentech/apply/users/models.py +++ b/opentech/apply/users/models.py @@ -48,6 +48,9 @@ class User(AbstractUser): email = models.EmailField(_('email address'), unique=True) full_name = models.CharField(verbose_name='Full name', max_length=255, blank=True) + # Meta: used for migration purposes only + drupal_id = models.IntegerField(null=True, blank=True, editable=False) + USERNAME_FIELD = 'email' REQUIRED_FIELDS = []