cakephp isAuthorized() not being called - php

I am trying to use the isAuthorized() method to do a check for an admin flag, but the function never seems to be called. Even when I set the function to always return false, it allows any user. It just seems like it isn't being called.
Do I need to do something more than setting $this->Auth->authorize = 'controller' ?
from /app/app_controller.php
class AppController extends Controller
{
var $components = array('Auth');
function beforeFilter()
{
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'pages', 'display' => 'home');
$this->Auth->logoutRedirect = '/';
$this->Auth->authorize = 'controller';
$this->Auth->userScope = array('User.active' => 1);
}
function isAuthorized()
{
if (strpos($this->action, "admin_") != false)
{
if ($this->Auth->user('isAdmin') == '0')
{
return false;
}
}
return true;
}
}

You should check if you're overriding your Auth settings in your other controller.
First, to verify that isAuthorized() is being called, try putting a simple debug($this); die; in it.
If it is not dying, you're probably overriding it in some other controller (you're missing the parent::isAuthorized() call).
If it's not that, then you're probably doing that same thing with beforeFilter().

Additional to the Answer of dr Hannibal Lecter, there is another possible reason if you experience this problem (as i did ...):
If your controller is named tests_controller, the startUp method of the Auth-Component aborts without starting the authentication (at least in cakePHP 1.3.10 - haven't checked 2.x). So be sure that you never name a Controller tests_controller...
Excerpt from cake\libs\controller\components\auth.php
function startup(&$controller) {
$isErrorOrTests = (
strtolower($controller->name) == 'cakeerror' ||
(strtolower($controller->name) == 'tests' && Configure::read() > 0)
);
if ($isErrorOrTests) {
return true;
}
...

you need to make sure that 'Auth' is in the components array for that controller:
$this->components[] = 'Auth';
drop that in the constructor and it should work (unless, of course, it doesn't). Good luck!

Related

CakePHP 3: Different login redirection depending on user roles

I'm using CakePHP 3 and trying to change the default route after user is logged in. I want to set default route different depends on user's role_id.
I found a solution but it's only for CakePHP 2.
I can't use it in CakePHP 3, I can't use Session component in bootstrap.
So I tried this in my AppController
public $redirects = [
'admin' => ['controller' => 'Clients', 'action' => 'statistics'],
'user' => ['controller' => 'Clients', 'action' => 'index'],
];
public function initialize()
{
parent::initialize();
...
if ($this->Auth->user())
Configure::write('Route.default', $this->redirects[$this->Auth->user('role_id')]);
else
Configure::write('Route.default', ['controller' => 'Users', 'action' => 'login']);
Router::scope('/', function($routes) {
$routes->connect('/', Configure::read('Route.default'));
$routes->fallbacks('InflectedRoute');
});
}
My default route is
$routes->connect('/', \Cake\Core\Configure::read('Route.default'));
And I defined Route.default in bootstrap.php as
Configure::write('Route.default', ['controller' => 'Users', 'action' => 'login']);
But when I open the / page I still see the users/login page even if I have already logged in
So I added the redirection before Router::scope
if (
$this->Auth->user()
&& $this->request->params['controller'] == 'Users'
&& $this->request->params['action'] == 'login'
) {
$this->redirect(Configure::read('Route.default'));
}
Could anyone help me with that?
We can check user role from session data and make redirect according the role.
We can edit in the users controllers login function as follows
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
$loggedUser = $this->request->session()->read('Auth.User');
if($loggedUser['role'] == 'customer'){
return $this->redirect('/');
}else if($loggedUser['role'] == 'admin'){
return $this->redirect('/admin');
}else{
return $this->redirect($this->Auth->redirectUrl());
}
}
}
}
My cakephp version is 3.3.8
hey i found a solution!
create an file in App\Routing\Filter like that:
<?php
namespace App\Routing\Filter;
use Cake\Event\Event;
use Cake\Routing\DispatcherFilter;
class HFilter extends DispatcherFilter {
public function beforeDispatch(Event $event) {
$request = $event->data['request'];
if (isset($request->url) && $request->url == '') {
if ($request->session()->read('Auth.User')){
$request->params['controller'] = 'Users';
$request->params['action'] = 'index';
} else {
$request->params['controller'] = 'Pages';
$request->params['action'] = 'home';
}
}
}
}
?>
after add it into the bootstrap.php file without the Filter in the name like that
DispatcherFactory::add('H');
DispatcherFactory::add('Asset');
DispatcherFactory::add('Routing');
DispatcherFactory::add('ControllerFactory');

Overriding redirect in AppController

