summaryrefslogtreecommitdiffstats
path: root/template
diff options
context:
space:
mode:
authorByron Jones <glob@mozilla.com>2015-08-25 07:40:13 +0200
committerByron Jones <glob@mozilla.com>2015-08-25 07:40:13 +0200
commite6d45b6d6028527079744af20dc9407a2a3867f2 (patch)
tree9f229ada0012cac216a73c442c56e8ac6f1cfe2a /template
parent90a618266ecb83f138cd5d0a3ff5bf26012625e9 (diff)
downloadbugzilla-e6d45b6d6028527079744af20dc9407a2a3867f2.tar.gz
bugzilla-e6d45b6d6028527079744af20dc9407a2a3867f2.tar.xz
Bug 1196134 - add ability for admins to force a user to change their password on next login
Diffstat (limited to 'template')
-rw-r--r--template/en/default/account/reset-password.html.tmpl210
-rw-r--r--template/en/default/admin/users/edit.html.tmpl12
-rw-r--r--template/en/default/admin/users/userdata.html.tmpl37
-rw-r--r--template/en/default/global/messages.html.tmpl4
-rw-r--r--template/en/default/global/user-error.html.tmpl4
5 files changed, 255 insertions, 12 deletions
diff --git a/template/en/default/account/reset-password.html.tmpl b/template/en/default/account/reset-password.html.tmpl
new file mode 100644
index 000000000..2b1d297dc
--- /dev/null
+++ b/template/en/default/account/reset-password.html.tmpl
@@ -0,0 +1,210 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[% inline_style = BLOCK %]
+
+.field-hr, .field-row {
+ clear: both;
+}
+
+.field-row {
+ height: 2.5em;
+}
+
+.field-name {
+ text-align: right;
+ width: 150px;
+ float: left;
+ padding-top: 2px;
+ font-weight: bold;
+}
+
+.field-value {
+ margin-left: 160px;
+}
+
+#errors, #complexity_rules {
+ margin-left: 160px;
+ max-width: 500px;
+}
+
+#errors {
+ color: #dd4848;
+ position: absolute;
+ margin-left: 500px;
+}
+
+#errors ul {
+ padding: 0;
+ margin: 0;
+}
+
+#complexity_rules {
+ margin-bottom: 50px;
+}
+
+[% END %]
+
+[% inline_js = BLOCK %]
+$(function() {
+
+ $('#old_password, #new_password1, #new_password2')
+ .keyup(function() {
+ var errors = [];
+ var old = $('#old_password').val();
+ var new1 = $('#new_password1').val();
+ var new2 = $('#new_password2').val();
+
+ if (old === '') {
+ errors.push('Missing current password');
+ }
+ if (new1 === '' || new2 === '') {
+ errors.push('Missing new password');
+ }
+ else if (new1 !== new2) {
+ errors.push('New passwords do not match');
+ }
+ else if (new1 === old) {
+ errors.push('Your new password must be different from your old password');
+ }
+ else if (new1.length < [% constants.USER_PASSWORD_MIN_LENGTH FILTER none %]) {
+ errors.push('Your password must be at least [% constants.USER_PASSWORD_MIN_LENGTH FILTER none %] long');
+ }
+ else {
+ var complexity_fn;
+ [% SWITCH Param('password_complexity') %]
+ [% CASE 'no_constraints' %]
+ complexity_fn = function() {};
+ [% CASE 'mixed_letters' %]
+ complexity_fn = function(pass, errors) {
+ if (
+ pass.search(/[a-z]/) == -1 ||
+ pass.search(/[A-Z]/) == -1
+ ) {
+ errors.push('New password is not complex enough');
+ }
+ };
+ [% CASE 'letters_numbers' %]
+ complexity_fn = function(pass, errors) {
+ if (
+ pass.search(/[a-z]/) == -1 ||
+ pass.search(/[A-Z]/) == -1 ||
+ pass.search(/[0-9]/) == -1
+ ) {
+ errors.push('New password is not complex enough');
+ }
+ };
+ [% CASE 'letters_numbers_specialchars' %]
+ complexity_fn = function(pass, errors) {
+ if (
+ pass.search(/[a-z]/) == -1 ||
+ pass.search(/[A-Z]/) == -1 ||
+ pass.search(/[0-9]/) == -1 ||
+ pass.search(/\W/) == -1
+ ) {
+ errors.push('New password is not complex enough');
+ }
+ };
+ [% END %]
+ complexity_fn(new1, errors);
+ }
+
+ $('#submit').attr('disabled', errors.length > 0);
+ if ((old !== '' || new1 !== '' || new2 !== '') && errors.length) {
+ $('#errors').html('<ul><li>' + errors.join('</li><li>') + '</li></ul>');
+ }
+ else {
+ $('#errors').html('');
+ }
+ })
+ .keyup();
+
+ $('#forgot_password')
+ .click(function(event) {
+ event.preventDefault();
+ $('#forgot-form').submit();
+ });
+});
+
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Password change required"
+ style = inline_style
+ javascript = inline_js
+%]
+
+<h1>Password Reset</h1>
+
+<p>
+ [% user.password_change_reason || "You are required to update your password." FILTER html %]
+</p>
+
+<form method="POST" action="reset_password.cgi">
+<input type="hidden" name="token" value="[% token FILTER html %]">
+<input type="hidden" name="do_save" value="1">
+
+<div id="password-reset">
+ <div class="field-hr">&nbsp;</div>
+ <div class="field-row">
+ <div class="field-name">Email</div>
+ <div class="field-value">
+ [% user.login FILTER html %]
+ </div>
+ </div>
+ <div class="field-row">
+ <div class="field-name">Current Password</div>
+ <div class="field-value">
+ <input type="password" name="old_password" id="old_password" size="30">
+ </div>
+ </div>
+ <div class="field-hr">&nbsp;</div>
+ <div id="errors"></div>
+ <div class="field-row">
+ <div class="field-name">New Password</div>
+ <div class="field-value">
+ <input type="password" name="new_password1" id="new_password1" size="30">
+ </div>
+ </div>
+ <div class="field-row">
+ <div class="field-name">New Password</div>
+ <div class="field-value">
+ <input type="password" name="new_password2" id="new_password2" size="30">
+ (again)
+ </div>
+ </div>
+ <div class="field-hr">&nbsp;</div>
+ <div class="field-row">
+ <div class="field-value">
+ <input type="submit" id="submit" value="Update Password">
+ <a id="forgot_password" href="#">Forgot Password</a>
+ </div>
+ </div>
+</div>
+
+</form>
+
+<p id="complexity_rules">
+ Your password must be a minimum of [% constants.USER_PASSWORD_MIN_LENGTH FILTER none %] characters long
+ [% SWITCH Param('password_complexity') %]
+ [% CASE 'mixed_letters' %]
+ and must contain at least one UPPER and one lowercase letter
+ [% CASE 'letters_numbers' %]
+ and must contain at least one UPPER and one lowercase letter and a number
+ [% CASE 'letters_numbers_specialchars' %]
+ and must contain at least one letter, a number and a special character
+ [% END ~%].
+</p>
+
+<form action="token.cgi" method="post" id="forgot-form">
+ <input type="hidden" name="loginname" value="[% user.login FILTER html %]">
+ <input type="hidden" name="a" value="reqpw">
+ <input type="hidden" name="token" value="[% issue_hash_token(['reqpw']) FILTER html %]">
+</form>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/template/en/default/admin/users/edit.html.tmpl b/template/en/default/admin/users/edit.html.tmpl
index a5ab5cf03..fbf283574 100644
--- a/template/en/default/admin/users/edit.html.tmpl
+++ b/template/en/default/admin/users/edit.html.tmpl
@@ -38,6 +38,18 @@ $(function() {
}
})
.keyup();
+
+ $('#password_change_required')
+ .change(function() {
+ $('#password').prop('disabled', $(this).is(':checked'));
+ if ($(this).is(':checked')) {
+ $('#password_change_reason_container').show();
+ }
+ else {
+ $('#password_change_reason_container').hide();
+ }
+ })
+ .change();
});
[% END %]
diff --git a/template/en/default/admin/users/userdata.html.tmpl b/template/en/default/admin/users/userdata.html.tmpl
index 63f69cfe9..ebe7451e4 100644
--- a/template/en/default/admin/users/userdata.html.tmpl
+++ b/template/en/default/admin/users/userdata.html.tmpl
@@ -64,24 +64,37 @@
</td>
</tr>
-[%# XXX This condition (can_change_password) will cause a problem
- # if we ever have a login system that can create accounts through
- # createaccount.cgi but can't change passwords.
- #%]
-
[% IF editusers %]
- [% IF user.authorizer.can_change_password %]
<tr>
- <th><label for="password">Password:</label></th>
+ <th>
+ <label for="password">
+ [% IF editform %]
+ [% otheruser.cryptpassword == '*' ? "Set" : "Update" =%]
+ [% END %]
+ Password:
+ </label>
+ </th>
<td>
- <input type="password" size="16" name="password" id="password"
- value="" autocomplete="off">
- [% IF editform %]<br>
- (Enter new password to change.)
+ <input type="password" size="16" name="password" id="password" value="" autocomplete="off">
+ [%# if a user's cryptpassword is '*' it means they use an auth provider
+ # such as github, or you can't log in with that account. in either case
+ # forcing a password reset isn't valid %]
+ [% IF otheruser.cryptpassword != '*' && editform %]
+ <br>
+ <input type="checkbox" name="password_change_required" id="password_change_required" maxlength="64"
+ [% " checked" IF otheruser.password_change_required %]>
+ <label for="password_change_required">User must change their password immediately</label>
+ <div id="password_change_reason_container">
+ Password change reason (will be displayed to the user):<br>
+ <input type="text" size="64"
+ name="password_change_reason" id="password_change_reason"
+ value="[% otheruser.password_change_reason || "You are required to change your password." FILTER html %]"
+ >
+ </div>
[% END %]
</td>
</tr>
- [% END %]
+
<tr>
<th><label for="disable_mail">[% terms.Bug %]mail Disabled:</label></th>
<td>
diff --git a/template/en/default/global/messages.html.tmpl b/template/en/default/global/messages.html.tmpl
index 0f408842f..4cefe2a3f 100644
--- a/template/en/default/global/messages.html.tmpl
+++ b/template/en/default/global/messages.html.tmpl
@@ -70,6 +70,10 @@
[% ELSE %]
[% terms.Bug %]mail has been enabled.
[% END %]
+ [% ELSIF field == 'password_change_required' %]
+ The user [% otheruser.password_change_required ? "must" : "no longer needs to" %] update their password.
+ [% ELSIF field == 'password_change_reason' %]
+ The password change reason has been modified.
[% END %]
</li>
[% END %]
diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl
index 814a02c13..98076ce1c 100644
--- a/template/en/default/global/user-error.html.tmpl
+++ b/template/en/default/global/user-error.html.tmpl
@@ -1352,6 +1352,10 @@
[% title = "New Password Missing" %]
You must enter a new password.
+ [% ELSIF error == "new_password_same" %]
+ [% title = "Password Unchanged" %]
+ Your new password cannot be the same as your old password.
+
[% ELSIF error == "no_axes_defined" %]
[% title = "No Axes Defined" %]
[% docslinks = {'reporting.html' => 'Reporting'} %]