Skip to content

Commit

Permalink
Merge pull request #1017 from amosfolz/user-set-password
Browse files Browse the repository at this point in the history
Set password manually when creating new user
  • Loading branch information
lcharette committed Jul 20, 2019
2 parents 827ab6b + 657aa0e commit ccf048e
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 64 deletions.
38 changes: 38 additions & 0 deletions app/sprinkles/admin/assets/userfrosting/js/widgets/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,49 @@ function attachUserForm() {
// Reload page on success
window.location.reload();
});

toggleSetPasswordMode(modal, 'link');

// On submission, submit either the PUT request, or POST for a password reset, depending on the toggle state
modal.find("input[name='change_password_mode']").click(function() {
var changePasswordMode = $(this).val();
toggleSetPasswordMode(modal, changePasswordMode);
});
});
}

/**
* Enable/disable password fields when switch is toggled
* Applies to 'creating' a user
*/
function toggleSetPasswordMode(el, changePasswordMode) {
var form = el.find("form");
if (changePasswordMode == 'link') {
$(".controls-password").find("input[type='password']").prop('disabled', true);
// Form submits password reset request

var validator = form.validate();
if (validator) {
//Iterate through named elements inside of the form, and mark them as error free
el.find("input[type='password']").each(function() {
validator.successList.push(this); //mark as error free
});
validator.resetForm(); //remove error class on name elements and clear history
validator.reset(); //remove all error and success data
}
el.find("input[type='password']").closest('.form-group')
.removeClass('has-error has-success');
el.find('.form-control-feedback').each(function() {
$(this).remove();
});
} else {
$(".controls-password").find("input[type='password']").prop('disabled', false);
}
}

/**
* Enable/disable password fields when switch is toggled
* Applies to 'reseting' a users password
*/
function toggleChangePasswordMode(el, userName, changePasswordMode) {
var form = el.find("form");
Expand Down
29 changes: 29 additions & 0 deletions app/sprinkles/admin/schema/requests/user/create.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,32 @@ group_id:
label: "&GROUP"
domain: server
message: VALIDATE.INTEGER
password:
validators:
required:
domain: client
label: "&PASSWORD"
message: VALIDATE.REQUIRED
length:
domain: client
label: "&PASSWORD"
min: 12
max: 100
message: VALIDATE.LENGTH_RANGE
passwordc:
validators:
required:
domain: client
label: "&PASSWORD.CONFIRM"
message: VALIDATE.REQUIRED
matches:
domain: client
field: value
label: "&PASSWORD.CONFIRM"
message: VALIDATE.PASSWORD_MISMATCH
length:
domain: client
label: "&PASSWORD.CONFIRM"
min: 12
max: 100
message: VALIDATE.LENGTH_RANGE
21 changes: 14 additions & 7 deletions app/sprinkles/admin/src/Controller/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,12 @@ public function create(Request $request, Response $response, $args)
}

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

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

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

$message->from($config['address_book.admin'])
$message->from($config['address_book.admin'])
->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
->addParams([
'user' => $user,
'create_password_expiration' => $config['password_reset.timeouts.create'] / 3600 . ' hours',
'token' => $passwordRequest->getToken(),
]);

$this->ci->mailer->send($message);
$this->ci->mailer->send($message);
}

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

