Symofny -'password' cannot be null - php

I have implemented function to check my password length in register api call like..
if($password){
$this->validatePassword($password);
}
from other api call..
public function validatePassword($password)
{
if (strlen($password) < 6)
{
throw new PasswordLength('Password must be minimum 6 characters long!');
}
}
and in my postman I am not returning an empty field but I keep getting error
Integrity constraint violation: 1048 Column 'password' cannot be null

In symfony, the plainPassword field is purely used to carry the users 'new' password into a method that would encode it and set it to password.
After the password field is populated, then the plainPassword field is blanked so that no plain text credentials are saved to the db. This is done by calling the implemented eraseCredentials method (found in the required UserInterface). Or, you can make the plainPassword method non-persistent in the user class.
Have a look here at the docs to see how to go about it all.
The docs show an extract from what should be a user manager utility class. Use this to set and update passwords as well as creating new users.
Theres a more complete explination here where the whole process is explained from end-to-end.

Solved!
if($password){
$this->validatePassword($password);
}
$user->setPassword($password);

Related

PHP MVC: Best Practice and Right way for print data validation error

I have Php Login system using MVC structure. For database data validation I create LoginModel. I need to print failure error to view like: User Not Exist Now Which way is right and better:
1- Add error data validation in Login Model and get in Controller and Print to View Like This:
class LoginModel extends \App\Core\Model
{
public function login($user_name, $user_password, $set_remember_me_cookie = null)
{
$returnError = array();
// checks if user exists, if login is not blocked (due to failed logins) and if password fits the hash
$result = $this->validateAndGetUser($user_name, $user_password);
// check if that user exists.
if (!$result) {
$returnError['isMessage'] = false;
$returnError['name'] = "User Not Found";
}
return $returnError;
}
private function validateAndGetUser($user_name, $user_password){
//Check User Data Validation
}
}
2- Add Only True Or False in LoginModel and Get in Controller And Set Error Name and Print to View Like This:
class LoginModel extends \App\Core\Model
{
public function login($user_name, $user_password, $set_remember_me_cookie = null)
{
// checks if user exists, if login is not blocked (due to failed logins) and if password fits the hash
$result = $this->validateAndGetUser($user_name, $user_password);
// check if that user exists.
if (!$result) {
return false;
}
return true;
}
private function validateAndGetUser($user_name, $user_password){
//Check User Data Validation
}
}
In action my really question is: Can I add error message in Model and Get in Controller?! Which way is right and true?
There are many ways to do this.
For me the best way is the first way you have suggested, but better declare bug reports in a single file eg errors.php and make the model return you array with 2 keys, the first key is always TRUE or FALSE and then if your model returns the first key FALSE reads the error number from the second key.
Then, in the controller you can replace the error number with the corresponding key in the array you declared in errors.php
If the first key is TRUE, then the second key will be your user information.
Suggestion:
Split the login functionality into two (main) steps:
Check if the posted user already exists. If not, throw an exception.
Match the posted password against the stored one. If they don't match, throw an exception. I suggest the use of password_hash for storing passwords, and of password_verify for matching a password with the stored one.
Then - based on your current architecture, in your controller, use a try-catch block to catch the exception thrown by the login steps and proceed as you wish to display the exception message to the user.
Just as a note: In case of an ajax request, you would send a specific response header (with status code 500, for example) or a custom response header (with status code 420, for example) back to the client, e.g. browser, in order to activate the error function of the ajax request.
Notes:
The domain model is a layer. And it must have no knowledge about the outside world.
A controller should only (!) update the domain model (through services).
A view should be a class - not a template file - responsible with fetching data from the model layer (through services), preparing/formatting it for presentation, and passing it to a response object, in order for this to be returned and printed.
The controller and the view (mostly 1:1 relation) should be created separately. The controller should not have any knowledge about the view. This creation step would take place in the front-controller class or file.
As for error reporting, I would recommend to read this.

Symfony data transformer after $form->isValid()

