diff --git a/pykeg/core/kb_common.py b/pykeg/core/kb_common.py index 3bb6065fa..fb31ae25f 100644 --- a/pykeg/core/kb_common.py +++ b/pykeg/core/kb_common.py @@ -51,3 +51,6 @@ # Low volume threshold: 15% full KEG_VOLUME_LOW_PERCENT = 0.15 + +# Valid usernames. +USERNAME_REGEX = '^[\w.@+-]+$' diff --git a/pykeg/core/models.py b/pykeg/core/models.py index 3723f1e9b..c1c67ba68 100644 --- a/pykeg/core/models.py +++ b/pykeg/core/models.py @@ -106,7 +106,7 @@ class User(AbstractBaseUser): '@/./+/-/_ characters'), validators=[ validators.RegexValidator( - re.compile('^[\w.@+-]+$'), + re.compile(kb_common.USERNAME_REGEX), _('Enter a valid username.'), 'invalid')]) display_name = models.CharField( diff --git a/pykeg/web/api/api_test.py b/pykeg/web/api/api_test.py index fdbc62d5b..29f88eb12 100644 --- a/pykeg/web/api/api_test.py +++ b/pykeg/web/api/api_test.py @@ -209,6 +209,22 @@ def test_record_drink(self): active_user = users[0] self.assertEquals(self.normal_user.username, active_user.username) + def test_record_drink_usernames(self): + new_keg_data = { + 'keg_size': 'half-barrel', + 'beverage_name': 'Test Brew', + 'producer_name': 'Test Producer', + 'style_name': 'Test Style,' + } + response, data = self.post('taps/1/activate', data=new_keg_data, + HTTP_X_KEGBOT_API_KEY=self.apikey.key) + self.assertEquals(data.meta.result, 'ok') + + user = models.User.objects.create(username='test.123') + response, data = self.post('taps/1', HTTP_X_KEGBOT_API_KEY=self.apikey.key, + data={'ticks': 1000, 'username': 'test.123'}) + self.assertEquals(data.meta.result, 'ok') + @override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend') @override_settings(EMAIL_FROM_ADDRESS='test-from@example') def test_registration(self): diff --git a/pykeg/web/api/forms.py b/pykeg/web/api/forms.py index c1681e290..55a97b590 100644 --- a/pykeg/web/api/forms.py +++ b/pykeg/web/api/forms.py @@ -19,6 +19,7 @@ from django import forms from pykeg.core import models +from pykeg.core.kb_common import USERNAME_REGEX ALL_METERS = models.FlowMeter.objects.all() ALL_TOGGLES = models.FlowToggle.objects.all() @@ -28,7 +29,7 @@ class DrinkPostForm(forms.Form): """Form to handle posts to /tap//""" ticks = forms.IntegerField() volume_ml = forms.FloatField(required=False) - username = forms.RegexField(required=False, max_length=30, regex=r"^[\w-]+$") + username = forms.RegexField(required=False, max_length=30, regex=USERNAME_REGEX) pour_time = forms.IntegerField(required=False) now = forms.IntegerField(required=False) duration = forms.IntegerField(required=False)