From ddf01d1631f2d1235f4c3ba93bb5238a9447dbeb Mon Sep 17 00:00:00 2001 From: Johnny Date: Thu, 20 Sep 2018 00:06:09 +0000 Subject: [PATCH] Implements password validation via the native Django framework. --- evennia/contrib/security/__init__.py | 0 evennia/contrib/security/validators.py | 51 ++++++++++++++++++++++++++ evennia/settings_default.py | 23 ++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 evennia/contrib/security/__init__.py create mode 100644 evennia/contrib/security/validators.py diff --git a/evennia/contrib/security/__init__.py b/evennia/contrib/security/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/evennia/contrib/security/validators.py b/evennia/contrib/security/validators.py new file mode 100644 index 0000000000..b10f990a8a --- /dev/null +++ b/evennia/contrib/security/validators.py @@ -0,0 +1,51 @@ +from django.core.exceptions import ValidationError +from django.utils.translation import gettext as _ +import re + +class EvenniaPasswordValidator: + + def __init__(self, regex=r"^[\w. @+\-',]+$", policy="Password should contain a mix of letters, spaces, digits and @/./+/-/_/'/, only."): + """ + Constructs a standard Django password validator. + + Args: + regex (str): Regex pattern of valid characters to allow. + policy (str): Brief explanation of what the defined regex permits. + + """ + self.regex = regex + self.policy = policy + + def validate(self, password, user=None): + """ + Validates a password string to make sure it meets predefined Evennia + acceptable character policy. + + Args: + password (str): Password to validate + user (None): Unused argument but required by Django + + Returns: + None (None): None if password successfully validated, + raises ValidationError otherwise. + + """ + # Check complexity + if not re.findall(self.regex, password): + raise ValidationError( + _(self.policy), + code='evennia_password_policy', + ) + + def get_help_text(self): + """ + Returns a user-facing explanation of the password policy defined + by this validator. + + Returns: + text (str): Explanation of password policy. + + """ + return _( + "%s From a terminal client, you can also use a phrase of multiple words if you enclose the password in double quotes." % self.policy + ) \ No newline at end of file diff --git a/evennia/settings_default.py b/evennia/settings_default.py index 9c34a6165a..d705d77d18 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -802,6 +802,29 @@ INSTALLED_APPS = ( # This should usually not be changed. AUTH_USER_MODEL = "accounts.AccountDB" +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + 'OPTIONS': { + 'min_length': 8, + } + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, + { + 'NAME': 'evennia.contrib.security.validators.EvenniaPasswordValidator', + }, +] + # Use a custom test runner that just tests Evennia-specific apps. TEST_RUNNER = 'evennia.server.tests.EvenniaTestSuiteRunner'