From a722e039fc7abee75996969239a4b9ff06c335d4 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Thu, 29 Dec 2011 15:45:45 -0300 Subject: added extra user name validation to make it slugification safe --- askbot/tests/form_tests.py | 1 + askbot/utils/forms.py | 48 ++++++++++++++++++++++++++++++++-------------- askbot/utils/slug.py | 5 +++-- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/askbot/tests/form_tests.py b/askbot/tests/form_tests.py index 2fa572e5..5235b13a 100644 --- a/askbot/tests/form_tests.py +++ b/askbot/tests/form_tests.py @@ -303,5 +303,6 @@ class UserNameFieldTest(AskbotTestCase): #invalid username and username in reserved words self.assertRaises(django_forms.ValidationError, self.username_field.clean, ' ') self.assertRaises(django_forms.ValidationError, self.username_field.clean, 'fuck') + self.assertRaises(django_forms.ValidationError, self.username_field.clean, '......') #TODO: test more things diff --git a/askbot/utils/forms.py b/askbot/utils/forms.py index c3bccf24..536d06b5 100644 --- a/askbot/utils/forms.py +++ b/askbot/utils/forms.py @@ -1,11 +1,12 @@ -from django import forms import re +from django import forms +from django.http import str_to_unicode +from django.contrib.auth.models import User +from django.conf import settings from django.utils.translation import ugettext as _ from django.utils.safestring import mark_safe -from django.conf import settings from askbot.conf import settings as askbot_settings -from django.http import str_to_unicode -from django.contrib.auth.models import User +from askbot.utils.slug import slugify from askbot import const import logging import urllib @@ -26,7 +27,7 @@ def get_next_url(request, default = None): return clean_next(request.REQUEST.get('next'), default) class StrippedNonEmptyCharField(forms.CharField): - def clean(self,value): + def clean(self, value): value = value.strip() if self.required and value == '': raise forms.ValidationError(_('this field is required')) @@ -34,7 +35,14 @@ class StrippedNonEmptyCharField(forms.CharField): class NextUrlField(forms.CharField): def __init__(self): - super(NextUrlField,self).__init__(max_length = 255,widget = forms.HiddenInput(),required = False) + super( + NextUrlField, + self + ).__init__( + max_length = 255, + widget = forms.HiddenInput(), + required = False + ) def clean(self,value): return clean_next(value) @@ -43,19 +51,29 @@ login_form_widget_attrs = { 'class': 'required login' } class UserNameField(StrippedNonEmptyCharField): RESERVED_NAMES = (u'fuck', u'shit', u'ass', u'sex', u'add', u'edit', u'save', u'delete', u'manage', u'update', 'remove', 'new') - def __init__(self,db_model=User, db_field='username', must_exist=False,skip_clean=False,label=_('choose a username'),**kw): + def __init__( + self, + db_model=User, + db_field='username', + must_exist=False, + skip_clean=False, + label=_('choose a username'), + **kw + ): self.must_exist = must_exist self.skip_clean = skip_clean self.db_model = db_model self.db_field = db_field self.user_instance = None - error_messages={'required':_('user name is required'), - 'taken':_('sorry, this name is taken, please choose another'), - 'forbidden':_('sorry, this name is not allowed, please choose another'), - 'missing':_('sorry, there is no user with this name'), - 'multiple-taken':_('sorry, we have a serious error - user name is taken by several users'), - 'invalid':_('user name can only consist of letters, empty space and underscore'), - } + error_messages={ + 'required': _('user name is required'), + 'taken': _('sorry, this name is taken, please choose another'), + 'forbidden': _('sorry, this name is not allowed, please choose another'), + 'missing': _('sorry, there is no user with this name'), + 'multiple-taken': _('sorry, we have a serious error - user name is taken by several users'), + 'invalid': _('user name can only consist of letters, empty space and underscore'), + 'meaningless': _('please use at least some alphabetic characters in the user name'), + } if 'error_messages' in kw: error_messages.update(kw['error_messages']) del kw['error_messages'] @@ -90,6 +108,8 @@ class UserNameField(StrippedNonEmptyCharField): raise forms.ValidationError(self.error_messages['invalid']) if username in self.RESERVED_NAMES: raise forms.ValidationError(self.error_messages['forbidden']) + if slugify(username, force_unidecode = True) == '': + raise forms.ValidationError(self.error_messages['meaningless']) try: user = self.db_model.objects.get( **{'%s' % self.db_field : username} diff --git a/askbot/utils/slug.py b/askbot/utils/slug.py index 1c8010c8..58f228da 100644 --- a/askbot/utils/slug.py +++ b/askbot/utils/slug.py @@ -10,11 +10,12 @@ from django.template import defaultfilters from django.conf import settings import re -def slugify(input_text, max_length=50): +def slugify(input_text, max_length=50, force_unidecode = False): """custom slugify function that removes diacritic modifiers from the characters """ - if getattr(settings, 'ALLOW_UNICODE_SLUGS', False) == False: + allow_unicode_slugs = getattr(settings, 'ALLOW_UNICODE_SLUGS', False) + if allow_unicode_slugs == False or force_unidecode == True: if input_text == '': return input_text slug = defaultfilters.slugify(unidecode(input_text)) -- cgit v1.2.3-1-g7c22 From a54f01e943d7bfdd05a4a2405f98f0d92c5d2f06 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Thu, 29 Dec 2011 15:57:58 -0300 Subject: fixed two more remaining issues with the url translations --- askbot/skins/default/templates/main_page/javascript.html | 4 ++-- askbot/skins/default/templates/question/javascript.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/askbot/skins/default/templates/main_page/javascript.html b/askbot/skins/default/templates/main_page/javascript.html index 619574d9..7f136a40 100644 --- a/askbot/skins/default/templates/main_page/javascript.html +++ b/askbot/skins/default/templates/main_page/javascript.html @@ -38,8 +38,8 @@ askbot['urls']['question_url_template'] = scriptUrl + '{% trans %}question/{% endtrans %}{{ "{{QuestionID}}/" }}'; askbot['urls']['user_url_template'] = scriptUrl + '{% trans %}users/{% endtrans %}{{ "{{user_id}}" }}/{{ "{{slug}}" }}/'; {% else %} - askbot['urls']['question_url_template'] = scriptUrl + 'question/{{ "{{QuestionID}}/" }}'; - askbot['urls']['user_url_template'] = scriptUrl + 'users/{{ "{{user_id}}" }}/{{ "{{slug}}" }}/'; + askbot['urls']['question_url_template'] = scriptUrl + '{% trans %}question/{% endtrans %}{{ "{{QuestionID}}/" }}'; + askbot['urls']['user_url_template'] = scriptUrl + '{% trans %}users/{% endtrans %}{{ "{{user_id}}" }}/{{ "{{slug}}" }}/'; {% endif %} askbot['messages']['name_of_anonymous_user'] = '{{ name_of_anonymous_user }}'; diff --git a/askbot/skins/default/templates/question/javascript.html b/askbot/skins/default/templates/question/javascript.html index c5dd9f37..af1c7056 100644 --- a/askbot/skins/default/templates/question/javascript.html +++ b/askbot/skins/default/templates/question/javascript.html @@ -15,8 +15,8 @@ askbot['urls']['question_url_template'] = scriptUrl + '{% trans %}question/{% endtrans %}{{ "{{QuestionID}}/{{questionSlug}}" }}';{# yes it needs to be that whacky #} askbot['urls']['vote_url_template'] = scriptUrl + '{% trans %}questions/{% endtrans %}{{ "{{QuestionID}}/" }}{% trans %}vote/{% endtrans %}'; {%else%} - askbot['urls']['question_url_template'] = scriptUrl + 'question/{{ "{{QuestionID}}/{{questionSlug}}" }}';{# yes it needs to be that whacky #} - askbot['urls']['vote_url_template'] = scriptUrl + 'questions/{{ "{{QuestionID}}/" }}vote/'; + askbot['urls']['question_url_template'] = scriptUrl + '{% trans %}question/{% endtrans %}{{ "{{QuestionID}}/{{questionSlug}}" }}';{# yes it needs to be that whacky #} + askbot['urls']['vote_url_template'] = scriptUrl + '{% trans %}questions/{% endtrans %}{{ "{{QuestionID}}/" }}vote/'; {%endif%} askbot['urls']['user_signin'] = '{{ settings.LOGIN_URL }}'; askbot['urls']['swap_question_with_answer'] = '{% url swap_question_with_answer %}'; -- cgit v1.2.3-1-g7c22 From 0e52079587cf0868d484e718dcc800a811eb56d7 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Thu, 29 Dec 2011 16:02:14 -0300 Subject: updated the changelog --- askbot/doc/source/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst index 3138110d..a3e4ef05 100644 --- a/askbot/doc/source/changelog.rst +++ b/askbot/doc/source/changelog.rst @@ -9,6 +9,7 @@ Development version (not released yet) make sure it does not contain a `.` (dot) symbol (Evgeny) * made askbot compatible with django's `CSRFViewMiddleware` that may be used for other projects (Evgeny) +* added more rigorous test for the user name to make it slug safe (Evgeny) 0.7.36 (Dec 20, 2011) --------------------- -- cgit v1.2.3-1-g7c22