// Generate form
$fields = [
'hidden' => ['theme'],
'hidden' => ['theme', 'password'],
'disabled' => ['user_name'],
];

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!-- Prevent browsers from trying to autofill the password field. See http://stackoverflow.com/a/23234498/2970321 -->
<input type="text" style="display:none">
<input type="password" style="display:none">
<div class="col-sm-12">
<div class="radio">
<label for="change_password_mode_link">
<input type="radio" name="change_password_mode" id="change_password_mode_link" value="link" checked>
{{translate("USER.ADMIN.SEND_PASSWORD_LINK")}}
</label>
</div>
</div>
<div class="col-sm-12">
<div class="radio">
<label for="change_password_mode_manual">
<input type="radio" name="change_password_mode" id="change_password_mode_manual" value="manual">
{{translate("USER.ADMIN.SET_PASSWORD")}}:
</label>
</div>
<div class="row controls-password">
<div class="col-sm-11 col-sm-offset-1">
<div class="form-group">
<label>{{translate('PASSWORD')}}</label>
<div class="input-group">
<span class="input-group-addon"><i class="fas fa-key"></i></span>
<input type="password" class="form-control" name="password" autocomplete="off" value="" placeholder="{{translate('PASSWORD.BETWEEN', {min: 12, max: 50})}}">
</div>
</div>
<div class="form-group">
<label>{{translate('PASSWORD.CONFIRM')}}</label>
<div class="input-group">
<span class="input-group-addon"><i class="fas fa-key"></i></span>
<input type="password" class="form-control" name="passwordc" autocomplete="off" value="" placeholder="{{translate('PASSWORD.CONFIRM')}}">
</div>
</div>
</div>
</div>
</div>
21 changes: 21 additions & 0 deletions app/sprinkles/admin/templates/forms/user-set-password.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<form class="js-form" method="PUT" action="{{site.uri.public}}/api/users/u/{{user.user_name}}">
{% include "forms/csrf.html.twig" %}
<div class="js-form-alerts">
</div>
<div class="row">
{% include "forms/partials/user-set-password.html.twig" %}
</div>
<br>
<div class="row">
<div class="col-xs-8 col-sm-4">
<button type="submit" class="btn btn-block btn-lg btn-success">{{translate('SUBMIT')}}</button>
</div>
<div class="col-xs-4 col-sm-3 pull-right">
<button type="button" class="btn btn-block btn-lg btn-link" data-dismiss="modal">{{translate('CANCEL')}}</button>
</div>
</div>
</form>
<!-- Include validation rules -->
<script>
{% include "pages/partials/page.js.twig" %}
</script>
3 changes: 3 additions & 0 deletions app/sprinkles/admin/templates/forms/user.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
</div>
</div>
{% endif %}
{% if 'password' not in form.fields.hidden %}
{% include "forms/partials/user-set-password.html.twig" %}
{% endif %}
{% endblock %}
</div><br>
<div class="row">
Expand Down
58 changes: 1 addition & 57 deletions app/sprinkles/admin/templates/modals/user-set-password.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,5 @@
{% block modal_title %}{{translate("USER.ADMIN.CHANGE_PASSWORD")}}{% endblock %}

{% block modal_body %}
<form class="js-form" method="PUT" action="{{site.uri.public}}/api/users/u/{{user.user_name}}">
{% include "forms/csrf.html.twig" %}
<!-- Prevent browsers from trying to autofill the password field. See http://stackoverflow.com/a/23234498/2970321 -->
<input type="text" style="display:none">
<input type="password" style="display:none">
<div class="js-form-alerts">
</div>
<div class="row">
<div class="col-sm-12">
<div class="radio">
<label for="change_password_mode_link">
<input type="radio" name="change_password_mode" id="change_password_mode_link" value="link" checked>
{{translate("USER.ADMIN.SEND_PASSWORD_LINK")}}
</label>
</div>
</div>
<div class="col-sm-12">
<div class="radio">
<label for="change_password_mode_manual">
<input type="radio" name="change_password_mode" id="change_password_mode_manual" value="manual">
{{translate("USER.ADMIN.SET_PASSWORD")}}:
</label>
</div>
<div class="row controls-password">
<div class="col-sm-11 col-sm-offset-1">
<div class="form-group">
<label>{{translate('PASSWORD')}}</label>
<div class="input-group">

<span class="input-group-addon"><i class="fas fa-key"></i></span>
<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})}}">
</div>
</div>
<div class="form-group">
<label>{{translate('PASSWORD.CONFIRM')}}</label>
<div class="input-group">
<span class="input-group-addon"><i class="fas fa-key"></i></span>
<input type="password" class="form-control" name="passwordc" autocomplete="off" value="" placeholder="{{translate('PASSWORD.CONFIRM')}}">
</div>
</div>
</div>
</div>
</div>
</div><br>
<div class="row">
<div class="col-xs-8 col-sm-4">
<button type="submit" class="btn btn-block btn-lg btn-success">{{translate('SUBMIT')}}</button>
</div>
<div class="col-xs-4 col-sm-3 pull-right">
<button type="button" class="btn btn-block btn-lg btn-link" data-dismiss="modal">{{translate('CANCEL')}}</button>
</div>
</div>
</form>
<!-- Include validation rules -->
<script>
{% include "pages/partials/page.js.twig" %}
</script>
{% include "forms/user-set-password.html.twig" %}
{% endblock %}

0 comments on commit ccf048e

Please sign in to comment.