Repository: learningequality/kolibri

Issue:
can no longer sign in using a pre-existing superuser account after upgrade
It appears that my superuser account is no longer available since upgrading to the latest develop. 

I would have expected it to get migrated to an admin account with superuser flags enabled.

It actually looks like the user might still be there:

![image](https://user-images.githubusercontent.com/2367265/29852726-81f2b1b4-8cf0-11e7-9b0a-adb9fb0cb264.png)




Discussion:
Yeah, replicated this issue. Guessing the password setting during migration is not working as expected.
Actually - that doesn't seem to be the issue, as I can still login through the Django admin login with this user without problems. Will investigate further.
It seems like the wrong facility id is being assigned to the superuser. Not happy, not happy at all.
Can confirm that this happens if there are any other collections with a 'lower' id than the facility. It seems that inside the Django data migration the differences between Proxy Models are not recognized, and so it just grabs the first Collection, rather than the first Facility.

Resolving patch:
diff --git a/kolibri/auth/migrations/0004_auto_20170816_1607.py b/kolibri/auth/migrations/0004_auto_20170816_1607.py
--- a/kolibri/auth/migrations/0004_auto_20170816_1607.py
+++ b/kolibri/auth/migrations/0004_auto_20170816_1607.py
@@ -8,17 +8,17 @@
 
 
 def device_owner_to_super_user(apps, schema_editor):
-    DeviceOwner = apps.get_model('kolibriauth', 'DeviceOwner')
-    FacilityUser = apps.get_model('kolibriauth', 'FacilityUser')
-    Facility = apps.get_model('kolibriauth', 'Facility')
-    default_facility = Facility.objects.all().first()
-    DevicePermissions = apps.get_model('device', 'DevicePermissions')
-    DeviceSettings = apps.get_model('device', 'DeviceSettings')
-    Role = apps.get_model('kolibriauth', 'Role')
     from kolibri.auth.models import FacilityUser as RealFacilityUser, Facility as RealFacility, Role as RealRole
     real_default_facility = RealFacility.get_default_facility()
     # Can't do much if no facilities exist, as no facility to FK the users onto
-    if default_facility:
+    if real_default_facility:
+        DeviceOwner = apps.get_model('kolibriauth', 'DeviceOwner')
+        FacilityUser = apps.get_model('kolibriauth', 'FacilityUser')
+        Facility = apps.get_model('kolibriauth', 'Facility')
+        default_facility = Facility.objects.get(pk=real_default_facility.id)
+        DevicePermissions = apps.get_model('device', 'DevicePermissions')
+        DeviceSettings = apps.get_model('device', 'DeviceSettings')
+        Role = apps.get_model('kolibriauth', 'Role')
         for device_owner in DeviceOwner.objects.all():
             dataset_id = real_default_facility.dataset_id
             real_superuser = RealFacilityUser(


Test patch:
diff --git a/kolibri/auth/test/test_data_migrations.py b/kolibri/auth/test/test_data_migrations.py
new file mode 100644
--- /dev/null
+++ b/kolibri/auth/test/test_data_migrations.py
@@ -0,0 +1,65 @@
+from django.test import TestCase
+from django.db.migrations.executor import MigrationExecutor
+from django.db import connection
+from kolibri.auth.models import Classroom, Facility, FacilityUser
+from kolibri.auth.constants.role_kinds import ADMIN
+
+# Modified from https://www.caktusgroup.com/blog/2016/02/02/writing-unit-tests-django-migrations/
+
+class TestMigrations(TestCase):
+
+    migrate_from = None
+    migrate_to = None
+    app = 'kolibriauth'
+
+    def setUp(self):
+        assert self.migrate_from and self.migrate_to, \
+            "TestCase '{}' must define migrate_from and migrate_to properties".format(type(self).__name__)
+
+        migrate_from = [(self.app, self.migrate_from)]
+        migrate_to = [(self.app, self.migrate_to)]
+        executor = MigrationExecutor(connection)
+        old_apps = executor.loader.project_state(migrate_from).apps
+
+        # Reverse to the original migration
+        executor.migrate(migrate_from)
+
+        self.setUpBeforeMigration(old_apps)
+
+        # Run the migration to test
+        executor = MigrationExecutor(connection)
+        executor.loader.build_graph()  # reload.
+        executor.migrate(migrate_to)
+
+        self.apps = executor.loader.project_state(migrate_to).apps
+
+    def setUpBeforeMigration(self, apps):
+        pass
+
+
+class MultipleCollectionTestCase(TestMigrations):
+
+    migrate_from = '0003_auto_20170621_0958'
+    migrate_to = '0004_auto_20170816_1607'
+
+    def setUp(self):
+        self.facility = Facility.objects.create(name='Test')
+        self.classroom = Classroom.objects.create(name='TestClass', parent=self.facility)
+        super(MultipleCollectionTestCase, self).setUp()
+
+    def setUpBeforeMigration(self, apps):
+        DeviceOwner = apps.get_model('kolibriauth', 'DeviceOwner')
+        deviceowner = DeviceOwner.objects.create(
+            username="test",
+        )
+        self.username = deviceowner.username
+
+    def test_username_migrated(self):
+        self.assertEqual(self.username, FacilityUser.objects.get().username)
+
+    def test_in_default_facility_migrated(self):
+        self.assertEqual(self.facility, FacilityUser.objects.get().facility)
+
+    def test_admin(self):
+        self.assertEqual(FacilityUser.objects.get().roles.first().collection, self.facility)
+        self.assertEqual(FacilityUser.objects.get().roles.first().kind, ADMIN)