I have my UsersController with my edit.ctp view. When I browse /users/edit/1, I see password field filled with ***** (filled with hash in entity User.php, using DefaultPasswordHasher). My UsersTable.php has password has required.
So, I can try:
unset($user->password); // in edit() from UsersController.php
and setting [require => false] in edit.ctp
When I save, I get
The user could not be saved. Please, try again.
Because in my UsersTable.php I have:
$validator
->requirePresence('password', 'create')
->notEmpty('password');
If I try to leave blank from controller I get error, if I try to fill with actual password, it hashes again.
How could I edit any user without change his password? Can I set this from model or I need to make password as not required?
I don't need show the real password to admins
I validate from controller for password_confirm (already works)
In add.ctp there is no problem because default value is always blank
I want to change password only if password field is filled
I suppose password needs to be required in Model because all users need their passwords, that's why I'm trying to keep it far from validation in controller
Validation says "on create" but even in update is needed, bug possible?
My cake version is 3.4.4
Thanks in advance
Couple of things:
Firstly, if you haven't already, you may want to mark the password field as hidden to prevent it from exposing the hash in toArray calls or JSON views.
Secondly, any data field provided to patchEntity will be validated and saved (as you've discovered), even if the value for the field is blank.
If you look at the entity with debug($user) you'll notice it tracks which fields are "dirty", and since patchEntity saw you submitted a password field (even if it was blank), it set the User entity's password to blank and marked it as "dirty". Even if you later call unset($user->password) it's still got a record of it being dirty, and so it'll attempt to validate a value for it.
You could potentially mark the field clean with $export->setDirty('password', false); but then when a new password was submitted in the form it wouldn't be saved.
A better option would be to check if the password field was blank before calling patchEntity, and unset it then:
if ($this->request->is(['patch', 'post', 'put'])) {
$data = $this->request->getData();
if(empty($data['password'])){
unset($data['password']);
}
$user = $this->Users->patchEntity($user, $data);
Related
I have a user model(sequelize for Postgres) have below comparePassword function:
In login controller, I am checking password to let user login as below:
But any user fail to login because of comparePassword always return "false". I created several new users successfully and then when try to login, it gave the same "false" compare results.
I had tried the two module (bcrypt and bcryptjs), while same results.
Checked the stackoverflow, and found similar issue by post title, while not the same.
I tried the compareSync, it also gave false compare result.
My question: The hash calculation should be the same when creating the password hash to store in the database and the later comparing Password. where is the pit? what's the mistakes in my User model?
Thanks in advance.
In similar situation I had placed the lowercase validation on password in the User Model. That was giving me always bcrypt compare false. When removing it everything ran as usual.
Excuse me if the answer is obvious but whilst I know Java I am very new to Scala, the Play framework and general web app development.
I have taken on a project that has a view where you can set up some database connection details that includes fields such as database name, username, password etc. At present the code uses the Play input helper 'inputText' and so the password field shows the password in plain text. I need to fix this and so have changed it to use the 'inputPassword' helper however whenever I visit this page in my app to edit one of the other fields the password field has not been populated with the password so the user needs to re-enter it in order to save, I do not want to have to do this.
The password populated when it was an inputText helper so I can only assume that there's something in the inputPassword helper that stops the value from populating in the form, maybe it expects the password field to only be used when inputting a new one? Is there a way to override this and have it fill in the on screen form with the password so the user does not have to re-enter in order to change another field on the page?
This is the old version in my view
#inputField(form("password"), '_label -> "Password", '_labelwidth -> "2", 'class -> "form-control", '_type -> "password", '_single -> false)</code>
This is the new version
#inputPassword(form("password"), '_label -> "Password", '_labelwidth -> "2", 'class -> "form-control", '_single -> false, '_type -> "password")
I then have an the templates inputField.scala.html which contains #helper.inputText(field, args:_*) and the inputPassword.scala.html which contains #helper.inputPassword(field, args:_*)
I tried adding 'value -> form("password").value to the parameters in the inputPassword version and whilst this displayed something in stars in the password field the credentials were incorrect so it cannot have been the correct information.
Any help or suggestions are appreciated, even if it is to just understand why inputText populates the field whereas inputPassword does not. The only other way I can think of to do this is possibly to have the password as a separate form on the same page and make it so the password entry is only mandatory when using the page for the initial set up of the database credentials and optional on the edit page.
I don't think it's really necessary to send password values back and forth for security reasons. As an internet user I've never seen form with filled password.
Regarding your case I see two options:
Either separate password change into another form (but this is usually an option if you have more sophisticated password reset process, like two-step verification)
Or apply the following password validation logic on the server: leave the password unchanged if it is empty
I am working on a website, which already has a working registration form, using the ZfcUser module.
However,
I need to also be able to create a user via the admin page i've created.
Step by step it goes something like this:
Admin adds user by filling in first name, last name and email.
email gets sent to user.
user clicks validation link and gets redirected to website.
now the user only has to enter his desired password and he is done.
How would i be able to do this, if at all possible?
first of all, im not sure what would be the best aproach, but a few come to my mind.
I think the easier would be to load the register form in your admin, remember you can load it from any controller with the service manager, something like
$form = $sm->get('zfcuser_register_form');
and then you can work with it as you would do with any form, sending it to the view, and so.
You would have the full register form, with all the fields you have set as required in your zfcuser.global.php, including the password. I think it is good to set a temp password, and have the user change it later. also you could have its status as unconfirmed until the first password change.
If you dont want an specific field, you can take it out as you would with any form, by means of
$form->remove('element_name');
You would want to check the element names at ZfcUser\Form\Register
Also, remember that if you remove any field, you would have to modify the input filter, otherwise the validation will fail. For this, in your module's bootstrap, you should attach an event listener, something like this:
$em = $e->getApplication ()->getEventManager ();
$em->attach ( 'ZfcUser\Form\RegisterFilter', 'init', function ($e) {
$filter = $e->getTarget ();
//now modify the inputfilter as you need
});
Then, you will have to send the mail to the user. For that i will also use the event manager, at your bootstrap you register a listener for when the user is created, this is by means of
$sm = $e->getApplication ()->getServiceManager ();
$zfcServiceEvents = $sm->get ( 'zfcuser_user_service' )->getEventManager ();
$zfcServiceEvents->attach ( 'register.post', function ($e) {
$form = $e->getParam ( 'form' );
$user = $e->getParam ( 'user' );
//now you have all the info from the form and the already created user, so you can send the mail and whatever you need.
The last step, is to let the user change his password. To do this, i will send him to a module where you show the change password form, that you can retrieve with:
$sm->get('zfcuser_change_password_form');
or directly, sending him to the /user/change-password url that is one of the predefined with zfc-user.
I think this will be the cleanest way.
Another approach
If you dont like it that way, you can use another approach where you create your own form, fill it, save the data to a temp table, send the mail and then...when the user comes to set his password, you build a register form, with the fields pre-filled (and hidden, changing the input type to hidden, or by css) and let him send the form, so while he thinks he is sending just the password, actually he is sending all the registration form, and from here everything is like in normal registration.
For this solution you will also have to use the events, but probably you'd have to take a look at the register event,that is triggered when the form is sent, before the user is saved in the database, so you can modify any data you could need.
$zfcServiceEvents->attach ( 'register', function ($e) {
$form = $e->getParam ( 'form' );
And also you should take a look to the already mentioned init event, where you can retrieve the form before you show it to the user, and prefill any data from the temp table.
$events->attach ( 'ZfcUser\Form\Register', 'init', function ($e) {
$form = $e->getTarget ();
//now you set form element values from the temp table
Probably this is so confusing, but i hope you at least get a clue of where start from!
I'm using same form to new client and edit client in Code Igniter. Sometimes I'll include new client so the field must be empty. However, sometimes I'll edit a client and I must put respect value to a field.
For example:
echo form_input('client_name', $client_to_edit['client_name']);
How can I use "set_values()" and $client_to_edit['client_name'] to pass data to the field?
set_value() is really only needed for form_validation and in this case you'll probably need that too. Basically you need to determine if the form is editing or for a new client, if editing it needs to run a query on the database to return that users data and pass it to a variable.
echo form_input('client_name',set_value
('client_name',($user['client_name'] ? $user['client_name']:'')));
Basically what's happening is if the form is editing you're populating the $user variable in the controller with that users data. The set value statement has 3 options. First if the form is returning from form_validation it sets it to whatever was entered when the form was posted, if there is no post data it then looks to see if $user['client_name'] exists, if it does it uses that, if it doesn't it just returns blank.
Not sure if this is a security feature, an oversight, or me missing the ocean for the waves, but wondering why there is no value attribute for the password field constructor
This is not an issue for user signup and other form creation events, but becomes a headache when, for example, a user renewal form does not have the password field filled in (and thus fails validation, which is ironic given that they just logged in in order to be able to renew in the first place ;-))
My workaround has been to set the value attrib manually by supplying it as an extra argument:
#inputPassword(
_form("password"), '_label-> "Password*", 'class-> "required",
'value-> _form("password").value map{Some(_)} getOrElse Some("")
)
would prefer the value attribute included by default, however, as with other input elements. Yes, I can override it, but wondering what the dealy-O is regardless
To me, you shouldn't be able to retrieve the user password in any way, since the password should be encrypted before storing it somewhere.