CakePHP - Password confirmation not allowing user to submit registration - php

I'm trying to set up validation for user registration but I'm having troubles. When I only have the email,role and password fields in the $validation array (remove the others) it works and will save a new user. When I try to add the other fields it fails and gives the flash message error "The user could not be saved. Please, try again."
I'm pretty sure it's the re_password check. When I remove the validation for that it works. However, the re_password validation does display an error when the passwords are different, so I'm not sure where to look
Here's my users table
id | email | password | location | website | role | created | modified
Here's the validation requirements. To get it to save a new user I have to remove everything but email, password and role.
public $validate = array(
'email' => 'email'
,
'password' => array(
'required' => array(
'rule' => array('minLength', '8'),
'message' => 'A password with a minimum length of 8 characters is required'
)
),
're_password' => array(
'required' => array(
'rule' => array('equalTo', 'password' ),
'message' => 'Both password fields must be filled out'
)
),
'role' => array(
'valid' => array(
'rule' => array('inList', array('admin', 'author')),
'message' => 'Please enter a valid role',
'allowEmpty' => false
)
),
'location' => array(
'valid' => array(
'rule' => array('notEmpty'),
'message' => 'Please select a location'
)
)
);
Here's the form (the options array is above, figured it's not necessary to show)
echo $this->Form->input('email');
echo $this->Form->input('password');
echo $this->Form->input('re_password', array('type'=>'password', 'label'=>'Re-Enter Password', 'value'=>'', 'autocomplete'=>'off'));
echo $this->Form->input('location', array('options' => $options, 'label' => 'Select Nearest Location'));
echo $this->Form->input('website',array('label'=>'Enter your website, such as www.example.com. '));
echo $this->Form->input('role', array('type' => 'hidden', 'default' => 'user'));
Here's the re_password checking function in the User model
function check_user_password($userid) {
$salt = Configure::read('Security.salt');
$this->User->id = $userid;
$hashed_password = $this->User->field('password');
// check password
if($hashed_password == md5($data['User']['re_password'].$salt)) {
return true;
} else {
return false;
}
}
And finally, here's the add function in UsersController
public function add() {
if ($this->request->is('post')) {
$this->User->create(); //create initiates a form on User/add.ctp
if ($this->User->save($this->request->data)) { //save the form data
$this->Session->setFlash(__('The user has been saved'));
$this->redirect(array('controller' => 'demos', 'action' => 'index'));
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
}
}
}
Please let me know if there's anything else you need to see

I believe that your re_passwords valiadtion rule equalTo compares its value to string password and not the actual field. I like to use custom functions for this.
so try replacing re_passwords rule array
//'rule' => array('equalTo', 'password' ),
'rule' => array('equalToField', 'password'),
and declare equalToField function in that model
function equalToField($array, $field) {
return strcmp($this->data[$this->alias][key($array)], $this->data[$this->alias][$field]) == 0;
}
** Also in the future when you seem to have a problem with validation rules
try this in your controllers action (its faster than removing every single rule)
if ($this->User->save($this->request->data)) {
...
} else {
debug($this->User->validationErrors);
...
}
I hope this helps.

Hi Please use following code for your requirement :
override equalTo function by putting your own method in user model:
function equalTo( $field=array(), $compare_field=null )
{
foreach( $field as $key => $value ){
$v1 = $value;
$v2 = $this->data[$this->name][ $compare_field ];
if($v1 !== $v2) {
return FALSE;
} else {
continue;
}
}
return TRUE;
}

