Cake php and using auth in layout - cakephp

I am using auth component and it works ok.
But in my default layout before the content I have some menu which is different if user is logged in. So I want to determine if user is logged in or not - normally I use $this->Auth->user('id') but $this->Auth doesnt work in layout (it only works in view which controller is using Auth component).
How to do it?

In beforeRender() just call
$this->set('userData', $this->Auth->user());
and set the data to the view and do your checks in the view.
In order to get data in layout, you should call beforeRender() method in AppController.
Passing it through session is not a good idea IMHO. It might be not the usual case but at least I prefer to do things solid: If you're using the session for that your code will fail in a system that is not using a session (stateless auth). Overall I'm not a big fan of accessing the session in a view at all. Session is for me more like a datasource.

You can read Auth data from session. Something like:
$user = $session->read('Auth');
Don`t forget to add Session helper in your AppController.
var $helpers = array('Session');

Related

Setting permissions in cakephp Pages controller

I followed Andrew Perkins excellent tutorial on setting up permissions in CakePHP 2.0.
My question, however, relates to how to use the allow and deny method in the Pages controller. Currently I have $this->Auth->allow('display') which allows all methods in the Pages controller to be view.
What if I only want the home page allowed but the rest denied? How do I code that?
Thanks in advance.
Make sure you have copied the PageController.php to your app/Controller folder. Then, add a beforeFilter callback method and set access based on the passed page parameter:
public function beforeFilter() {
// Use $this->request->pass to get the requested page name/id
// Decide on access with $this->Auth->allow()
}
This should solve your problem.
You can find more information on request's lifecycle in CakePHP manual. That's pretty useful stuff.
Have you tried this code?
You can out it into your PageController or into your Controller directly
$views = array ('index'); //array of view that you want allow
$this->Auth->allow($views);

Putting ajax and non-ajax actions in the same controller in CakePHP

I've run into a problem in my CakePHP app as a result of adding some ajax actions.
My table is called orders so obviously my controller is called OrdersController and the model is called Order
It is my understanding of CakePHP's best practices that if I am going to run any logic on the Order model, that it should be done in the OrdersController. This is fine for the basic CRUD stuff but now that some of my views need to send ajax requests to manipulate Order data I have a problem.
The problem is that for ajax to work properly, I have to put this at the beginning of the OrdersController
var $layout = 'ajax'; // uses an empty layout
var $autoRender=false; // renders nothing by default
Then, to stop the security component interfering with my Ajax form submissions, I also need this:
public function beforeFilter() {
parent::beforeFilter();
$this->Security->csrfUseOnce = false;
$this->Security->csrfExpires = '+1 hour';
}
None of this would be a problem if the controller was only being used for Ajax requests, but the problem is that it's being used for regular Cake actions too.
Is the answer that I should have two controllers? One for regular actions and one for ajax actions? This doesn't seem to be mentioned in the Cake docs and it doesn't seem like a very efficient way of doing things.
I know I can change the layout and possibly the auto-render setting on a per-action basis, but I don't see how it's possible to do this with the csrf settings, which need to be in the beforeFilter.
No need for a separate controller. Use cakes request handler. In your controller method, you can test if it's an Ajax request.
if ($this->request->is('ajax')) {
//set to Ajax layout and security settings, etc
You'll need to include the request handler component at the top of your controller:
public $components = array('RequestHandler');
See this page in the cook book For more info: http://book.cakephp.org/2.0/en/core-libraries/components/request-handling.html

Getting associated models with $this->Auth in Cakephp

I am using CakePHP 2.0's integrated Auth component.
I have the following tables :
Users
Groups
Profiles
My model relations are as follows:
User belongsTo Group
User hasMany Profiles
While logged in to the site, I noticed the Auth session contains only User table information, but I need the information of Groups and Profiles tables too for the logged in user.
Is there any way to do that with the Auth component?
There is no way to do this with the AuthComponent because of the way it handles the session keys. You can, however, just save it to the session yourself.
The only way to do this is to add to the session when the user logs in:
function login() {
if ($this->Auth->login($this->data)) {
$this->User->id = $this->Auth->user('id');
$this->User->contain(array('Profile', 'Group'));
$this->Session->write('User', $this->User->read());
}
}
Then in your beforeFilter() in your AppController, save a var for the controllers to get to:
function beforeFilter() {
$this->activeUser = $this->Session->read('User');
}
// and allow the views to have access to user data
function beforeRender() {
$this->set('activeUser', $this->activeUser);
}
Update: As of CakePHP 2.2 (announced here), the AuthComponent now accepts the 'contain' key for storing extra information in the session.
As far as I'm aware the Auth component only caches the data from your Users model. You can use that information to retrieve the desired data from the other models, by for example using this in your controller:
$group_data = $this->Group->findById($this->Auth->user('group_id'));
Or
$profile_data = $this->Profile->findByUserId($this->Auth->user('id'));
But I don't think you can get it from the Auth component directly, as it doesn't cache the related model data out of the box.
Two ways:
1) Extend the FormAuthenticate class (see /Controller/Component/Auth) or whatever you use to login and override the _findUser() method and tell the Auth component to use this authorize class. See this page how to do all of that http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
2) Simply implement a method in the model that will fetch all data you want and call it in the login method of your controller and write the data into the session. IMO it is handy to have such a method because sometimes you need to refresh the session data anyways.
Because of your comment on the other answer:
You will have to write a method and some code in a model that will return you the data. CakePHP can't read your mind and a database without code. No matter which of both suggested ways you're going to use, you'll have to write code.

CakePHP Spark Plug auth plugin causing redirect loops

I am attempting to use the auth plugin Spark Plug on a new CakePHP 1.3 app at http://sandbox.andrewcroce.com. It is easy enough to set up, but for some reason I am getting redirect loop errors when trying to access anything other than the Users controller.
The plugin successfully allows you to register and login, the database appears to be written correctly. Confirmation emails are sent, and the verification link seems to activate a new user. However I am unable to access any page or controller, other than the Users controller. The result is a redirect loop where http://sandbox.andrewcroce.com/errors/unauthorized is repeatedly requested.
For me this raises 2 questions: if I am logged in successfully, why is it trying to direct me to the unauthorized page? and why the heck does it keep redirecting to iself?
I wonder if this is a configuration setting I am not understanding in the spark plug config, but there isn't much explanation in the comments about what these settings do.
Any help would be appreciated.
I'm not sure about the Spark Plug specifics, but whenever you activate the Auth component you need to make sure you specify which actions are allowed for non-authenticated users, or else any requests for the action will be redirected to whatever your error action is. And then, if you error action isn't allowed, it will throw an error, sending you to... you guessed it, your error action, over and over.
Inside every controller, you need something inside your beforeFilter() method like this:
function beforeFilter() {
parent::beforeFilter();
// Allow all actions
$this->allow(*);
// Only allow view and index
$this->allow('view', 'index');
}
If you don't run the allow() method, you're saying that none of the actions should be available to non-authenticated users. In particular, if you put allow('unauthorized') in your ErrorsController class, the unauthorized action wouldn't redirect in a loop.
There is a table called "user_group_permissions" on spark_plug, for instance if you want to access a controller nameed "posts" and the action "sortBy" (http://localhost/posts/sortby/) then you need to add that permission to the table like this:
INSERT INTO `user_group_permissions` ( `user_group_id`, `plugin`, `controller`, `action`, `allowed`) VALUES
( 3, '', 'posts', 'sortBy', 1)
For this specific case the user_group_id number 3 is "Guest", in other words everybody will be able to access that action in the controller

CakePHP global variables in model

I am making one CakePHP project with Auth component. When I log in I got Session variable with user data. At the moment I am using this variable in controllers to pass data to the model.
$user = $this->Session->read('Auth');
$costs = $this->Posts->get_quartal_cost($user, $quartal, TRUE);
As I am using this in many controllers/models I am thinking that this is not DRY approach, so I wanted to make it better - something in AppModel(?)
Do you have some advice how to do that better?
Thanks
You could use the beforeFilter event in your AppController and do something like this:
public function beforeFilter()
{
if ( $this->Session->check('Auth') )
Configure::write('Auth', $this->Session->read('Auth'));
}
From anywhere in your controllers, models and even views, you'll be able to access it by using echo Configure::read('Auth');. See the Configuration class documentation for more information.

Resources