I ran into a trouble of understanding how exactly data is processed in DataTransformers of Symfony.
I have a just a password form. Just one field. This field belongs to the User entity which has to constraints defined in .yml file.
Software\Bundle\Entity\User:
password:
- NotBlank: ~
- Length:
min: 6
max: 155
The validation works fine, as supposed to. The problem arise when password must be encoded automatically from the field. So,
$builder->add('password', 'password', [
'label' => 'word.password'
]);
$builder->get('password')
->addModelTransformer(new EncodePasswordTransformer());
And the transformer itself:
class EncodePasswordTransformer implements DataTransformerInterface
{
public function transform($value)
{
return $value;
}
public function reverseTransform($value)
{
// encode password
return PasswordHash::createHash($value);
}
}
So here's what's happening:
The form should contain 6 to 155 characters but $form->isValid() is always true, because the PasswordHash::createHash($value) encodes the password to 32 characters. What I was expecting is:
Form validates raw password, if more than 6 chars then go to $form->isValid() true and then encode the password after it's validated.
I know I can just encode the password manually while the form is valid without using DataTransformer but I was hoping for a bit more elegant way.
Am I wrong?
You can't, according to the documents.
Symfony's form library uses the validator service internally to validate the underlying object after values have been submitted.
So you're not actually validating form, but the object underneath which has no "notion" of the plain password.
A not so elegant solution would be to include a plain password field on your user and not persist it. However you probably won't be able to validate your existing user objects (e.g: in an update form), since their plain password fields will be null. To get around that you could create a custom validator that checks the validity of the $plainPassword field only if the user is not new. You could check that by using doctrine's UnitOfWork or by checking if the id of the user is null.
I suggest you also take a look at FOSUserBundle it has (or had) a similar approach to the plain password field and might have what you're looking for.

create custom authenticate controller with different database filed in Laravel

Auth::attempt(['u_email'=>$credentials['email'],'u_password'=>sha1($credentials['password'])])
i'm use this code for authentication but i'm getting Undefined index: password error can any one help for create custom authentication control without changing in vendor library
Thank you in advance for help me...
There are 3 things you need to do.
Pass plain-text password to Auth::attempt() as Laravel will hash that itself before verifying it against the hash stored in the database.
Auth::attempt(['u_email'=>$credentials['email'],'password' => $credentials['password']]);
Pass password as password, not u_password to Auth::attempt(). The key doesn't need to match the password column name (why? see point 3.), but it must be equal to password - see point 1 for example.
Implement getAuthPassword() method in your user model, that will return value of u_password column. This method is used by user provider to fetch the password hash that is later verified against what was passed to Auth::attempt()
//in your User.php
public function getAuthPassword() {
return $this->u_password;
}

change password to set value in cakephp