Attention, in #luboss answer, where he declares:
function equalToField($array, $field) {
return strcmp($this->data[$this->alias][key($array)], $this->data[$this->alias][$field]) == 0;
}
That cannot work as we are comparing inconsistent fields:
the left member of strcmp has already been hashed, but not the right member.
This happens as a CakePHP automation because the field is called password.
The way I got this to work was to reuse the hashing function in the equalToField helper:
public function equalToField($array, $field) {
$valueFirstOccurrence = $this->data[$this->alias][$field];
$valueSecondOccurrence = Security::hash($this->data[$this->alias][key($array)], $type = 'sha1', $salt = true) ;
return !strcmp($valueFirstOccurrence, $valueSecondOccurrence);
}
Other point :
If you are interested in adding a minLength validation field for your password field, you want to read this good post first:
minLength data validation is not working with Auth component for CakePHP

Related

Wrong Laravel validation messasges

I get the wrong error messages. My purpose is following :
1. checking username / pw combination, and if it doesn't match, "wrong username/pw combination" error through validator.
2. captcha (mews) is troubling me. Even user enters true captcha chars (no case-sensitive by config) I get the error message.
Here is my validator :
FYI: i have a table "user" instead of users, and i can use it nicely in other controllers.
protected function loginValidator()
{
$message = array(
'exists:user,username' => 'Wrong username/pass combination',
'exists' => 'Wrong :attribute.',
'required' => ':attribute cannot be empty',
'captcha' => 'Wrong captcha'
);
return Validator::make(Input::all(),[
'usernameInput' => 'required|exists:user,username',
'passwordInput' => 'required',
'captchaInput' => 'captcha|required'
], $message);
}
Even if username/pass combination is true, i get wrong captcha message.
Thanks in advance.
protected function loginValidator()
{
$validator = Validator::make(
array(
'name' => 'Dayle',
'password' => 'lamepassword',
'email' => 'email#example.com'
),
array(
'name' => 'required',
'password' => 'required|min:8',
'email' => 'required|email|unique:users'
)
);
if ($validator->fails())
{
// The given data did not pass validation
$data['messages'] = $validator->messages()->all();
}
else
{
//complete validation
}
return View::make('home.login', $data);
}

ASK CakePHP - work with password field

