Repository: django/django
File: tests/auth_tests/test_management.py (Python)

Code before:


@override_settings(
    MIGRATION_MODULES=dict(
        settings.MIGRATION_MODULES,
        auth_tests="auth_tests.operations_migrations",
    ),
)
class PermissionRenameOperationsTests(TransactionTestCase):
    available_apps = [
        "django.contrib.contenttypes",
        "django.contrib.auth",
        "auth_tests",
    ]

    def test_permission_rename(self):
        ct = ContentType.objects.create(app_label="auth_tests", model="oldmodel")
        actions = ["add", "change", "delete", "view"]
        for action in actions:
            Permission.objects.create(
                codename=f"{action}_oldmodel",
                name=f"Can {action} old model",
                content_type=ct,
            )

        call_command("migrate", "auth_tests", verbosity=0)
        for action in actions:
            self.assertFalse(
                Permission.objects.filter(codename=f"{action}_oldmodel").exists()
            )
            self.assertTrue(
                Permission.objects.filter(codename=f"{action}_newmodel").exists()
            )

        call_command(
            "migrate",
            "auth_tests",
            "zero",
            database="default",
            interactive=False,
            verbosity=0,
        )

        for action in actions:
            self.assertTrue(
                Permission.objects.filter(codename=f"{action}_oldmodel").exists()
            )
            self.assertFalse(
                Permission.objects.filter(codename=f"{action}_newmodel").exists()
            )


Review comment (security):
I think it would be simpler & model some realism to rely on the behavior of the post_migrate handler, so just migrate one step:
```suggestion
        # Create initial content type and permissions for OldModel.
        call_command("migrate", "auth_tests", "0001", verbosity=0)

        # Apply the migration that renames OldModel to NewModel.
        call_command("migrate", "auth_tests", "0002", verbosity=0)
        actions = ContentType._meta.default_permissions
```

Code after:

@override_settings(
    MIGRATION_MODULES=dict(
        settings.MIGRATION_MODULES,
        auth_tests="auth_tests.operations_migrations",
    ),
)
class PermissionRenameOperationsTests(TransactionTestCase):
    available_apps = [
        "django.contrib.contenttypes",
        "django.contrib.auth",
        "auth_tests",
    ]

    databases = {"default", "other"}

    def setUp(self):
        self.stdout = StringIO()
        self.addCleanup(self.stdout.close)

    def test_permission_rename(self):
        # Create initial content type and permissions for OldModel.
        call_command("migrate", "auth_tests", "0001", verbosity=0)
        # Apply the migration that renames OldModel to NewModel.
        call_command("migrate", "auth_tests", "0002", verbosity=0)

        actions = ContentType._meta.default_permissions

        for action in actions:
            self.assertFalse(
                Permission.objects.filter(codename=f"{action}_oldmodel").exists()
            )
            self.assertTrue(
                Permission.objects.filter(codename=f"{action}_newmodel").exists()
            )

        # Unapply that migration, renaming NewModel back to OldModel.
        call_command(
            "migrate",
            "auth_tests",
            "0001",
            database="default",
            interactive=False,
            verbosity=0,
        )

        for action in actions:
            self.assertTrue(
                Permission.objects.filter(codename=f"{action}_oldmodel").exists()
            )
            self.assertFalse(