src/templates/people/modules/cdr.html \
src/templates/people/modules/channels.html \
src/templates/people/modules/mos.html \
+ src/templates/people/modules/password.html \
+ src/templates/people/modules/password.js \
src/templates/people/modules/registrations.html \
src/templates/people/modules/sip-status.html
\
src/static/js/jquery-3.3.1.min.js \
src/static/js/popper.min.js \
- src/static/js/prettify.js
+ src/static/js/prettify.js \
+ \
+ src/static/js/zxcvbn/dist/zxcvbn.js \
+ src/static/js/zxcvbn/dist/zxcvbn.js.map
static_jsdir = $(staticdir)/js
--- /dev/null
+<fieldset>
+ <div class="form-group">
+ <label>{{ _("New Password") }}</label>
+
+ <input type="password" class="form-control" name="password1"
+ id="password1" placeholder="{{ _("New Password") }}" required
+ data-user-input="{{ " ".join((account.first_name, account.last_name)) }}">
+ </div>
+
+ <div class="form-group">
+ <input type="password" class="form-control" name="password2"
+ id="password2" placeholder="{{ _("Repeat Password") }}" required>
+
+ <div id="password-mismatch" class="invalid-feedback">
+ {{ _("Passwords do not match") }}
+ </div>
+ </div>
+
+ <div class="form-group">
+ <div class="progress">
+ <div class="progress-bar" id="password-strength" role="progressbar"></div>
+ </div>
+ </div>
+
+ <div class="form-group text-muted">
+ <p class="mb-0" id="password-warning"></p>
+
+ <small class="form-text">
+ <ul id="password-feedback"></ul>
+ </small>
+ </div>
+</fieldset>
--- /dev/null
+$(function() {
+ var progress = $("#password-strength");
+ var warning = $("#password-warning");
+ var feedback = $("#password-feedback");
+
+ $("#password1").keyup(function(event) {
+ var password1 = $(this).val();
+
+ // Fetch words that are common to the user
+ var user_inputs = $(this).data("user-input").split(" ");
+
+ if (password1) {
+ // Estimate password quality
+ var quality = zxcvbn(password1, user_inputs);
+
+ // Convert score into percentage
+ var percentage = (quality.score + 1) * 20;
+
+ // Set progress bar width
+ progress.css("width", percentage + "%");
+
+ // Clear all previous backgrounds
+ progress.removeClass([
+ "bg-success", "bg-warning", "bg-danger"
+ ]);
+
+ // Make progress bar show in the right colour
+ switch (quality.score) {
+ case 0:
+ case 1:
+ case 2:
+ progress.addClass("bg-danger");
+ break;
+
+ case 3:
+ progress.addClass("bg-warning");
+ break;
+
+ case 4:
+ progress.addClass("bg-success");
+ break;
+ }
+
+ // Show any feedback
+ warning.empty();
+ feedback.empty();
+
+ if (quality.feedback) {
+ if (quality.feedback.warning) {
+ warning.html(quality.feedback.warning);
+ }
+
+ $.each(quality.feedback.suggestions, function (i, suggestion) {
+ feedback.append("<li>" + suggestion + "</li>");
+ });
+ }
+ } else {
+ progress.css("width", "0%");
+
+ // Clear all feedback
+ warning.empty();
+ feedback.empty();
+ }
+ });
+
+ $("input[type=submit]").click( function(event) {
+ var password1 = $("#password1");
+ var password2 = $("#password2");
+
+ // If the passwords match, we allow to submit the form
+ if (password1.val() === password2.val()) {
+ return true;
+
+ } else {
+ $("#password-mismatch").show();
+ return false;
+ }
+ });
+});
placeholder="{{ _("Current Password") }}">
</div>
- <fieldset>
- <div class="form-group">
- <label>{{ _("New Password") }}</label>
-
- <input type="password" class="form-control" name="password1"
- placeholder="{{ _("New Password") }}">
- </div>
-
- <div class="form-group">
- <input type="password" class="form-control" name="password2"
- placeholder="{{ _("Repeat Password") }}">
- </div>
- </fieldset>
+ {% module Password(account) %}
<input class="btn btn-primary btn-block" type="submit" value="{{ _("Change Password") }}">
</form>
"CDR" : people.CDRModule,
"Channels" : people.ChannelsModule,
"MOS" : people.MOSModule,
+ "Password" : people.PasswordModule,
"Registrations" : people.RegistrationsModule,
"SIPStatus" : people.SIPStatusModule,
return self.render_string("people/modules/mos.html", call=call)
+class PasswordModule(ui_modules.UIModule):
+ def render(self, account):
+ return self.render_string("people/modules/password.html", account=account)
+
+ def javascript_files(self):
+ return "js/zxcvbn.js"
+
+ def embedded_javascript(self):
+ return self.render_string("people/modules/password.js")
+
+
class RegistrationsModule(ui_modules.UIModule):
def render(self, account):
return self.render_string("people/modules/registrations.html", account=account)