Skip to content

Commit ccf048e

Browse files
authored
Merge pull request #1017 from amosfolz/user-set-password
Set password manually when creating new user
2 parents 827ab6b + 657aa0e commit ccf048e

7 files changed

Lines changed: 143 additions & 64 deletions

File tree

app/sprinkles/admin/assets/userfrosting/js/widgets/users.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,49 @@ function attachUserForm() {
2424
// Reload page on success
2525
window.location.reload();
2626
});
27+
28+
toggleSetPasswordMode(modal, 'link');
29+
30+
// On submission, submit either the PUT request, or POST for a password reset, depending on the toggle state
31+
modal.find("input[name='change_password_mode']").click(function() {
32+
var changePasswordMode = $(this).val();
33+
toggleSetPasswordMode(modal, changePasswordMode);
34+
});
2735
});
2836
}
2937

3038
/**
3139
* Enable/disable password fields when switch is toggled
40+
* Applies to 'creating' a user
41+
*/
42+
function toggleSetPasswordMode(el, changePasswordMode) {
43+
var form = el.find("form");
44+
if (changePasswordMode == 'link') {
45+
$(".controls-password").find("input[type='password']").prop('disabled', true);
46+
// Form submits password reset request
47+
48+
var validator = form.validate();
49+
if (validator) {
50+
//Iterate through named elements inside of the form, and mark them as error free
51+
el.find("input[type='password']").each(function() {
52+
validator.successList.push(this); //mark as error free
53+
});
54+
validator.resetForm(); //remove error class on name elements and clear history
55+
validator.reset(); //remove all error and success data
56+
}
57+
el.find("input[type='password']").closest('.form-group')
58+
.removeClass('has-error has-success');
59+
el.find('.form-control-feedback').each(function() {
60+
$(this).remove();
61+
});
62+
} else {
63+
$(".controls-password").find("input[type='password']").prop('disabled', false);
64+
}
65+
}
66+
67+
/**
68+
* Enable/disable password fields when switch is toggled
69+
* Applies to 'reseting' a users password
3270
*/
3371
function toggleChangePasswordMode(el, userName, changePasswordMode) {
3472
var form = el.find("form");

app/sprinkles/admin/schema/requests/user/create.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,32 @@ group_id:
7070
label: "&GROUP"
7171
domain: server
7272
message: VALIDATE.INTEGER
73+
password:
74+
validators:
75+
required:
76+
domain: client
77+
label: "&PASSWORD"
78+
message: VALIDATE.REQUIRED
79+
length:
80+
domain: client
81+
label: "&PASSWORD"
82+
min: 12
83+
max: 100
84+
message: VALIDATE.LENGTH_RANGE
85+
passwordc:
86+
validators:
87+
required:
88+
domain: client
89+
label: "&PASSWORD.CONFIRM"
90+
message: VALIDATE.REQUIRED
91+
matches:
92+
domain: client
93+
field: value
94+
label: "&PASSWORD.CONFIRM"
95+
message: VALIDATE.PASSWORD_MISMATCH
96+
length:
97+
domain: client
98+
label: "&PASSWORD.CONFIRM"
99+
min: 12
100+
max: 100
101+
message: VALIDATE.LENGTH_RANGE

app/sprinkles/admin/src/Controller/UserController.php

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,12 @@ public function create(Request $request, Response $response, $args)
133133
}
134134

135135
$data['flag_verified'] = 1;
136-
// Set password as empty on initial creation. We will then send email so new user can set it themselves via a verification token
137-
$data['password'] = '';
136+
if (!isset($data['password'])) {
137+
// Set password as empty on initial creation. We will then send email so new user can set it themselves via a verification token
138+
$data['password'] = '';
139+
} else {
140+
$data['password'] = Password::hash($data['password']);
141+
}
138142

