Understanding when Model's $validate rules work - validation

I'm trying to activate a user with CakePHP 2 by activation url, but I get a validation error used on user registration page.
I've created a registration action and view, where I've defined this UserModel validation rules:
<?php
class User extends AppModel {
public $name = 'User';
public $validate = array (
'username' => array (
'not_empty' => array (
'rule' => 'notEmpty',
'message' => 'Username cannot be empty'
)
),
'password' => array (
'not_empty' => array (
'rule' => 'notEmpty',
'message' => 'Password cannot be empty'
),
'between_chars' => array (
'rule' => array ('between', 5, 40),
'message' => 'Password must be between 5 and 40 chars'
),
'match_password' => array (
'rule' => 'matchPasswords',
'message' => 'Password is different from Password confirm'
)
),
'password_confirm' => array (
'not_empty' => array (
'rule' => 'notEmpty',
'message' => 'Password confirm cannot be empty'
),
'between_chars' => array (
'rule' => array ('between', 5, 40),
'message' => 'Password confirm must be between 5 and 40 chars'
)
),
'email' => array (
'invalid_email' => array (
'rule' => 'email',
'message' => 'Invalid email, try again'
),
'existing_email' => array (
'rule' => 'isUnique',
'message' => 'This email is already registered'
)
),
'activation_key' => array (
'alphanumeric_key' => array(
'allowEmpty' => true,
'rule' => 'alphaNumeric',
'message' => 'Invalid activation key',
'last' => true
)
)
);
public function matchPasswords ($data) {
debug($this->data); // Undefined index: password_confirm [APP/Model/User.php, line 59] points here
if ($data['password'] == $this->data['User']['password_confirm']) {
return true;
}
$this->invalidate('password_confirm', 'Password confirm must be equal to Password field');
return false;
}
public function beforeSave () {
if (isset($this->data['User']['password'])) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
}
return true;
}
}
?>
Everything works perfect until I reach the activate action of the UsersController with the activation code, here I get an Undefined index: password_confirm [APP/Model/User.php, line 59] which points to matchPasswords of the User Model validation rule.
<?php
App::uses('CakeEmail', 'Network/Email');
class UsersController extends AppController {
public $name = 'Users';
public function index () {
$this->User->recursive = 0;
$this->set('users', $this->User->find('all'));
}
public function view ($id = null) {
if (!$id) {
$this->Session->setFlash('Invalid user');
$this->redirect(array('action'=>'index'));
}
$this->User->id = $id;
if (!$this->User->exists()) {
throw new NotFoundException('Invalid user');
}
$this->set('user', $this->User->read());
}
public function edit () {
}
public function delete () {
}
public function register () {
// code for user registration
}
public function registration ($sub_action = null) {
}
public function password ($sub_action = null, $code = null) {
if ($sub_action == 'reset' && !empty ($code)) {
$this->render('password_reset_code');
} else if ($sub_action == 'reset' && empty ($code)) {
$this->render('password_reset_mail');
}
}
public function login () {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect ($this->Auth->redirect());
} else {
$this->Session->setFlash('Errore di accesso, email/password sbagliati, ricontrolla i dati inseriti');
}
}
}
public function logout () {
$this->redirect($this->Auth->logout());
}
public function activate ($code = null) {
if (!empty ($code)) {
$user = $this->User->find('first', array('conditions' => array('User.activation_key' => $code)));
if (!empty($user)) {
$user['User']['activation_key'] = null;
$user['User']['active'] = 1;
if ($this->User->save($user)) { // here is where Invalid index error starts
$this->render('activation_successful');
} else {
$this->set('status', 'Salvataggio fallito');
$this->render('activation_fail');
}
// debug($this->User->invalidFields());
// debug($this->User->data);
} else {
$this->set('status', 'Nessun account collegato alla chiave');
$this->render('activation_fail');
}
} else {
$this->set('status', 'Nessuna chiave');
$this->render('activation_fail');
}
}
private function registrationEmail ($account_email, $username, $code) {
// code for email registration
}
}
?>
Why I get the error?
Why matchPasswords is executed in the activate action?
Are these validation rules executed in every view of the controller?

