How to login with an element in CakePHP? - cakephp

Currently I have a functional login procedure. My users go to a specific login view, type their username and password, access and are redirected to a specific dashboard.
In my users controller:
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect();
}
$this->Session->setFlash('Incorrect user or password.');
}
}
The login view:
<h1>Access with your username:</h1>
<?php
echo $this->Form->create('User', array('action' => 'login'));
echo $this->Form->input('username', array('label' => 'User:'));
echo $this->Form->input('password', array('label' => 'Password:'));
echo $this->Form->end('Login');
?>
The issue came when I was asked to add some login fields directly in my main menu. So I tried adding them as an element in my header. It didn't work.
The element I'm adding in my header:
<div>
<?php
echo $this->Form->create('user', array('action' => 'login'));
echo $this->Form->input('username', array('placeholder' => 'User', 'label' => false));
echo $this->Form->input('password', array('placeholder' => 'Password', 'label' => false));
echo $this->Form->submit('Ingresar', array('div' => true));
echo $this->Form->end();
?>
</div>
I enter username and password and click the "login" button. It throws me the "Incorrect user or password." error message and redirects me to the view for the login action (without login in the user).
In there, one can successfully login without further issue, but the point was to reduce by 1 the needed clicks for the action.
What am I missing? What should I change/add/move?

In your second html form, the model User is not typed as it should be
change
echo $this->Form->create('user', array('action' => 'login'));
To
echo $this->Form->create('User', array('action' => 'login'));
Note the u changed to U from the model name

Related

Calling a element after login

I have a post index view calling a element which content input field for comment.
I call it in this way
<?php echo $this->element('addcomment', array('post_id' => $post['Post']['id'])); ?>
This work fine, I pass the post id parameter, in the addcomment element, because the post_id input field is hidden in the addcomment. and of course I dont want that the user type the post id.
I have set up the authorization mechanism in order to allow adding comment to the user identified (connected).
When a non-connected user try to add a comment, he receives the login screen.
After login, he is redirected to the add commment form. The problem is that in the mean time it loose the value of the post_id variable.
Rem: If the user is connected before adding comments to the post, it works.
Dont hesitate to contact me in case my explanation is not clear or if you need more information.
This is my addcomment element
<div class="Addcomment form">
<?php
echo $this->Form->create('Comment', array(
'url' => array('controller' => 'comments', 'action' => 'add')
)); ?>
<fieldset>
<legend><?php echo __('Add Comment'); ?></legend>
<?php if (isset($current_user['id']) && isset($post_id)): ?>
<?php $this->request->data['Comment']['user_id'] = $current_user['id']; ?>
<?php $this->request->data['Comment']['post_id'] = $post_id; ?>
<?php echo $this->Form->input('post_id', array('type' => 'hidden')); ?>
<?php echo $this->Form->input('user_id', array('type' => 'hidden')); ?>
<?php else: echo $this->Form->input('post_id'); ?>
<?php endif; ?>
<?php echo $this->Form->input('content', array('class' => 'comment')); ?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
As per i understand your problem. You can use a session variable to store a post id which should not affected if user logs in. And using this session you can redirect a user to particular post after login.
Set a session value before redirecting user to login.
$this->Session->write('last_post_id',YOUR_POST_ID);
Redirect user to the post if user successfully logged in and if you find a session value not empty.
if ($this->Session->check('last_post_id') && $this->Session->read('last_post_id') != '') {
$this->redirect(YOUR_URL_TO_POST . '?postid=' . $this->Session->read('last_post_id'));
exit;
}else{
//NORMAL REDIRECTION
}
Hope this will help you. Unset session last_post_id after redirection and if no longer required.

CakePHP login function for ajax call

