Bug 23816: Add minimum password length and require strong password overrides by category
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / members / member-password.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% USE Koha %]
4 [% USE Branches %]
5 [% SET footerjs = 1 %]
6 [% INCLUDE 'doc-head-open.inc' %]
7 <title>Koha &rsaquo; Patrons &rsaquo; [% IF ( newpassword ) %]Password updated [% ELSE %]Update password for [% patron.surname | html %], [% patron.firstname | html %][% END %]</title>
8 [% INCLUDE 'doc-head-close.inc' %]
9 </head>
10
11 <body id="pat_member-password" class="pat">
12 [% INCLUDE 'header.inc' %]
13 [% INCLUDE 'patron-search.inc' %]
14
15 <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/members/members-home.pl">Patrons</a>  &rsaquo; <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% patron.borrowernumber | html %]">[% patron.firstname | html %] [% patron.surname | html %]</a> &rsaquo; [% IF ( newpassword ) %]Password Updated[% ELSE %]Change username and/or password[% END %]</div>
16
17 <div class="main container-fluid">
18     <div class="row">
19         <div class="col-sm-10 col-sm-push-2">
20             <main>
21
22 [% INCLUDE 'members-toolbar.inc' %]
23
24 [% IF ( newpassword ) %]
25 <h1>Password Updated</h1>
26
27 [% ELSE %]
28
29 <form method="post" id="changepasswordf" action="/cgi-bin/koha/members/member-password.pl">
30 <input type="hidden" name="destination" value="[% destination | html %]" />
31 <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% patron.borrowernumber | html %]" />
32         [% IF ( errormsg ) %]
33                 <div class="dialog alert">
34                 <h4>The following errors have occurred:</h4>
35                 <ul>
36                 [% IF ( BADUSERID ) %]
37         <li>You have entered a username that already exists. Please choose another one.</li>
38                 [% END %]
39         [% IF ( ERROR_password_too_short ) %]
40             <li id="ERROR_short_password">Password must be at least [% patron.category.effective_min_password_length | html %] characters long.</li>
41         [% END %]
42         [% IF ( ERROR_password_too_weak ) %]
43             <li id="ERROR_weak_password">Password must contain at least one digit, one lowercase and one uppercase.</li>
44         [% END %]
45         [% IF ( ERROR_password_has_whitespaces ) %]
46             <li id="ERROR_weak_password">Password must not contain leading or trailing whitespaces.</li>
47         [% END %]
48         [% IF ( ERROR_from_plugin ) %]
49             <li id="ERROR_from_plugin">The password was rejected by a plugin.</li>
50         [% END %]
51                 [% IF ( NOPERMISSION ) %]
52                 <li>You do not have permission to edit this patron's login information.</li>
53                 [% END %]
54                 [% IF ( NOMATCH ) %]
55                 <li><strong>The passwords entered do not match</strong>. Please re-enter the new password.</li>
56                 [% END %]
57                 </ul>
58                 </div>
59         [% END %]
60
61
62     <fieldset class="brief"><legend>Change username and/or password for [% patron.firstname | html %] [% patron.surname | html %]</legend>
63         <ol>
64     <li><label for="newuserid">New username:</label>
65     <input type="hidden" name="member" value="[% patron.borrowernumber | html %]" /><input type="text" id="newuserid" name="newuserid" size="20" value="[% patron.userid | html %]" /></li>
66     [% SET password_pattern = ".{" _ patron.category.effective_min_password_length _ ",}" %]
67     [% IF patron.category.effective_require_strong_password %]
68         [% SET password_pattern = '(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{' _ patron.category.effective_min_password_length _ ',}' %]
69     [% END %]
70     <li>
71         <label for="newpassword">New password:</label>
72         <div class="hint">Koha cannot display existing passwords. Leave the field blank to leave password unchanged.</div>
73         <input name="newpassword"  id="newpassword" type="password" size="20" />
74     </li>
75     <li>
76         <label for="newpassword2">Confirm new password:</label>
77         <input name="newpassword2"  id="newpassword2" type="password" size="20" />
78     </li>
79         </ol>
80 </fieldset>
81     <fieldset class="action">
82         <input type="hidden" name="csrf_token" value="[% csrf_token | html %]" />
83         <input type="submit" value="Save" />
84         <a class="cancel" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% patron.borrowernumber | html %]">Cancel</a>
85     </fieldset>
86 </form>[% END %]
87
88
89 <div class="loading hide"><strong>Processing...</strong><img src="[% interface | html %]/[% theme | html %]/img/loading.gif" alt="" /></div>
90
91             </main>
92         </div> <!-- /.col-sm-10.col-sm-push-2 -->
93
94         <div class="col-sm-2 col-sm-pull-10">
95             <aside>
96                 [% INCLUDE 'circ-menu.inc' %]
97             </aside>
98         </div> <!-- /.col-sm-2.col-sm-pull-10 -->
99     </div> <!-- /.row -->
100
101 [% MACRO jsinclude BLOCK %]
102     [% INCLUDE 'str/members-menu.inc' %]
103     [% Asset.js("js/members-menu.js") | $raw %]
104     <script>
105         function generate_password() {
106             // Always generate a strong password
107             var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
108             var length = [% patron.category.effective_min_password_length | html %];
109             if ( length < 8 ) length = 8;
110             var password='';
111             for ( var i = 0 ; i < length ; i++){
112                 password += chars.charAt(Math.floor(Math.random()*chars.length));
113             }
114             return password;
115         }
116         $(document).ready(function() {
117             $("body").on('click', "#fillrandom",function(e) {
118                 e.preventDefault();
119                 var password = '';
120                 var pattern_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{[% patron.category.effective_min_password_length | html %],}/;
121                 while ( ! pattern_regex.test( password ) ) {
122                     password = generate_password();
123                 }
124                 $("#newpassword").val(password);
125                 $("#newpassword").attr('type', 'text');
126                 $("#newpassword2").val(password);
127                 $("#newpassword2").attr('type', 'text');
128             });
129             $("div.hint").eq(0).after(" <div class=\"hint\"><a href=\"#\" id=\"fillrandom\">"+_("Click to fill with a randomly generated suggestion. ")+"<strong>"+_("Passwords will be displayed as text")+"</strong>.</a></div>");
130
131             $(document).ajaxStart(function () {
132                 $("input[name^=newpassword]").hide();
133                 $("label[for=newpassword2]").hide();
134                 $(".hint:last").after($(".loading").show());
135             });
136             $(document).ajaxStop(function () {
137                 $("input[name^=newpassword]").show();
138                 $("label[for=newpassword2]").show();
139                 $(".loading").hide();
140                 $("label.error").hide();
141             });
142             [% IF NOMATCH %]
143                 $("#newpassword").addClass('focus');
144             [% END %]
145
146             $("#changepasswordf").validate({
147                 rules: {
148                     newpassword: {
149                         password_strong: true,
150                         password_no_spaces: true
151                     },
152                     newpassword2: {
153                         password_match: true
154                     }
155                 }
156             });
157         });
158     </script>
159     [% PROCESS 'password_check.inc' new_password => 'newpassword', minPasswordLength => patron.category.effective_min_password_length, RequireStrongPassword => patron.category.effective_require_strong_password %]
160 [% END %]
161
162 [% INCLUDE 'intranet-bottom.inc' %]