From 04326af2daaf93de87b0498e6b72a1ce804ec38e Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Thu, 16 Jun 2022 11:15:17 +0200 Subject: [PATCH] password validation working --- cps/admin.py | 2 +- .../libs/pwstrength/pwstrength-bootstrap.js | 6 +---- cps/static/js/password.js | 11 +++++---- cps/templates/config_edit.html | 1 - cps/web.py | 23 ++++++++++++++++--- 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/cps/admin.py b/cps/admin.py index c2b9e500..5667fcd3 100755 --- a/cps/admin.py +++ b/cps/admin.py @@ -1778,7 +1778,7 @@ def _configuration_update_helper(): _config_checkbox(to_save, "config_password_upper") _config_checkbox(to_save, "config_password_special") _config_int(to_save, "config_password_min_length") - _config_int(to_save, "config_session") + reboot_required |= _config_int(to_save, "config_session") # Rarfile Content configuration _config_string(to_save, "config_rarfile_location") diff --git a/cps/static/js/libs/pwstrength/pwstrength-bootstrap.js b/cps/static/js/libs/pwstrength/pwstrength-bootstrap.js index e64d1f97..040983b0 100644 --- a/cps/static/js/libs/pwstrength/pwstrength-bootstrap.js +++ b/cps/static/js/libs/pwstrength/pwstrength-bootstrap.js @@ -25,10 +25,6 @@ var i18n = {}; wordTwoCharacterClasses: 'Use different character classes', wordRepetitions: 'Too many repetitions', wordSequences: 'Your password contains sequences', - // wordLowercase: "Use at least one lowercase character", - // wordUppercase: "Use at least one uppercase character", - // wordOneNumber: "Use at least one number", - // wordOneSpecialChar: "Use at least one special character", errorList: 'Errors:', veryWeak: 'Very Weak', weak: 'Weak', @@ -376,7 +372,7 @@ defaultOptions.rules.activated = { wordIsACommonPassword: true }; defaultOptions.rules.raisePower = 1.4; -defaultOptions.rules.specialCharClass = '[!,@,#,$,%,^,&,*,?,_,~]'; +defaultOptions.rules.specialCharClass = "(?=.*?[^A-Za-z\s0-9])"; //'[!,@,#,$,%,^,&,*,?,_,~]'; // List taken from https://github.com/danielmiessler/SecLists (MIT License) defaultOptions.rules.commonPasswords = [ '123456', diff --git a/cps/static/js/password.js b/cps/static/js/password.js index 43a1a0ac..209eea87 100644 --- a/cps/static/js/password.js +++ b/cps/static/js/password.js @@ -37,20 +37,21 @@ $(document).ready(function() { showVerdicts: false, } options.rules= { + specialCharClass: "(?=.*?[^A-Za-z\\s0-9])", activated: { wordNotEmail: false, - wordMinLength: $('#password').data("min") ? true : false, + wordMinLength: $('#password').data("min"), // wordMaxLength: false, // wordInvalidChar: true, wordSimilarToUsername: false, wordSequences: false, wordTwoCharacterClasses: false, wordRepetitions: false, - wordLowercase: $('#password').data("lower") ? true : false, - wordUppercase: $('#password').data("upper") ? true : false, - wordOneNumber: $('#password').data("number") ? true : false, + wordLowercase: $('#password').data("lower") === "True" ? true : false, + wordUppercase: $('#password').data("upper") === "True" ? true : false, + wordOneNumber: $('#password').data("number") === "True" ? true : false, wordThreeNumbers: false, - wordOneSpecialChar: $('#password').data("special") ? true : false, + wordOneSpecialChar: $('#password').data("special") === "True" ? true : false, // wordTwoSpecialChar: true, wordUpperLowerCombo: false, wordLetterNumberCombo: false, diff --git a/cps/templates/config_edit.html b/cps/templates/config_edit.html index 92e38217..22ce2de8 100644 --- a/cps/templates/config_edit.html +++ b/cps/templates/config_edit.html @@ -400,7 +400,6 @@ -
diff --git a/cps/web.py b/cps/web.py index 02ac75b1..b02526ce 100755 --- a/cps/web.py +++ b/cps/web.py @@ -23,6 +23,7 @@ import json import mimetypes import chardet # dependency of requests import copy +import re from flask import Blueprint, jsonify from flask import request, redirect, send_from_directory, make_response, flash, abort, url_for @@ -55,6 +56,7 @@ from .kobo_sync_status import remove_synced_book from .render_template import render_title_template from .kobo_sync_status import change_archived_books + feature_support = { 'ldap': bool(services.ldap), 'goodreads': bool(services.goodreads_support), @@ -1355,10 +1357,25 @@ def logout(): def change_profile(kobo_support, local_oauth_check, oauth_status, translations, languages): to_save = request.form.to_dict() current_user.random_books = 0 - if current_user.role_passwd() or current_user.role_admin(): - if to_save.get("password"): - current_user.password = generate_password_hash(to_save.get("password")) try: + if current_user.role_passwd() or current_user.role_admin(): + if to_save.get("password"): + if config.config_password_policy: + verify = "" + if config.config_password_min_length > 0: + verify += "^(?=\S{" + str(config.config_password_min_length) + ",}$)" + if config.config_password_number: + verify += "(?=.*?\d)" + if config.config_password_lower: + verify += "(?=.*?[a-z])" + if config.config_password_upper: + verify += "(?=.*?[A-Z])" + if config.config_password_special: + verify += "(?=.*?[^A-Za-z\s0-9])" + match = re.match(verify, to_save.get("password")) + if not match: + raise Exception(_("Password doesn't comply with password validation rules")) + current_user.password = generate_password_hash(to_save.get("password")) if to_save.get("kindle_mail", current_user.kindle_mail) != current_user.kindle_mail: current_user.kindle_mail = valid_email(to_save.get("kindle_mail")) if to_save.get("email", current_user.email) != current_user.email: