CakePHP 2 - Validating password fields - php

I have some problem with Cakephp 2 validation.
I am trying to validate several fields on an Edit form. Some of them are a password and confirm password fields.
I want to validate both only if they are supplied. If they are empty I dont change the password, but if the user writes over them I would like to validate if they have a minLength or the passwords matchs.
Code:
'pwd' => array(
'length' => array(
'rule' => array('between', 8, 40),
'message' => 'Your password must be between 8 and 40 characters.',
'allowEmpty' => true
),
),
'pwd_repeat' => array(
'length' => array(
'rule' => array('between', 8, 40),
'message' => 'Your password must be between 8 and 40 characters.',
'allowEmpty' => true
),
'compare' => array(
'rule' => array('validate_passwords'),
'message' => 'The passwords you entered do not match.',
'allowEmpty' => true
),
I dont know if I have to define some rules on edit() function in the controller or it should be enough, but my code is not working.
Thanks!
Edit: (Controller Code)
public function edit($id = null) {
if (!$this->User->exists($id)) {
throw new NotFoundException(__('Usuario incorrecto'));
}
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->User->save($this->request->data)) {
$this->Session->setFlash(__('El usuario ha sido actualizado.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('El usuario no ha podido actualizarse. Por favor, inténtelo de nuevo.'));
}
unset($this->request->data['User']['pwd']);
unset($this->request->data['User']['pwd_repeat']);
} else {
$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
$this->request->data = $this->User->find('first', $options);
}
$roles = $this->User->Role->find('list');
$this->set(compact('roles'));
}
(View Code)
<div id="contenedor" class="users form">
<?php echo $this->Form->create('User', array('name' => 'form')); ?>
<fieldset>
<legend><?php echo __('Editar Usuario'); ?></legend>
<?php
echo $this->Form->input('id');
echo $this->Form->input('username', array('label' => __('Usuario')));
echo $this->Form->input('pwd', array('label' => __('Contraseña'), 'type' => 'password', 'name' => 'pass', 'onKeyUp' => 'habilita()', 'value' => ''));
echo $this->Form->input('pwd_repeat', array('label' => __('Repite Contraseña'), 'type' => 'password', 'name' => 'rpass', 'disabled' => 'disabled'));
echo $this->Form->input('firstname', array('label' => __('Nombre')));
echo $this->Form->input('lastname', array('label' => __('Apellidos')));
echo $this->Form->input('telephone', array('label' => __('Teléfono')));
echo $this->Form->input('email', array('label' => __('Email')));
echo $this->Form->input('role_id', array('label' => __('Rol')));
?>
</fieldset>
<?php echo $this->Form->end(__('Aceptar')); ?>

Make the validation rules like this
'pwd' => array(
'length' => array(
'rule' => array('between', 8, 40),
'message' => 'Your password must be between 8 and 40 characters.',
),
),
'pwd_repeat' => array(
'length' => array(
'rule' => array('between', 8, 40),
'message' => 'Your password must be between 8 and 40 characters.',
),
'compare' => array(
'rule' => array('validate_passwords'),
'message' => 'The passwords you entered do not match.',
)
)
And your validate_passwords function should be like this.
public function validate_passwords() {
return $this->data[$this->alias]['pwd'] === $this->data[$this->alias]['pwd_repeat']
}

Related

Email Validation in cakephp Model

I have the below setup of validation rules. For some reason, 'on' => 'create' block doesn't work. The conditions to be implemented are standard create / modify regarding email. Also, in edit section, I'm getting the error from 'on' => 'create' block.
How to validate the email? I'm using CakePHP v 2.6.1.
public $validate = array(
'email' => array(
'required' => array(
'rule' => array('email'),
'message' => 'Kindly provide your email for verification.'
),
'maxLength' => array(
'rule' => array('maxLength', 255),
'message' => 'Email cannot be more than 255 characters.'
),
'editunique' => array(
'rule' => array('editunique'),
'message' => 'Provided Email address already exists.',
'on' => 'update'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'Provided Email already exists.',
'on' => 'create'
)
)
);
public function editunique($email) {
// email should be one and of the logged in user only.
if ($this->find('count', array(
'conditions' => array(
$this->alias . '.id <>' => $this->data[$this->alias]['id'],
$this->alias . '.email' => $email
)
)) > 1) {
return false;
}
}
Also, I'm not getting the $this->data[$this->alias]['id'] value.
My Controller has the following section:
if ($this->Client->hasAny(array('Client.id' => base64_decode(trim($this->request->query['client_id']))))){
if ( $this->request->is('ajax') && $this->request->is('post') ){
$this->Client->create();
$this->Client->id = base64_decode(trim($this->request->query['client_id']));
$this->Client->set($this->request->data);
// validate
if($this->Client->validates()) {
// save the data after validation
if($this->Client->save($this->request->data)){
}
}
}
}
I think you are misunderstanding what Cake's isUnique rule checks for and as a result over complicating things. Cake defines isUnique as:-
The data for the field must be unique, it cannot be used by any other rows
When it checks if a value is unique it is smart enough to exclude existing data of the current row (which appears to be what you are attempting to do with your editunique rule).
So you just need your validation rules to look like:-
public $validate = array(
'email' => array(
'required' => array(
'rule' => array('email'),
'message' => 'Kindly provide your email for verification.'
),
'maxLength' => array(
'rule' => array('maxLength', 255),
'message' => 'Email cannot be more than 255 characters.'
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'Provided Email already exists.'
)
)
);
This removes the editunique rule and drops the on condition of your unique rule.
As of cakephp 3.0 in the entities table it should look something like this
namespace App\Model\Table;
public function validationDefault($validator)
{
$validator
->email('email')
->add('email', 'email', [
'rule' => [$this, 'isUnique'],
'message' => __('Email already registered')
])
->requirePresence('email', 'create')
->notEmpty('email', 'Email is Required', function( $context ){
if(isset($context['data']['role_id']) && $context['data']['role_id'] != 4){
return true;
}
return false;
});
return $validator;
}
}
function isUnique($email){
$user = $this->find('all')
->where([
'Users.email' => $email,
])
->first();
if($user){
return false;
}
return true;
}

Add function in cakephp suddenly stopped working

I'm new to cakePHP, so I may be missing something obvious.
I have an add form that was working and saving to the database, and suddenly stopped. I didn't think I added anything significant, mostly just styling stuff...unfortunately my last backup was before I had finished the add function, so I don't have a way to go back to when it worked. If anyone can take a look and see where I'm going wrong, I would appreciate it!
My Task model:
App::uses('AuthComponent', 'Controller/Component');
class Task extends AppModel {
public $belongsTo = 'User';
public $validate = array(
'task_name' => array(
'custom' => array(
'rule' => array('custom', '/^[a-z0-9 ]*$/i'),
'required' => true,
'message' => 'This field accepts letters and numbers only.'
),
'maxLength' => array(
'rule' => array('maxLength', 50),
'message' => 'Task name cannot exceed 50 characters'
)
),
'frequency' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'allowEmpty' => true
)
),
'day' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'allowEmpty' => true
)
),
'user_id' => array(
'numeric' => array(
'rule' => 'numeric'
)
),
'month_type' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => false
)
),
'month_number' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => false
)
),
'month_day' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'allowEmpty' => true
)
),
'day_number' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => false
)
)
);
}
The add function from my TasksController file:
public function add() {
if ($this->request->is('post')) {
$this->Task->create();
if ($this->Task->save($this->request->data)) {
$this->Session->setFlash(__('Task saved!'));
$this->redirect(array('action' => 'index'));
}
else {
$this->Session->setFlash(__('The task could not be saved'));
}
}
}
And the form from my tasks/add.ctp file:
<?php
echo $this->Form->create('Task',array('class' => 'taskForm'));
$userId = $this->Session->read('Auth.User.id');?>
<fieldset>
<legend class="welcomeText"><?php echo __('Add a Task'); ?></legend>
<?php
echo $this->Form->hidden('user_id', array('value' => $userId));
echo $this->Form->input('task_name', array('label' => 'Task Name', 'maxLength' => 50));
//set frequency
echo "<p>How often should this task be done?</p>";
$options = array('unset' => 'Decide Later','daily' => 'Daily','weekly' => 'Weekly','monthly' => 'Monthly');
$attributes = array('value' => 'unset','separator' => '<br/>','class' => 'frequencyRadio','legend' => false);
echo $this->Form->radio('frequency', $options, $attributes);
//optional answers
//if "weekly" is selected
echo "<div id=\"weeklyRadio\" >";
echo "<p>Set a day of the week for this task?</p>";
$options = array('unset' => 'Decide later','monday' => 'Monday','tuesday' => 'Tuesday','wednesday' => 'Wednesday',
'thursday' => 'Thursday','friday' => 'Friday','saturday' => 'Saturday','sunday' => 'Sunday');
$attributes = array('value' => 'unset','separator' => '<br/>','class' => 'weeklyRadio','legend' => false);
echo $this->Form->radio('day',$options,$attributes);
echo "</div>";
//if "monthly" is selected
?>
<div id="monthlyRadio">
<p>Schedule this task?</p>
<input type="radio" name="data[Task][month_type]" id="TaskMonthTypeUnset"
value="unset" class="monthlyRadio" required="required" checked="checked" />
<label for="TaskMonthTypeUnset">Decide later</label><br/>
<input type="radio" name="data[Task][month_type]" id="TaskMonthTypeNumber"
value="number" class="monthlyRadio" required="required" />
<label for="TaskMonthTypeNumber">
<?php
echo "On the ";
$options = array(1 => '1st',2 => '2nd',3 => '3rd',4 => '4th',5 => '5th',6 => '6th',7 => '7th',8 => '8th',9 => '9th',
10 => '10th',11 => '11th',12 => '12th',13 => '13th',14 => '14th',15 => '15th', 16 => '16th',
17 => '17th',18 => '18th',19 => '19th',20 => '20th',21 => '21st',22 => '22nd',23 => '23rd',
24 => '24th',25 => '25th',26 => '26th',27 => '27th',28 => '28th',29 => '29th',30 => '30th',31 => '31st');
echo $this->Form->select('month_number',$options,array('value' => null));
echo " of the month";
?>
</label><br/>
<input type="radio" name="data[Task][month_type]" id="TaskMonthTypeDay" value="day" class="monthlyRadio" required="required" />
<label for="TaskMonthTypeDay">
<?php
echo "On the ";
$options = array(1 => '1st',2 => '2nd',3 => '3rd',4 => '4th',5 => '5th',6 => 'last');
echo $this->Form->select('day_number',$options,array('value' => null));
echo "&nbsp";
$options = array('monday' => 'Monday','tuesday' => 'Tuesday','wednesday' => 'Wednesday',
'thursday' => 'Thursday','friday' => 'Friday','saturday' => 'Saturday','sunday' => 'Sunday');
echo $this->Form->select('month_day',$options,array('value' => null));
echo " of the month";
?>
</label>
</div>
<?php
echo $this->Form->submit('Add Task', array('class' => 'formSubmit', 'title' => 'Create Task') );
?>
</fieldset>
<?php echo $this->Form->end(); ?>
There is also a javascript file that shows and hides the optional radio buttons, but I assume that wouldn't have anything to do with why it stopped saving to the database.
When I click the "Add Task" button on the form, it doesn't do anything at all (doesn't save to the database, and doesn't redirect to the index.ctp view like it used to). No idea what I'm missing here!
UPDATE
Fixed the problem! The places in my form where I specified a default value of null, it was passing an empty string. The data model was expecting numeric values for 'month_number' and 'day_number,' so it wasn't processing.
I fixed it by adding 0 => '' to the selection list, and specifying 0 as the default value, and now it works fine.
Thanks for the help!
I don't see errors in your code.
Add this in the controller add and make a debug for more information about what happens.
public function add() {
$this->loadModel('Task');
debug($this->request->is('post')); //try this first
//debug($this->request); //after try this
if ($this->request->is('post')) {
$this->Task->create();
if ($this->Task->save($this->request->data)) {
$this->Session->setFlash(__('Task saved!'));
$this->redirect(array('action' => 'index'));
}
else {
$this->Session->setFlash(__('The task could not be saved'));
}
}
}
loadModel adds this. update your question with that display the debug, and I update mi answer.
It looks like you have the submit form button assigned to a different class, which is why its not firing the form.
echo $this->Form->submit('Add Task', array('class' => 'formSubmit', 'title' => 'Create Task') );
Try changing it to either of the following
echo $this->Form->submit('Add Task', array(
'class' => 'taskForm',
'title' => 'Create Task'));
echo $this->Form->button('Add Task', array(
'class' => 'taskForm',
'title' => 'Create Task',
'action' => 'submit;));
or amend the form ending tag to see if it fires properly.
Change this
echo $this->Form->end();
to
echo $this-Form->end('Submit');

Getting validation on login form in CakePHP 2.2

I have built a simple CakePHP app with a users login system and have hooked up the Cake Form plugin by Milesj.me (not sure if that's causing the problems).
However my validation seems to have applied itself to the login form as well as the signup form. So when I try and login, I am getting errors like 'Username already in use'.
Any ideas what would cause this? Has something changed in CakePHP that adds the validation to authentication forms as well?
Also why am I having to hash the password in the model? I was under the impression that CakePHP hashed passwords automatically? And I've not needed to do it before. However If I don't do it, then it was saving the password in the DB as in and not hashed...
Here is my view, controller and model:
<?php echo $this->Form->create(); ?>
<?php echo $this->Form->input('User.username',
array('tabindex'=>1, 'autofocus',
'label'=>array('class'=>'placeholder','text'=>'Username'))); ?>
<?php echo $this->Form->input('User.password',
array('tabindex'=>2, 'type'=>'password',
'label'=>array('class'=>'placeholder','text' =>'Password' ))); ?>
<div class="input button">
<button class="orangeButton" tabindex="3" type="submit"><span class="icon login">Log in</span></button>
</div>
<?php echo $this->Form->end(); ?>
controller:
public function login() {
if ($this->request->data) {
$this->User->set($this->request->data);
if ($this->User->validates() && $this->Auth->login()) {
if ($user = $this->Auth->user()) {
$this->User->Profile->login($user['id']);
$this->Session->delete('Forum');
$this->redirect($this->referer());
}
}
}
}
Note: the calls to Profile model for login just saves some data for when last logged in and other stuff and doesn't actually do anything regarding authentication!
and the model:
class User extends AppModel {
public $name = 'User';
public $hasOne = array(
'Profile' => array('className' => 'Forum.Profile')
);
public $hasMany = array(
'Access' => array('className' => 'Forum.Access'),
'Moderator' => array('className' => 'Forum.Moderator')
);
public $validate = array(
'email' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A valid email address is required'
),
'email' => array(
'rule' => array('email'),
'message' => 'This is not a valid email address'
),
'unique' => array(
'rule' => array('isUnique'),
'message' => 'This email is already in use'
)
),
'username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A username is required'
),
'unique' => array(
'rule' => array('isUnique'),
'message' => 'This username is already in use'
),
'alphaNumeric' => array(
'rule' => array('alphaNumeric'),
'message' => 'Usernames must only contain letters and numbers'
),
'between' => array(
'rule' => array('between', 4, 20),
'message' => 'Usernames must be between 4 and 20 characters long'
)
),
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A password is required'
)
)
);
public function beforeSave()
{
if (isset($this->data[$this->alias]['password']))
{
$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
}
return true;
}
Just add to your validation rules 'on' => 'create'
http://book.cakephp.org/2.0/en/models/data-validation.html#on
As per cakephp
In case of multiple rules per field by default if a particular rule
fails error message for that rule is returned and the following rules
for that field are not processed.
But if first rule doesn't fail, then it continue to evaluate second
rule.
You can remove particular validation by following way
$this->validator()->remove('username', 'unique');