So here is situation:
I'm using Js helper to create ajax login form in CakePHP and this is placed in my view:
<?php
$data = $this->Js->get('#UserLoginForm')->serializeForm(array('isForm' => true, 'inline' => true));
$this->Js->get('#UserLoginForm')->event(
'submit',
$this->Js->request(
array ('controller' => 'users', 'action' => 'login'),
array (
'update' => '#messagediv',
'before' => '$("#loading").fadeIn()',
'complete' => '$("#loading").fadeOut()',
'data' => $data,
'async' => true,
'dataExpression'=>true,
'method' => 'POST',
)
)
);
?>
Then below this I have my form included and below form I have:
<?php echo $this->Form->create('User');
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->end('submit);
?>
<?php echo $this->Js->writeBuffer(); ?>
Now I don't know how to make proper function in controller to check for login and redirect if successfull or display error if not..
I was able to make something that check for login and echo 1 if login deatils are correct and echo 0 if not but whenever I try to use redirect in controller function it just load "whole login page" in div #messagediv...
This is how my controller action looks now:
public function login() {
if ($this->request->isAjax()) {
$this->layout = 'ajax';
if ($this->Auth->login()) {
$this->Session->setFlash('Login Successfull');
} else {
$this->Session->setFlash('Login Incorrect');
}
}
}
Can anyone tell me what I'm doing wrong?
So how to redirect after login successfull and how to output error message to #messagediv if wrong username or pw?
If I understand correctly what you're trying to do (load only the flash message and not the whole page), change your action like this:
public function login() {
if ($this->request->isAjax()) {
$this->layout = 'ajax';
if ($this->Auth->login()) {
$this->Session->setFlash('Login Successfull');
$this->redirect('wherever');
} else {
$this->Session->setFlash('Login Incorrect');
$this->render('messagediv');
}
}
}
Then create a View at View/Users/messagediv.ctp that only contains echo $this->Session->flash();
There might be other ways of doing this that might be better, though I'm not sure depending on your exact use for it. This should solve what you're trying to do (if I'm not mistaken).
Try adding RequestHandler to your $components array.
var $components = array("RequestHandler");

Multiple form with same model name on single page cakephp

I have two form on a single page: login form and register form. When I submit the register form, it validates both: form fields that are in login and registeration. How can I handle it if both form have the same model (user model)
Register form
<?php echo $this->Form->create('User', array('url' => array('controller' => 'users', 'action' => 'add'))); ?>
<?php echo $this->Form->input('username', array('label' => false, 'div' => false, 'class' => 'reg_input'));?>
<?php echo $this->Form->input('email', array('label' => false, 'div' => false, 'class' => 'reg_input'));?>
<?php echo $this->Form->input('password', array('label' => false, 'div' => false, 'class' => 'reg_input'));?>
<?php echo $this->Form->input('confirm_password', array('type' => 'password', 'label' => false, 'div' => false, 'class' => 'reg_input'));?>
<?php echo $this->Form->submit(__('Submit', true), array ('class' => 'reg_button', 'div' => false));
echo $this->Form->end();?>
and Login form is below
<?php echo $this->Form->create('User', array('controller' => 'users', 'action' => 'login'))?>
<?php echo $this->Form->input('User.username',array('label'=>false,'div'=>false, 'class' => 'reg_input'));?>
<?php echo $this->Form->input('User.password',array('label'=>false,'div'=>false, 'class' => 'reg_input'));?>
<?php echo $this->Form->submit(__('Log in', true), array ('class' => 'reg_button', 'div' => false)); ?>
<?php echo $this->Form->end();?>
When I submit registration form it validates both forms, I want to validate only the registration form.
How can I handle that?
I've come up with a "solution" (I find the approach dirty, but it works) for a different question (very similar to this). That other question worked with elements and views, though. I'll post the entire solution here to see if it helps someone (though I rather someone else comes with a different approach).
So, first: change the creation names for the two forms.
//for the registration
<?php echo $this->Form->create('Registration',
array('url' => array('controller' => 'users', 'action' => 'add'))); ?>
//for the login
<?php echo $this->Form->create('Login',
array('controller' => 'users', 'action' => 'login'))?>
The forms should work, look and post to the same actions, so no harm done.
Second step: I don't have your action code, so I'm going to explain what needs to be done in general
public function login() {
if ($this->request->is('post')) {
//we need to change the request->data indexes to make everything work
if (isset($this->request->data['Login'] /*that's the name we gave to the form*/)) {
$this->request->data['User'] = $this->request->data['Login'];
unset($this->request->data['Login']); //clean everything up so all work as it is working now
$this->set('formName', 'Login'); //we need to pass a reference to the view for validation display
} //if there's no 'Login' index, we can assume the request came the normal way
//your code that should work normally
}
}
Same thing for the registration (only need to change 'Login' to 'Registration').
Now, the actions should behave normally, since it has no idea we changed the form names on the view (we made sure of that changing the indexes in the action). But, if there are validation errors, the view will check for them in
$this->validationErrors['Model_with_errors']
And that 'Model_with_errors' (in this case 'User') won't be displayed in the respective forms because we've changed the names. So we need to also tweak the view. Oh! I'm assuming these both forms are in a view called index.ctp, for example, but if they are on separate files (if you're using an element or similar) I recommend add the lines of code for all the files
//preferably in the first line of the view/element (index.ctp in this example)
if (!empty($this->validationErrors['User']) && isset($formName)) {
$this->validationErrors[$formName] = $this->validationErrors['User'];
}
With that, we copy the model validation of the User to the fake-named form, and only that one. Note that if you have a third form in that view for the same model, and you use the typical $this->form->create('User'), then the validation errors will show for that one too unless you change the form name for that third one.
Doing that should work and only validate the form with the correct name.
I find this a messy approach because it involves controller-view changes. I think everything should be done by the controller, and the view shouldn't even blink about validation issues... The problem with that is that the render function of Controller.php needs to be replaced... It can be done in the AppController, but for every updgrade of Cakephp, you'll have to be careful of copying the new render function of Controller.php to the one replacing it in AppController. The advantage of that approach, though, is that the "feature" would be available for every form without having to worry about changing the views.
Well, it's just not that maintainable anyway, so better to leave it alone if it's just for this one case... If anyone is interested on how to handle this just in the controller side, though, comment and I'll post it.
You can duplicate your model and change his name and define $useTable as the same table name.
Example :
class Registration extends AppModel {
public $useTable = 'users';
You define the action in form->create like Nunser for your login form
<?php
echo $this->Form->create('User',array(
'url' => array(
'controller' => 'Users',
'action' => 'login',
'user' => true
),
'inputDefaults' => array(
'div' => false,
'label' => false
),
'novalidate'=>true,
));
?>
and your registration form
<?php
echo $this->Form->create('Registration',array(
'url' => array(
'controller' => 'Users',
'action' => 'validation_registration',
'user' => false
),
'inputDefaults' => array(
'div' => false,
'label' => false
),
'novalidate'=>true,
));
?>
In your controller define a method for registration validation and the most important define the render
public function validation_registration(){
$this->loadModel('Registration');
if($this->request->is('post')){
if($this->Registration->save($this->request->data)){
--- code ---
}else{
--- code ---
}
}
$this->render('user_login');
}
Sorry for my english ! Have a nice day ! :D
The create method on your login form is missing the 'url' key for creating the action attribute. I tried to re-create this once I fixed this and could not. Maybe that will fix it?

Disable specific divs in CakePHP based on page selected

I'm new with CakePHP and I need your assistance. I need to display a specific widget which is in the form of a div on a specific page i.e. my homepage and disable on the rest of the pages. Essentially I have been able to specifically display specific divs based on log in status as indicated below:
<?php if (!$this->Session->read('Auth.User.id')): ?>
<div class="register link right <?php if ($active == 'register') echo 'active'; ?>"><?php echo $html->link('Register', array('controller' => 'users', 'action' => 'register')); ?></div>
<div class="login link right <?php if ($active == 'login') echo 'active'; ?>"><?php echo $html->link('Login', array('controller' => 'users', 'action' => 'login')); ?></div>
<?php else: ?>
<div class="logout link right"><?php echo $html->link('Logout', array('controller' => 'users', 'action' => 'logout')); ?></div>
<div class="myaccount link right <?php if ($active == 'myaccount') echo 'active'; ?>"><?php echo $html->link('My account', array('controller' => 'account', 'action' => 'summary')); ?></div>
<?php endif; ?>
I was asking for any help with regards to displaying a specific div based on the selection of my homepage.
The pseudocode below indicates my the line of thinking I'm taking to solve this issue:
<?php if (the selected page is homepage or default.ctp)?>
// set the display property for the desired div to none
<?php else: ?>
// do not set the display property for the desired div to none
<?php endif; ?>
In cakephp you cannot use directly $this->Session->read('Auth.User.id') in your view is bettere to do this into your controller:
$this->set('authUser', $this->Auth->user());
and into your view
if (!$authUser)
{
//not logged
}
else{
//logged
}
And if you wanna check which is the page you can try something like that
echo Router::url($this->last, true);
Is what you want?
In your controller you can define something like:
$this->set('pageName', $pageName);
Then you can do in your view:
$class='';
if($pageName=='homepage') {
$class=' hide';
}
echo $this->Html->div($class, 'your content here');
Also think about why you need a structure of this in your view. Maybe you can just not supply the content if it is not needed to the view? So you make the decision in your controller. That makes most of the time more clean views and the smallest amount of data needed in your view.

CakePHP login, password field returns hashed password?

When I enter username and password on a login form, it doesn't redirect to the $loginRedirect path and show the login form again with the password field filled with the hashed password in the database for that username!
I use thew Auth component and the sign_me_up plugin.
This is file login.ctp:
<?php
if($session->check('Message.Auth'))
$session->flash();
echo $form->create('User',array('action'=>'/login'));
echo $form->input('username');
echo $form->input('password');
echo $form->end('login');
?>
and this is beforeFilter()
function beforeFilter(){
$this->Auth->loginRedirect = array('controller' => 'posts', 'action' => 'index');
}
The login problem is just for / in action.
It is usually good to empty password field for every failed submission attempt, you can do so by
echo $form->input('password', array('value' => false));
I asked a similar question (to my answer) a while back:
CakePHP: Clearing password field on failed submission

Resources