diff options
Diffstat (limited to 'ishtar_common')
| -rw-r--r-- | ishtar_common/tests.py | 15 | ||||
| -rw-r--r-- | ishtar_common/utils.py | 44 | 
2 files changed, 57 insertions, 2 deletions
diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index e7e665a6f..774fab2a2 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -93,6 +93,7 @@ from ishtar_common.utils import (      rename_and_simplify_media_name,      try_fix_file,      reverse_coordinates, +    EachCharacterTypeValidator,  )  from ishtar_common.tasks import launch_export  from ishtar_common import utils_secretary @@ -4040,3 +4041,17 @@ class TemplateGenerationTest(TestCase):                  filtr = doc.get_filter(template, filter_re)                  for key in expected_keys:                      self.assertIn(key, filtr) + + +class PasswordValidatorTest(TestCase): +    def test_eachcharactertypevalidator(self): +        validator = EachCharacterTypeValidator() +        self.assertRaises(ValidationError, validator.validate, "") +        self.assertRaises(ValidationError, validator.validate, "1") +        self.assertRaises(ValidationError, validator.validate, "1a") +        self.assertRaises(ValidationError, validator.validate, "1aA") +        try: +            validator.validate("1aA.") +        except ValidationError: +            self.fail("Each character class is put, ValidationError should " +                      "not raise.") diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 65b937339..12ab2e646 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -34,6 +34,7 @@ import re  import requests  from secretary import Renderer as MainSecretaryRenderer, UndefinedSilently  import shutil +import string  import subprocess  import sys  import tempfile @@ -51,7 +52,8 @@ from django.contrib.contenttypes.models import ContentType  from django.contrib.gis.geos import GEOSGeometry  from django.contrib.sessions.backends.db import SessionStore  from django.core.cache import cache -from django.core.exceptions import SuspiciousOperation, ObjectDoesNotExist +from django.core.exceptions import SuspiciousOperation, ObjectDoesNotExist, \ +    ValidationError  from django.core.files import File  from django.core.files.storage import FileSystemStorage  from django.core.validators import EMPTY_VALUES @@ -2249,4 +2251,42 @@ def reverse_coordinates(wkt):  def reverse_list_coordinates(lst): -    return list(reversed(lst))
\ No newline at end of file +    return list(reversed(lst)) + + +class EachCharacterTypeValidator: +    def __init__(self, character_types=None): +        if not character_types: +            character_types = ( +                (_("uppercase letter"), string.ascii_uppercase), +                (_("lowercase letter"), string.ascii_lowercase), +                (_("number"), [str(i) for i in range(10)]), +                (_("punctuation sign"), string.punctuation) +            ) +        self.character_types = character_types + +    def validate(self, password, user=None): +        ok = set() +        for letter in password: +            for idx, character_type in enumerate(self.character_types): +                __, character_type = character_type +                if idx in ok: +                    continue +                if letter in character_type: +                    ok.add(idx) +        missing  = [ +            str(character_type[0]) +            for idx, character_type in enumerate(self.character_types) +            if idx not in ok] +        if not missing: +            return +        msg = str(_("This password must contain one of this character: ")) + ", ".join( +                missing) + str(_(".")) +        raise ValidationError(msg, code='missing_character_types') + +    def get_help_text(self): +        return str( +            _("Your password must contain each of these characters: ") +        ) + ", ".join( +            [str(character_type[0]) for character_type in self.character_types] +        ) + str(_("."))  | 