I have searched many topic in here but I can't solve my problem. Please check this for me.
I made the register page and when I made for password field...
I had users_controller.php like:
class UsersController extends AppController
{
var $name = "Users";
var $helpers = array('Paginator','Html');
var $paginate = array();
//Doi tuong component de thuc thi thao tac login
public $components = array
(
'Auth' => array
(
'authorize' => 'controller',
'loginRedirect' => array
(
'admin' => FALSE,
'controller' => 'users',
'action' => 'dashboard'
),
'loginError' => 'Invalid account',
'authError' => 'You don\'t have permission'
),
'Session'
);
//Ham loc cac user truoc khi truy cap trang
public function beforeFilter()
{
parent::beforeFilter();
$this->Auth->allow('add');
$this->Auth->allow('viewuserall');
}
//Ham them moi user
public function add()
{
$this->layout = 'TDCake';
$this->User->set($this->data);
if($this->User->valid_user() == TRUE)
{
if(!empty($this->data))
{
$this->User->create();
if($this->User->save($this->data))
{
$this->Session->setFlash('User has been created!');
$this->redirect(array('action'=>'login'));
}
else
{
$this->Session->setFlash('Please correct the errors');
}
};
}
else
{
$this->Session->setFlash("Your data is NOT available");
}
}
//Ham login cho user
public function login()
{
$this->layout = 'TDCake';
if
(
!empty($this->data) &&
!empty($this->Auth->data['User']['username'])&&
!empty($this->Auth->data['User']['password'])
)
{
$user = $this->User->find
(
'first',array
(
'conditions'=>array
(
'User.email'=>$this->Auth->data['User']['username'],
'User.password'=>$this->Auth->data['User']['password']
),
'recursive' => -1
)
);
if(!empty($user) && $this->Auth->login($user))
{
if($this->Auth->autoRedirect)
{
$this->redirect($this->Auth->redirect());
}
}
else
{
$this->Session->setFlash
(
$this->Auth->loginError,
$this->Auth->flashElement,
array(),'auth'
);
}
}
}
//Ham logout cho user
public function logout()
{
$this->redirect($this->Auth->logout());
}
//Ham gi cha biet, de do tinh sau =))
public function dashboard()
{
$this->layout = 'TDCake';
}
//Ham view cac user khong dieu kien trong table users
function viewuserall()
{
$this->layout = 'TDCake';
$this->paginate=array
(
'limit' => 10,
'order' => array('id' => 'asc'),
);
$data = $this->paginate("User");
$this->set("data",$data);
}
}
User.php in Model is:
class User extends AppModel
{
var $name = "User";
var $validate = array();
function validate_passwords()
{
if($this->data[$this->alias]['pass'] == $this->data[$this->alias]['rpass'])
{
return $this->data[$this->alias]['pass'] = $this->data['User']['password'];
}
else return FALSE;
}
function valid_user()
{
$this->validate = array
(
//Kiem tra username truoc khi add
'username' => array
(
'rule01_notEmpty' => array
(
'rule' => 'notEmpty',
'message' => 'You must enter your Username !'
),
'rule02_max16' => array
(
'rule' => array('maxLength', 20),
'message' => 'Your Username must be less than 20 chars !'
),
'rule03_exists' => array
(
'rule' => 'isUnique',
'message' => 'Your Username have already existed !'
)
),
//Kiem tra email truoc khi add
'email' => array
(
'rule01_notEmpty' => array
(
'rule' => 'notEmpty',
'message' => 'You must enter your Email !'
),
'rule02_exists' => array
(
'rule' => 'isUnique',
'message' => 'Your Email have already existed !'
),
'rule03_emailtype' => array
(
'rule' => 'email',
'message' => 'You didn\'t type a email !'
)
),
//Kiem tra password truoc khi add
'pass' => array
(
'length' => array
(
'rule' => array('between', 6, 20),
'message' => 'Your password must be between 8 and 40 characters.',
),
),
'rpass' => array
(
'length' => array
(
'rule' => array('between', 6, 20),
'message' => 'Your password must be between 8 and 40 characters.',
),
'compare' => array
(
'rule' => 'validate_passwords',
'message' => 'The passwords you entered do not match.',
)
)
);//End this->validate=array
if($this->validates($this->validate==TRUE))
{
return TRUE;
}
else
{
return FALSE;
}
}//End function valid_user
}
add.ctp is
echo $this->Session->flash('auth');
echo $this->Form->create();
echo $this->Form->input('username', array('label' => ('Username')));
echo $this->Form->input('email', array('label' => ('Email')));
echo $this->Form->input('pass', array('label' => ('Password'),'type' => 'password', 'value' => ''));
echo $this->Form->input('rpass', array('label' => ('Repeat Password'), 'type' => 'password', 'value' => ''));
echo $this->Form->input('firstname', array('label' =>('Firstname')));
echo $this->Form->input('lastname', array('label' =>('Lastname')));
echo $this->Form->input('dob', array('label' =>('DOB'),'type' => 'date'));
echo $this->Form->end('Register');
Explanation:
So, in this case, I can validate 2 Password Fields (empty, not equal,...), but it can't insert to the database. That mean it INSERTED current data into the DB but password column in DB is EMPTY. In database, my password column name "password" also.
In another case, I change the name "pass" into "password" for the
echo $this->Form->input('pass', array(
Of course, I have changed any place related to...
and in that case, it can be inserted the password but can not validate anything.
I am too confused about this...I don't know what I am wrong is....can anybody help me.
I am not sure why you are doing an assignment in your validate function:
return $this->data[$this->alias]['pass'] = $this->data['User']['password'];
And even if you were doing an assignment, it should be:
return $this->data['User']['password'] = $this->data[$this->alias]['pass'];
Realize that the field "password" is getting the value from $this->data which has the information, not the other way around.
Also. It would be better (in terms of clarity), to break this code in two lines.
$this->data['User']['password'] = $this->data[$this->alias]['pass'];
return $this->data['User']['password'];
You should name your field the exact name "password" if that's what it is called in the database AND if you are not explicitly assigning it.
Your add function is not doing the above, and further more, as a best practice, you should be hashing the password.
See the CakePHP book on tutorials and examples.
Take some time to go through it with all the snippets and recommendations. And don't forget the standards. :)

cakephp update more field unique

I have a site developed in cakephp.
I have a model called User like this:
class User extends AppModel {
public $name = 'User';
public $validate = array(
'username' => array(
'not_empty' => array(
'rule'=> 'notEmpty',
'message'=> 'Username not empty'
)
),
'email' => array(
'email_invalid' => array(
'rule' => 'email',
'message' => 'Invalid mail'
),
'email_unique' => array(
'rule' => 'isUnique',
'message' => 'Mail already exist inside database'
)
)
);
public function beforeSave(){
if (isset($this->data['User']['password'])){
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
}
}
}
Into my validate I have the rules email_unique that check if inside the database is already present another email equal.
When I update a user I make this inside my controller:
$this->User->id = $this->request->data['User']['id'];
if ($this->User->save($this->request->data)) {
$this->redirect (array ('action'=>'index'));
}
else{
$this->Session->write('flash_element','error');
$this->Session->setFlash ('Error');
}
It always fail because email isn't unique but is the same record!
I would like to know what is the best method to escape the validation if the save is an update not a create?
Or something like: check if the page is edit escape validation or I don't know.. maybe there are many system, I would like to know what is the more correct for my problem.
Thanks
You can adjust your validation rules to only apply when a new record is created, not when an existing record is updated. You can do this by setting the on key in your validation rule to create, so it will look like this:
'email_unique' => array(
'rule' => 'isUnique',
'message' => 'Mail already exist inside database',
'on' => 'create' // Only apply this rule upon creation of a new record
)
See the documentation on this for further details.
If you also want to block duplicate e-mails upon updating, create a beforeSave method in your User model, looking for the e-mail address:
public function beforeSave($options = array()) {
// If the email key is set in the data to be saved...
if (isset($this->data[$this->alias]['email'])) {
// Make sure the email is not already in use by another user
if ($this->find('count', array(
'conditions' => array(
$this->alias . '.id !=' => $this->data[$this->alias]['id'],
$this->alias . '.email' => $this->data[$this->alias]['email']
)
)) > 0) {
// The email is found for a user with another id, abort!
return false;
}
}
}

validating in cakephp model compare two fields

I have a model Interesttype where i want two fields to be validated one should not be more than the other and none should be less than a particular set value. Here is my model.
class Interesttype extends AppModel
{
public $primaryKey = 'int_id';
public $displayField = 'int_name';
public $hasMany= array(
'Loan' => array(
'className' => 'Loan',
'foreignKey' => 'lon_int_id'
)
);
public $validate = array(
'int_name'=> array(
'rule' => 'notEmpty',
'allowEmpty' => false,
'message' => 'The interest type name is required.'
),
'int_active'=>array(
'rule'=>array('boolean'),
'allowEmpty'=>false,
'message'=>'Please select the status of this interest type'
),
'int_max'=> array(
'numeric'=>array(
'rule' => 'numeric',
'allowEmpty' => false,
'message' => 'Please specify a valid maximum interest rate.'
),
'comparison'=>array(
'rule' => array('comparison','>',1000),
'allowEmpty' => false,
'message' => 'The Maximum interest rate cannot be less than the special rate.'
),
'checklimits'=>array(
'rule' => array('checkRateLimits','int_min'),
'allowEmpty' => false,
'message' => 'The Maximum interest rate cannot be less than the minimum rate.'
)
),
'int_min'=> array(
'numeric'=>array(
'rule' => 'numeric',
'allowEmpty' => false,
'message' => 'Please specify a valid minimum interest rate.'
),
'comparison'=>array(
'rule' => array('comparison','>',1000),
'allowEmpty' => false,
'message' => 'The Minimum interest rate cannot be less than the special rate.'
))
);
function checkRateLimits($maxr,$minr){
if($maxr>=$minr){
return true;
}
else{
return false;
}
}
}
the above model validates my forms well except that one check will not be done, it will not check if the maximum interest rate is indeed more than or equal to the minimum inerest rate.
Where am i going wrong on the validation?
You'll have to add your own Validation Method to make this possible. Here's a pretty generic example that makes use of Validation::comparison() and supports all of its operators (>, <, >=, <=, ==, !=, isgreater, isless, greaterorequal, lessorequal, equalto, notequal) as the second argument in the options array and a field name to compare the validated value to as a third parameter.
class MyModel extends AppModel
{
/* Example usage of custom validation function */
public $validate = array(
'myfield' => array(
'lessThanMyOtherField' => array(
'rule' => array('comparisonWithField', '<', 'myotherfield'),
'message' => 'Myfield value has to be lower then Myotherfield value.',
),
),
);
/* Custom validation function */
public function comparisonWithField($validationFields = array(), $operator = null, $compareFieldName = '') {
if (!isset($this->data[$this->name][$compareFieldName])) {
throw new CakeException(sprintf(__('Can\'t compare to the non-existing field "%s" of model %s.'), $compareFieldName, $this->name));
}
$compareTo = $this->data[$this->name][$compareFieldName];
foreach ($validationFields as $key => $value) {
if (!Validation::comparison($value, $operator, $compareTo)) {
return false;
}
}
return true;
}
}
This is generic, so you could throw the function in your AppModel if you want to make use of it in multiple models in your App. You could also make this a Behavior to share it between different models.
I won't help you to do your code however I will suggest you to read the following backery article http://bakery.cakephp.org/articles/aranworld/2008/01/14/using-equalto-validation-to-compare-two-form-fields
<?php
class Contact extends AppModel
{
var $name = 'Contact';
var $validate = array(
'email' => array(
'identicalFieldValues' => array(
'rule' => array('identicalFieldValues', 'confirm_email' ),
'message' => 'Please re-enter your password twice so that the values match'
)
)
);
function identicalFieldValues( $field=array(), $compare_field=null )
{
foreach( $field as $key => $value ){
$v1 = $value;
$v2 = $this->data[$this->name][ $compare_field ];
if($v1 !== $v2) {
return FALSE;
} else {
continue;
}
}
return TRUE;
}
}
?>
modify the code I think it should be easy from here.
I don't think you can achieve this with directly inserting it into the validate array in a model. You can however specify your own validation function. An example is given here (look at the model code):
Example custom validation function
In your Model your validate should be field name with rule pointing to the function you want to run.
And "None should be less than a particular set value" I would use the "range" validation as seen below. The example will accept any value which is larger than 0 (e.g., 1) and less than 10
public $validate = array(
'maxr'=>array(
'Rate Limits'=>array(
'rule'=>'checkRateLimits',
'message'=>'Your Error Message'
),
'Greater Than'=>array(
'rule'=>array('range', -1, 11),
'message'=>'Please enter a number between 0 and 10'
)
),
);
In the function you pass $data which is the fields being passed. If $data doesn't work try $this->data['Model']['field'] ex($this->data['Model']['maxr'] >= $this->data['Model']['minr'])
function checkRateLimits($data){
if ( $data['maxr'] >= $data['minr'] ) {
return true;
} else {
$this->invalidate('minr', 'Your error message here');
return false;
}
}
Your Form would be something like
echo $this->Form->create('Model');
echo $this->Form->input('maxr');
echo $this->Form->input('minr');
echo $this->Form->end('Submit');

CakePHP data validation on create and update

I'm writing a customer management system using cakePHP (the first thing I've ever attempted to build using this framework), and I'm struggling to figure out how to validate certain fields when adding a new customer.
Each customer has an id that I need to be able to add manually, and a username that has to be unique but can be empty.
Here is what I want to happen:
When adding a new customer:
Check whether the id already exists and alert the user if it does (and not add the user)
Check whether the username already exists and alert the user if it does (and not add the user)
When updating a customer profile (the id cannot be modified at this point):
If the username has been modified, check whether it already exists and alert the user.
As it now stands, whenever I try adding a user with an existing id, cakePHP simply overwrites the existing id's info with the new info.
I've tried several validation options but nothing seems to work.
Here's the first:
public $validate = array(
'id' => array(
'idRule-1' => array(
'on' => 'create',
'rule' => 'uniqueID',
'message' => 'This Oracle ID already exists.',
'last' => false
),
'idRule-2' => array(
'rule' => 'numeric',
'message' => 'Oracle ID can only contain numbers.',
'last' => false
),
),
'username' => array(
'userRule-1' => array(
'on' => 'create',
'rule' => 'uniqueUser',
'message' => 'This username already exists',
'last' => false,
),
'userRule-2' => array(
'on' => 'update',
'rule' => 'oneUser',
'message' => 'The eBay username you are trying to modify already belongs to another seller',
'last' => false,
),
)
);
public function uniqueID() {
return ($this->find('count', array('conditions' =>array('Seller.id' => $this->data['Seller']['id']))) == 0);
}
public function uniqueUser() {
return ($this->find('count', array('conditions' =>array('Seller.username' => $this->data['Seller']['username']))) == 0);
}
public function oneUser() {
return ($this->find('count', array('conditions' =>array('Seller.username' => $this->data['Seller']['username']))) == 1);
}
and the second (only for the id):
public $validate = array(
'id' => array(
'unique' => array(
'rule' => 'isUnique',
'on' => 'create',
'message' => 'This Oracle ID already exists.',
)
)
);
And here are the add() and edit() methods of the controller:
public function add() {
if ($this->request->is('post')) {
$this->Seller->create();
if ($this->Seller->save($this->request->data)) {
$this->Session->setFlash(__('The seller has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The seller could not be saved. Please, try again.'));
}
}
$accountManagers = $this->Seller->AccountManager->find('list');
$primaries = $this->Seller->Primary->find('list');
$thirdParties = $this->Seller->ThirdParty->find('list');
$sites = $this->Seller->Site->find('list');
$meetings = $this->Seller->Meeting->find('list');
$this->set(compact('accountManagers', 'primaries', 'thirdParties', 'sites', 'meetings'));
}
/**
* edit method
*
* #throws NotFoundException
* #param string $id
* #return void
*/
public function edit($id = null) {
if (!$this->Seller->exists($id)) {
throw new NotFoundException(__('Invalid seller'));
}
if ($this->request->is('post') || $this->request->is('put')) {
$this->Seller->id = $id;
if ($this->Seller->save($this->request->data)) {
$this->Session->setFlash(__('The seller has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The seller could not be saved. Please, try again.'));
}
debug($this->Seller->validationErrors);
} else {
$options = array('conditions' => array('Seller.' . $this->Seller->primaryKey => $id));
$this->request->data = $this->Seller->find('first', $options);
}
$accountManagers = $this->Seller->AccountManager->find('list');
$primaries = $this->Seller->Primary->find('list');
$thirdParties = $this->Seller->ThirdParty->find('list');
$sites = $this->Seller->Site->find('list');
$meetings = $this->Seller->Meeting->find('list');
$this->set(compact('accountManagers', 'primaries', 'thirdParties', 'sites', 'meetings'));
}
Any and all tips will be greatly appreciated!
If the data you are trying to save contains an id, CakePHP assumes that you are updating an existing record. For a validation rule to be triggered on "create", the id should not be set. If the id is set, Cake will check for "update" rules.
So you should let your database affect ids for new records with an autoincrement, and then only manage validation when editing your existing users.

Categories