codeforlife-portal 8.1.3__py2.py3-none-any.whl → 8.2.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of codeforlife-portal might be problematic. Click here for more details.
- {codeforlife_portal-8.1.3.dist-info → codeforlife_portal-8.2.1.dist-info}/METADATA +1 -1
- {codeforlife_portal-8.1.3.dist-info → codeforlife_portal-8.2.1.dist-info}/RECORD +14 -12
- deploy/middleware/maintenance.py +25 -0
- example_project/portal_test_settings.py +1 -0
- example_project/settings.py +1 -0
- portal/__init__.py +1 -1
- portal/forms/teach.py +20 -0
- portal/templates/maintenance.html +34 -0
- portal/templates/portal/teach/dashboard.html +1 -1
- portal/tests/test_class.py +21 -0
- portal/urls.py +5 -0
- {codeforlife_portal-8.1.3.dist-info → codeforlife_portal-8.2.1.dist-info}/LICENSE.md +0 -0
- {codeforlife_portal-8.1.3.dist-info → codeforlife_portal-8.2.1.dist-info}/WHEEL +0 -0
- {codeforlife_portal-8.1.3.dist-info → codeforlife_portal-8.2.1.dist-info}/top_level.txt +0 -0
|
@@ -94,6 +94,7 @@ deploy/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
94
94
|
deploy/middleware/admin_access.py,sha256=-uF9Wgm7WPmNCEQ2Ti-rBXMrYJb0NnrIfnUdRIXzlWs,1207
|
|
95
95
|
deploy/middleware/basicauth.py,sha256=DiSImGc9mepmsVK1Be5hc2iLnGzsOFx-S2i8AQnXMwY,1170
|
|
96
96
|
deploy/middleware/exceptionlogging.py,sha256=qE3fJnaCwEslrCpF3k8jK1MeqldnvALPnlrUsiqV-5g,474
|
|
97
|
+
deploy/middleware/maintenance.py,sha256=JhlQD7FowzxnRxk1_uGXYRQ2Aas6v3C9BRxYgN1HLAY,932
|
|
97
98
|
deploy/middleware/screentime_warning.py,sha256=-YmaOn9_RQwTU8C6VxDLWct_0G3Y5oHjAv9AvKZSvIw,1152
|
|
98
99
|
deploy/middleware/security.py,sha256=LOZ-OUFo2dVhbRzI_KdSCMh4TItcJhhqzZg5zNAH-6Q,870
|
|
99
100
|
deploy/middleware/session_timeout.py,sha256=Vfl6_9d8KwPsWRvCIcpBm7kWjgvHC8I7exJOejbyI4k,1023
|
|
@@ -106,11 +107,11 @@ deploy/static/robots.txt,sha256=5cS4RITuQhbpNzvpk4AyDCXdlIBfmfCoBYRvCHY2VT8,24
|
|
|
106
107
|
deploy/templates/deploy/csrf_failure.html,sha256=-pBRPn4Y7nUdYHGpTHCokT9Boi-isuwuivF8V2K1SgM,412
|
|
107
108
|
example_project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
108
109
|
example_project/manage.py,sha256=EUgybZlZ7xk2Zf2KCwBbK_z7gf7Ifqs0_bl4Kijhdgo,242
|
|
109
|
-
example_project/portal_test_settings.py,sha256=
|
|
110
|
-
example_project/settings.py,sha256=
|
|
110
|
+
example_project/portal_test_settings.py,sha256=mTyObCGkZEI0IQSZkqCjb1WZ7ebjQLwuiT_SykRnP6g,7315
|
|
111
|
+
example_project/settings.py,sha256=pHQDI_A_yXV3u1efj689tc-vPI6nBFma4gMMPBzj0aI,5652
|
|
111
112
|
example_project/urls.py,sha256=FUTzHPlUS1O5kqMHjL5V4L552N2ln7uTDXcw9wjKUto,422
|
|
112
113
|
example_project/wsgi.py,sha256=U1W6WzZxZaIdYZ5tks7w9fqp5WS5qvn2iThsVcskrWw,829
|
|
113
|
-
portal/__init__.py,sha256=
|
|
114
|
+
portal/__init__.py,sha256=lPYx_JLWGM0F2xAcHXVLkIwicje2ZtdqEBMpuaNCsEU,22
|
|
114
115
|
portal/admin.py,sha256=RKJizTF6dPJKmGPZw7nZUM0X8jkiTjgyKhLQxtvHJ0I,6148
|
|
115
116
|
portal/app_settings.py,sha256=DhWLQOwM0zVOXE3O5TNKbMM9K6agfLuCsHOdr1J7xEI,651
|
|
116
117
|
portal/backends.py,sha256=2Dss6_WoQwPuDzJUF1yEaTQTNG4eUrD12ujJQ5cp5Tc,812
|
|
@@ -118,7 +119,7 @@ portal/beta.py,sha256=0TCC-9_KZoM1nuzJ9FiuKR5n9JITdMYenHGQtRvn9UU,255
|
|
|
118
119
|
portal/context_processors.py,sha256=1TrUZqnMqGa5f7ERph9EpBqojSMJvOrcpnJzTdeCLDI,133
|
|
119
120
|
portal/handlers.py,sha256=gF99OfQrGcIGDnUyONhvylZNU8sl6XHYEurwu0fuiss,422
|
|
120
121
|
portal/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
121
|
-
portal/urls.py,sha256=
|
|
122
|
+
portal/urls.py,sha256=LFSumASmTGjFciMcc6OEFvJ1MWgFUS5wNRugGWON40E,18211
|
|
122
123
|
portal/wsgi.py,sha256=3yRcNxBQG30NhzrVi93bX-DrbXtsIQBc70HiW5wbOyE,401
|
|
123
124
|
portal/forms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
124
125
|
portal/forms/admin.py,sha256=Cdl8-wvasAzvMfgUlFYzQjYeuyC7gIsSiy8V_-jMp7w,2080
|
|
@@ -128,7 +129,7 @@ portal/forms/invite_teacher.py,sha256=jkDNcCfkts4_lXRzhcI3xBam21Zn2yX9wMpMVhDtW1
|
|
|
128
129
|
portal/forms/organisation.py,sha256=QcQyd7AiqBmvt4y8uQSQylguUbKOKqo2pjqWIkpWjDg,7433
|
|
129
130
|
portal/forms/play.py,sha256=j_QYAKb4qyW0uy0VUUG49dmzDLINc3jR6ddK-djrbc4,11523
|
|
130
131
|
portal/forms/registration.py,sha256=a-TuzikRc0Q-BAYs3rJ3Sz1wmQ1o_rTEtZmWdF7-xss,6008
|
|
131
|
-
portal/forms/teach.py,sha256=
|
|
132
|
+
portal/forms/teach.py,sha256=c0t9XLfQJFd8hDWbnMUGX15Nt_XDXFG2BfwAKizE-Uw,22381
|
|
132
133
|
portal/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
133
134
|
portal/helpers/captcha.py,sha256=Amwg3HZ9eIh1LGYVYWYruk1ccNj6P3nYP_evufOY8BY,254
|
|
134
135
|
portal/helpers/decorators.py,sha256=Bs6AVCvcgxfHLdJVWzTmZpxlYbJZXJh5e9AGRXf7cwo,3617
|
|
@@ -432,6 +433,7 @@ portal/templates/404.html,sha256=Tk6HmuzDdIT4ojoIHvH2MibU_0OekU5gmuJmk5M4K_Q,563
|
|
|
432
433
|
portal/templates/500.html,sha256=aqJfDXPzaEw9K6LToPpE4rARuunLSxiIrJ_GnuJr8pI,1703
|
|
433
434
|
portal/templates/email.html,sha256=MXB64zc1Sd34eIq8mGT1HhrjAiZUNvRx0_XjZllfKUU,268
|
|
434
435
|
portal/templates/email.txt,sha256=z3bkT2WnkCrVa1RLVbGd-pE81cLEHlZ_QowfbSQAOvg,19
|
|
436
|
+
portal/templates/maintenance.html,sha256=RmPSkcTt9Vs6nGsIK9Q9rMyMAICqbaqMql4FmwL6Rak,1599
|
|
435
437
|
portal/templates/django_recaptcha/widget_v2_invisible.html,sha256=3t5JHgyr_so5FQEUtbq501kEjz80KYBOoVz3PuU1JOc,318
|
|
436
438
|
portal/templates/django_recaptcha/includes/js_v2_invisible.html,sha256=QQnBzZBqdtPeJeYFOIihJM18YoSUWbsGjuoMy-5gxNM,1408
|
|
437
439
|
portal/templates/portal/about.html,sha256=_iD0GCP6q3-XuZ2LC-9O0KYY-mKL6c9qk3O-NRRqsRM,10321
|
|
@@ -490,7 +492,7 @@ portal/templates/portal/tag_manager/tag_manager_body.html,sha256=M_c9T2cfmVm6_Gj
|
|
|
490
492
|
portal/templates/portal/tag_manager/tag_manager_head.html,sha256=kWQ4ccJ062cWRJOcfTNaWYTxCmzDsB9JD5v_YdyO5Ic,1288
|
|
491
493
|
portal/templates/portal/teach/base_registering.html,sha256=jpANyRQbsmWO404l9Mez91zolNP9ic1khWi27WW0FMQ,582
|
|
492
494
|
portal/templates/portal/teach/class.html,sha256=zir7a7y4hbg9E6-zFIC0iv8kccIzF-qkni4DXlvkjgM,6726
|
|
493
|
-
portal/templates/portal/teach/dashboard.html,sha256=
|
|
495
|
+
portal/templates/portal/teach/dashboard.html,sha256=DcY6rcUjAT9h6VbSIA3mq4fyCIATIlWYDH2qMU1LySg,32697
|
|
494
496
|
portal/templates/portal/teach/invited.html,sha256=lTsydONG5se1E099KaRgsxGuG12qVHxFUL2X0E3HBmQ,4188
|
|
495
497
|
portal/templates/portal/teach/onboarding_classes.html,sha256=K212dunXG7eByyCg5lhv4ne-SniMz3kcKXrfianIY6g,2872
|
|
496
498
|
portal/templates/portal/teach/onboarding_print.html,sha256=4vD2ZDNRxERNdCNj3ZNXJWYAFBQPn9C7Pzsz5TZjZHw,8862
|
|
@@ -535,7 +537,7 @@ portal/tests/test_2FA.py,sha256=0N4C9Ab3TvO9W__oQLCo-fLDH1Ho3CiGGsSg-2TiZUE,3597
|
|
|
535
537
|
portal/tests/test_admin.py,sha256=AM2dgv8j9m4L-SDO-sMA9tQvQH9GwRBrlwRG9OgqtfI,1451
|
|
536
538
|
portal/tests/test_api.py,sha256=Yo5s_nEGOoG35jA39yZ6nuDOUZvuCZ8o8o8XhZos61w,13819
|
|
537
539
|
portal/tests/test_captcha_forms.py,sha256=Yn_VYO_6jbq6AeKeLcv-YFL1YwXZpU0C3y7SK8fRUm4,1033
|
|
538
|
-
portal/tests/test_class.py,sha256=
|
|
540
|
+
portal/tests/test_class.py,sha256=_P2CEtqH67MM9h6MMQB_PxXFyQj4tZZbN42NJQpIJ7o,18308
|
|
539
541
|
portal/tests/test_emails.py,sha256=pLr06j3uMBxP1raoZQWzUTBVFvsEDFtUh85J8OnqCwE,9238
|
|
540
542
|
portal/tests/test_global_forms.py,sha256=GIm_oSN4VsfaO--E2SMRu8CwVraan0UBj-_LE_tu8w0,833
|
|
541
543
|
portal/tests/test_helper_methods.py,sha256=-SQCDZm2XUtyXGEp0CHIb_SSC9CPD-XOSnpnY8QclHk,890
|
|
@@ -632,8 +634,8 @@ portal/views/two_factor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
|
632
634
|
portal/views/two_factor/core.py,sha256=Lk32z2SN2Pg0rRkK-N-LXMvXC1kKKsH3l692kiSDQ4E,964
|
|
633
635
|
portal/views/two_factor/form.py,sha256=lnHNKI-BMlpncTuW3zUzjPaJJNuEra2I_nOam0eOKFY,257
|
|
634
636
|
portal/views/two_factor/profile.py,sha256=SHSg_xHccE5PtD-OfuOkYhREYz_er4bj5ro1RjJ88Yw,393
|
|
635
|
-
codeforlife_portal-8.1.
|
|
636
|
-
codeforlife_portal-8.1.
|
|
637
|
-
codeforlife_portal-8.1.
|
|
638
|
-
codeforlife_portal-8.1.
|
|
639
|
-
codeforlife_portal-8.1.
|
|
637
|
+
codeforlife_portal-8.2.1.dist-info/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
|
|
638
|
+
codeforlife_portal-8.2.1.dist-info/METADATA,sha256=x6DvD4-jLnlOAwIbP6k0mLhRatr4zoTaZMtTpmsCZOQ,3077
|
|
639
|
+
codeforlife_portal-8.2.1.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
|
|
640
|
+
codeforlife_portal-8.2.1.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
|
|
641
|
+
codeforlife_portal-8.2.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from django.http import HttpResponseRedirect
|
|
2
|
+
from django.urls import reverse, reverse_lazy
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MaintenanceMiddleware(object):
|
|
6
|
+
"""
|
|
7
|
+
This middleware allows us to turn on "Maintenance Mode". Toggle `MAINTENANCE_MODE` to True in
|
|
8
|
+
`process_view` to redirect all requests in the app to the maintenance holding page.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, get_response):
|
|
12
|
+
self.get_response = get_response
|
|
13
|
+
|
|
14
|
+
def __call__(self, request):
|
|
15
|
+
response = self.get_response(request)
|
|
16
|
+
return response
|
|
17
|
+
|
|
18
|
+
def process_view(self, request, callback, callback_args, callback_kwargs):
|
|
19
|
+
MAINTENANCE_MODE = False
|
|
20
|
+
|
|
21
|
+
if MAINTENANCE_MODE and not request.path.startswith(reverse("maintenance")):
|
|
22
|
+
return HttpResponseRedirect(reverse_lazy("maintenance"))
|
|
23
|
+
|
|
24
|
+
if not MAINTENANCE_MODE and request.path.startswith(reverse("maintenance")):
|
|
25
|
+
return HttpResponseRedirect(reverse_lazy("home"))
|
|
@@ -157,6 +157,7 @@ MIDDLEWARE = [
|
|
|
157
157
|
"preventconcurrentlogins.middleware.PreventConcurrentLoginsMiddleware",
|
|
158
158
|
"csp.middleware.CSPMiddleware",
|
|
159
159
|
"deploy.middleware.screentime_warning.ScreentimeWarningMiddleware",
|
|
160
|
+
"deploy.middleware.maintenance.MaintenanceMiddleware",
|
|
160
161
|
]
|
|
161
162
|
|
|
162
163
|
TEMPLATES = [
|
example_project/settings.py
CHANGED
|
@@ -115,6 +115,7 @@ MIDDLEWARE = [
|
|
|
115
115
|
"preventconcurrentlogins.middleware.PreventConcurrentLoginsMiddleware",
|
|
116
116
|
"csp.middleware.CSPMiddleware",
|
|
117
117
|
"deploy.middleware.screentime_warning.ScreentimeWarningMiddleware",
|
|
118
|
+
"deploy.middleware.maintenance.MaintenanceMiddleware",
|
|
118
119
|
]
|
|
119
120
|
|
|
120
121
|
TEMPLATES = [
|
portal/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "8.1
|
|
1
|
+
__version__ = "8.2.1"
|
portal/forms/teach.py
CHANGED
|
@@ -234,6 +234,16 @@ class ClassCreationForm(forms.Form):
|
|
|
234
234
|
|
|
235
235
|
self.fields["teacher"].choices = teacher_choices
|
|
236
236
|
|
|
237
|
+
def clean(self):
|
|
238
|
+
name = self.cleaned_data.get("class_name", "")
|
|
239
|
+
|
|
240
|
+
if re.match(re.compile("^[\w -]+$"), name) is None:
|
|
241
|
+
raise forms.ValidationError(
|
|
242
|
+
"Class name may only contain letters, numbers, dashes, underscores, and spaces."
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
return self.cleaned_data
|
|
246
|
+
|
|
237
247
|
|
|
238
248
|
class ClassEditForm(forms.Form):
|
|
239
249
|
# select dropdown choices for potentially limiting time in which external students may join
|
|
@@ -288,6 +298,16 @@ class ClassEditForm(forms.Form):
|
|
|
288
298
|
widget=forms.Select(),
|
|
289
299
|
)
|
|
290
300
|
|
|
301
|
+
def clean(self):
|
|
302
|
+
name = self.cleaned_data.get("name", "")
|
|
303
|
+
|
|
304
|
+
if re.match(re.compile("^[\w -]+$"), name) is None:
|
|
305
|
+
raise forms.ValidationError(
|
|
306
|
+
"Class name may only contain letters, numbers, dashes, underscores, and spaces."
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
return self.cleaned_data
|
|
310
|
+
|
|
291
311
|
|
|
292
312
|
class ClassLevelControlForm(forms.Form):
|
|
293
313
|
def __init__(self, *args, **kwargs):
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{% load static %}
|
|
2
|
+
{% load app_tags %}
|
|
3
|
+
<!DOCTYPE html>
|
|
4
|
+
<html>
|
|
5
|
+
<head>
|
|
6
|
+
<title>Code For Life - maintenance</title>
|
|
7
|
+
<link rel="stylesheet" type="text/css" href="{% static 'portal.css' %}">
|
|
8
|
+
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500&display=swap" rel="stylesheet">
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
|
10
|
+
<link rel="shortcut icon" href="{% static 'portal/img/favicon.ico' %}" type="image/x-icon">
|
|
11
|
+
<link rel="icon" href="{% static 'portal/img/favicon.ico' %}" type="image/x-icon">
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
<div class="content-footer-wrapper">
|
|
15
|
+
<div id="contentWrapper">
|
|
16
|
+
{% block topBar %}
|
|
17
|
+
{% include 'portal/partials/header.html' %}
|
|
18
|
+
{% endblock topBar %}
|
|
19
|
+
<div class="content">
|
|
20
|
+
<div class="error-page background container">
|
|
21
|
+
<div class="row mx-0 d-flex justify-content-between">
|
|
22
|
+
<div class="flex-grow-1">
|
|
23
|
+
<h2>Works in progress!</h2>
|
|
24
|
+
<h5>Apologies! Dee is working on something important.</h5>
|
|
25
|
+
<p>The website is temporarily unavailable.</p>
|
|
26
|
+
</div>
|
|
27
|
+
<img title="Dee" alt="Dee" src="{% static 'portal/img/dee.png' %}"/>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
portal/tests/test_class.py
CHANGED
|
@@ -15,6 +15,7 @@ from django.urls import reverse
|
|
|
15
15
|
from game.models import Level
|
|
16
16
|
|
|
17
17
|
from .base_test import BaseTest
|
|
18
|
+
from .pageObjects.portal.home_page import HomePage
|
|
18
19
|
from .pageObjects.portal.teach.class_page import TeachClassPage
|
|
19
20
|
from .utils.classes import create_class
|
|
20
21
|
from .utils.messages import is_class_created_message_showing
|
|
@@ -537,3 +538,23 @@ class TestClassFrontend(BaseTest):
|
|
|
537
538
|
page, class_name_3 = create_class(page)
|
|
538
539
|
|
|
539
540
|
assert is_class_created_message_showing(self.selenium, class_name_3)
|
|
541
|
+
|
|
542
|
+
def test_create_invalid_name(self):
|
|
543
|
+
email, password = signup_teacher_directly()
|
|
544
|
+
create_organisation_directly(email)
|
|
545
|
+
|
|
546
|
+
class_name = "Class!"
|
|
547
|
+
|
|
548
|
+
self.selenium.get(self.live_server_url)
|
|
549
|
+
page = (
|
|
550
|
+
HomePage(self.selenium)
|
|
551
|
+
.go_to_teacher_login_page()
|
|
552
|
+
.login_no_class(email, password)
|
|
553
|
+
.open_classes_tab()
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
page = page.create_class(class_name, False)
|
|
557
|
+
|
|
558
|
+
assert page.was_form_invalid(
|
|
559
|
+
"form-create-class", "Class name may only contain letters, numbers, dashes, underscores, and spaces."
|
|
560
|
+
)
|
portal/urls.py
CHANGED
|
@@ -527,4 +527,9 @@ urlpatterns = [
|
|
|
527
527
|
name="remove_fake_accounts",
|
|
528
528
|
),
|
|
529
529
|
re_path(r"^celebrate/", ten_year_map_page, name="celebrate"),
|
|
530
|
+
re_path(
|
|
531
|
+
r"^maintenance/$",
|
|
532
|
+
TemplateView.as_view(template_name="maintenance.html"),
|
|
533
|
+
name="maintenance",
|
|
534
|
+
),
|
|
530
535
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|