139143
// All checks passed! log events/activities, create user, and send verification email (if required)
140144
// Begin transaction - DB will be rolled back if an exception occurs
@@ -162,18 +166,21 @@ public function create(Request $request, Response $response, $args)
162166
// Try to generate a new password request
163167
$passwordRequest = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.create']);
164168

165-
// Create and send welcome email with password set link
166-
$message = new TwigMailMessage($this->ci->view, 'mail/password-create.html.twig');
169+
// If the password_mode is manual, do not send an email to set it. Else, send the email.
170+
if (!isset($data['value'])) {
171+
// Create and send welcome email with password set link
172+
$message = new TwigMailMessage($this->ci->view, 'mail/password-create.html.twig');
167173

168-
$message->from($config['address_book.admin'])
174+
$message->from($config['address_book.admin'])
169175
->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
170176
->addParams([
171177
'user' => $user,
172178
'create_password_expiration' => $config['password_reset.timeouts.create'] / 3600 . ' hours',
173179
'token' => $passwordRequest->getToken(),
174180
]);
175181

176-
$this->ci->mailer->send($message);
182+
$this->ci->mailer->send($message);
183+
}
177184

178185
$ms->addMessageTranslated('success', 'USER.CREATED', $data);
179186
});
@@ -694,7 +701,7 @@ public function getModalEdit(Request $request, Response $response, $args)
694701

695702
// Generate form
696703
$fields = [
697-
'hidden' => ['theme'],
704+
'hidden' => ['theme', 'password'],
698705
'disabled' => ['user_name'],
699706
];
700707

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!-- Prevent browsers from trying to autofill the password field. See http://stackoverflow.com/a/23234498/2970321 -->
2+
<input type="text" style="display:none">
3+
<input type="password" style="display:none">
4+
<div class="col-sm-12">
5+
<div class="radio">
6+
<label for="change_password_mode_link">
7+
<input type="radio" name="change_password_mode" id="change_password_mode_link" value="link" checked>
8+
{{translate("USER.ADMIN.SEND_PASSWORD_LINK")}}
9+
</label>
10+
</div>
11+
</div>
12+
<div class="col-sm-12">
13+
<div class="radio">
14+
<label for="change_password_mode_manual">
15+
<input type="radio" name="change_password_mode" id="change_password_mode_manual" value="manual">
16+
{{translate("USER.ADMIN.SET_PASSWORD")}}:
17+
</label>
18+
</div>
19+
<div class="row controls-password">
20+
<div class="col-sm-11 col-sm-offset-1">
21+
<div class="form-group">
22+
<label>{{translate('PASSWORD')}}</label>
23+
<div class="input-group">
24+
<span class="input-group-addon"><i class="fas fa-key"></i></span>
25+
<input type="password" class="form-control" name="password" autocomplete="off" value="" placeholder="{{translate('PASSWORD.BETWEEN', {min: 12, max: 50})}}">
26+
</div>
27+
</div>
28+
<div class="form-group">
29+
<label>{{translate('PASSWORD.CONFIRM')}}</label>
30+
<div class="input-group">
31+
<span class="input-group-addon"><i class="fas fa-key"></i></span>
32+
<input type="password" class="form-control" name="passwordc" autocomplete="off" value="" placeholder="{{translate('PASSWORD.CONFIRM')}}">
33+
</div>
34+
</div>
35+
</div>
36+
</div>
37+
</div>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<form class="js-form" method="PUT" action="{{site.uri.public}}/api/users/u/{{user.user_name}}">
2+
{% include "forms/csrf.html.twig" %}
3+
<div class="js-form-alerts">
4+
</div>
5+
<div class="row">
6+
{% include "forms/partials/user-set-password.html.twig" %}
7+
</div>
8+
<br>
9+
<div class="row">
10+
<div class="col-xs-8 col-sm-4">
11+
<button type="submit" class="btn btn-block btn-lg btn-success">{{translate('SUBMIT')}}</button>
12+
</div>
13+
<div class="col-xs-4 col-sm-3 pull-right">
14+
<button type="button" class="btn btn-block btn-lg btn-link" data-dismiss="modal">{{translate('CANCEL')}}</button>
15+
</div>
16+
</div>
17+
</form>
18+
<!-- Include validation rules -->
19+
<script>
20+
{% include "pages/partials/page.js.twig" %}
21+
</script>

