__init__.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. """
  2. Creates permissions for all installed apps that need permissions.
  3. """
  4. from __future__ import unicode_literals
  5. import getpass
  6. import unicodedata
  7. from django.apps import apps
  8. from django.contrib.auth import get_permission_codename
  9. from django.core import exceptions
  10. from django.db import DEFAULT_DB_ALIAS, router
  11. from django.utils import six
  12. from django.utils.encoding import DEFAULT_LOCALE_ENCODING
  13. def _get_all_permissions(opts):
  14. """
  15. Returns (codename, name) for all permissions in the given opts.
  16. """
  17. builtin = _get_builtin_permissions(opts)
  18. custom = list(opts.permissions)
  19. return builtin + custom
  20. def _get_builtin_permissions(opts):
  21. """
  22. Returns (codename, name) for all autogenerated permissions.
  23. By default, this is ('add', 'change', 'delete')
  24. """
  25. perms = []
  26. for action in opts.default_permissions:
  27. perms.append((
  28. get_permission_codename(action, opts),
  29. 'Can %s %s' % (action, opts.verbose_name_raw)
  30. ))
  31. return perms
  32. def create_permissions(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs):
  33. if not app_config.models_module:
  34. return
  35. try:
  36. Permission = apps.get_model('auth', 'Permission')
  37. except LookupError:
  38. return
  39. if not router.allow_migrate_model(using, Permission):
  40. return
  41. from django.contrib.contenttypes.models import ContentType
  42. # This will hold the permissions we're looking for as
  43. # (content_type, (codename, name))
  44. searched_perms = list()
  45. # The codenames and ctypes that should exist.
  46. ctypes = set()
  47. for klass in app_config.get_models():
  48. # Force looking up the content types in the current database
  49. # before creating foreign keys to them.
  50. ctype = ContentType.objects.db_manager(using).get_for_model(klass)
  51. ctypes.add(ctype)
  52. for perm in _get_all_permissions(klass._meta):
  53. searched_perms.append((ctype, perm))
  54. # Find all the Permissions that have a content_type for a model we're
  55. # looking for. We don't need to check for codenames since we already have
  56. # a list of the ones we're going to create.
  57. all_perms = set(Permission.objects.using(using).filter(
  58. content_type__in=ctypes,
  59. ).values_list(
  60. "content_type", "codename"
  61. ))
  62. perms = [
  63. Permission(codename=codename, name=name, content_type=ct)
  64. for ct, (codename, name) in searched_perms
  65. if (ct.pk, codename) not in all_perms
  66. ]
  67. Permission.objects.using(using).bulk_create(perms)
  68. if verbosity >= 2:
  69. for perm in perms:
  70. print("Adding permission '%s'" % perm)
  71. def get_system_username():
  72. """
  73. Try to determine the current system user's username.
  74. :returns: The username as a unicode string, or an empty string if the
  75. username could not be determined.
  76. """
  77. try:
  78. result = getpass.getuser()
  79. except (ImportError, KeyError):
  80. # KeyError will be raised by os.getpwuid() (called by getuser())
  81. # if there is no corresponding entry in the /etc/passwd file
  82. # (a very restricted chroot environment, for example).
  83. return ''
  84. if six.PY2:
  85. try:
  86. result = result.decode(DEFAULT_LOCALE_ENCODING)
  87. except UnicodeDecodeError:
  88. # UnicodeDecodeError - preventive treatment for non-latin Windows.
  89. return ''
  90. return result
  91. def get_default_username(check_db=True):
  92. """
  93. Try to determine the current system user's username to use as a default.
  94. :param check_db: If ``True``, requires that the username does not match an
  95. existing ``auth.User`` (otherwise returns an empty string).
  96. :returns: The username, or an empty string if no username can be
  97. determined.
  98. """
  99. # This file is used in apps.py, it should not trigger models import.
  100. from django.contrib.auth import models as auth_app
  101. # If the User model has been swapped out, we can't make any assumptions
  102. # about the default user name.
  103. if auth_app.User._meta.swapped:
  104. return ''
  105. default_username = get_system_username()
  106. try:
  107. default_username = (
  108. unicodedata.normalize('NFKD', default_username)
  109. .encode('ascii', 'ignore').decode('ascii')
  110. .replace(' ', '').lower()
  111. )
  112. except UnicodeDecodeError:
  113. return ''
  114. # Run the username validator
  115. try:
  116. auth_app.User._meta.get_field('username').run_validators(default_username)
  117. except exceptions.ValidationError:
  118. return ''
  119. # Don't return the default username if it is already taken.
  120. if check_db and default_username:
  121. try:
  122. auth_app.User._default_manager.get(username=default_username)
  123. except auth_app.User.DoesNotExist:
  124. pass
  125. else:
  126. return ''
  127. return default_username