Skip to content
Snippets Groups Projects
migrate_users.py 2.96 KiB
Newer Older
  • Learn to ignore specific revisions
  • Dan Braghis's avatar
    Dan Braghis committed
    import argparse
    import json
    
    
    Dan Braghis's avatar
    Dan Braghis committed
    from django.conf import settings
    
    Dan Braghis's avatar
    Dan Braghis committed
    from django.contrib.auth import get_user_model
    
    Dan Braghis's avatar
    Dan Braghis committed
    from django.contrib.auth.models import Group
    
    Dan Braghis's avatar
    Dan Braghis committed
    from django.core.management.base import BaseCommand
    
    from django.db import transaction
    
    Dan Braghis's avatar
    Dan Braghis committed
    from opentech.apply.users.groups import STAFF_GROUP_NAME
    
    
    Dan Braghis's avatar
    Dan Braghis committed
    
    class Command(BaseCommand):
        help = "User migration script. Requires a source JSON file."
    
    Dan Braghis's avatar
    Dan Braghis committed
        groups = Group.objects.all()
    
    Dan Braghis's avatar
    Dan Braghis committed
    
        def add_arguments(self, parser):
    
    Dan Braghis's avatar
    Dan Braghis committed
            parser.add_argument('source', type=argparse.FileType('r'), help='Migration source JSON file')
    
        @transaction.atomic
    
    Dan Braghis's avatar
    Dan Braghis committed
        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]
    
    
    Dan Braghis's avatar
    Dan Braghis committed
                    full_name = self.get_full_name(user)
                    user_object, created = User.objects.get_or_create(
    
    Dan Braghis's avatar
    Dan Braghis committed
                        email=user.get('mail'),
    
    Dan Braghis's avatar
    Dan Braghis committed
                        defaults={
                            'full_name': full_name,
                            'drupal_id': uid,
                        }
    
    Dan Braghis's avatar
    Dan Braghis committed
                    operation = "Imported" if created else "Processed"
    
    Dan Braghis's avatar
    Dan Braghis committed
    
    
    Dan Braghis's avatar
    Dan Braghis committed
                    groups = self.get_user_groups(user)
                    user_object.groups.set(groups)
    
    Dan Braghis's avatar
    Dan Braghis committed
    
                    # Ensure uid is set
                    user_object.drupal_id = uid
    
    Dan Braghis's avatar
    Dan Braghis committed
                    user_object.save()
    
    
    Dan Braghis's avatar
    Dan Braghis committed
                    self.stdout.write(f"{operation} user {uid} ({full_name})")
    
    Dan Braghis's avatar
    Dan Braghis committed
        def get_full_name(self, user):
            full_name = user.get('field_otf_real_name', None)
            try:
    
    Dan Braghis's avatar
    Dan Braghis committed
                """
                Drupal is i18n-ready out of the box. As such, the data
                structure includes a language reference, defaulting to 'und' (undefined)
                In addition to that, most fields are arrays indexed by language, and
                the value delta. Different field types will have a different value.
                Native entity fields are loaded directly (as string or int). They are
                things like entity id, owner, created/updated timestamp.
                And name/mail on users.
                """
    
    Dan Braghis's avatar
    Dan Braghis committed
                full_name = full_name['und'][0]['safe_value']
            except (KeyError, TypeError):
                full_name = user.get('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