My case is for change password option. I already have current password in object $pass. I want to validate this $pass against textbox form input current_password to proceed to create a new password for the user. How to validate with same validator. Sorry I'm new to laravel.
$rules = array('password_current' => "required|same:$pass");
doesn't work.
since same: used to ensure that the value of current field is the same as another field defined by the rule parameter (not object). so you can't use this function take a look this example code below.
$data = Input::all();
$rules = array(
'email' => 'required|same:old_email',
);
the above code will check if current email field is same as old_email field.
so i think you can you simple if else
in your handle controller function assume
public function handleCheck(){
$current_password = Input::get('current_password');
$pass = //your object pass;
if($current_password == $pass){
// password correct , show change password form
}else{
// password incorrect , show error
}
}
let me know if it works. see Laravel Validation same
If you have password stored in $pass already just inject $pass in the request and use its field instead for e.g.
$request->request->add(['password_old' => $pass]);
Then, you can validate it like
$rules = array('password_current' => "required|same:password_old");
Related
I need to do some extra checks on a user, I would like to get the user by username and password.
Firstly:
Is there a built in function that gets a user by username and password without authenticating them?
Secondly:
If the above is no, then how do I correctly hash the password, because if I use Hash::make( $password ) and then compare to the database, it is not the same... You would usually use Hash::check but I need to actually get the user by username and password.
In Laravel 5.2
You can use Auth::once($credentials) to validate credentials and thereafter Auth::getUser(); to get the user.
$credentials = Request::only('username', 'password');
if(!Auth::once($credentials)) {
// Invalid user credentials; throw Exception.
}
$user = Auth::getUser();
First:
If you want to check if user data to authentication is correct you can use:
if (Auth::validate($credentials))
{
//
}
But if you want to get user from database with user and password, you can use:
$user = User::whereName($username)->wherePassword(Hash::make($password))->first();
Second
To store password in database you should use Hash::make($password) as you showed and it works without any problems. Using Auth::validate should solve the issue.
Yes, there is a built in function you should use. I recommend you to read the docs. But here's a good example, it's pretty self-evident:
$input = array(
'username' => Input::get('username'),
'password' => Input::get('password'),
);
$remember = (boolean)Input::get('remember'); //'Remember me' checkbox
if (Auth::attempt($input, $remember)) {
return Redirect::intended('dashboard')->with("success", "You're logged in!"); //Redirect the user to the page intended to go to, with the dashboard page as default
}
Registering a user looks something like this:
$input = array(
'username' => Input::get('username'),
'email' => Input::get('email'),
'password' => Hash::make(Input::get('password')) //Encrypt password
);
$user = User::create($input);
I also recommend you to read about input validation. I hope this helps, good luck.
Edit: I didn't read the "without authenticating them" part. You should use Auth::validate($input) as Marcin already explained.
Laravel 5.7
To check a users credentials without logging them in, I had to do this:
$user = User::whereEmail($request->email)->first();
$user = password_verify($request->password, optional($user)->getAuthPassword()) ? $user : false;
Laravel auth validation makes use of https://www.php.net/manual/en/function.password-verify.php
I can not update the value in the database. Here's the code:
if($user = User::model()->findByAttributes(array('username'=>$verification->username)))
{
// Generating 8 random symbols for new password
$new_password = substr(str_shuffle(str_repeat("0123456789abcdefghijklmnopqrstuvwxyz", 8)), 0, 8);
// Transfering password to MD5 hash with salt!
$new_password = md5('salt'.$new_password);
$user->password = $new_password;
if($user->save())
{...
The debugger shows that the value and get it replaced (password), but when you save
if($user->save())
{
Gives false and resets to the most recent line of code:
$this->render('forget');
Questions:
How to find out what happened and why did not update the value?
How to find the error (error code, ...)?
As your last comment, If you have no repeat_password field into your table, add it by hand in your model. (User model). (Actually there is no need to have this field in your table.)
public $repeat_password
Then, define rules for the field. (for example, required and so on...)
To get validation error you can do like below:
CVarDumper::dump($model->getErrors(),56789,true);
To login in yii, i want to do it on a database table (mysql) instead of the default "admin" and "demo" default values provided in the UserIdentity class. The thing is, my user table in the database that i created does not use username and password fields for authentication, but rather email and password fields. So when i change all the "username" to "email" variables in UserIdentity.php, LoginForm.php, SiteController.php, login.php, i get an error:
Property "UserIdentity.email" is not defined.
and the error points to the change i made here by replacing username with email as shown below:
public function authenticate()
{
$user = User::model()->findByAttributes(array(
'email' => $this->email
));
Help on this would be much appreciated.
You may change email on login in UserIdentity.
$user = User::model()->findByAttributes(array(
'email' => $this->username
));
Or add new field 'email' to UserIdentity and use it.
I have a Profile form that inherits from sfGuardRegisterForm
I have these fields:
$this->useFields(
array('first_name',
'last_name',
'email_address',
'country',
'language',
'current_password',
'new_password',
'password_again',
)
);
Required fields are:
email_address, country and language
And the conditions are:
If the email_address is not equal with the current email_address
then check if it's unique then save it
If the current_password is the actual password of the user then verify if new_password and password_again are equals and verify that the new_password is not equal to the actual password of the user
I just can't figure out in how implement this
EDIT
Thanks 1ed your example works but the problem is that I load the user Profile and I fill the fields: 'first_name', 'last_name', 'email_address', 'country', 'language' with the actual logged user so the email_address field will show the email address:
//...
$this->widgetSchema['email_address']->setDefault($this->_user->getEmailAddress());
//...
If the user dont change the email it will always show this message:
An object with the same "email_address" already exist.
I just want to skip that
Also this $this->getObject()->checkPassword() does not works, always show this message:
Incorrect current password.
I use:
$this->_user = sfContext::getInstance()->getUser()->getGuardUser();
To get actual user profile
EDIT2
Thanks again 1ed
This is very weird and I'm getting frustated, this is the situation
I have a "workaround" for this but it does not follow the standard, I can make it works but using sfContext::getInstance()->getUser()->getGuardUser(); and it will be more unnecesary code
If I use new ProfileForm($user) automatically fills all the fields, that's very good but I can't setDefault() I can't set null or empty any field so I can't use doUpdateObject() because this function only works when the current data is updated, also I have tested overriding bind(), save() etc. without results
email_address uniqueness: you should set unique: true in schema, in sfDoctrineGuardPlugin that's the case by default, so in BasesfGuardUserForm you should see a unique validator already: sfValidatorDoctrineUnique(array('model' => 'sfGuardUser', 'column' => array('email_address'))
current_password: you should create a callback type post validator for this
// in sfGuardRegisterForm::configure()
// these fields can be blank
$this->getValidator('current_password')->setOption('required', false);
$this->getValidator('new_password')->setOption('required', false);
$this->getValidator('password_again')->setOption('required', false);
// check the current password (this validator is not `required` by default)
$this->mergePostValidator(new sfValidatorCallback(array(
'callback' => array($this, 'checkPassword'),
), array(
'invalid' => 'Incorrect current password.'
)));
// add this method to the same form class
public function checkPassword(sfValidatorBase $validator, array $values, array $arguments)
{
// if a new password is given check whether the old one is correct or not and rise an error if not correct
if(0 != strlen($values['new_password']) && !$this->getObject()->checkPassword($values['current_password']))
{
throw new sfValidatorErrorSchema($validator, array(
'current_password' => new sfValidatorError($validator, 'invalid')
));
}
return $values;
}
Alternatively you can create a custom post validator, but I think it's not necessary.
EDIT:
If you would like to display empty email address just like the password fields add these to your form class:
// at form load remove the default value
protected function updateDefaultsFromObject()
{
parent::updateDefaultsFromObject();
if (isset($this['email_address']))
{
$this->setDefault('email_address', '');
}
}
// before save remove empty email address
protected function doUpdateObject($values)
{
if (isset($values['email_address']) && 0 == strlen($values['email_address']))
{
unset($values['email_address']);
}
parent::doUpdateObject($values);
}
I'll try and explain this in methodical terms instead of giving you a big block of code....
So first, you want to if (email_addr != current_email) and if that's true, go on to do
if (new_pass != current_pass) then follow on to make sure if (new_pass == new_pass_again)
Inside all of these IFs, you can return a true/false or some kind of flag, or just //do code inside the brackets :p
EDIT: encase these IFs in: if (country != NULL && language != NULL && email_addr != NULL)
I need help understanding the logic to deal with validating user inputs.
my current state of validating user data is at worst, i feel pretty awkward using these messy lines of codes, have a look at my typical function which i uses it to get input from the user and process it to database.
public function saveUser($arguments = array()) {
//Check if $arguments have all the required values
if($this->isRequired(array('name','email','password','pPhone','gender','roleId'))) {
//$name should could minimum of 5 and maximum of 25 chars, and is a strict character.
$name = $this->isString(5, 25, $this->data['name'], 'STRICT_CHAR');
$email = $this->isEmail($this->data['email']);
$pPhone = $this->isString(5, 12, $this->data['pPhone'], 'STRICT_NUMBER');
$sPhone = (!empty($this->data['sPhone'])) ? $this->isString(5, 12, $this->data['sPhone'], 'STRICT_NUMBER') : 0;
//Check For Duplicate Email Value
$this->duplicate('user_details','email',$email);
//If Static Variable $error is not empty return false
if(!empty(Validation::$error)) { return false; }
//After Validation Insert the value into the database.
$sth = $this->dbh->prepare('INSERT QUERY');
$sth->execute();
}
}
Now is the time i focus on improving my validation code. i would like all my class methods to validate the user inputs before inserting into the database. basically a class methods which takes user input should be able to perform the following.
If class method accepts user input as an array then check for all required inputs from within the array.
Check the Minimum and Maximum Length of the input.
Check for any illegal character.
etc.
I would like to know how to deal with this, and also if there is any PHP Independent Validation Component which can come to my rescue. it would be of great help. if i am doing it wrong please suggest me on improving my code, i won't mind going to any extent as long as it guarantees that my code follows the coding standard.
I will also appreciate if someone could explain me on dealing with validation logic for validating user input for a class method of an object.
Thank you..
PHP 5.2 has a new core extension called "filter functions". You can use this extension to sanitize and validate user data.
For example, to validate an email address:
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "This (email) email address is considered valid.";
}
As for dealing with validation in general, you want to decouple the validation process from the incoming data and the objects themselves. I use the Lithium PHP framework, and their data validation class is implemented as a nearly independant utility class. Check it out for ideas on how to roll your own: http://li3.me/docs/lithium/util/Validator
Using their class, you get something like this:
// Input data. This can be an $object->data() or $_POST or whatever
$data = array(
'email' => 'someinvalidemailaddress';
);
// Validation rules
$rules = array(
'email' => array(
array('notEmpty', 'message' => 'email is empty'),
array('email', 'message' => 'email is not valid')
)
);
// Perform validation
Validator::check($data, $rules);
// If this were in your object
public validate($data = array(), $rules = array()) {
$data = !empty($data) ? $data : $this->data; // Use whatever data is available
$rules = $this->rules + $rules; // Merge $this's own rules with any passed rules
return Validator::check($data, $rules));
}
// You can have a save method like
public save() {
if ($this->validates()) {
// insert or update
}
}
// And your object would
$user = new User();
$user->data = array('email' => 'whatever');
$user->save();
And there's always Zend Validate. You can look it up at http://framework.zend.com/manual/en/zend.validate.set.html
Create your validation class first...Then when they submit the code. Just include the class on where every you have action set to on the form. You can create a loop to pass the POST or GET data though the instance which validates the input. Then if the input is good, return it(maybe as an array, that's what I do) and pass it to your database.
Example:
$validate = new validation_Class; //new instance of the validation class
$output = foreach($_POST as $input) // loop each input data into the class
{
$validate->$input;
}
Now if your validation class is setup right, you can have all the clean data stored in $output