I'm using Cake 2.1.1 and trying to write an ajax function to reset a users password to a specific format. I have been able to change the password, but unable to make it so that the new password actually works to log the user in.
I have this function in my Users controller:
function ajax_reset_password(){
$this->autoRender=false;
$user = $this->User->find('first',array(
'conditions'=>array('User.email'=>$_GET['email'])
));
$this->User->id = $user['User']['id'];
$pass = $_GET['name'].'2014';
$passHashed= $this->Auth->password($pass);
$this->User->set('password', $pass);
$this->User->set('updated_at',date("Y-m-d H:i:s"));
$this->User->save();
//... code to email user new password
}
And this is my Users Controller beforeSave:
public function beforeSave(){
if (isset($this->data['User']['password'])) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
}
return true;
}
If I run this function and check my database, I can see that the value of password has changed literally to "name2014", but I cannot login with that password.
If I set the password to $passHashed and check my database, I see that the value of password has changed to a hashed value, but again, I cannot use the new password to login.
There is also a 'salt' field in my Users table that never changes.
I am guessing that the issue is that the salt needs to update with the password hash in order to properly decyrpt it, but I'm unsure of how to update the salt. Can I get it in my controller and set the value directly, or is this handled some other way with the AuthComponent?
Other posts about this topic seem to work fine with the code I have been using, but I also haven't found any that trying to set the password value directly.
Use what you have in the beforeSave(). (Don't try the route of hashing in the Controller).
If it's not hashing, just do some standard debugging and find out why it's not getting into that part of the code:
debug($this->data);
exit;
if (isset($this->data['User']['password'])) {
// IT'S NOT GETTING HERE
//...
This is one of those where the "answer" is just a nudge toward debugging your code, since it's clear where you can find out exactly what's going on and why by just seeing what's in the data and when.

How can I update only certain fields in a Yii framework?

I dont want to update the password fields.how to use this.Im using md5 encode for password.So i dont want to update the password field in yii framework.any help appreciated??
I think a better approach would be to not use the scenario in this case. The next code in the rules just says to the scenario: the next fields are required. But not: skip the other else.
array('name, username, email', 'required', 'on' => 'update'),
For example, if we limit the length of the password up to 32 characters, but in a database is stored in a format sha1 (length 40), then we have a problem because the validator will block the database query.This is because when you make updating, the "validatŠµ" method checks all class properties (regards database table mapping), not just the new ones delivered by post.
Could use the method "saveAttributes", but then I noticed another problem. If the column "email" is unique in the database and in case edited email duplicate one of the existing, then the Yii message system defined in the rules can not notify and throws error code regards database query.
The easiest approach I think is: don't set scenario in this case. Just send as an argument the properties you want. This will keep the all CRUD features created by GII.
In your code it looks like this:
(in model)
public function rules() {
return array(
array('name, username, email, password', 'required'),
);
}
(in controller)
if($id==Yii::app()->user->id){
$model=$this->loadModel($id);
if(isset($_POST['JbJsJobResume'])) {
$model->attributes=$_POST['JbJsJobResume'];
if($model->save(true, array('name', 'username', 'email')))
$this->redirect(array('view','id'=>$model->id));
}
$this->render('update',array( 'model'=>$model, ));
}
I noticed that you do not use RBAC. It is very convenient and flexible - try it.
http://www.yiiframework.com/doc/guide/1.1/en/topics.auth#role-based-access-control
In your model you must do something like this:
public function rules() {
return array(
array('name, username, email, password', 'required', 'on' => 'create'),
array('name, username, email', 'required', 'on' => 'update'),
);
}
Lets say that the scenario that you run now is the update. So I don't require the password there. I require it only in the create scenario that you may have. So in the view file that you have you remove the password field and inside the action that you have you include this:
$model->setScenario('update');
so it will not require the password and it will remain the same.
For the password change you can create a new action (ex. actionPassChange) where you will require to type twice the new password.
$model->attributes=$_POST['JbJsJobResume'];
instead of assign all attributes just assign those only you want to save,
as
$model->name=$_POST['JbJsJobResume']['name'];
$model->save();
1st option Just unset password field before setting it:
function update(){
$model=$this->loadModel($id);
unset($_POST['JbJsJobResume']['password']);
$model->attributes=$_POST['JbJsJobResume'];
$model->save();
}
2nd option: Use temp variable:
function update(){
$model=$this->loadModel($id);
$temPassword = $model->passwrod;
$model->attributes=$_POST['JbJsJobResume'];
$model->passwrod = $temPassword;
$model->save();
}
3rd option: use scenarios
I am not sure why this is a problem, and some code could help us to understand why. If you do not wish to capture / update the password, then why is the password field in the form?
If you remove the password field from the view, the value of the password field will not be posted back to controller and then it will not be updated.
There is a possibility that the above method does not work and this could be that in your User model, you are encrypting the password in the afterValidate method?:
protected function afterValidate()
{
parent::afterValidate();
$this->password = $this->encrypt($this->password);
}
public function encrypt($value)
{
return md5($value);
}
In this scenario, if you remove the password field from the view, and just update the name, username or email, then the md5 hash of the password will be re-hashed automatically and you will lose the real password.
One method to get around this is to md5 the password in the afterValidate method (create or update) however if the user wishes to change profile details, in the same form, ask the user to verify their password again.
FORM: user changes name and verifies password
Form posted
Controller calls authenticate method.
If authenticate true, overwrite the entry in user table (including verified pw)
I think #Gravy's answer is right,Thanks Gravy and Nikos Tsirakis. I have fixed nearly same issue as #faizphp. I add scenario for User model as Nikos Tsirakis said, but got same issue also. Then I found I encrypt password in User.afterValidate, so when update the User model everytime, the program encrypt the password in database again to wrong password. So i changed my function from
protected function afterValidate()
{
parent::afterValidate();
if (!$this->hasErrors())
$this->password = $this->hashPassword($this->password);
}
</code>
to
protected function afterValidate()
{
parent::afterValidate();
if (!$this->hasErrors() && $this->scenario==="create")
$this->password = $this->hashPassword($this->password);
}
.
It seems work.

Categories