Try setting the User model's id before the save in the activate() function:
$this->User->id = $user['User']['id'];
or something similar.
When you don't set the id prior to the save() function, it tries to make a new table row. That's why it's validating everything.

Try changing
if ($data['password'] == $this->data['User']['password_confirm']) {
to
if (isset($this->data['User']['password_confirm']) && $data['password'] == $this->data['User']['password_confirm']) {
in your matchPasswords function in the User.php
In the activate action you are getting all of the fields for the user and then saving them so within the data you are saving will be the password field. As the password field is there CakePHP is trying to validate it against the password_confirm field which does not exist.
You should only validate that the password and password confirm fields match when they are both present, i.e when you have the password_confirm in your form.

Related

How to get the users detail info in api call in cs-cart?

I am trying to retrieve user information through api in CS-cart. But it returns only limited information. How can we modify the code to get all the user info for ex- user profiles, address, gst and all.
you can create your own API.
/var/www/html/app/addons/addon_name/Tygh/Api/Entities/Egg.php
<?php
namespace Tygh\Api\Entities;
use Tygh\Api\AEntity;
use Tygh\Api\Response;
class Egg extends AEntity
{
public function index($id = '', $params = array())
{
if(empty($id))
{
$dd=db_get_array("SELECT * FROM ?:table_name");
//result all rows
}
else
{
// for filtering purpose
$where=array("id"=>$id);
$dd=db_get_array("SELECT * FROM ?:table_name where ?w",$where);
//result-> specific one row
}
return array(
'status' => Response::STATUS_OK,
'data' => $dd
);
}
public function create($params)
{
return array(
'status' => Response::STATUS_OK,
'data' => array()
);
}
public function update($id, $params)
{
return array(
'status' => Response::STATUS_OK,
'data' => array()
);
}
public function delete($id)
{
return array(
'status' => Response::STATUS_NO_CONTENT,
);
}
public function privileges()
{
return array(
'index' => true,
'create' => 'create_things',
'update' => 'edit_things',
'delete' => 'delete_things',
'index' => 'view_things'
);
}
public function privilegesCustomer()
{
return array(
'index' => true
);
}
}
?>
Remarks:
file name,
class name,
file path
Or you can edit the user API entity from this location.
app/Tygh/Api/Entities/Users.php
Any doubts , then kick me in...

CakePHP: Warning (512): Model "User" is not associated with model "User" Windows to Ubuntu Deployment

I am trying to deploy a cakePHP app which works exactly as it should in Windows.
I use an LdapUser model to authenticate through Active Directory:
LdapUser:
<?php
class LdapUser extends AppModel
{
var $name = 'LdapUser';
var $useTable = false;
var $myCompany_ldap = "x.x.x.x";
//var $myCompany_ldap_config = array ('basedn' => 'CN=x,DC=x,DC=x');
var $basedn = 'CN=x,DC=x,DC=x';
var $myCompany_ldap_domain = "x.x";
// var $user = "x#x.x";
// var $pass = "x!";
var $exists = false;
var $ds;
function __construct()
{
parent::__construct();
ini_set('max_execution_time', 300); //300 seconds = 5 minutes
$this->ds=ldap_connect( $this->myCompany_ldap );
// print_r($this->basedn);
// debug($this->ds);
// print_r($this->ds);
ldap_set_option($this->ds, LDAP_OPT_PROTOCOL_VERSION, 3);
print_r($this->res);
//debug($this->exists);
//print_r($this->exists);
}
function __destruct()
{
ldap_close($this->ds);
// $this->loadModel('Cookie');
// $this->Cookie->destroy();
}
function isConnected(){
return ldap_bind($this->ds, $this->basedn);
}
function isLdapUser($user, $pass){
$this->exists = ldap_bind($this->ds, $user, $pass);
// debug($this->exists);
//debug($user);
// debug($pass);
return $this->exists;
}
}
And then in UserController inside login function:
// Login User
public function login() {
// Check if the user is already logged in
if ($this->Session->check('Auth.User.id')){
// Redirect to login page
$this->redirect($this->Auth->loginRedirect);
}
else{
// If the user is not logged in
session_set_cookie_params(0);
// If the request is a POST request
if ($this->request->is('post')) {
//get credentials
$this->username = $this->request->data['User']['username'];
$this->password = $this->request->data['User']['password'];
$this->domain = $this->request->data['User']['domain'];
//debug($this->username);
debug($this->domain) ;
if ($this->Auth->login() ) {
// Successful login
//Check if specific user exists in LDAP:
$this->loadModel('LdapUser');
$this->ds = $this->LdapUser->isConnected();
//print_r('Ldap status: '. $this->ds);
//debug($this->ds) ;
//echo $this->ds;
$this->isLdapUser =
$this->LdapUser->isLdapUser($this->username .
//debug($this->isLdapUser);
if ( $this->username =='tsc' || $this->ds ){
if ($this->isLdapUser || 'tsc' ) {
// Get all the user information and store in Session
$this->User->id = $this->Auth->user('id');
$this->User->contain(array('User', 'Role' => array('Ui', 'Action.name')));
$this->Session->write('User', $this->User->read());
$actions = array();
foreach ($this->Session->read('User.Role.Action') as $key => $value){
array_push($actions, $value['name']);
}
$this->Session->write('User.Role.Action', $actions);
// Render different layout depending on user type
if($this->Session->read('User.Role.Ui.name') == Configure::read('usertype.msp')){
$this->Session->write('SessionValues.ui', Configure::read('usertype.msp'));
$this->Auth->loginRedirect = array('controller' => 'PortStats', 'action' =>
'index');
}
else if($this->Session->read('User.Role.Ui.name') ==
Configure::read('usertype.tsc')){
$this->Session->write('SessionValues.ui', Configure::read('usertype.tsc'));
$this->Auth->loginRedirect = array('controller' => 'PortStats', 'action' =>
'index');
}
else if($this->Session->read('User.Role.Ui.name') ==
Configure::read('usertype.superAdminUserType')){
$this->Auth->loginRedirect = array('controller' => 'uis', 'action' => 'index');
}
// Redirect to main login page
$this->redirect($this->Auth->loginRedirect);
}
else {
// Failed login
session_destroy();
$this->Session->setFlash(__('Login failed: access not granted'), 'default',
array(), 'fail');
}
}
else {
// Failed login
session_destroy();
$this->Session->setFlash(__('Login failed: LDAP out of reach'), 'default',
array(), 'fail');
}
}
else {
// Failed login
$this->Session->setFlash(__('Invalid username or password, please try again'),
'default', array(), 'fail');
}
}
}
}
I get:
Warning (2): ldap_bind() [http://php.net/function.ldap-bind]: Unable to bind to
server: Invalid credentials [APP/Model/LdapUser.php, line 56]
Warning (512): Model "User" is not associated with model "User" [CORE/Cake/Model
/Behavior/ContainableBehavior.php, line 339]
My guess is that could be something with case sensitivity between platofrms but it's really bothering that doesn't work in Ubuntu....
[Edited] There is my User model:
<?php
App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
public $name = 'User';
var $actsAs = array('Containable');
// Define which database to use
var $useDbConfig = 'myDb';
// Many-To-One relationship
var $belongsTo = array('Role');
// validation of input data
public $validate = array(
'username' => array(
'required' => array(
'rule' => 'notEmpty',
'message' => 'A username is required'
),
'isUnique' => array (
'rule' => 'isUnique',
'message' => 'This username already exists'
)
),
'password' => array (
'not_empty' => array (
'rule' => 'notEmpty',
'message' => 'The field "Password" cannot be empty'
),
'between_chars' => array (
'rule' => array ('between', 4, 10),
'message' => 'Password must be between 4 and 10 chars'
)
),
'passwordVerify' => array(
'not_empty' => array (
'rule' => 'notEmpty',
'message' => 'The field "Confirm Password" cannot be empty'
),
'match_password' => array (
'rule' => 'matchPasswords',
'message' => '"Confirm Password" must be the same as "Password"'
)
),
'name' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A name is required'
)
),
'surname' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A surname is required'
)
),
'role_id' => array(
'valid' => array(
'rule' => 'notEmpty',
'message' => 'Please enter a valid role',
'allowEmpty' => false
)
),
'oldPassword' => array (
'match_password' => array (
'rule' => 'matchOldPassword',
'message' => 'Invalid password'
),
'required' => array (
'rule' => 'requiredOldPassword',
'message' => '"Current Password" is required if you wish to edit the password'
)
),
'newPassword' => array (
'required' => array (
'rule' => 'requiredNewPassword',
'message' => '"New Password" is required if you wish to edit the password'
),
'between_chars' => array (
'rule' => 'lengthNewPassword',
'message' => 'Password must be between 4 and 10 chars'
)
),
'newPasswordVerify' => array (
'required' => array (
'rule' => 'requiredNewPasswordVerify',
'message' => '"Confirm Password" is required if you wish to edit the password'
),
'match_password' => array (
'rule' => 'matchNewPasswordVerify',
'message' => '"Confirm Password" must be the same as "New Password"'
)
)
);
// Verify that password and password verification match when creating a new user
public function matchPasswords ($data) {
if ($this->data['User']['password'] == $this->data['User']['passwordVerify']) {
return true;
} else {
return false;
}
}
public function matchOldPassword ($data) {
if (!empty($this->data['User']['oldPassword'])){ // when an input is given for
'oldPassword'...
if ($_SESSION['User']['User']['password'] ==
AuthComponent::password($this->data['User']['oldPassword'])) { // when password
is correct (equal to 'password')
return true;
} else { // when password is invalid (not equal to 'password')
return false;
}
}
return false; // default value when 'oldPassword' is empty
}
// Verify that a value for 'oldPassword' (current password) is given when
'newPassword' or 'newPasswordVerify' are also given during the procedure of
editing the password
public function requiredOldPassword ($data) {
if (!empty($this->data['User']['newPassword']) || !empty($this->data['User']
['newPasswordVerify'])){ // when an input is given for 'newPassword' or
'newPasswordVerify'...
if (!empty($this->data['User']['oldPassword'])){ // when an input is given for
oldPassword...
return true;
} else { // when no input is given for oldPassword...
return false;
}
}
return false; // default value when 'newPassword' and 'newPasswordVerify'
are left empty
}
// Verify that a value for 'newPassword' (current password) is given when
public function requiredNewPassword ($data) {
if (!empty($this->data['User']['oldPassword']) ||
!empty($this->data['User']['newPasswordVerify'])){ // when an input is given for
'oldPassword' or 'newPasswordVerify'...
if (!empty($this->data['User']['newPassword'])){
return true;
} else { // when no input is given for newPassword...
return false;
}
}
return false;
}
// Verify that 'newPassword' has an appropriate length
public function lengthNewPassword ($data) {
if (!empty($this->data['User']['newPassword'])) { )>=4 && .
strlen($this->data['User']['newPassword'])<=10){ // when length is valid..
return true;
} else { // when length is invalid...
return false;
}
}
return false; // default value when 'newPassword' is left empty
}
public function matchNewPasswordVerify ($data) {
if ($this->data['User']['newPassword'] == $this->data['User']
['newPasswordVerify']) {
return true;
} else {
return false;
}
}
public function requiredNewPasswordVerify ($data) {
if (!empty($this->data['User']['oldPassword']) ||
!empty($this->data['User']['newPassword'])){ // when an input is given for
'oldPassword' or 'newPassword'...
if (!empty($this->data['User']['newPasswordVerify'])){ // when an
return true;
} else { // when no input is given for newPasswordVerify...
return false;
}
}
return false; // default value when 'oldPassword' and 'newPassword' are left empty
}
// Password stored with SHA1 (cakePHP default) or MD5 hashing algorithm
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$this->data[$this->alias]['password'] =
AuthComponent::password($this->data[$this->alias]['password']);
//$this->data['User']['password'] = md5($this->data['User']
['password']); // MD5 hashing algorithm
}
return true;
}
var $hasMany = array(
'MspDashboard' => array(
'className' => 'MspDashboard',
'foreignKey' => 'user_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
}
[Edit]:
I tend to believe the warning is not responsible for my problem:
It occurs in both platforms but shouldn't interrupt the site's funcionality.
So when in windows in debug level = 2 I see:
But then in ubuntu, it looks buggy all I get is this screen:
About the 512 associated error:
$this->User->contain(array('User', 'Role' => array('Ui', 'Action.name')));
Change to:
$this->User->contain(array('Role' => array('Ui', 'Action.name')));
Don't contain the model itself.
About the LDAP error, seems to be this line:
$this->exists = ldap_bind($this->ds, $user, $pass);
I would start with some code like this to debug:
var_dump($this->ds);
var_dump($user);
var_dump($pass);
$this->exists = ldap_bind($this->ds, $user, $pass);
Copy-paste this data into some LDAP tool and first verify they are correct.
Try this function to get more error information:
http://php.net/manual/en/function.ldap-error.php
OK, mystery solved:
The warning had nothing to do with this:
This line of code is error-proning:
if ($this->isLdapUser || 'tsc' ) {
.......
user tsc is admin in local db and doesn't exist in ldap so is certain to get a time out from ldap_bind, Looks like Ubuntu platform would crash my application on browser timeout. In contrary my local machine will wait during time out time and continue with log-in.
I just modified my code so admin user 'tsc'
will log-in directly without passing from ldap auth.

cake 2.1 data validation not working

I tried every method, but it cake php data validation does not working.would you tell me what is the wrong part?
I add all types of validations but still the form saves without validation data!
My model:
class contacts extends AppModel
{
public $name = 'contact';
public $useTable='contacts';
public $validate=array(
'name' => array(
'requierd'=>array(
'rule'=>array('Not empty'),
'message' => 'A username is required'
)
)
);
}
My controller
class ContactsController extends AppController
{
public $helpers=array('Html','Form');
public $components=array('session','Email');
public function index()
{
if($this->request->is('post'))
{
$this->Contact->create();
if($this->Contact->save($this->request->data))
{
$this->Session->setFlash('Thank you we will contact you soon');
$this->redirect(array('action'=>'index'));
}
else
{
$this->Session->setFlash('Unable to send your message.');
}
}
}
}
My view:
echo $this->Form->create('Contact');
echo $this->Form->input('name');
echo $this->Form->input('email');
echo $this->Form->input('subject');
echo $this->Form->input('message',array('rows' => '3'));
//echo $this->Form->checkbox('Send me a coppy');
echo $this->Form->end('Send');
Try with
public $validate=array(
'name' => array(
'rule' => 'notEmpty',
'message' => 'A username is required'
)
);
as seen in the docs example. Don't know why you added an extra array.
You can add required and allowEmpty indexes just to be strict-er
public $validate=array(
'name' => array(
'rule' => 'notEmpty',
'message' => 'A username is required',
'required' => true,
'allowEmpty' => false
)
);
I figured it out. the reason that they were not working was because the model name!!

How to disable direct access to callback functions?

<? if ( ! defined('BASEPATH')) exit();
class Registration extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->model('registration_model');
}
public function index() {
$this->load->library('form_validation');
$this->form_validation->set_rules('email', 'E-mail', 'trim|required|valid_email|callback_email_available');
if($this->form_validation->run() == FALSE) {
$this->load->view('registration');
} else {
$this->registration_model->add_user();
}
}
# Check E-mail
public function email_available($email) {
$this->db->select('email');
$this->db->where('email', $email);
$query = $this->db->get('users');
$result = $query->row();
if(!empty($result)) {
$this->form_validation->set_message('email_available', 'This e-mail belongs to another user.');
return FALSE;
} else {
return TRUE;
}
}
}
?>
I have a registration form with Form Validation.
And I have a callback function to validate email uniqueness.
All code works fine, but I can directly access to callback function with errors
examle.com/registration/email_available
A PHP Error was encountered
Severity: Warning
Message: Missing argument 1 for Registration::email_available()
Filename: controllers/registration.php
A PHP Error was encountered
Severity: Notice
Message: Undefined variable: email
Filename: controllers/registration.php
How can I deny direct access to callback function?
You can prefix the method name with an _ to deny access through HTTP request.
My suggestion is to tuck your validation rules into a separate file. CodeIgniter supports this by allowing you to save validation configurations in config/form_validation.php. Take a look at the Form Validation Documentation, specifically the section labelled Saving Sets of Validation Rules to a Config File.
Your controller's index:
public function index() {
$this->load->library('form_validation');
if($this->form_validation->run('submit_registration') == FALSE) {
$this->load->view('registration');
}
else{
$this->registration_model->add_user();
}
}
config/form_validation.php
$config = array
(
'submit_registration' => array
(
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'trim|required|valid_email|email_available'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'required|alpha_numeric|etc'
)
),
'some_other_submission' => array(
array(
'field' => 'somefield',
'label' => 'SomeField',
'rules' => 'some|rules'
),
array(
'field' => 'getit',
'label' => 'Get The Point?',
'rules' => 'trim'
)
)
);
libraries/MY_Form_validation.php
class MY_Form_validation extends CI_Form_validation
{
function __construct($config = array()){
parent::__construct($config);
}
function email_available($email){
$CI =& get_instance();
//check your database with the $CI variable...
if(email_exists) return TRUE;
else return FALSE;
}
}

