import json import uuid from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.auth.models import Group, Permission from django.core.management import call_command from django.core.management.base import BaseCommand from swapper import get_model_name, load_model, split User = get_user_model() Topology = load_model('topology', 'Topology') Organization = load_model('openwisp_users', 'Organization') class BaseUpdateFromDjangoNetjsonGraph(BaseCommand): help = 'Upgrade from django-netjsongraph' app_label_users = split(get_model_name('openwisp_users', 'Organization'))[0] app_label = split(get_model_name('topology', 'Topology'))[0] def add_arguments(self, parser): parser.add_argument( '--backup', action='store', default=settings.BASE_DIR, help='(Optional) Path to the backup files', ) parser.add_argument( '--organization', action='store', default=None, help=( '(Optional) organization UUID of the organization in ' 'which you want to import the data.' ), ) def int_to_uuid(self, pk): return "00000000-0000-0000-0000-{:012}".format(pk) def _get_updated_permission_list( self, permission_data, permissions_list, contenttype_data ): permit_list = [] for permit_pk in permissions_list: for item in permission_data: if item['pk'] == permit_pk: for content in contenttype_data: if item['fields']['content_type'] == content['pk']: permit_app_label = content['fields']['app_label'] if permit_app_label == 'django_netjsongraph': permit_app_label = self.app_label elif ( content['fields']['model'] in ['user', 'group'] and permit_app_label == 'auth' ): permit_app_label = self.app_label_users try: permit_list.append( Permission.objects.get( content_type__app_label=permit_app_label, codename=item['fields']['codename'], ).pk ) except Permission.DoesNotExist: # pragma: nocover pass return permit_list def handle(self, *args, **options): if options['organization']: org = Organization.objects.get(pk=options['organization']) else: org = Organization.objects.first() # Netjsongraph Models with open(f'{options["backup"]}/netjsongraph.json') as netjsongraph: netjsongraph_data = json.load(netjsongraph) # Make changes for data in netjsongraph_data: data['fields']['organization'] = str(org.pk) data['model'] = f'{self.app_label}.{data["model"].split(".")[1]}' # Save in anotherfile with open(f'{options["backup"]}/netjsongraph_loaded.json', 'w') as outfile: json.dump(netjsongraph_data, outfile) # Load to database call_command( 'loaddata', f'{options["backup"]}/netjsongraph_loaded.json', verbosity=0 ) # Group Model with open(f'{options["backup"]}/contenttype.json') as contenttype: contenttype_data = json.load(contenttype) with open(f'{options["backup"]}/permission.json') as permission: permission_data = json.load(permission) with open(f'{options["backup"]}/group.json') as group: group_data = json.load(group) load_group_data = [] for data in group_data: if not Group.objects.filter(name=data['fields']['name']).exists(): load_group_data.append( { 'model': f'{self.app_label_users}.group', 'pk': data['pk'] + Group.objects.count(), 'fields': { 'name': data['fields']['name'], 'permissions': self._get_updated_permission_list( permission_data, data['fields']['permissions'], contenttype_data, ), }, } ) if load_group_data: # Save in anotherfile with open(f'{options["backup"]}/group_loaded.json', 'w') as outfile: json.dump(load_group_data, outfile) # Load to database call_command( 'loaddata', f'{options["backup"]}/group_loaded.json', verbosity=0 ) # User Model with open(f'{options["backup"]}/user.json') as users: users_data = json.load(users) # Make changes org_users_data = [] load_users_data = [] for data in users_data: data['model'] = f'{self.app_label_users}.user' data['pk'] = self.int_to_uuid(data['pk']) # If the user doesn't have an email, give them a # @example.com email but in openwisp-network-topology # email is UNIQUE. if not data['fields']['email']: data['fields']['email'] = f'{data["fields"]["username"]}@example.com' group_list = [] for group_pk in data['fields']['groups']: for item in group_data: if item['pk'] == group_pk: group_list.append( Group.objects.filter(name=item['fields']['name']).first().pk ) data['fields']['groups'] = group_list data['fields']['user_permissions'] = self._get_updated_permission_list( permission_data, data['fields']['user_permissions'], contenttype_data ) if not User.objects.filter(email=data['fields']['email']): load_users_data.append(data) if not data['fields']['is_superuser']: org_users_data.append( { 'model': f'{self.app_label_users}.organizationuser', 'pk': str(uuid.uuid4()), 'fields': { 'created': data['fields']['date_joined'], 'modified': data['fields']['date_joined'], 'is_admin': False, 'user': data['pk'], 'organization': str(org.pk), }, } ) load_users_data.extend(org_users_data) if load_users_data: # Save in anotherfile with open(f'{options["backup"]}/user_loaded.json', 'w') as outfile: json.dump(load_users_data, outfile) # Load to database call_command( 'loaddata', f'{options["backup"]}/user_loaded.json', verbosity=0 ) self.stdout.write(self.style.SUCCESS('Migration Process Complete!')) class Command(BaseUpdateFromDjangoNetjsonGraph): pass