Validating an ajax request with CakePHP ajax view returns all fields invalid always instead of the proper ones

I'm not sure why I keep receiving all the errors instead of just the invalid fields even when I fill out some of the required fields properly.
Submissions Controller:
public function submit() {
$this->set('title_for_layout', 'Submit - ');
if ($this->request->is('ajax')) {
if (!empty($this->request->data)) {
$this->Submission->set($this->request->data);
if ($this->Submission->invalidFields($this->request->data)) {
$formErrors = $this->Submission->validationErrors;
} else {
$formErrors = null;
}
} else {
$formErrors = null;
}
$this->set(compact('formErrors'));
}
/Submissions/json/submit.ctp:
<?php
$toReturn = array(
'formErrors' => $formErrors
);
echo json_encode($toReturn);
Submission model:
var $validate = array(
'title' => array(
'title' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Please enter a title'
),
'minLength' => array(
'rule' => array('minLength', 5),
'message' => 'Please make your title longer (e.g. IJL John F. Kennedy donated his presidential salary to charity)'
),
'maxLength' => array(
'rule' => array('maxLength', 300),
'message' => 'Your title needs to be shorter'
),
),
'description' => array(
'shortDescription' => array(
'rule' => array('shortDescription'),
'message' => 'Your description needs to be longer'
),
'longDescription' => array(
'rule' => array('longDescription'),
'message' => 'Your description needs to be shorter'
),
),
'source' => array(
'source' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Enter a valid source URL (e.g. http://en.wikipedia.org/wiki/Penguins)'
),
'website' => array(
'rule' => 'url',
'message' => 'Enter a valid source URL (e.g. http://en.wikipedia.org/wiki/Penguins)'
),
),
'category' => array(
'category' => array(
'rule' => 'notEmpty',
'required' => true,
'allowEmpty' => false,
'message' => 'Please choose a category'
)
)
);
Form values that are getting serialized and sent:
Errors I'm getting in a json response:
Pulling hair out over here :|
You seem to have got a little muddle up with validates() and invalidFields()
invalidFields() returns the invalid fields after a validates(), see: http://book.cakephp.org/2.0/en/models/data-validation/validating-data-from-the-controller.html
So your code should look something like this:
$this->Submission->set($this->request->data);
if (!$this->Submission->validates()) {
$formErrors = $this->Submission->invalidFields();
} else {
$formErrors = null;
}
First, set the data to the model:
$this->ModelName->set($this->request->data);
Then, to check if the data validates, use the validates method of the model, which will return true if it validates and false if it doesn’t:
if ($this->ModelName->validates()) {
// it validated logic
} else {
// didn't validate logic
$errors = $this->ModelName->validationErrors;
}
Validating Data from the Controller

