Projet

Général

Profil

0001-add-password-validation-UI-in-registration-view-2443.patch

Anonyme, 15 juin 2018 12:01

Télécharger (11,2 ko)

Voir les différences:

Subject: [PATCH] add password validation UI in registration view (#24439)

 src/authentic2/registration_backend/forms.py  |  3 +
 src/authentic2/registration_backend/views.py  |  6 ++
 .../static/authentic2/css/style.css           | 59 ++++++++++++
 .../static/authentic2/js/password.js          | 95 +++++++++++++++++++
 .../registration_completion_form.html         |  9 +-
 src/authentic2/validators.py                  | 40 ++++----
 6 files changed, 195 insertions(+), 17 deletions(-)
 create mode 100644 src/authentic2/static/authentic2/js/password.js
src/authentic2/registration_backend/forms.py
115 115

  
116 116

  
117 117
class RegistrationCompletionForm(RegistrationCompletionFormNoPassword):
118
    class Media:
119
        js = ('authentic2/js/password.js',)
120

  
118 121
    password1 = CharField(widget=PasswordInput, label=_("Password"),
119 122
            validators=[validators.validate_password],
120 123
            help_text=validators.password_help_text())
src/authentic2/registration_backend/views.py
2 2
import collections
3 3
import logging
4 4
import random
5
import json
5 6

  
6 7
from django.conf import settings
7 8
from django.shortcuts import get_object_or_404
......
266 267
        ctx['email'] = self.email
267 268
        ctx['email_is_unique'] = self.email_is_unique
268 269
        ctx['create'] = 'create' in self.request.GET
270
        ctx['passwordpolicy'] = json.dumps({
271
            'A2_PASSWORD_POLICY_MIN_LENGTH': app_settings.A2_PASSWORD_POLICY_MIN_LENGTH,
272
            'A2_PASSWORD_POLICY_MIN_CLASSES': app_settings.A2_PASSWORD_POLICY_MIN_CLASSES,
273
            'A2_PASSWORD_POLICY_REGEX': app_settings.A2_PASSWORD_POLICY_REGEX,
274
        })
269 275
        return ctx
270 276

  
271 277
    def get(self, request, *args, **kwargs):
src/authentic2/static/authentic2/css/style.css
76 76
.a2-log-message {
77 77
  white-space: pre-wrap;
78 78
}
79

  
80
.a2-min-class-policy, .a2-min-length-policy, .a2-regexp-policy {
81
  display: inline;
82
}
83

  
84
.password-error {
85
  font-weight: bold;
86
  color: red;
87
}
88

  
89
.password-error:before {
90
  content: "\f071";
91
  margin-right: 0.3em;
92
  font-family: FontAwesome;
93
  font-size: 100%;
94
  color: red;
95
}
96

  
97
.password-ok:before {
98
  content: "\f00c";
99
  font-family: FontAwesome;
100
  font-size: 100%;
101
  color: green;
102
}
103

  
104
.show-password-button {
105
  padding-left: 0.5em;
106
  cursor: pointer;
107
}
108

  
109
.show-password-button:after {
110
	content: "\f06e";
111
	font-family: FontAwesome;
112
	font-size: 150%;
113
}
114

  
115
.hide-password-button:after {
116
	content: "\f070";
117
	font-family: FontAwesome;
118
	font-size: 150%;
119
}
120

  
121
.a2-passwords-unmatched {
122
  display: none;
123
  color: red;
124
}
125

  
126
.a2-passwords-matched {
127
  display: none;
128
  color: green;
129
}
130

  
131
.password-error .a2-passwords-unmatched {
132
  display: inline;
133
}
134

  
135
.password-ok .a2-passwords-matched {
136
  display: inline;
137
}
src/authentic2/static/authentic2/js/password.js
1
"use strict";
2
/* globals $ */
3

  
4
$(function () {
5
	var toggleError = function($elt) {
6
		$elt.removeClass('password-ok');
7
		$elt.addClass('password-error');
8
	}
9
	var toggleOk = function($elt) {
10
		$elt.removeClass('password-error');
11
		$elt.addClass('password-ok');
12
	}
13
	var validatePassword = function () {
14
		var settings = $(this).data('passwordPolicy');
15
		var inputName = $(this).data('passwordPolicyInputName');
16
		var minClassElt = $(this).find('.a2-min-class-policy');
17
		var minLengthElt = $(this).find('.a2-min-length-policy');
18
		var regexpElt = $(this).find('.a2-regexp-policy');
19
		$(this)
20
			.find('input[name='+inputName+']')
21
			.each(function () {
22
				var password = $(this).val();
23
				var min_len = settings.A2_PASSWORD_POLICY_MIN_LENGTH;
24
				if (min_len && password.length < min_len) {
25
					toggleError(minLengthElt);
26
				} else {
27
					toggleOk(minLengthElt);
28
				}
29
				var digits = /\d/g;
30
				var lowerCase = /[a-z]/g;
31
				var upperCase = /[A-Z]/g;
32
				var punctuation = /'!"#\$%&\\'\(\)\*\+,-\.\/:;<=>\?@\[\]\^_`\{\|\}~'/g;
33
				var minClassCount = settings.A2_PASSWORD_POLICY_MIN_CLASSES;
34
				var classCount = 0;
35
				if (minClassCount) {
36
					[digits, lowerCase, upperCase, punctuation].forEach(function (cls) {
37
						if (cls.test(password)) classCount++;
38
					})
39
					if (classCount < minClassCount) {
40
						toggleError(minClassElt);
41
					} else {
42
						toggleOk(minClassElt);
43
					}
44
				}
45
				if (settings.A2_PASSWORD_POLICY_REGEX) {
46
					var regExpObject = new RegExp(settings.A2_PASSWORD_POLICY_REGEX, 'g');
47
					if (!regExpObject.test(password)) {
48
						toggleError(regexpElt);
49
					} else {
50
						toggleOk(regexpElt);
51
					}
52
				}
53
			});
54
	}
55
	var passwordEquality = function () {
56
		var form = $(this).parents('form');
57
		var messages = form.find('.a2-password-messages');
58
		var input0 = form.find('input[type=password]').eq(0);
59
		var input1 = form.find('input[type=password]').eq(1);
60
		if (!input1.val() || !input0.val()) return;
61
		if (input0.val() !== input1.val()) {
62
			toggleError(messages);
63
		} else {
64
			toggleOk(messages);
65
		}
66
	}
67
	var showPassword = function () {
68
		$(this).addClass('hide-password-button');
69
		$(this)
70
			.parents('form')
71
			.find('input.showPassword')
72
			.attr('type', 'text');
73
	}
74
	var hidePassword = function () {
75
		$(this).removeClass('hide-password-button');
76
		$(this)
77
			.parents('form')
78
			.find('input.showPassword')
79
			.attr('type', 'password');
80
	}
81

  
82
	$('form[data-password-policy]')
83
		.keyup(validatePassword);
84
	$('form.passwordEquality input[type=password]')
85
		.keyup(passwordEquality);
86
	/* add the show-password-button after the first input */
87
	$('<i class="show-password-button"></i>')
88
		.insertAfter($('form.showPassword input[name='+
89
		$('form.showPassword').data('passwordShowInputName')
90
		+']').addClass('showPassword'));
91
	$('form.showPassword')
92
		.on('mousedown', '.show-password-button', showPassword);
93
	$('form.showPassword')
94
		.on('mouseup', '.show-password-button', hidePassword);
95
});
src/authentic2/templates/registration/registration_completion_form.html
25 25
{% block content %}
26 26
      <h2>{% trans "Registration" %}</h2>
27 27
      <p>{% trans "Please fill the form to complete your registration" %}</p>
28
      <form method="post">
28
      <form method="post" class="showPassword passwordEquality"
29
        data-password-policy='{% autoescape off %}{{ passwordpolicy }}{% endautoescape %}'
30
        data-password-policy-input-name='password1'
31
        data-password-show-input-name='password1'>
29 32
        {% csrf_token %}
30 33
        {{ form.as_p }}
34
        <div class="a2-password-messages">
35
          <span class="a2-passwords-matched">{% trans 'Passwords match.' %}</span>
36
          <span class="a2-passwords-unmatched">{% trans 'Passwords do not match.' %}</span>
37
        </div>
31 38
        <button class="submit-button">{% trans 'Submit' %}</button>
32 39
      </form>
33 40
{% endblock %}
src/authentic2/validators.py
120 120

  
121 121

  
122 122
def __password_help_text_helper():
123
    if app_settings.A2_PASSWORD_POLICY_MIN_LENGTH and \
124
            app_settings.A2_PASSWORD_POLICY_MIN_CLASSES:
125
        yield ugettext('Your password must contain at least %(min_length)d characters from at '
126
                'least %(min_classes)d classes among: lowercase letters, uppercase letters, '
127
                'digits and punctuations.') % {
128
                        'min_length': app_settings.A2_PASSWORD_POLICY_MIN_LENGTH,
129
                        'min_classes': app_settings.A2_PASSWORD_POLICY_MIN_CLASSES}
123
    '''
124
    Password fields help_text
125
    '''
126
    min_length_html = '<span class="a2-min-length-policy">%s</span>' %\
127
        ugettext('Your password must contain at least %(min_length)d characters.' %
128
        {'min_length': app_settings.A2_PASSWORD_POLICY_MIN_LENGTH})
129

  
130
    min_class_html = '<span class="a2-min-class-policy">%s</span>' %\
131
        ugettext(('at least %(min_classes)d classes among: lowercase letters, uppercase letters, digits and punctuations.') %
132
        {'min_classes': app_settings.A2_PASSWORD_POLICY_MIN_CLASSES})
133
    if app_settings.A2_PASSWORD_POLICY_REGEX_ERROR_MSG:
134
        regexp_html = '<span class="a2-regexp-policy">%s</span>' %\
135
            ugettext(app_settings.A2_PASSWORD_POLICY_REGEX_ERROR_MSG)
136
    else:
137
        regexp_html = '<span class="a2-regexp-policy">%s</span>' %\
138
            ugettext('Your password must match the regular expression: %(regexp)s, please change this message using the A2_PASSWORD_POLICY_REGEX_ERROR_MSG setting.') % \
139
                {'regexp': app_settings.A2_PASSWORD_POLICY_REGEX}
140

  
141
    if app_settings.A2_PASSWORD_POLICY_MIN_LENGTH and app_settings.A2_PASSWORD_POLICY_MIN_CLASSES:
142
        yield '%s %s %s' % (min_length_html, _('from'), min_class_html)
130 143
    else:
131 144
        if app_settings.A2_PASSWORD_POLICY_MIN_LENGTH:
132
            yield ugettext('Your password must contain at least %(min_length)d characters.') % {'min_length': app_settings.A2_PASSWORD_POLICY_MIN_LENGTH}
145
            yield min_length_html
133 146
        if app_settings.A2_PASSWORD_POLICY_MIN_CLASSES:
134
            yield ugettext('Your password must contain characters from at least %(min_classes)d '
135
                    'classes among: lowercase letters, uppercase letters, digits '
136
                    'and punctuations.') % {'min_classes': app_settings.A2_PASSWORD_POLICY_MIN_CLASSES}
147
            yield "%s %s" % (ugettext('Your password must contain characters from'), min_class_html)
137 148
    if app_settings.A2_PASSWORD_POLICY_REGEX:
138
        yield ugettext(app_settings.A2_PASSWORD_POLICY_REGEX_ERROR_MSG) or \
139
                ugettext('Your password must match the regular expression: '
140
                        '%(regexp)s, please change this message using the '
141
                        'A2_PASSWORD_POLICY_REGEX_ERROR_MSG setting.') % \
142
                        {'regexp': app_settings.A2_PASSWORD_POLICY_REGEX}
149
        yield regexp_html
150

  
143 151

  
144 152
def password_help_text():
145 153
    return ' '.join(__password_help_text_helper())
146
-