How do I prevent password field from changing every time a row is edited?
How do I prevent password field from changing every time a row is edited?
I've followed the instructions as per here: https://www.datatables.net/blog/2015-10-02#Password-fields
And I've reread this thread many times over: https://www.datatables.net/forums/discussion/27868/why-is-password-field-updated-when-updating-other-fields
However, I just can't get it working. When this line of code is added:
->on( 'preEdit', function ( $e, $id, $values ) {
if ( $values['Password'] === '' ) {
$e->field( 'Password' )->set( false );
}
} )
I'm getting this error in the PHP: <b>Notice</b>: Undefined index: Password in line...
Ideally, the password data (which is hashed) wouldn't be pulled into the field at all, when read by the standard edit window.
Strangely this seems to work fine with inline editing, but not when using the standard edit.
If I don't attempt the above code, the password updates each time (giving a false result, as it's rehashing the already hashed password).
Additionally, the field can't be empty, as I have client side validation preventing this from happening (so that I can enforce a password policy). But even when the validation is removed, the error still occurs.
For the record, the field (and DB field) is called Password !
In the blog post, it says this:
"but this is not the case with passwords, where you don't want to (and shouldn't be able to) read the actual values (they should after all be hashed"
But how to not pull in this information?!
Finally I have a test site set up, so you can easily reproduce the error if required (edit a row, then try and make a change):
http://benshaw.org.uk/misc/editortest/users.html
PHP:
Editor::inst( $db, 'LAF' )
->fields(
Field::inst( 'UserName' )->validator( 'Validate::notEmpty' )
->validator( 'Validate::unique', array(
"message" => "This User Name is already in use"
) ),
Field::inst( 'FullName' )->validator( 'Validate::notEmpty' ),
Field::inst( 'UserEmail' )->validator( 'Validate::notEmpty' )
->validator( 'Validate::email' )
->validator( 'Validate::unique', array(
"message" => "This Email address is already in use"
) ),
Field::inst( 'Password' )
->validator( function ( $val, $data, $opts ) {
return strlen( $val ) > 60 ?
'Password must be less than 60 characters' :
true;
} )
->setFormatter( function ( $val ) {
//return sha1( $val );
return password_hash($val, PASSWORD_BCRYPT);
} ),
Field::inst( 'Access' ),
Field::inst( 'EndDate' )
->validator( 'Validate::dateFormat', array(
"format" => Format::DATE_ISO_8601,
"message" => "Please enter a date in the format yyyy-mm-dd"
) )
->getFormatter( 'Format::date_sql_to_format', Format::DATE_ISO_8601 )
->setFormatter( 'Format::date_format_to_sql', Format::DATE_ISO_8601 ),
Field::inst( 'ChangePass' )
->setFormatter( function ( $val, $data, $opts ) {
return ! $val ? 0 : 1;
} )
)
->on( 'preEdit', function ( $e, $id, $values ) {
if ( $values['Password'] === '' ) {
$e->field( 'Password' )->set( false );
}
} )
->process( $_POST )
->json();
In the JS, I've also added:
formOptions: {
main: {
submit: 'changed'
}
},
This question has an accepted answers - jump to answer
Answers
This suggests that the hashed password is being read from the database (i.e. it is being read and then submitted, which is why the check for an empty string isn't working) - is that the case? You can check by looking at the JSON data and looking to see if it contains the hashed passwords, but I suspect it is based on the above.
That's probably something you don't want to do. The server should just return an empty string for the passwords on read, which you could do with a formatter
For example:
Regards,
Allan
Thanks Allan, Good to know.
I made that change, and removed the client side formatting, but I'm still getting "System Error", and the php in the console is reporting: Undefined index: Password
Can you think of any way to troubleshoot this further?
http://benshaw.org.uk/misc/editortest/users.html
Many thanks.
Error screengrab:
http://benshaw.org.uk/misc/editortest/error.png
I think you can remove this now:
If you want to keep it then you would need to check for the password parameter being submitted using
isset()
.Since you are only submitting changed values at the moment, and you don't change the value, then it isn't submitted. Hence the error (from code that is expecting it to always be present).
Allan
Thanks Allan. It's getting closer now, but the problem still exists when trying to edit any of the other fields using inline editing. It works with the main edit modal, but not with inline editing (reports the system error, and doesn't allow changes to be saved).
Is there anything extra I need to add in order to prevent the error occuring on "blur" submissions? I currently have:
(Sorry for my frequent posts on here by the way, I'm still awaiting my company to process my order for professional support. It should happen soon).
Full JS:
Many thanks again for all your help.
Hi,
So the error now is very similar to before - previously in the main editing view only the changed data was being submitted. Removing that so it will submit all fixes the issue.
With inline editing, by default it will only submit the changed values. You can modify that to submit all parameters using the
form-options
parameter forinline()
, but I'd suggest you simply check for thePassword
variable being submitted before attempting to use it, using theisset()
method I suggested above. e.g.:Allan
Thanks Allan! That's really great, and it's working now.
However, there's one last burning question: How do I now apply validation to the password field? e.g must be not blank, must contain a number, one capital letter etc?
I have versions of these validation processes working in PHP and JS, but neither of them now work, presumably because the inline editing is expecting the validation to be met when data is submitted upon the change of other fields.
Even when I add:
the inline editing is still not allowing me to edit other fields when password validation is enabled.. :(
For example:
I don't understand why all fields are being submitted, despite setting the form options to "changed". There are no javascript or PHP errors this time..
I think I may have successfully worked around this in a really weird way (though there's probably a better method):
I've replaced the blank password default with a random string: "sdkfjhHHjj33" that matches the validation requirements.
I think the length being forced to 6 characters or above was upsetting things.
It seems to be working now:
A bit unorthodox, but seems to work..
I've also added:
To make editing of passwords inline easier.
Feel free to suggest any problems with this method, or better alternatives, but otherwise thanks very much again for all your help, Allan.
Your best bet would probably be to use a custom validator. You can use the built in validators to check if a value was given if submitted (
notEmpty
) but there isn't a built in validator for checking a capital letter etc - that would need a one or two liner custom function.You are running into complications because it is doing validation on the client-side. Using a server-side validator will side step that and avoid the need for the workaround above.
Allan
Great, I'll investigate that option further. Many thanks Allan, I really appreciate your help.