Validation for "at least one phone number is required" in CakePHP

This is the model file vechile_enquiry.php
<?php
class VechileEnquiry extends AppModel{
var $name ='VechileEnquiry';
var $validate = array('name' => array
('rule' => 'notEmpty',
'message' => 'Please type name')
);
}
?>
This is the view file vechile.ctp
<?php
echo $this->Form->input('name', array('label'=>false));
?>
At least one phone number is required:
<?php
echo $this->Form->input('mobile_phone', array('label'=>false));
echo $this->Form->input('work_phone', array('label'=>false));
echo $this->Form->input('home_phone', array('label'=>false));
?>
Validation is working in the name field but I'm not getting how to implement validation in mobile_phone,
work_phone, home_phone for the condition that at least one phone number is required.
This should do it for you:
var $validate = array(
'name' => array(
'rule' => 'notEmpty',
'message' => 'Please type name'
),
'mobile_phone' => array(
'check_phone' => array(
'rule' => array('hasPhone'),
'required' => false,
'allowEmpty' => true,
'message' => 'At least one phone number is required.'
)
),
'work_phone' => array(
'check_phone' => array(
'rule' => array('hasPhone'),
'required' => false,
'allowEmpty' => true,
'message' => 'At least one phone number is required.'
)
),
'home_phone' => array(
'check_phone' => array(
'rule' => array('hasPhone'),
'required' => false,
'allowEmpty' => true,
'message' => 'At least one phone number is required.'
)
)
);
function hasPhone($field){
if(!empty($this->data[$this->name]['mobile_phone']) || !empty($this->data[$this->name]['work_phone']) || !empty($this->data[$this->name]['home_phone'])){
return true;
} else {
return false;
}
}

Categories