app/sprinkles/admin/templates/forms/user.html.twig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@
110110
</div>
111111
</div>
112112
{% endif %}
113+
{% if 'password' not in form.fields.hidden %}
114+
{% include "forms/partials/user-set-password.html.twig" %}
115+
{% endif %}
113116
{% endblock %}
114117
</div><br>
115118
<div class="row">

app/sprinkles/admin/templates/modals/user-set-password.html.twig

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,61 +3,5 @@
33
{% block modal_title %}{{translate("USER.ADMIN.CHANGE_PASSWORD")}}{% endblock %}
44

55
{% block modal_body %}
6-
<form class="js-form" method="PUT" action="{{site.uri.public}}/api/users/u/{{user.user_name}}">
7-
{% include "forms/csrf.html.twig" %}
8-
<!-- Prevent browsers from trying to autofill the password field. See http://stackoverflow.com/a/23234498/2970321 -->
9-
<input type="text" style="display:none">
10-
<input type="password" style="display:none">
11-
<div class="js-form-alerts">
12-
</div>
13-
<div class="row">
14-
<div class="col-sm-12">
15-
<div class="radio">
16-
<label for="change_password_mode_link">
17-
<input type="radio" name="change_password_mode" id="change_password_mode_link" value="link" checked>
18-
{{translate("USER.ADMIN.SEND_PASSWORD_LINK")}}
19-
</label>
20-
</div>
21-
</div>
22-
<div class="col-sm-12">
23-
<div class="radio">
24-
<label for="change_password_mode_manual">
25-
<input type="radio" name="change_password_mode" id="change_password_mode_manual" value="manual">
26-
{{translate("USER.ADMIN.SET_PASSWORD")}}:
27-
</label>
28-
</div>
29-
<div class="row controls-password">
30-
<div class="col-sm-11 col-sm-offset-1">
31-
<div class="form-group">
32-
<label>{{translate('PASSWORD')}}</label>
33-
<div class="input-group">
34-
35-
<span class="input-group-addon"><i class="fas fa-key"></i></span>
36-
<input type="password" class="form-control" name="value" autocomplete="off" value="" placeholder="{{translate("PASSWORD.BETWEEN", {min: site.password.length.min, max: site.password.length.max})}}">
37-
</div>
38-
</div>
39-
<div class="form-group">
40-
<label>{{translate('PASSWORD.CONFIRM')}}</label>
41-
<div class="input-group">
42-
<span class="input-group-addon"><i class="fas fa-key"></i></span>
43-
<input type="password" class="form-control" name="passwordc" autocomplete="off" value="" placeholder="{{translate('PASSWORD.CONFIRM')}}">
44-
</div>
45-
</div>
46-
</div>
47-
</div>
48-
</div>
49-
</div><br>
50-
<div class="row">
51-
<div class="col-xs-8 col-sm-4">
52-
<button type="submit" class="btn btn-block btn-lg btn-success">{{translate('SUBMIT')}}</button>
53-
</div>
54-
<div class="col-xs-4 col-sm-3 pull-right">
55-
<button type="button" class="btn btn-block btn-lg btn-link" data-dismiss="modal">{{translate('CANCEL')}}</button>
56-
</div>
57-
</div>
58-
</form>
59-
<!-- Include validation rules -->
60-
<script>
61-
{% include "pages/partials/page.js.twig" %}
62-
</script>
6+
{% include "forms/user-set-password.html.twig" %}
637
{% endblock %}

0 commit comments

Comments
 (0)