# -*- coding: utf-8 -*- from django.core.exceptions import ValidationError from django.test import SimpleTestCase from ..validators import PasswordScoreValidator, CustomWordlistPasswordValidator, CharacterClassPasswordValidator class PasswordScoreValidatorTestCase(SimpleTestCase): def test_too_little_score(self): passwords = [ '', # score = 0 'abcdefghijklmnopq', # score = 17 'Abcdefghijklmnop', # score = 16 + 1 'ABcdefghijklmno', # score = 15 + 2 'AB1defghijklmn', # score = 14 + 2 + 1 'AB12efghijklm', # score = 13 + 2 + 2 'AB12+fghijkl', # score = 12 + 2 + 2 + 1 'AB12+-ghijk', # score = 11 + 2 + 2 + 2 'AB12+-*hij', # score = 10 + 2 + 2 + 3 'AB12+-*hi/', # score = 10 + 2 + 2 + 3 'AB12+-*hi3', # score = 10 + 2 + 2 + 3 'AB12+-*hiC', # score = 10 + 2 + 2 + 3 'abcbbbgbbjklmnopqr', # score = 17 ] validator = PasswordScoreValidator(min_classes=0) for password in passwords: with self.assertRaises(ValidationError, msg=password) as cm: validator.validate(password) self.assertEqual('too_little_score', cm.exception.code) def test_too_few_classes(self): passwords = [ '', # classes = 0 'abcdefgh', # classes = 1 'abcdef+-', # classes = 2 'abcd12gh', # classes = 2 'abcd12-+', # classes = 3 'abCDefgh', # classes = 2 'abCDef+-', # classes = 3 'abCD12gh', # classes = 3 'ABCD12-+', # classes = 3 ] validator = PasswordScoreValidator(min_score=0, min_classes=4) for password in passwords: with self.assertRaises(ValidationError, msg=password) as cm: validator.validate(password) self.assertEqual('too_few_classes', cm.exception.code) def test_valid(self): passwords = [ 'Abcdefghijklmnopq', 'ABcdefghijklmnop', 'AB1defghijklmno', 'AB12efghijklmn', 'AB12+fghijklm', 'AB12+-ghijkl', 'AB12+-*hijk', 'ab1defghijklmnopq', 'abcd+fghijklmnopq', 'AB1CDEFGHIJKLMNOPQ', ] validator = PasswordScoreValidator() for password in passwords: try: validator.validate(password) except ValidationError as e: # pragma: no cover self.fail('%s: %s' % (password, e)) def test_help_text(self): validator = PasswordScoreValidator() help_text = validator.get_help_text() self.assertIn('The password must get a minimum score of 18 points.', help_text) self.assertIn('Also the password must contain characters from 2 different character classes' ' (i.e. lower, upper, digits, others).', help_text) class CustomWordlistPasswordValidatorTestCase(SimpleTestCase): def test_invalid(self): invalid_passwords = [ ('passwort', [ 'Das Passwort darf nicht die Zeichenfolge \'passwort\' enthalten.', ]), ('abcdDaVefgh', [ 'Das Passwort darf nicht die Zeichenfolge \'dav\' enthalten.', ]), ('abcdsektIonefgh', [ 'Das Passwort darf nicht die Zeichenfolge \'sektion\' enthalten.', ]), ('alpen12verein34KArlsruhE berge', [ 'Das Passwort darf nicht die Zeichenfolge \'karlsruhe\' enthalten.', 'Das Passwort darf nicht die Zeichenfolge \'berge\' enthalten.', ]), ('heinzel@alpenverein-karlsruhe.de', [ 'Das Passwort darf nicht die Zeichenfolge \'heinzel\' enthalten.', 'Das Passwort darf nicht die Zeichenfolge \'alpenverein\' enthalten.', 'Das Passwort darf nicht die Zeichenfolge \'karlsruhe\' enthalten.', ]), ] validator = CustomWordlistPasswordValidator() for password, expected_errors in invalid_passwords: try: validator.validate(password) except ValidationError as e: errors = e.messages for expected_error in expected_errors: self.assertIn(expected_error, errors) for error in errors: self.assertIn(error, expected_errors) else: self.fail('%s: no validation error was raised' % password) # pragma: no cover def test_valid(self): passwords = [ '', 'password', 'münchen', ] validator = CustomWordlistPasswordValidator() for password in passwords: try: validator.validate(password) except ValidationError as e: # pragma: no cover self.fail(e) def test_help_text(self): validator = CustomWordlistPasswordValidator() help_text = validator.get_help_text() self.assertIn('The password must not contain some specific words,', help_text) self.assertIn('All words are matched case insensitive.', help_text) class CharacterClassPasswordValidatorTestCase(SimpleTestCase): def setUp(self): super().setUp() self.validator = CharacterClassPasswordValidator() def test_invalid(self): invalid_passwords = [ ('', [ 'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Großbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Ziffern enthalten.', 'Das Passwort muss mindestens 2 Sonderzeichen enthalten.', ]), ('A+-', [ 'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Großbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Ziffern enthalten.', ]), ('1234567890*', [ 'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Großbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Sonderzeichen enthalten.', ]), ('34*/()', [ 'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Großbuchstaben enthalten.', ]), ('AA', [ 'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Ziffern enthalten.', 'Das Passwort muss mindestens 2 Sonderzeichen enthalten.', ]), ('CD0.,', [ 'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Ziffern enthalten.', ]), ('EF56', [ 'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Sonderzeichen enthalten.', ]), ('8GH?!8', [ 'Das Passwort muss mindestens 2 Kleinbuchstaben enthalten.', ]), ('bbX', [ 'Das Passwort muss mindestens 2 Großbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Ziffern enthalten.', 'Das Passwort muss mindestens 2 Sonderzeichen enthalten.', ]), ('$cd%', [ 'Das Passwort muss mindestens 2 Großbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Ziffern enthalten.', ]), ('ef90', [ 'Das Passwort muss mindestens 2 Großbuchstaben enthalten.', 'Das Passwort muss mindestens 2 Sonderzeichen enthalten.', ]), ('1g=h3~', [ 'Das Passwort muss mindestens 2 Großbuchstaben enthalten.', ]), ('Gi&jH', [ 'Das Passwort muss mindestens 2 Ziffern enthalten.', 'Das Passwort muss mindestens 2 Sonderzeichen enthalten.', ]), ('IkK:i;', [ 'Das Passwort muss mindestens 2 Ziffern enthalten.', ]), ('mKn4L8', [ 'Das Passwort muss mindestens 2 Sonderzeichen enthalten.', ]), ] validator = self.validator for password, expected_errors in invalid_passwords: try: validator.validate(password) except ValidationError as e: errors = e.messages for expected_error in expected_errors: self.assertIn(expected_error, errors) for error in errors: self.assertIn(error, expected_errors) else: self.fail('%s: no validation error was raised' % password) # pragma: no cover def test_valid(self): valid_passwords = ['abCD12+-'] validator = self.validator for password in valid_passwords: try: validator.validate(password) except ValidationError as e: # pragma: no cover self.fail(e) def test_help_text(self): validator = self.validator help_text = validator.get_help_text() self.assertIn('The password must contain at least 2 characters from a-z.', help_text) self.assertIn('The password must contain at least 2 characters from A-Z.', help_text) self.assertIn('The password must contain at least 2 digits from 0-9.', help_text) self.assertIn('The password must contain at least 2 non alpha numeric characters.', help_text)