So I have this controller and method:
Contorller/UsersController.php
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Event\Event;
use Cake\Network\Exception\NotFoundException;
use Cake\ORM\TableRegistry;
/**
* Jobs Controller
*
* #property \App\Model\Table\JobsTable $Jobs
*/
class UsersController extends AppController
{
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Users->allow('register');
}
public function register()
{
//Get Categories
$getCategories = TableRegistry::get('Categories');
$categories = $getCategories->find('all');
$this->set('categories',$categories);
$this->set('title', 'Registration');
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'register']);
}
$this->Flash->error(__('Unable to add the user.'));
}
$this->set('user', $user);
}
}
Model/Table/UsersTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class UsersTable extends Table
{
public function validationDefault(Validator $validator)
{
return $validator
->notEmpty('first_name', 'A username is required')
->notEmpty('last_name', 'A username is required')
->notEmpty('email', 'A username is required')
->notEmpty('username', 'A username is required')
->notEmpty('password', 'A username is required')
->add('role', 'inList', [
'rule' => ['inList', ['Employer', 'Job Seeker']],
'message' => 'Please enter a valid role'
]);
}
}
?>
Template/Users/register.ctp:
<div class="users form">
<?php echo $this->Form->create($user); ?>
<fieldset>
<legend><?= __('Create New User'); ?></legend>
<?php
echo $this->Form->input('first_name');
echo $this->Form->input('last_name');
echo $this->Form->input('email',array('type'=>'email'));
echo $this->Form->input('username');
echo $this->Form->input('password',array('type'=>'password'));
echo $this->Form->input('confirm_password',array('type'=>'password'));
echo $this->Form->input('role',array(
'type' => 'select',
'options' => ['Employer'=>'Employer','Job Seeker'=>'Job Seeker'],
'empty' => 'Select Role'
));
?>
</fieldset>
<?= $this->Form->button(__('Submit')); ?>
<?= $this->Form->end() ?>
</div>
Entity/User.php:
<?php
namespace App\Model\Entity;
use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;
/**
* User Entity.
*/
class User extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* #var array
*/
protected $_accessible = array(
'first_name' => true,
'last_name' => true,
'email' => true,
'username' => true,
'password' => true,
'role' => true,
'created' => true
);
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
}
So when I'm trying to access /users/register view, it gives me next error:
Unknown method "allow": $this->Users->allow('register');
But if I remove next method inside of my Users controller:
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Users->allow('register');
}
It works fine, but I guess it also must work with it as well. So what am I doing wrong or missing?
Related
I have a problem validatin fields in my code usign cakephp3.4.13
It always says "This field cannot be left empty" event the username fields has value input, but when i remove the validation in userstable.php it will submit but the username field is empty in the database.
PLease help me
Userstable.php
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator->requirePresence('username', 'Please enter username.');
$validator
->requirePresence('password', 'create')
->notEmpty('password', 'You must enter a password', 'create')
->add('password', [
'length' => [
'rule' => ['minLength', 8],
'message' => 'Passwords must be at least 8 characters long.',
]
]);
$validator
->requirePresence('age', 'create')
->notEmpty('age');
$validator
->requirePresence('address', 'create')
->notEmpty('address');
$validator
->email('email')
->requirePresence('email', 'create')
->notEmpty('email');
$validator
->requirePresence('gender', 'create')
->notEmpty('gender');
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['email']));
$rules->add($rules->isUnique(['username']));
return $rules;
}
Userscontroller.php //register
<?php
public function register()
{
$user= $this->Users->newEntity();
if ($this->request->is('post')) {
$image_name = $this->request->data['profile_pic']['name'];
$image_tmp = $this->request->data['profile_pic']['tmp_name'];
$destination = WWW_ROOT.'img'.DS.'users'.DS.$image_name;
move_uploaded_file($image_tmp,$destination);
$this->request->data['profile_pic'] = $image_name;
$this->request->data['destination'] = $destination;
$user= $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('Data has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}
?>
User.php //Model/Entity
<?php
namespace App\Model\Entity;
use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;
/**
* User Entity.
*/
class User extends Entity
{
protected $_accessible = [
'*' => true,
'id' => false
];
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
}
?>
register.ctp
<div class="actions columns large-2 medium-3">
<h3><?= __('Actions') ?></h3>
<ul class="side-nav">
<li><?= $this->Html->link(__('List Users'), ['action' => 'index']) ?></li>
</ul>
</div>
<div class="users form large-10 medium-9 columns">
<div id="output"></div>
<?php
if ($this->request->session()->read('Auth.User.username')) {
echo"You must logout first ";
print $this->request->session()->read('Auth.User.username');
echo $this->Html->link('Logout',array('controller' =>'users','action' => 'logout'));
}else{
?>
<?php
//$this->Form->create($user, array('class' => 'insertForm'));
echo $this->Form->create($user, array('type'=>'file'));
?>
<fieldset>
<legend><?= __('Add User') ?></legend>
<?php
$date_posted = date("Y-m-d") ;
echo $this->Form->input('username');
echo $this->Form->input('email');
echo $this->Form->input('age');
$options = ['Male' => 'Male', 'Female' => 'Female'];
echo $this->Form->input('gender', array(
'options' => $options,
'type' => 'select',
//'empty' => 'Select the gender',
'label' => 'Gender')
);
echo $this->Form->input('address');
echo $this->Form->input('created',array('type'=>'hidden','value' => $date_posted));
echo $this->Form->input('password');
echo $this->Form->input('profile_pic', ['type' => 'file']);
?>
</fieldset>
<?php echo $this->Form->button('Register', ['type' => 'submit']); ?>
<?php } ?>
</div>
I'm creating a change password form in CakePHP, which requires that a user enter his/her current password, new password, and confirm new password. After all that is entered, the user's password will be changed, given that all entries follow the validation rules that are set.
However, the validation rules aren't working. The user doesn't have to fill in all of the fields, set the new password to a certain length, make sure that the new password and confirm password fields match, etc. I cant seem to find out what the problem is.
I'll provide all of the relevant code below. Thanks :)
change_password.ctp (The view file)
<div class="users form large-9 medium-9 columns">
<?= $this->form->create() ?>
<fieldset>
<legend> <?= __('Change Password') ?> </legend>
<?= $this->Form->input('current_password', ['type' => 'password']) ?>
<?= $this->Form->input('new_password', ['type' => 'password']) ?>
<?= $this->Form->input('confirm_new_password', ['type' => 'password']) ?>
</fieldset>
<?= $this->Form->button(__('Save')) ?>
<?= $this->Form->end() ?>
</div>
changePassword() in UsersController
public function changePassword()
{
$user = $this->Users->get($this->Auth->user('id'));
if (!empty($this->request->data)) {
$user = $this->Users->patchEntity($user, [
'password' => $this->request->data['new_password'],
],
['validate' => 'password']
);
if ($this->Users->save($user)) {
$this->Flash->success('The password is successfully changed');
$this->redirect('/users');
} else {
$this->Flash->error('There was an error during the save!');
}
}
$this->set('user', $user);
}
validationPassword() in UsersTable (i.e The validation rules)
public function validationPassword(Validator $validator )
{
$validator
->add('current_password','custom',[
'rule'=> function($value, $context){
$user = $this->get($context['data']['id']);
if ($user) {
if ((new DefaultPasswordHasher)->check($value, $user->password)) {
return true;
}
}
return false;
},
'message'=>'Incorrect Password!',
])
->notEmpty('current_password');
$validator
->add('new_password', [
'length' => [
'rule' => ['minLength', 6],
'message' => 'The password must be at least 6 characters!',
]
])
->add('new_password',[
'match'=>[
'rule'=> ['compareWith','confirm_new_password'],
'message'=>'The passwords does not match!',
]
])
->notEmpty('new_password');
$validator
->add('confirm_new_password', [
'length' => [
'rule' => ['minLength', 6],
'message' => 'The password must be at least 6 characters!',
]
])
->add('confirm_new_password',[
'match'=>[
'rule'=> ['compareWith','new_password'],
'message'=>'The passwords does not match!',
]
])
->notEmpty('confirm_new_password');
return $validator;
}
EDIT: Added User.php file
<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Validation\Validator;
/**
* User Entity.
*
* #property int $id
* #property string $first_name
* #property string $last_name
* #property string $email
* #property string $username
* #property string $password
*/
class User extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* #var array
*/
protected $_accessible = [
'*' => true,
'id' => false,
];
/**
* Fields that are excluded from JSON an array versions of the entity.
*
* #var array
*/
protected $_hidden = [
'password'
];
protected function _setPassword($value) {
$hasher = new DefaultPasswordHasher();
return $hasher->hash($value);
}
}
You have validation rules for fields current_password, new_password and confirm_new_password but you are only setting the field password with patchEntity that's why this validators are not called.
public function changePassword()
{
...
$user = $this->Users->patchEntity($user, [
'password' => $this->request->data['new_password'], // There is no validator defined for the field 'password'
],
['validate' => 'password']
);
...
}
In your case you must change your code with
public function changePassword()
{
...
$user = $this->Users->patchEntity($user, [
'password' => $this->request->data['new_password'], // Your actual field in db
'current_password' => $this->request->data['current_password'], // Trigger validation rule current_password
'new_password' => $this->request->data['new_password'], // Trigger validation rule new_password
'confirm_new_password' => $this->request->data['new_password'], // Trigger validation rule confirm_new_password
],
['validate' => 'password']
);
...
}
In the view file you have also forgot to pass the entity as first parameter of Form::create()
So this is my login method:
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error(__('Invalid username or password, try again'));
}
}
}
And this is how I has my password inside my User entity:
<?php
namespace App\Model\Entity;
use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;
/**
* User Entity.
*/
class User extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* #var array
*/
protected $_accessible = array(
'first_name' => true,
'last_name' => true,
'email' => true,
'username' => true,
'password' => true,
'role' => true,
'created' => true
);
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
}
I already have working user registration and it's working without problems(password is being hashed), but for some reason I can't login, it always says that
Invalid username or password, try again
But those are present in my table, here is the query:
SELECT
Users.id AS `Users__id`,
Users.first_name AS `Users__first_name`,
Users.last_name AS `Users__last_name`,
Users.email AS `Users__email`,
Users.username AS `Users__username`,
Users.password AS `Users__password`,
Users.role AS `Users__role`,
Users.created AS `Users__created`
FROM
users Users
WHERE
Users.username = 'admin' LIMIT 1
But for some reason it does nothing in my app. I guess something is wrong with the password?
Form:
<div class="users form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __('Please enter your username and password') ?></legend>
<?= $this->Form->input('username') ?>
<?= $this->Form->input('password') ?>
</fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>
AppController:
class AppController extends Controller
{
/**
* Initialization hook method.
*
* Use this method to add common initialization code like loading components.
*
* #return void
*/
public function initialize()
{
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'loginRedirect' => [
'controller' => 'Jobs',
'action' => 'index'
],
'logoutRedirect' => [
'controller' => 'Jobs',
'action' => 'index'
],
'authorize' => ['controller']
]);
}
public function beforeFilter(Event $event)
{
$this->Auth->allow(['index', 'browse', 'view', 'register']);
}
}
Found the answer here:
Login [ Auth->identify() ] always false on CakePHP 3
Summary:
Table field password was VARCHAR(45) instead of VARCHAR(255)
I'm facing trouble with my login system. I managed to register my user in my database but whenever I try to log in, it keeps prompting "Invalid email or password, try again".
This is my model:
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class UsersTable extends Table
{
public function validationDefault(Validator $validator)
{
return $validator
->notEmpty('email', 'A email is required')
->add('email', 'valid' , ['rule'=> 'email'])
->add('email', [
'unique' => ['rule' => 'validateUnique', 'provider' => 'table']
])
->requirePresence('email','create')
->notEmpty('password', 'A password is required')
->notEmpty('role', 'A role is required')
->add('role', 'inList', [
'rule' => ['inList', ['admin', 'author']],
'message' => 'Please enter a valid role'
]);
}
}
My controller:
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Event\Event;
use Cake\Network\Exception\NotFoundException;
class UsersController extends AppController
{
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow(['add', 'logout']);
}
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Invalid email or password, try again'));
}
}
public function logout()
{
return $this->redirect($this->Auth->logout());
}
public function index()
{
$this->set('users', $this->Users->find('all'));
}
public function view($id)
{
if (!$id) {
throw new NotFoundException(__('Invalid user'));
}
$user = $this->Users->get($id);
$this->set(compact('user'));
}
public function add()
{
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'add']);
}
$this->Flash->error(__('Email already existed.'));
}
$this->set('user', $user);
}
}
AppController:
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
class AppController extends Controller
{
public function initialize()
{
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'loginRedirect' => [
'controller' => 'Articles',
'action' => 'index'
],
'logoutRedirect' => [
'controller' => 'Pages',
'action' => 'display',
'home'
]
]);
}
public function isAuthorized($user)
{
if (isset($user['role']) && $user['role'] === 'admin') {
return true;
}
return false;
}
public function beforeFilter(Event $event)
{
$this->Auth->allow(['index', 'view', 'display']);
}
}
login.ctp
<div class="users form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __('Please enter your username and password') ?></legend>
<?= $this->Form->input('email') ?>
<?= $this->Form->input('password') ?>
</fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>
I think the problem comes from the AppController
Have a quick look at this : CookBook CakePHP 3.0 Example Bookmarker Part 1
The login part is here : CookBook CakePHP 3.0 Example Bookmarker Part 2
Find the similarities with your project, try to make an analogy, a relation.
Thanks guys! Managed to find the answer after referring to the tutorials. Turns out i miss out
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
All good now! Cheers =)
In version 2.2.1 I could validate a form using rules and custom messages like below. But somehow the password rule isn't working as of version 2.3. Any help what I might be doing wrong here?
Model:
class User extends AppModel {
public $validate = array(
'password' => array(
'rule' => array ('between', 5, 10 ),
'message' => 'Password must between 5 and 10 characters long'
)
);
public function beforeSave($options = array()) {
$this->data['User']['password'] = Security::hash($this->data['User']['password'], 'sha1', true);
return true;
}
}
View:
<?php
echo $this->Form->create();
echo $this->Form->input('firstname', array('label' => 'First name'));
echo $this->Form->input('lastname', array('label' => 'Last name'));
echo $this->Form->input('adminrole', array('type' => 'checkbox', 'label' => 'Is admin?<br /><br />'));
echo $this->Form->input('email', array('label' => 'E-mail address'));
echo $this->Form->input('password', array('label' => 'Password'));
echo $this->Form->input('picturethumb', array('type' => 'file', 'label' => 'Profile picture'));
echo $this->Form->end('Save');
?>
Please bare in mind that this exact same code validates correctly in 2.2.1
Controller:
class UsersController extends AppController {
public function index() {
$users = $this->User->find('all');
$this->set('users', $users);
}
public function add() {
if ($this->request->is('post')) {
$this->User->save($this->request->data);
$this->redirect('/users');
}
}
}
Try this-
public function add() {
if ($this->request->is('post')) {
$this->User->create();
if($this->User->save($this->request->data)){
$this->redirect('/users');
}else{
$this->Session->setFlash('Opps... Something is wrong');
}
}
}
I don't work with cake sometime, but I remember had this problem before. The problem is, the cakephp will create a hash of password, so when Model get password is already big. What I did in time was make another validate, like password_tmp and use it like field and create the hash by myself in controller for the real field password.