Bug 18298: Use the validate jQuery plugin
authorJonathan Druart <jonathan.druart@bugs.koha-community.org>
Fri, 17 Mar 2017 01:59:51 +0000 (22:59 -0300)
committerJonathan Druart <jonathan.druart@bugs.koha-community.org>
Mon, 16 Oct 2017 12:44:32 +0000 (09:44 -0300)
To validate password fields we need to use the validate jQuery plugin.
To make things reusable this patch adds a new include file
'password_check.inc' at the intranet and opac sides, it creates 3 new
validation methods:
- password_strong => make sure the passwords are strong enough according
to the values of the RequireStrongPassword and minPasswordLength prefs
- password_no_spaces => prevent passwords to be entered with leading or
trailing spaces
- password_match => make sure both password fields match

Signed-off-by: Marc VĂ©ron <veron@veron.ch>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
koha-tmpl/intranet-tmpl/prog/en/includes/password_check.inc [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/modules/members/member-password.tt
koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt
koha-tmpl/intranet-tmpl/prog/js/members.js
koha-tmpl/opac-tmpl/bootstrap/en/includes/password_check.inc [new file with mode: 0644]
koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-memberentry.tt
koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-passwd.tt

diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/password_check.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/password_check.inc
new file mode 100644 (file)
index 0000000..eb730e6
--- /dev/null
@@ -0,0 +1,25 @@
+[% USE Koha %]
+[% BLOCK add_password_check %]
+<script type="text/javascript">
+    var pwd_title = "";
+    var pattern_title = "";
+    var new_password_node_name = "[% new_password %]";
+    [% IF Koha.Preference('RequireStrongPassword') %]
+        pwd_title = _("Password must contain at least %s characters, including UPPERCASE, lowercase and numbers").format([% minPasswordLength %]);
+        pattern_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{[% minPasswordLength %],}/;
+    [% ELSIF minPasswordLength %]
+        pwd_title = _("Password must contain at least %s characters").format([% minPasswordLength %]);
+        pattern_regex = /.{[% minPasswordLength %],}/;
+    [% 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"));
+    jQuery.validator.addMethod("password_match", function(value, element){
+        var new_password_node = $("input[name='" + new_password_node_name + "']:first");
+        return this.optional(element) || value == $(new_password_node).val();
+    }, _("Please enter the same password as above"));
+</script>
+[% END %]
index 2c28996..5191551 100644 (file)
@@ -1,3 +1,4 @@
+[% USE Koha %]
 [% USE Branches %]
 [% INCLUDE 'doc-head-open.inc' %]
 <title>Koha &rsaquo; Patrons &rsaquo; [% IF ( newpassword ) %]Password updated [% ELSE %]Update password for [% surname %], [% firstname %][% END %]</title>
@@ -5,28 +6,7 @@
 <script type="text/JavaScript">
 //<![CDATA[
 
-    function check_password( password ) {
-        if ( password.match(/^\s/) || password.match(/\s$/)) {
-            return false;
-        }
-        return true;
-    }
-
     $(document).ready(function() {
-        var MSG_PASSWORD_CONTAINS_TRAILING_SPACES = _("Password contains leading and/or trailing spaces.");
-        $("#changepasswordf").submit(function(){
-            if($("input[name='newpassword']").val() != $("input[name='newpassword2']").val()){
-                alert(_("Passwords do not match"));
-                return false;
-            } else {
-                if ( ! check_password( $("input[name='newpassword']").val() ) ) {
-                  alert(MSG_PASSWORD_CONTAINS_TRAILING_SPACES);
-                  return false;
-              } else {
-                return true;
-}
-            }
-        });
         $("body").on('click', "#fillrandom",function(e) {
             e.preventDefault();
             $.get("/cgi-bin/koha/members/member-password.pl?member=[% userid %]", function(response) {
             $("input[name^=newpassword]").show();
             $("label[for=newpassword2]").show();
             $(".loading").hide();
+            $("label.error").hide();
+        });
+        [% IF NOMATCH %]
+            $("#newpassword").addClass('focus');
+        [% END %]
+
+        $("#changepasswordf").validate({
+            rules: {
+                newpassword: {
+                    required: true,
+                    password_strong: true,
+                    password_no_spaces: true
+                },
+                newpassword2: {
+                    required: true,
+                    password_match: true
+                }
+            }
         });
     });
 //]]>
        <ol>
     <li><label for="newuserid">New username:</label>
        <input type="hidden" name="member" value="[% borrowernumber %]" /><input type="text" id="newuserid" name="newuserid" size="20" value="[% userid %]" /></li>
-    <li><label for="newpassword">New password:</label>
-    <div class="hint">Koha cannot display existing passwords. Leave the field blank to leave password unchanged.</div>
-       [% IF ( minPasswordLength ) %]<div class="hint">Minimum password length: [% minPasswordLength %]</div>[% END %]
-       [% IF ( NOMATCH ) %]
-       <input name="newpassword"  id="newpassword" type="password" size="20" class="focus" />
-       <input name="newpassword" id="newpassword_random" readonly="readonly" disabled="disabled" type="hidden" />
-       [% ELSE %]
-       <input name="newpassword"  id="newpassword" type="password" size="20" />
-       <input name="newpassword" readonly="readonly" disabled="disabled" type="hidden" />
-       [% END %]
-       </li>
-    <li><label for="newpassword2">Confirm new password:</label>
-       <input name="newpassword2"  id="newpassword2" type="password" size="20" />
-       <input name="newpassword2" id="newpassword2_random" readonly="readonly" disabled="disabled" type="hidden" />
-       </li>
+    [% SET password_pattern = ".{" _ minPasswordLength _ ",}" %]
+    [% IF Koha.Preference('RequireStrongPassword') %]
+        [% SET password_pattern = '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{' _ minPasswordLength _ ',}' %]
+    [% END %]
+    <li>
+        <label for="newpassword">New password:</label>
+        <div class="hint">Koha cannot display existing passwords. Leave the field blank to leave password unchanged.</div>
+        <input name="newpassword"  id="newpassword" type="password" size="20" />
+    </li>
+    <li>
+        <label for="newpassword2">Confirm new password:</label>
+        <input name="newpassword2"  id="newpassword2" type="password" size="20" />
+    </li>
        </ol>
 </fieldset>
     <fieldset class="action">
 </div>
 </div>
 [% INCLUDE 'intranet-bottom.inc' %]
+[% PROCESS 'password_check.inc' %]
+[% PROCESS 'add_password_check' new_password => 'newpassword' %]
index 091486e..745fa5d 100644 (file)
@@ -70,6 +70,21 @@ $(document).ready(function() {
         }
         else {return false;}
     });
+
+    $("#entryform").validate({
+        rules: {
+            password: {
+                required: true,
+                password_strong: true,
+                password_no_spaces: true
+            },
+            password2: {
+                required: true,
+                password_match: true
+            }
+        }
+    });
+
     $("#saverecord").click(function(){
         if( check_form_borrowers() ){
             $("#entryform").submit();
@@ -86,8 +101,6 @@ $(document).ready(function() {
         var MSG_DUPLICATE_ORGANIZATION = _("Warning: Duplicate organization");
         var MSG_LATE_EXPIRY = _("Warning: Expiration date falls before enrollment date");
         var MSG_DUPLICATE_SUSPICION = _("Please confirm whether this is a duplicate patron");
-        var MSG_PASSWORD_MISMATCH = _("The passwords entered do not match");
-        var MSG_PASSWORD_CONTAINS_TRAILING_SPACES = _("Password contains leading and/or trailing spaces.");
         var MSG_MONTH = _("%s month")
         var MSG_MONTHS = _("%s months")
         var MSG_YEAR = _("%s year")
@@ -1259,4 +1272,5 @@ $(document).ready(function() {
 [% END %]
 </div>
 [% INCLUDE 'intranet-bottom.inc' %]
-
+[% PROCESS 'password_check.inc' %]
+[% PROCESS 'add_password_check' new_password => 'password' %]
index 2ced2ec..aea1f68 100644 (file)
@@ -103,20 +103,6 @@ function check_form_borrowers(nav){
             }
         }
     }
-    if ( document.form.password ) {
-        if ( document.form.password.value != document.form.password2.value ){
-            if ( message_champ !== '' ){
-                message_champ += "\n";
-            }
-            message_champ+= MSG_PASSWORD_MISMATCH;
-            statut=1;
-        }
-
-        if ( ! check_password( document.form.password.value ) ) {
-            message_champ += MSG_PASSWORD_CONTAINS_TRAILING_SPACES;
-            statut = 1;
-        }
-    }
 
     //patrons form to test if you checked no to the question of double
     if (statut!=1 && document.form.check_member.value > 0 ) {
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/password_check.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/password_check.inc
new file mode 100644 (file)
index 0000000..e2ed62e
--- /dev/null
@@ -0,0 +1,25 @@
+[% USE Koha %]
+[% BLOCK add_password_check %]
+<script type="text/javascript">
+    var pwd_title = "";
+    var pattern_title = "";
+    var new_password_node_name = "[% new_password %]";
+    [% IF Koha.Preference('RequireStrongPassword') %]
+        pwd_title = _("Password must contain at least %s characters, including UPPERCASE, lowercase and numbers").format([% minPasswordLength %]);
+        pattern_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{[% minPasswordLength %],}/;
+    [% ELSIF minPasswordLength %]
+        pwd_title = _("Password must contain at least %s characters").format([% minPasswordLength %]);
+        pattern_regex = /.{[% minPasswordLength %],}/;
+    [% END %]
+    jQuery.validator.addMethod("password_strong", function(value, element){
+        return this.optional(element) || 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"));
+    jQuery.validator.addMethod("password_match", function(value, element){
+        var new_password_node = $("input[name='" + new_password_node_name + "']:first");
+        return this.optional(element) || value == $(new_password_node).val();
+    }, _("Please enter the same password as above"));
+</script>
+[% END %]
index d3b89bf..588ad25 100644 (file)
 [% INCLUDE 'opac-bottom.inc' %]
 [% BLOCK jsinclude %]
     <script type="text/javascript" src="[% interface %]/[% theme %]/lib/jquery/plugins/jquery.validate.min.js"></script>
+    [% PROCESS 'password_check.inc' %]
+    [% PROCESS 'add_password_check' new_password => 'borrower_password' %]
     <script type="text/javascript">
         //<![CDATA[
         $(document).ready(function() {
                     },
                     borrower_B_email: {
                         email: true
+                    },
+                    borrower_password: {
+                        [% IF mandatory.defined('password') %]
+                        required: true,
+                        [% END %]
+                        password_strong: true,
+                        password_no_spaces: true
+                    },
+                    borrower_password2: {
+                        [% IF mandatory.defined('password') %]
+                        required: true,
+                        [% END %]
+                        password_match: true
+                    },
+                    captcha: {
+                        required: true,
                     }
                 },
                 submitHandler: function(form) {
index 136bbac..baa083b 100644 (file)
@@ -47,6 +47,7 @@
 
                     [% IF ( OpacPasswordChange ) %]
                         [% IF ( Ask_data ) %]
+
                             <form action="/cgi-bin/koha/opac-passwd.pl" name="mainform" id="mainform" method="post">
                                 <fieldset>
                                     [% UNLESS ( ShortPass ) %]<div class="alert alert-info">Your password must be at least [% minpasslen %] characters long.</div>[% END %]
 
 
 [% INCLUDE 'opac-bottom.inc' %]
-[% BLOCK jsinclude %][% END %]
+[% BLOCK jsinclude %]
+    <script type="text/javascript" src="[% interface %]/[% theme %]/lib/jquery/plugins/jquery.validate.min.js"></script>
+    [% PROCESS 'password_check.inc' %]
+    [% PROCESS 'add_password_check' new_password => 'Newkey' %]
+    <script type="text/javascript">
+        $(document).ready(function() {
+            $("#mainform").validate({
+                rules: {
+                    Newkey: {
+                        required: true,
+                        password_strong: true,
+                        password_no_spaces: true
+                    },
+                    Confirm: {
+                        required: true,
+                        password_match: true
+                    }
+                }
+            });
+        });
+    </script>
+[% END %]