Browse Source

Add config for username length and blacklist

sh4nks 8 years ago
parent
commit
b4d12811b0
4 changed files with 65 additions and 8 deletions
  1. 19 5
      flaskbb/auth/forms.py
  2. 20 0
      flaskbb/fixtures/settings.py
  3. 2 3
      flaskbb/utils/populate.py
  4. 24 0
      tests/unit/utils/test_populate.py

+ 19 - 5
flaskbb/auth/forms.py

@@ -16,12 +16,14 @@ from wtforms.validators import (DataRequired, InputRequired, Email, EqualTo,
 from flask_babelplus import lazy_gettext as _
 
 from flaskbb.user.models import User
+from flaskbb.utils.settings import flaskbb_config
 from flaskbb.utils.helpers import time_utcnow
 from flaskbb.utils.fields import RecaptchaField
 
 USERNAME_RE = r'^[\w.+-]+$'
-is_username = regexp(USERNAME_RE,
-                     message=_("You can only use letters, numbers or dashes."))
+is_valid_username = regexp(
+    USERNAME_RE, message=_("You can only use letters, numbers or dashes.")
+)
 
 
 class LoginForm(FlaskForm):
@@ -43,8 +45,8 @@ class LoginRecaptchaForm(LoginForm):
 
 class RegisterForm(FlaskForm):
     username = StringField(_("Username"), validators=[
-        DataRequired(message=_("A valid username is required.")),
-        is_username])
+        DataRequired(message=_("A valid username is required")),
+        is_valid_username])
 
     email = StringField(_("Email address"), validators=[
         DataRequired(message=_("A valid email address is required.")),
@@ -66,6 +68,18 @@ class RegisterForm(FlaskForm):
     submit = SubmitField(_("Register"))
 
     def validate_username(self, field):
+        # would through an out of context error if used with validators.Length
+        min_length = flaskbb_config["AUTH_USERNAME_MIN_LENGTH"]
+        max_length = flaskbb_config["AUTH_USERNAME_MAX_LENGTH"]
+        if len(field.data) < min_length or len(field.data) > max_length:
+            raise ValidationError(_(
+                "Username must be between %(min)s and %(max)s characters long.",
+                min=min_length, max=max_length)
+            )
+        if field.data.lower() in flaskbb_config["AUTH_USERNAME_BLACKLIST"]:
+            raise ValidationError(_(
+                "This is a system reserved name. Choose a different one.")
+            )
         user = User.query.filter_by(username=field.data).first()
         if user:
             raise ValidationError(_("This username is already taken."))
@@ -126,7 +140,7 @@ class ResetPasswordForm(FlaskForm):
 class RequestActivationForm(FlaskForm):
     username = StringField(_("Username"), validators=[
         DataRequired(message=_("A valid username is required.")),
-        is_username])
+        is_valid_username])
 
     email = StringField(_("Email address"), validators=[
         DataRequired(message=_("A valid email address is required.")),

+ 20 - 0
flaskbb/fixtures/settings.py

@@ -83,6 +83,26 @@ fixture = (
                 'name':         "Enable Account Activation",
                 'description':  "Enable to let the user activate their account by sending a email with an activation link."
             }),
+            ('auth_username_min_length', {
+                'value':        3,
+                'value_type':   "integer",
+                'extra':        {'min': 0},
+                'name':         "Username Minimum Length",
+                'description':  "The minimum length of the username. Changing this will only affect new registrations.",
+            }),
+            ('auth_username_max_length', {
+                'value':        20,
+                'value_type':   "integer",
+                'extra':        {'min': 0},
+                'name':         "Username Maximum Length",
+                'description':  "The Maximum length of the username. Changing this will only affect new registrations.",
+            }),
+            ('auth_username_blacklist', {
+                'value':        "me,administrator,moderator",
+                'value_type':   "string",
+                'name':         "Username Blacklist",
+                'description':  "A comma seperated list with forbidden usernames.",
+            }),
             ('auth_ratelimit_enabled', {
                 'value':        True,
                 'value_type':   "boolean",

+ 2 - 3
flaskbb/utils/populate.py

@@ -104,7 +104,7 @@ def update_settings_from_fixture(fixture, overwrite_group=False,
                 )
 
             group.save()
-            updated_settings[group] = []
+        updated_settings[group.key] = []
 
         for settings in settingsgroup[1]["settings"]:
 
@@ -131,8 +131,7 @@ def update_settings_from_fixture(fixture, overwrite_group=False,
                     )
 
                 setting.save()
-                updated_settings[group].append(setting)
-
+                updated_settings[group.key].append(setting)
     return updated_settings
 
 

+ 24 - 0
tests/unit/utils/test_populate.py

@@ -41,6 +41,30 @@ def test_update_settings_from_fixture(database):
                                                  overwrite_setting=True)
     assert len(force_updated) == SettingsGroup.query.count()
 
+    updated_fixture = (
+        ('general', {
+            'name': "General Settings",
+            'description': "How many items per page are displayed.",
+            'settings': (
+                ('project_title', {
+                    'value': "FlaskBB",
+                    'value_type': "string",
+                    'name': "Project title",
+                    'description': "The title of the project.",
+                }),
+                ('test_fixture', {
+                    'description': 'This is a test fixture',
+                    'name': 'Test Fixture',
+                    'value': 'FlaskBBTest',
+                    'value_type': 'string'
+                })
+            )
+        }),
+    )
+
+    updated = update_settings_from_fixture(updated_fixture)
+    assert len(updated) == 1
+
 
 def test_create_user(default_groups):
     user = User.query.filter_by(username="admin").first()