Browse Source

Add mitigation for bad tz values

pull/522/head
Pēteris Caune 4 years ago
parent
commit
fa5dd8b45a
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
3 changed files with 35 additions and 3 deletions
  1. +11
    -2
      hc/accounts/forms.py
  2. +22
    -0
      hc/accounts/tests/test_notifications.py
  3. +2
    -1
      hc/accounts/views.py

+ 11
- 2
hc/accounts/forms.py View File

@ -8,7 +8,7 @@ from django.contrib.auth import authenticate
from django.contrib.auth.models import User from django.contrib.auth.models import User
from hc.accounts.models import REPORT_CHOICES from hc.accounts.models import REPORT_CHOICES
from hc.api.models import TokenBucket from hc.api.models import TokenBucket
from hc.front.validators import TimezoneValidator
import pytz
class LowercaseEmailField(forms.EmailField): class LowercaseEmailField(forms.EmailField):
@ -88,7 +88,7 @@ class PasswordLoginForm(forms.Form):
class ReportSettingsForm(forms.Form): class ReportSettingsForm(forms.Form):
reports = forms.ChoiceField(choices=REPORT_CHOICES) reports = forms.ChoiceField(choices=REPORT_CHOICES)
nag_period = forms.IntegerField(min_value=0, max_value=86400) nag_period = forms.IntegerField(min_value=0, max_value=86400)
tz = forms.CharField(max_length=36, validators=[TimezoneValidator()])
tz = forms.CharField()
def clean_nag_period(self): def clean_nag_period(self):
seconds = self.cleaned_data["nag_period"] seconds = self.cleaned_data["nag_period"]
@ -98,6 +98,15 @@ class ReportSettingsForm(forms.Form):
return td(seconds=seconds) return td(seconds=seconds)
def clean_tz(self):
# Declare tz as "clean" only if we can find it in pytz.all_timezones
if self.cleaned_data["tz"] in pytz.all_timezones:
return self.cleaned_data["tz"]
# Otherwise, return None, and *don't* throw a validation exception:
# If user's browser reports a timezone we don't recognize, we
# should ignore the timezone but still save the rest of the form.
class SetPasswordForm(forms.Form): class SetPasswordForm(forms.Form):
password = forms.CharField(min_length=8) password = forms.CharField(min_length=8)


+ 22
- 0
hc/accounts/tests/test_notifications.py View File

@ -95,3 +95,25 @@ class NotificationsTestCase(BaseTestCase):
self.profile.refresh_from_db() self.profile.refresh_from_db()
self.assertEqual(self.profile.nag_period.total_seconds(), 3600) self.assertEqual(self.profile.nag_period.total_seconds(), 3600)
def test_it_saves_tz(self):
self.client.login(username="[email protected]", password="password")
r = self.client.post(self.url, self._payload())
self.assertEqual(r.status_code, 200)
self.profile.refresh_from_db()
self.assertEqual(self.profile.tz, "Europe/Riga")
def test_it_ignores_bad_tz(self):
self.profile.tz = "Europe/Riga"
self.profile.save()
self.client.login(username="[email protected]", password="password")
r = self.client.post(self.url, self._payload(reports="weekly", tz="Foo/Bar"))
self.assertEqual(r.status_code, 200)
self.profile.refresh_from_db()
self.assertEqual(self.profile.reports, "weekly")
self.assertEqual(self.profile.tz, "Europe/Riga")

+ 2
- 1
hc/accounts/views.py View File

@ -446,8 +446,9 @@ def notifications(request):
if request.method == "POST": if request.method == "POST":
form = forms.ReportSettingsForm(request.POST) form = forms.ReportSettingsForm(request.POST)
if form.is_valid(): if form.is_valid():
if form.cleaned_data["tz"]:
profile.tz = form.cleaned_data["tz"]
profile.reports = form.cleaned_data["reports"] profile.reports = form.cleaned_data["reports"]
profile.tz = form.cleaned_data["tz"]
profile.next_report_date = profile.choose_next_report_date() profile.next_report_date = profile.choose_next_report_date()
profile.reports_allowed = profile.reports != "off" profile.reports_allowed = profile.reports != "off"


Loading…
Cancel
Save