I want to override "redirect" to insert a language prefix. For that I've added thist to AppController.php
public function redirect( $url, $status = NULL, $exit = true ) {
die(debug('$url'));
if (!isset($url['language']) && $this->Session->check('Config.language')) {
$url['language'] = $this->Session->read('Config.language');
}
parent::redirect($url,$status,$exit);
}
Obviously the die(..) is just for testing if this function is called.
My controller code:
public function add() {
if ($this->request->is('post')) {
$this->request->data['Party']['language_id'] = $this->Session->read('Config.LanguageId');
$this->Party->create();
if ($this->Party->save($this->request->data)) {
$this->Session->write('partyId', $this->Party->id);
return $this->redirect(array(
'controller' => 'parties',
'action' => 'editGuestlist',
));
} else {
$this->Session->setFlash(__('The party could not be saved. Please, try again.'));
}
}
}
I expected that "$this->redirect" in XyzController will call my public function "redirect" in AppController.
If I'm adding a party I'm getting redirected to /parties/editGuestlist no prefix is added and the code doesn't stop. So it is prety obvious that my overriding is not working. As I'm new to cakephp I'm hoping that somebody can explain this behavior to me.
UPDATE
I've found an error in /config/routes.php that fixed the behavior but I still have no clue why my overriding function isn't called at all.
I've added array('language' => '[a-z]{3}') to
Router::connect('/:language/:controller/:action/*',
array(),
array('language' => '[a-z]{3}')
);

Checking if user is logged in using CakePHP

I want to display a different navigation bar to my users based on if they're logged in or not. I have handled the registration and logging in stage, but having trouble checking if the users are logged in and displaying the correct navigation bar.
This is what I have in AppController.php:
public $components = array('Session', 'Auth' => array(
'loginRedirect' => array('controller' => 'users', 'action' => 'account'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'home')
));
public $loggedIn = false;
public function beforeFilter() {
$this->Auth->allow('home', 'register', 'login');
if ($this->Auth->user('id')) {
$this->set('loggedIn', true);
}
}
and then in my layout (not view):
<?php if ($loggedIn): ?>
logged in
<?php else: ?>
<li class="right">Register</li>
<li class="right">Login</li>
<?php endif; ?>
However, $loggedIn is always false. If do $this->set('loggedIn', $this->loggedIn); from within my individual controllers it works fine, but in an attempt to keep my code DRY I only want it in the controller that all my other controllers inherit from (AppController).
Is there an easy way to do this that i'm missing?
I know this has already been answered but I will post my findings anyway..
The way I solved this issue and made $loggedIn globally available was adding it to the AppController.php file in beforeFilter()
public function beforeFilter() {
$this->set('loggedIn', $this->Auth->loggedIn());
}
Try using:
if ($this->Auth->loggedIn()) {
For cakephp3
Controller wide:
public function beforeFilter(Event $event) {
$this->set('login_status', $this->Auth->user('id'));
}
In Template you can the check session object
$user = $this->request->session()->read('Auth.User');
Just put this code after login() action:
if($this->Auth->loggedIn()){
$this->redirect(array('action' => 'index'));
}

How to edit only their own data in CakePHP 2?

how to make the registered user can edit only their data but not others. When it was set up ACL(aro and aco).
My settings:
class User extends AppModel {
public function bindNode($user) {
return array('model' => 'Group', 'foreign_key' => $user['User']['group_id']);
}
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
You should add the isAuthorized method to your controller. In this method you check that the users are authorized for the actions they are trying to do with the parameters they are passing. You could use code like this:
switch ($this->action) {
case 'delete':
case 'edit':
// id of what they are trying to edit
$this->Topic->id = $this->params['pass'][0];
// id of the owner of what they are trying to edit
$ownerId = $this->Topic->field('user_id');
$userId = $this->Auth->user('id');
if ($ownerId == $userId) {
// allow users to edit or delete their own topics
return TRUE;
} else {
// allow admin group to edit any topic
return $this->Auth->user('group') == 'admin';
}
}
If you want to use Cake's ACL system for checking permissions rather than hard-coding checks like "user is a member of admin group", see the tutorial here: http://jonisalonen.com/2010/role-based-acl-in-cakephp/
It was written for Cake 1.3 though, I haven't checked if there are major differences.

CakePHP Validation Question with Plugin

In my CakePHP application, I have setup the PersistantValidation plugin to validate my forms on the model level thanks to a kind previous suggestion. The plugin essentially makes it so that you can use model validation on a partial without having it redirect to the underlying page (ie. the register.ctp view or the login.ctp view, for example).
The validation works great for the login form, but it's not working properly on the user registration form for some reason.
The controller looks like this:
function register() {
if(!empty($this->data)) {
$name = $this->data['User']['name'];
$email = $this->data['User']['email'];
$password = $this->Password->generatePassword();
$this->data['User']['password'] = $this->Auth->password($password);
$this->User->create();
if($this->User->save($this->data)) {
$this->Session->setFlash(__('Your account has been created!', true));
$this->redirect(array('controller' => 'users', 'action' => 'offers'));
} else {
$this->redirect($this->referer());
}
}
}
The PresistentValidation component is also properly setup and included, since it works just fine in the login() function in the same controller. When I run this code, nothing happens. There is no redirect away from the partial, which is good, but the errors don't show up. Also, the errors do show up going to the register.ctp view, which means it isn't a problem with the validations themselves.
Does anyone have any ideas?
function register() {
if(!empty($this->data)) {
$this->data['User']['password'] = $this->Auth->password($password);
if($this->User->save($this->data)) {
$this->Session->setFlash(__('Your account has been created!', true));
$this->redirect(array('controller' => 'users', 'action' => 'offers'));
} else {
$this->redirect($this->referer());
}
}
}

Categories