CakePHP mapping HTTP request to the correct action - cakephp

I have been trying to set up RESTful functionality in my app and I face a problem of whatever action I call it is router to that particular controllers index action. I have been trying to call add and view actions, but they are just not being routed properly. Here is the resposne I get when trying to call the view action:
{"code":404,"url":"\/application\/rest_customers\/54.json","name":"Action RestCustomersController::54() could not be found."}
And here is the way it is all set up in. RestCustomersController:
class RestCustomersController extends AppController {
public $uses = array('Customer');
public $helpers = array('Html', 'Form');
public $components = array('RequestHandler');
public function index() {
}
public function view($id=null){
$customer = $this->Customer->find('first', array(
'conditions'=>array('Customer.id'=> $id)));
$this->set(array(
'customer' => $customer,
'_serialize' => array('customer')
)); }}
Here are the routes:
Router::mapResources('customers');
Router::parseExtensions('json', 'xml', 'csv', 'pdf');
And here os the AppControllers beforeFitler function:
if(in_array($this->params['controller'], array('rest_customers'))){
$this->Auth->allow();
$this->Security->unlockedActions = array('add','index', 'view');
}else{
$this->Security->unlockedActions = array('add', 'edit');
$this->Auth->allow('index', 'view');
$this->set('logged_in', $this->Auth->loggedIn());
$this->set('current_user', $this->Auth->user());
}}
Any help is very much appreciated.

You are creating REST routes for a controller named Customers, but you are actually accessing a controller named RestCustomers, so what you are experiencing is the expected behavior as there simply are no REST routes connected for the RestCustomers controller.
You should either rename your controller to CustomersController, or change your mapping to use the correct name so that it will connect the routes to RestCustomersController
Router::mapResources('rest_customers');

Related

In CakePHP 2, how do you tell the Paginator component which model to use?

Given the following working example,
// ProductsController.php
<?php
App::uses('AppController', 'Controller');
class ProductsController extends AppController {
public $helpers = array('Html', 'Form');
public $components = array('Session', 'Paginator');
public $paginate = array(
'limit' => 5
);
public function index() {
$this->Product->recursive = -1;
$this->set('products', $this->paginate());
}
}
?>
What tells Paginator which model to use when it sets the variable? Currently this seems to be automatically using the Products model, but I don't really understand why. Is it just part CakePHP's magic that it selects the model that has the same name as the current controller? And if so, how would I tell Paginator to use some other model? Like if I wanted to also paginate the User model on the same page, how would I implement that?
According to Cakephp2,
$this->paginate() by default works on the current model.
if you want to use other model on the same page you can do like this:
$this->paginate('User');
You can all pass other parameters like:
$this->Paginator->settings = array(
'fields' => array('User.*'),
'order' => array('User.username' => 'asc'),
'limit' => 10,
);
$this->set('users', $this->paginate('User'));
Reference: Pagination
So, after some trial and error, it seems like by default Paginator will just use whatever model is associated with the controller via the naming conventions (the 'User' model is associated with the 'UsersController' controller, and so on).
The first argument of $this->paginate() will accept a different model if you want to use one, for example $this->paginate('Dinglehopper'), but the specified model needs to be available to the controller/action in order for it to work. In order to do that you need $this->loadModel('Dinglehopper'); inside the action where $this->paginate('Dinglehopper') is called.
So in the hypothetical situation where you want to use and paginate the model 'Dinglehopper' inside your 'Products' controller you would do,
// ProductsController.php
<?php
App::uses('AppController', 'Controller');
class ProductsController extends AppController {
public $helpers = array('Html', 'Form');
public $components = array('Session', 'Paginator');
public $paginate = array(
'limit' => 5
);
public function index() {
$this->loadModel('Dinglehopper');
$this->Product->recursive = -1;
$this->set('dinglehoppers', $this->paginate('Dinglehopper'));
}
}
?>
$this->loadModel('Dinglehopper'); makes the model 'Dinglehopper' available to the action, and then $this->paginate('Dinglehopper') returns the paginated Dinglehopper model.

Cakephp Auth login keeps redirecting to UserController->login