ORM/Extra Validate iby two field

Kohana 3.2
I want to check my parent_id but i need the second value of type_id.
Code:
public function rules()
{
return array(
'type_id' => array(
array('not_empty'),
array('digit'),
),
'parent_id' => array(
array('digit'),
array(array($this,'check_category'),array(':value', ':field','type_id'))
),
);
}
public function check_category($parent_id,$field,$type_id)
{
die($type_id);
}
How to sent two values of my field to my function ??
After i make that in my controller :
if(isset($_POST['submit']))
{
$data = Arr::extract($_POST, array('type_id', 'parent_id', 'name', 'comment'));
$category = ORM::factory('kindle_category');
$category->values($data);
try {
$extra_rules = Validation::factory($_POST)
->rule('parent_id','Kindle::check_category',array($data['type_id'],$data['parent_id'],'parent_id',':validation'));
$category->save($extra_rules);
$this->request->redirect('kindle/category');
}
catch (ORM_Validation_Exception $e) {
$errors = $e->errors('validation');
}
}
if($parent->type_id!=$type_id)
{
$validation->error($field, 'Dog name, not cat!');
return false;
}
How to see my error "Dog name,not cat!' in my View ?
Array errors doesnot have this value.
public function rules()
{
return array(
'type_id' => array(
array('not_empty'),
array('digit'),
),
'parent_id' => array(
array('digit'),
array(array($this,'check_category'),array(':validation'))
),
);
}
public function check_category($validation)
{
$type_id = $validation['type_id'];
...
}
http://kohanaframework.org/3.2/guide/orm/examples/validation

Resources