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