From cdaddc101d5f4e8b267e753d16e8ddfa67f408bb Mon Sep 17 00:00:00 2001 From: Emmi Takkinen Date: Mon, 20 Jul 2020 10:48:01 +0300 Subject: [PATCH 2/2] Bug 12617: Add new regex patterns to password_check.inc This patch adds new regex patterns to follow into password_check.inc files. To test: 1. Create or find existing patron. 2. Set or edit invalid password for patron in OPAC and staff interfaces: a) create and edit patron pages b) 'Change password' pages 3. Confirm alert text next to input field is displayed and it follows set passwordpolicy. Sponsored-by: Koha-Suomi Oy --- .../prog/en/includes/password_check.inc | 42 ++++++++++++++++-- .../en/modules/members/member-password.tt | 2 +- .../prog/en/modules/members/memberentrygen.tt | 2 +- .../bootstrap/en/includes/password_check.inc | 43 +++++++++++++++++-- .../bootstrap/en/modules/opac-memberentry.tt | 2 +- .../bootstrap/en/modules/opac-passwd.tt | 2 +- members/memberentry.pl | 1 + 7 files changed, 83 insertions(+), 11 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/password_check.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/password_check.inc index 1c11896c57..5b040b530a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/password_check.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/password_check.inc @@ -7,26 +7,60 @@ var category_selector = "[% category_selector | html %]"; var STRONG_MSG = _("Password must contain at least %s characters, including UPPERCASE, lowercase and numbers"); var WEAK_MSG = _("Password must contain at least %s characters"); - + var COMPLEX_MSG = _("Password must contain numbers, lower and uppercase characters and special characters and must be at least %s characters long."); + var ALPHA_MSG = _("Password must contain both numbers and non-special characters and must be at least %s characters long."); + var SIMPLE_MSG = _("Password can only contain digits 0-9 and must be at least %s characters long."); if(category_selector && $('select'+category_selector).length) { jQuery.validator.addMethod("password_strong", function(value, element){ var require_strong = $('select'+category_selector+' option:selected').data('pwdStrong'); var min_lenght = $('select'+category_selector+' option:selected').data('pwdLength'); - var regex_text = require_strong?"(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{"+min_lenght+",}":".{"+min_lenght+",}"; + var passwordpolicy = $('select'+category_selector+' option:selected').data('pwdPolicy'); + var regex_text = ''; + if(passwordpolicy){ + if(passwordpolicy == 'complex'){ + regex_text = "(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\|\[\]\{\}!@#\$%\^&\*\(\)_\-\+\?]).{"+min_lenght+",}"; + }else if(passwordpolicy == 'alphanumeric'){ + regex_text = "(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{"+min_lenght+",}"; + }else{ + regex_text = "(?=.*\\d)(?=.*[0-9]).{"+min_lenght+",}"; + } + }else{ + regex_text = require_strong?"(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{"+min_lenght+",}":".{"+min_lenght+",}"; + } var pattern_regex = new RegExp(regex_text); return this.optional(element) || pattern_regex.test(value); }, function(unused, element) { var require_strong = $('select'+category_selector+' option:selected').data('pwdStrong'); var min_lenght = $('select'+category_selector+' option:selected').data('pwdLength'); - return (require_strong?STRONG_MSG:WEAK_MSG).format(min_lenght) + var passwordpolicy = $('select'+category_selector+' option:selected').data('pwdPolicy'); + if(passwordpolicy){ + if(passwordpolicy == 'complex'){ + return (COMPLEX_MSG).format(min_lenght); + }else if(passwordpolicy == 'alphanumeric'){ + return (ALPHA_MSG).format(min_lenght); + }else{ + return (SIMPLE_MSG).format(min_lenght); + } + }else{ + return (require_strong?STRONG_MSG:WEAK_MSG).format(min_lenght) + } }); } else { [% IF RequireStrongPassword %] pwd_title = STRONG_MSG.format([% minPasswordLength | html %]); pattern_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{[% minPasswordLength | html %],}/; - [% ELSIF minPasswordLength %] + [% ELSIF minPasswordLength && !password_policy %] pwd_title = WEAK_MSG.format([% minPasswordLength | html %]); pattern_regex = /.{[% minPasswordLength | html %],}/; + [% ELSIF password_policy == 'simplenumeric' %] + pwd_title = SIMPLE_MSG.format([% minPasswordLength | html %]); + pattern_regex = /(?=.*\d)([0-9]){[% minPasswordLength | html %],}/; + [% ELSIF password_policy == 'alphanumeric' %] + pwd_title = ALPHA_MSG.format([% minPasswordLength | html %]);; + pattern_regex = /(?=.*\d)(?=.*[a-zA-Z])([a-zA-Z0-9]){[% minPasswordLength | html %],}/; + [% ELSIF password_policy == 'complex' %] + pwd_title = COMPLEX_MSG.format([% minPasswordLength | html %]); + pattern_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\|\[\]\{\}!@#\$%\^&\*\(\)_\-\+\?])([a-zA-Z0-9\|\[\]\{\}!@#\$%\^&\*\(\)_\-\+\?]){[% minPasswordLength | html %],}/; [% END %] jQuery.validator.addMethod("password_strong", function(value, element){ return this.optional(element) || value == '****' || pattern_regex.test(value); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-password.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-password.tt index 970f213243..b4e0e4726d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-password.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-password.tt @@ -175,7 +175,7 @@ }); }); - [% PROCESS 'password_check.inc' new_password => 'newpassword', minPasswordLength => patron.category.effective_min_password_length, RequireStrongPassword => patron.category.effective_require_strong_password %] + [% PROCESS 'password_check.inc' new_password => 'newpassword', minPasswordLength => patron.category.effective_min_password_length, RequireStrongPassword => patron.category.effective_require_strong_password, password_policy => patron.category.passwordpolicy %] [% END %] [% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt index 10fbb58a5b..003b6bf40a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt @@ -1739,7 +1739,7 @@ legend:hover { [% Asset.js("js/members.js") | $raw %] [% Asset.js("js/messaging-preference-form.js") | $raw %] - [% PROCESS 'password_check.inc' new_password => 'password', category_selector => '#categorycode_entry', minPasswordLength => patron.category.effective_min_password_length, RequireStrongPassword => patron.category.effective_require_strong_password %] + [% PROCESS 'password_check.inc' new_password => 'password', category_selector => '#categorycode_entry', minPasswordLength => patron.category.effective_min_password_length, RequireStrongPassword => patron.category.effective_require_strong_password, password_policy => patron.category.passwordpolicy %] [% END %] [% INCLUDE 'intranet-bottom.inc' %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/password_check.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/password_check.inc index 338d07bbbb..51ae54648b 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/password_check.inc +++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/password_check.inc @@ -4,33 +4,70 @@ var pattern_title = ""; var new_password_node_name = "[% new_password | html %]"; var category_selector = "[% category_selector | html %]"; + var password_policy = "[% password_policy | html %]"; var STRONG_MSG = _("Password must contain at least %s characters, including UPPERCASE, lowercase and numbers"); var WEAK_MSG = _("Password must contain at least %s characters"); + var COMPLEX_MSG = _("Password must contain numbers, lower and uppercase characters and special characters and must be at least %s characters long."); + var ALPHA_MSG = _("Password must contain both numbers and non-special characters and must be at least %s characters long."); + var SIMPLE_MSG = _("Password can only contain digits 0-9 and must be at least %s characters long."); if(category_selector && $('select'+category_selector).length) { jQuery.validator.addMethod("password_strong", function(value, element){ var require_strong = $('select'+category_selector+' option:selected').data('pwdStrong'); var min_lenght = $('select'+category_selector+' option:selected').data('pwdLength'); - var regex_text = require_strong?"(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{"+min_lenght+",}":".{"+min_lenght+",}"; + var passwordpolicy = $('select'+category_selector+' option:selected').data('pwdPolicy'); + var regex_text = ''; + if(passwordpolicy){ + if(passwordpolicy == 'complex'){ + regex_text = "(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\|\[\]\{\}!@#\$%\^&\*\(\)_\-\+\?]).{"+min_lenght+",}"; + }else if(passwordpolicy == 'alphanumeric'){ + regex_text = "(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{"+min_lenght+",}"; + }else{ + regex_text = "(?=.*\\d)(?=.*[0-9]).{"+min_lenght+",}"; + } + }else{ + regex_text = require_strong?"(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{"+min_lenght+",}":".{"+min_lenght+",}"; + } var pattern_regex = new RegExp(regex_text); return this.optional(element) || pattern_regex.test(value); }, function(unused, element) { var require_strong = $('select'+category_selector+' option:selected').data('pwdStrong'); var min_lenght = $('select'+category_selector+' option:selected').data('pwdLength'); - return (require_strong?STRONG_MSG:WEAK_MSG).format(min_lenght) + var passwordpolicy = $('select'+category_selector+' option:selected').data('pwdPolicy'); + if(passwordpolicy){ + if(passwordpolicy == 'complex'){ + return (COMPLEX_MSG).format(min_lenght); + }else if(passwordpolicy == 'alphanumeric'){ + return (ALPHA_MSG).format(min_lenght); + }else{ + return (SIMPLE_MSG).format(min_lenght); + } + }else{ + return (require_strong?STRONG_MSG:WEAK_MSG).format(min_lenght) + } }); } else { [% IF RequireStrongPassword %] pwd_title = STRONG_MSG.format([% minPasswordLength | html %]); pattern_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{[% minPasswordLength | html %],}/; - [% ELSIF minPasswordLength %] + [% ELSIF minPasswordLength && !password_policy %] pwd_title = WEAK_MSG.format([% minPasswordLength | html %]); pattern_regex = /.{[% minPasswordLength | html %],}/; + [% ELSIF password_policy == 'simplenumeric' %] + pwd_title = SIMPLE_MSG.format([% minPasswordLength | html %]); + pattern_regex = /(?=.*\d)([0-9]){[% minPasswordLength | html %],}/; + [% ELSIF password_policy == 'alphanumeric' %] + pwd_title = ALPHA_MSG.format([% minPasswordLength | html %]);; + pattern_regex = /(?=.*\d)(?=.*[a-zA-Z])([a-zA-Z0-9]){[% minPasswordLength | html %],}/; + [% ELSIF password_policy == 'complex' %] + pwd_title = COMPLEX_MSG.format([% minPasswordLength | html %]); + pattern_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\|\[\]\{\}!@#\$%\^&\*\(\)_\-\+\?])([a-zA-Z0-9\|\[\]\{\}!@#\$%\^&\*\(\)_\-\+\?]){[% minPasswordLength | html %],}/; [% END %] jQuery.validator.addMethod("password_strong", function(value, element){ return this.optional(element) || value == '****' || pattern_regex.test(value); }, pwd_title); } + jQuery.validator.addMethod("password_no_spaces", function(value, element){ return ( this.optional(element) || !value.match(/^\s/) && !value.match(/\s$/) ); }, _("Password contains leading and/or trailing spaces")); diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt index 06ab0b1544..f67d686e84 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt @@ -1226,6 +1226,6 @@ [% END %] //]]> - [% PROCESS 'password_check.inc' new_password => 'borrower_password', category_selector => '#borrower_categorycode', RequireStrongPassword => patron.category.effective_require_strong_password, minPasswordLength => patron.category.effective_min_password_length %] + [% PROCESS 'password_check.inc' new_password => 'borrower_password', category_selector => '#borrower_categorycode', RequireStrongPassword => patron.category.effective_require_strong_password, minPasswordLength => patron.category.effective_min_password_length, password_policy => patron.category.passwordpolicy %] [% END %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-passwd.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-passwd.tt index a2812f3e32..e0c810439e 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-passwd.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-passwd.tt @@ -108,7 +108,7 @@ [% INCLUDE 'opac-bottom.inc' %] [% BLOCK jsinclude %] [% Asset.js("lib/jquery/plugins/jquery.validate.min.js") | $raw %] - [% PROCESS 'password_check.inc' new_password => 'Newkey', minPasswordLength => logged_in_user.category.effective_min_password_length, RequireStrongPassword => logged_in_user.category.effective_require_strong_password %] + [% PROCESS 'password_check.inc' new_password => 'Newkey', minPasswordLength => logged_in_user.category.effective_min_password_length, RequireStrongPassword => logged_in_user.category.effective_require_strong_password, password_policy => logged_in_user.category.passwordpolicy %]