Simple question
Here is the Auth related code in my AppController that all my Controllers inherit from.
class AppController extends Controller {
public $components = array(
'DebugKit.Toolbar',
'Session',
'Auth'=>array(
//destination after logging in, or auto friendly fowarding depending on what user was trying to access
'loginRedirect'=>array('controller'=>'Access', 'action'=>'login'),
'logoutRedirect'=>array('controller'=>'Access', 'action'=>'logout'),
'authError'=>'You cannot access that page', //Error message whenever someone access a page without auth
'authorize'=>array('Controller') //Where in our application that authorization will occur
)
);
Here is my Access Controller that is supposed to control the logins and logouts
class AccessController extends AppController {
public $helpers = array('Html', 'Form', 'Session', 'Js' => array('Jquery'));
public function index() {
echo "index";
}
public function login() {
$this->layout = 'login';
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash('Your username/password combination was incorrect');
}
}
}
public function logout() {
$this->redirect($this->Auth->logout());
}
Anytime I try to access a page so that the login page is prompted, the browser gives me an error:
The action login is not defined in controller UsersController
Now I am using UsersController for some other purpose (not for logging in and logging out) which is why i specified the AccessController in my AppController for the login/logout redirects.
Why is trying to pull up UsersController?
I think i have fixed it. This website supports my claim
http://boulderinformationservices.wordpress.com/2013/04/25/cakephp-logoutredirect-is-not-the-same-as-loginaction/
I had to add a loginAction to my Auth array to lead to the login screen. Apparently loginRedirect is not what I thought it was.
class AppController extends Controller {
public $components = array(
'DebugKit.Toolbar',
'Session',
'Auth'=>array(
//destination after logging in, or auto friendly fowarding depending on what user was trying to access
'loginRedirect'=>array('controller'=>'access', 'action'=>'login'),
'loginAction'=>array('controller'=>'access', 'action'=>'login'),
'logoutRedirect'=>array('controller'=>'access', 'action'=>'logout'),
'authError'=>'You cannot access that page', //Error message whenever someone access a page without auth
'authorize'=>array('Controller') //Where in our application that authorization will occur
)
);

CakePHP: using a different users table

After setting up the simple Cakephp login concept I would like to let CakePHP use a different table to check the users and the login. I can't figure out how to change the table name within the Auth-component.
Below my basic Controller. How can I let Cakephp know it has to look into a different database table?
class AppController extends Controller {
public $components = array(
'Session',
'Auth'=>array(
'loginRedirect'=>array('controller'=>'users', 'action'=>'index'),
'logoutRedirect'=>array('controller'=>'users', 'action'=>'index'),
'authError'=>"You can't access that page",
'authorize'=>array('Controller')
)
);
public function isAuthorized($user) {
return true;
}
public function beforeFilter() {
//$this->Auth->allow('index', 'view');
$this->set('siteCategory', 'home');
$this->set('logged_in', $this->Auth->loggedIn());
$this->set('current_user', $this->Auth->user());
}
}
Best Solution:
This is something that's done in the User model with the useTable property.
I.e. in app/Model/User.php you should have something like this:
class User extends AppModel {
public $useTable = 'table_name';
//... rest of Model stuff here
}
Alternative:
Alternatively you can specify a different model to be used for the user, although I don't think that's what you're asking for. If I'm wrong there though, just set the userModel value like this:
public $components = array(
'Auth'=>array(
'authenticate'=>array(
'Form' => array('userModel' => 'ADifferentUserModel')
)));

CakePHP Auth Deny Admin Routing Pages

I have been reading Stack Overflow questions all afternoon trying to figure this out..
I have a users controller with index/login/logout/register functions but also has admin_index/admin_add/admin_edit/admin_delete etc.
I have Auth component enabled and in my users_controller i am trying to deny access to the admin_* pages if the Auth.User.role != 'admin', when i enable the $this->Auth->authorize = 'controller'; it denies access to the site.com/admin/users/ page and also seems to kill the logout function even tho my account has the role set to admin.
However if i type the url in i get redirected back to the main homepage.
users_controller.php
<?php
class UsersController extends AppController {
var $name = 'Users';
function beforeFilter(){
parent::beforeFilter();
$this->Auth->authorize = 'controller';
$this->Auth->allow('register');
}
function isAuthorized() {
if ($this->Auth->user('role') != 'admin') {
$this->Auth->deny('admin_index','admin_view', 'admin_add', 'admin_edit','admin_delete');
}
}
app_controller.php
<?php
class AppController extends Controller {
var $components = array('Auth', 'Session');
function beforeFilter() {
$this->Auth->loginAction = array('controller'=>'users','action'=>'login', 'admin'=>false);
$this->Auth->logoutRedirect = array('controller'=>'users','action'=>'logout');
$this->Auth->loginRedirect = array('controller'=>'shows', 'action'=>'index');
$this->Auth->autoRedirect = false;
$this->Auth->allow('home');
}
My Second question relates to the way $this->Auth->deny('page'); redirects the user, as far as i can tell it redirects to / but i need it to redirect back to the users controller.
Hope it all makes sense and i have provided enough info..
The root of your problem is probably your isAuthorized() method. This should simply return true or false, and indicates whether an authenticated user is AUTHORIZED to access a particular action.
It's difficult to say why you'd be redirected to the home page instead of the login page. But it's possible that you have other code somewhere that's messing things up.
Try modifying your code as below and see if that doesn't help get things working:
app_controller.php
<?php
class AppController extends Controller {
var $components = array('Session', 'Auth' => array(
'loginAction' => array('controller'=>'users','action'=>'login', 'admin'=>false),
'logoutRedirect' => array('controller'=>'users','action'=>'logout'),
'loginRedirect' => array('controller'=>'shows', 'action'=>'index'),
'autoRedirect' => false,
'authorize' => 'controller'
);
function beforeFilter() {
$this->Auth->allow('home');
}
function isAuthorized() {
if (!empty($this->params['prefix']) && $this->params['prefix'] == 'admin') {
if ($this->Auth->user('role') != 'admin') {
return false;
}
}
return true;
}
?>
users_controller.php
<?php
class UsersController extends AppController {
var $name = 'Users';
function beforeFilter(){
parent::beforeFilter();
$this->Auth->allow('register');
}
?>
I moved all the Auth settings to the declaration in the $components variable because it seems cleaner and to make more sense to declare default values there. But this is more a matter of personal preference and it shouldn't have a real effect on the code's functioning.
Also, note that if you set autoRedirect to false, you'll have to redirect logged-in users manually in your Users::login() action, getting the loginRedirect value with $this->Auth->redirect().
I don't see any reason why you should be sent to / when you're not logged in and you try to access a blocked action, but maybe it will be easier to figure out after you fix the above. **
you should do this like...
function beforeFilter()
{
if($this->Auth->user('role')=='admin'){
$this->Auth->allow('admin_view','admin_controls');//put your all admin actions separated by comma
}
else
{
$this->Auth->allow('home');//put your all non-admin actions separated by comma
}
}
hope it will work... if any problem let me know....

CakePhp ACL permissions

Checking my application, I saw that every user can access to all the actions in it.
I'm using cakePhp build-in ACL Component...
Checking permissions through terminal displays correctly is the user is allowed or not to call a certain action. But once I'm checking the application on the browser all users have access to every action. Any clue what could be doing this?
You can have CakePHP automatically handle things for you if you're using the built-in Auth and ACL components. To start, you can make sure you have an app_controller.php file in the App folder. Mine looks something like this:
<?php
class AppController extends Controller {
var $helpers = array('Form', 'Html', 'Javascript', 'Time');
var $components = array( 'Acl', 'Auth', 'Session', 'Cookie');
function beforeFilter() {
$this->Auth->authorize = 'actions';
$this->Auth->actionPath = 'controllers/';
$this->Auth->authError = ' Access Denied!';
$this->Auth->loginRedirect = '/registrations';
$this->__checkAuth();
}
private function __checkAuth() {
$currentUser = $this->Auth->user();
$currentUser = $currentUser['User'];
$this->set(compact('currentUser'));
}
}
?>
If you're authorizing 'actions' then try including that code in your app_controller.php file, or create one if you don't already have one. Then start browsing to see if it has made any changes.
If you have custom code in each controller's beforeFilter, you'll also need to add a single line of code to each controller.
function beforeFilter(){
parent::beforeFilter();
}
Any beforeFilter (even a blank one) placed in a controller will override the beforeFilter of the AppController unless you specifically call the AppController's beforeFilter using the code above.
You can also find some of the best tutorials on using CakePHP's ACL here: http://aranworld.com/article/161/cakephp-acl-tutorial-what-is-it

Resources