diff --git a/ckanext/security/validators.py b/ckanext/security/validators.py index 77ba480..02657cd 100644 --- a/ckanext/security/validators.py +++ b/ckanext/security/validators.py @@ -3,15 +3,15 @@ import string from ckan import authz -from ckan.common import _ +from ckan.plugins.toolkit import _, asbool, config from ckan.lib.navl.dictization_functions import Missing, Invalid -MIN_PASSWORD_LENGTH = 10 -MIN_LEN_ERROR = ( - 'Your password must be {} characters or longer, and consist of at least ' - 'three of the following character sets: uppercase characters, lowercase ' - 'characters, digits, punctuation & special characters.' +MIN_LEN_ERROR = 'Your password must be {} characters or longer.' +COMPLEXITY_ERROR = ( + 'Your password must consist of at least three of the following character sets: ' + 'uppercase characters, lowercase characters, digits, punctuation & special characters.' ) +SAME_USERNAME_PASSWORD_ERROR = 'Your password cannot be the same as your username.' def user_password_validator(key, data, errors, context): @@ -24,15 +24,32 @@ def user_password_validator(key, data, errors, context): elif value == '': pass # Already handled in core else: - # NZISM compliant password rules - rules = [ - any(x.isupper() for x in value), - any(x.islower() for x in value), - any(x.isdigit() for x in value), - any(x in string.punctuation for x in value) + min_password_length = int(config.get('ckanext.security.min_password_length', 8)) + nzism_compliant = asbool(config.get('ckanext.security.nzism_compliant_passwords', True)) + + username = data.get(('name',), None) + password_fields = [ + data.get(('password',), None), + data.get(('password1',), None), + data.get(('password2',), None), ] - if len(value) < MIN_PASSWORD_LENGTH or sum(rules) < 3: - raise Invalid(_(MIN_LEN_ERROR.format(MIN_PASSWORD_LENGTH))) + + if username in password_fields: + errors[key].append(_(SAME_USERNAME_PASSWORD_ERROR)) + + if len(value) < min_password_length: + errors[key].append(_(MIN_LEN_ERROR).format(min_password_length)) + + if nzism_compliant: + # NZISM compliant password rules + rules = [ + any(x.isupper() for x in value), + any(x.islower() for x in value), + any(x.isdigit() for x in value), + any(x in string.punctuation for x in value) + ] + if sum(rules) < 3: + errors[key].append(_(COMPLEXITY_ERROR)) def old_username_validator(key, data, errors, context):