Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set password manually when creating new user #1017

Merged
merged 10 commits into from Jul 20, 2019
38 changes: 38 additions & 0 deletions app/sprinkles/admin/assets/userfrosting/js/widgets/users.js
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
Expand Up @@ -70,3 +70,32 @@ group_id:
label: "&GROUP"
domain: server
message: VALIDATE.INTEGER
value:
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
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['value'])) {
lcharette marked this conversation as resolved.
Show resolved Hide resolved
// 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['value']);
}

// 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
@@ -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="fa fa-key"></i></span>
<input type="password" class="form-control" name="value" 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="fa 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
@@ -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
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
57 changes: 1 addition & 56 deletions app/sprinkles/admin/templates/modals/user-set-password.html.twig
Expand Up @@ -3,60 +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="fa 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="fa 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 %}