1. from importlib import import_module
    
  2. 
    
  3. from django.apps import apps
    
  4. from django.contrib.auth.models import Permission, User
    
  5. from django.contrib.contenttypes.models import ContentType
    
  6. from django.db import connection, connections
    
  7. from django.test import TransactionTestCase
    
  8. from django.test.utils import captured_stdout
    
  9. 
    
  10. from .models import Proxy, UserProxy
    
  11. 
    
  12. update_proxy_permissions = import_module(
    
  13.     "django.contrib.auth.migrations.0011_update_proxy_permissions"
    
  14. )
    
  15. 
    
  16. 
    
  17. class ProxyModelWithDifferentAppLabelTests(TransactionTestCase):
    
  18.     available_apps = [
    
  19.         "auth_tests",
    
  20.         "django.contrib.auth",
    
  21.         "django.contrib.contenttypes",
    
  22.     ]
    
  23. 
    
  24.     def setUp(self):
    
  25.         """
    
  26.         Create proxy permissions with content_type to the concrete model
    
  27.         rather than the proxy model (as they were before Django 2.2 and
    
  28.         migration 11).
    
  29.         """
    
  30.         Permission.objects.all().delete()
    
  31.         self.concrete_content_type = ContentType.objects.get_for_model(UserProxy)
    
  32.         self.default_permission = Permission.objects.create(
    
  33.             content_type=self.concrete_content_type,
    
  34.             codename="add_userproxy",
    
  35.             name="Can add userproxy",
    
  36.         )
    
  37.         self.custom_permission = Permission.objects.create(
    
  38.             content_type=self.concrete_content_type,
    
  39.             codename="use_different_app_label",
    
  40.             name="May use a different app label",
    
  41.         )
    
  42. 
    
  43.     def test_proxy_model_permissions_contenttype(self):
    
  44.         proxy_model_content_type = ContentType.objects.get_for_model(
    
  45.             UserProxy, for_concrete_model=False
    
  46.         )
    
  47.         self.assertEqual(
    
  48.             self.default_permission.content_type, self.concrete_content_type
    
  49.         )
    
  50.         self.assertEqual(
    
  51.             self.custom_permission.content_type, self.concrete_content_type
    
  52.         )
    
  53.         with connection.schema_editor() as editor:
    
  54.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  55.         self.default_permission.refresh_from_db()
    
  56.         self.assertEqual(self.default_permission.content_type, proxy_model_content_type)
    
  57.         self.custom_permission.refresh_from_db()
    
  58.         self.assertEqual(self.custom_permission.content_type, proxy_model_content_type)
    
  59. 
    
  60.     def test_user_has_now_proxy_model_permissions(self):
    
  61.         user = User.objects.create()
    
  62.         user.user_permissions.add(self.default_permission)
    
  63.         user.user_permissions.add(self.custom_permission)
    
  64.         for permission in [self.default_permission, self.custom_permission]:
    
  65.             self.assertTrue(user.has_perm("auth." + permission.codename))
    
  66.             self.assertFalse(user.has_perm("auth_tests." + permission.codename))
    
  67.         with connection.schema_editor() as editor:
    
  68.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  69.         # Reload user to purge the _perm_cache.
    
  70.         user = User._default_manager.get(pk=user.pk)
    
  71.         for permission in [self.default_permission, self.custom_permission]:
    
  72.             self.assertFalse(user.has_perm("auth." + permission.codename))
    
  73.             self.assertTrue(user.has_perm("auth_tests." + permission.codename))
    
  74. 
    
  75.     def test_migrate_backwards(self):
    
  76.         with connection.schema_editor() as editor:
    
  77.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  78.             update_proxy_permissions.revert_proxy_model_permissions(apps, editor)
    
  79.         self.default_permission.refresh_from_db()
    
  80.         self.assertEqual(
    
  81.             self.default_permission.content_type, self.concrete_content_type
    
  82.         )
    
  83.         self.custom_permission.refresh_from_db()
    
  84.         self.assertEqual(
    
  85.             self.custom_permission.content_type, self.concrete_content_type
    
  86.         )
    
  87. 
    
  88.     def test_user_keeps_same_permissions_after_migrating_backward(self):
    
  89.         user = User.objects.create()
    
  90.         user.user_permissions.add(self.default_permission)
    
  91.         user.user_permissions.add(self.custom_permission)
    
  92.         for permission in [self.default_permission, self.custom_permission]:
    
  93.             self.assertTrue(user.has_perm("auth." + permission.codename))
    
  94.             self.assertFalse(user.has_perm("auth_tests." + permission.codename))
    
  95.         with connection.schema_editor() as editor:
    
  96.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  97.             update_proxy_permissions.revert_proxy_model_permissions(apps, editor)
    
  98.         # Reload user to purge the _perm_cache.
    
  99.         user = User._default_manager.get(pk=user.pk)
    
  100.         for permission in [self.default_permission, self.custom_permission]:
    
  101.             self.assertTrue(user.has_perm("auth." + permission.codename))
    
  102.             self.assertFalse(user.has_perm("auth_tests." + permission.codename))
    
  103. 
    
  104. 
    
  105. class ProxyModelWithSameAppLabelTests(TransactionTestCase):
    
  106.     available_apps = [
    
  107.         "auth_tests",
    
  108.         "django.contrib.auth",
    
  109.         "django.contrib.contenttypes",
    
  110.     ]
    
  111. 
    
  112.     def setUp(self):
    
  113.         """
    
  114.         Create proxy permissions with content_type to the concrete model
    
  115.         rather than the proxy model (as they were before Django 2.2 and
    
  116.         migration 11).
    
  117.         """
    
  118.         Permission.objects.all().delete()
    
  119.         self.concrete_content_type = ContentType.objects.get_for_model(Proxy)
    
  120.         self.default_permission = Permission.objects.create(
    
  121.             content_type=self.concrete_content_type,
    
  122.             codename="add_proxy",
    
  123.             name="Can add proxy",
    
  124.         )
    
  125.         self.custom_permission = Permission.objects.create(
    
  126.             content_type=self.concrete_content_type,
    
  127.             codename="display_proxys",
    
  128.             name="May display proxys information",
    
  129.         )
    
  130. 
    
  131.     def test_proxy_model_permissions_contenttype(self):
    
  132.         proxy_model_content_type = ContentType.objects.get_for_model(
    
  133.             Proxy, for_concrete_model=False
    
  134.         )
    
  135.         self.assertEqual(
    
  136.             self.default_permission.content_type, self.concrete_content_type
    
  137.         )
    
  138.         self.assertEqual(
    
  139.             self.custom_permission.content_type, self.concrete_content_type
    
  140.         )
    
  141.         with connection.schema_editor() as editor:
    
  142.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  143.         self.default_permission.refresh_from_db()
    
  144.         self.custom_permission.refresh_from_db()
    
  145.         self.assertEqual(self.default_permission.content_type, proxy_model_content_type)
    
  146.         self.assertEqual(self.custom_permission.content_type, proxy_model_content_type)
    
  147. 
    
  148.     def test_user_still_has_proxy_model_permissions(self):
    
  149.         user = User.objects.create()
    
  150.         user.user_permissions.add(self.default_permission)
    
  151.         user.user_permissions.add(self.custom_permission)
    
  152.         for permission in [self.default_permission, self.custom_permission]:
    
  153.             self.assertTrue(user.has_perm("auth_tests." + permission.codename))
    
  154.         with connection.schema_editor() as editor:
    
  155.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  156.         # Reload user to purge the _perm_cache.
    
  157.         user = User._default_manager.get(pk=user.pk)
    
  158.         for permission in [self.default_permission, self.custom_permission]:
    
  159.             self.assertTrue(user.has_perm("auth_tests." + permission.codename))
    
  160. 
    
  161.     def test_migrate_backwards(self):
    
  162.         with connection.schema_editor() as editor:
    
  163.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  164.             update_proxy_permissions.revert_proxy_model_permissions(apps, editor)
    
  165.         self.default_permission.refresh_from_db()
    
  166.         self.assertEqual(
    
  167.             self.default_permission.content_type, self.concrete_content_type
    
  168.         )
    
  169.         self.custom_permission.refresh_from_db()
    
  170.         self.assertEqual(
    
  171.             self.custom_permission.content_type, self.concrete_content_type
    
  172.         )
    
  173. 
    
  174.     def test_user_keeps_same_permissions_after_migrating_backward(self):
    
  175.         user = User.objects.create()
    
  176.         user.user_permissions.add(self.default_permission)
    
  177.         user.user_permissions.add(self.custom_permission)
    
  178.         for permission in [self.default_permission, self.custom_permission]:
    
  179.             self.assertTrue(user.has_perm("auth_tests." + permission.codename))
    
  180.         with connection.schema_editor() as editor:
    
  181.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  182.             update_proxy_permissions.revert_proxy_model_permissions(apps, editor)
    
  183.         # Reload user to purge the _perm_cache.
    
  184.         user = User._default_manager.get(pk=user.pk)
    
  185.         for permission in [self.default_permission, self.custom_permission]:
    
  186.             self.assertTrue(user.has_perm("auth_tests." + permission.codename))
    
  187. 
    
  188.     def test_migrate_with_existing_target_permission(self):
    
  189.         """
    
  190.         Permissions may already exist:
    
  191. 
    
  192.         - Old workaround was to manually create permissions for proxy models.
    
  193.         - Model may have been concrete and then converted to proxy.
    
  194. 
    
  195.         Output a reminder to audit relevant permissions.
    
  196.         """
    
  197.         proxy_model_content_type = ContentType.objects.get_for_model(
    
  198.             Proxy, for_concrete_model=False
    
  199.         )
    
  200.         Permission.objects.create(
    
  201.             content_type=proxy_model_content_type,
    
  202.             codename="add_proxy",
    
  203.             name="Can add proxy",
    
  204.         )
    
  205.         Permission.objects.create(
    
  206.             content_type=proxy_model_content_type,
    
  207.             codename="display_proxys",
    
  208.             name="May display proxys information",
    
  209.         )
    
  210.         with captured_stdout() as stdout:
    
  211.             with connection.schema_editor() as editor:
    
  212.                 update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  213.         self.assertIn(
    
  214.             "A problem arose migrating proxy model permissions", stdout.getvalue()
    
  215.         )
    
  216. 
    
  217. 
    
  218. class MultiDBProxyModelAppLabelTests(TransactionTestCase):
    
  219.     databases = {"default", "other"}
    
  220.     available_apps = [
    
  221.         "auth_tests",
    
  222.         "django.contrib.auth",
    
  223.         "django.contrib.contenttypes",
    
  224.     ]
    
  225. 
    
  226.     def setUp(self):
    
  227.         ContentType.objects.all().delete()
    
  228.         Permission.objects.using("other").delete()
    
  229.         concrete_content_type = ContentType.objects.db_manager("other").get_for_model(
    
  230.             Proxy
    
  231.         )
    
  232.         self.permission = Permission.objects.using("other").create(
    
  233.             content_type=concrete_content_type,
    
  234.             codename="add_proxy",
    
  235.             name="Can add proxy",
    
  236.         )
    
  237. 
    
  238.     def test_migrate_other_database(self):
    
  239.         proxy_model_content_type = ContentType.objects.db_manager(
    
  240.             "other"
    
  241.         ).get_for_model(Proxy, for_concrete_model=False)
    
  242.         with connections["other"].schema_editor() as editor:
    
  243.             update_proxy_permissions.update_proxy_model_permissions(apps, editor)
    
  244.         self.permission.refresh_from_db()
    
  245.         self.assertEqual(self.permission.content_type, proxy_model_content_type)