Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

checks.py 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. from itertools import chain
  2. from types import MethodType
  3. from django.apps import apps
  4. from django.conf import settings
  5. from django.core import checks
  6. from .management import _get_builtin_permissions
  7. def check_user_model(app_configs=None, **kwargs):
  8. if app_configs is None:
  9. cls = apps.get_model(settings.AUTH_USER_MODEL)
  10. else:
  11. app_label, model_name = settings.AUTH_USER_MODEL.split(".")
  12. for app_config in app_configs:
  13. if app_config.label == app_label:
  14. cls = app_config.get_model(model_name)
  15. break
  16. else:
  17. # Checks might be run against a set of app configs that don't
  18. # include the specified user model. In this case we simply don't
  19. # perform the checks defined below.
  20. return []
  21. errors = []
  22. # Check that REQUIRED_FIELDS is a list
  23. if not isinstance(cls.REQUIRED_FIELDS, (list, tuple)):
  24. errors.append(
  25. checks.Error(
  26. "'REQUIRED_FIELDS' must be a list or tuple.",
  27. obj=cls,
  28. id="auth.E001",
  29. )
  30. )
  31. # Check that the USERNAME FIELD isn't included in REQUIRED_FIELDS.
  32. if cls.USERNAME_FIELD in cls.REQUIRED_FIELDS:
  33. errors.append(
  34. checks.Error(
  35. "The field named as the 'USERNAME_FIELD' "
  36. "for a custom user model must not be included in 'REQUIRED_FIELDS'.",
  37. hint=(
  38. "The 'USERNAME_FIELD' is currently set to '%s', you "
  39. "should remove '%s' from the 'REQUIRED_FIELDS'."
  40. % (cls.USERNAME_FIELD, cls.USERNAME_FIELD)
  41. ),
  42. obj=cls,
  43. id="auth.E002",
  44. )
  45. )
  46. # Check that the username field is unique
  47. if not cls._meta.get_field(cls.USERNAME_FIELD).unique and not any(
  48. constraint.fields == (cls.USERNAME_FIELD,)
  49. for constraint in cls._meta.total_unique_constraints
  50. ):
  51. if settings.AUTHENTICATION_BACKENDS == [
  52. "django.contrib.auth.backends.ModelBackend"
  53. ]:
  54. errors.append(
  55. checks.Error(
  56. "'%s.%s' must be unique because it is named as the "
  57. "'USERNAME_FIELD'." % (cls._meta.object_name, cls.USERNAME_FIELD),
  58. obj=cls,
  59. id="auth.E003",
  60. )
  61. )
  62. else:
  63. errors.append(
  64. checks.Warning(
  65. "'%s.%s' is named as the 'USERNAME_FIELD', but it is not unique."
  66. % (cls._meta.object_name, cls.USERNAME_FIELD),
  67. hint=(
  68. "Ensure that your authentication backend(s) can handle "
  69. "non-unique usernames."
  70. ),
  71. obj=cls,
  72. id="auth.W004",
  73. )
  74. )
  75. if isinstance(cls().is_anonymous, MethodType):
  76. errors.append(
  77. checks.Critical(
  78. "%s.is_anonymous must be an attribute or property rather than "
  79. "a method. Ignoring this is a security issue as anonymous "
  80. "users will be treated as authenticated!" % cls,
  81. obj=cls,
  82. id="auth.C009",
  83. )
  84. )
  85. if isinstance(cls().is_authenticated, MethodType):
  86. errors.append(
  87. checks.Critical(
  88. "%s.is_authenticated must be an attribute or property rather "
  89. "than a method. Ignoring this is a security issue as anonymous "
  90. "users will be treated as authenticated!" % cls,
  91. obj=cls,
  92. id="auth.C010",
  93. )
  94. )
  95. return errors
  96. def check_models_permissions(app_configs=None, **kwargs):
  97. if app_configs is None:
  98. models = apps.get_models()
  99. else:
  100. models = chain.from_iterable(
  101. app_config.get_models() for app_config in app_configs
  102. )
  103. Permission = apps.get_model("auth", "Permission")
  104. permission_name_max_length = Permission._meta.get_field("name").max_length
  105. permission_codename_max_length = Permission._meta.get_field("codename").max_length
  106. errors = []
  107. for model in models:
  108. opts = model._meta
  109. builtin_permissions = dict(_get_builtin_permissions(opts))
  110. # Check builtin permission name length.
  111. max_builtin_permission_name_length = (
  112. max(len(name) for name in builtin_permissions.values())
  113. if builtin_permissions
  114. else 0
  115. )
  116. if max_builtin_permission_name_length > permission_name_max_length:
  117. verbose_name_max_length = permission_name_max_length - (
  118. max_builtin_permission_name_length - len(opts.verbose_name_raw)
  119. )
  120. errors.append(
  121. checks.Error(
  122. "The verbose_name of model '%s' must be at most %d "
  123. "characters for its builtin permission names to be at "
  124. "most %d characters."
  125. % (opts.label, verbose_name_max_length, permission_name_max_length),
  126. obj=model,
  127. id="auth.E007",
  128. )
  129. )
  130. # Check builtin permission codename length.
  131. max_builtin_permission_codename_length = (
  132. max(len(codename) for codename in builtin_permissions.keys())
  133. if builtin_permissions
  134. else 0
  135. )
  136. if max_builtin_permission_codename_length > permission_codename_max_length:
  137. model_name_max_length = permission_codename_max_length - (
  138. max_builtin_permission_codename_length - len(opts.model_name)
  139. )
  140. errors.append(
  141. checks.Error(
  142. "The name of model '%s' must be at most %d characters "
  143. "for its builtin permission codenames to be at most %d "
  144. "characters."
  145. % (
  146. opts.label,
  147. model_name_max_length,
  148. permission_codename_max_length,
  149. ),
  150. obj=model,
  151. id="auth.E011",
  152. )
  153. )
  154. codenames = set()
  155. for codename, name in opts.permissions:
  156. # Check custom permission name length.
  157. if len(name) > permission_name_max_length:
  158. errors.append(
  159. checks.Error(
  160. "The permission named '%s' of model '%s' is longer "
  161. "than %d characters."
  162. % (
  163. name,
  164. opts.label,
  165. permission_name_max_length,
  166. ),
  167. obj=model,
  168. id="auth.E008",
  169. )
  170. )
  171. # Check custom permission codename length.
  172. if len(codename) > permission_codename_max_length:
  173. errors.append(
  174. checks.Error(
  175. "The permission codenamed '%s' of model '%s' is "
  176. "longer than %d characters."
  177. % (
  178. codename,
  179. opts.label,
  180. permission_codename_max_length,
  181. ),
  182. obj=model,
  183. id="auth.E012",
  184. )
  185. )
  186. # Check custom permissions codename clashing.
  187. if codename in builtin_permissions:
  188. errors.append(
  189. checks.Error(
  190. "The permission codenamed '%s' clashes with a builtin "
  191. "permission for model '%s'." % (codename, opts.label),
  192. obj=model,
  193. id="auth.E005",
  194. )
  195. )
  196. elif codename in codenames:
  197. errors.append(
  198. checks.Error(
  199. "The permission codenamed '%s' is duplicated for "
  200. "model '%s'." % (codename, opts.label),
  201. obj=model,
  202. id="auth.E006",
  203. )
  204. )
  205. codenames.add(codename)
  206. return errors