I have had installed and configured a new CakePHP 2.4 instance. Now I wanted to implement the AuthComponent. I have had implemented the component exactly as in recent projects, too. Now I have the problem that I get the error message Missing Controller: SteadinessController. But Steadiness is the project name. I'm confused haha.
The URL I want to open is http://localhost/steadiness/users/view/2 and I will be redirected to http://localhost/steadiness/steadiness/users/login. The controller and action invoked is correct but the second steadiness is false.
Thanks a lot for help.
Alex
Can you post the code where you try to direct the user to this url?
I'm guessing it's a redirect to do with the Auth component.
In your AppController when you set up Auth there should be something similar yo:
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => '/',
'logoutRedirect' => '/',
'authorize' => 'controller',
'unauthorizedRedirect' => '/'
)
);
The loginRedirect tells Cake where to send users after login who went directly to the login page (they didn't try to access a restricted link whilst not logged in).
The logoutRedirect tells Cake where to send users after logout.
The unauthorizedRedirect tells Cake where to send logged in users that try to access a link that they do not have the priveleges for (e.g. a non-admin tries to delete an account - only admins should be able to do that).
If one of these is not set then when Cake tries to use it you get redirected to '/{app-directory}' which is NOT the same as '/'.
This is most likely why your url has the domain appear twice - so Cake thinks it is looking for a controller with the same name as your domain.
Related
Basically, i'm using a standard Yii2 set up. i have a login that allows a user to see links to files. the files are in a download folder.. but the page to see the links is only able to be seen if a user is "not guest." now, if anyone just copies the link to someone else, that other person will be able to download the file without being logged in. the files in question aren't being "paid for" BUT i am required to have people login before they are allowed to download them becuase of terms of service and other laws. can i dynamically create download links via php? at least check for "isGuest" and if isGuest = True then redirect to login page. how would i do that instead of just having a direct download link?
You can provide acces to an specific action to specific roles or users with AccessControl Class .
You can do something like this:
class DownloadController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => false,
'actions' => ['download'],
'roles' => ['?'],
],
],
],
];
}
// ...
}
'?' Role are the guest users.
You can add a check in your controller's action to validate if the user is logged in or not, using:
Yii::$app->user->getIsGuest();
Look at the documentation for more details: Yii2 web user
Forbid access for anyone to the file to direct download. You can do so with htaccess or by putting the download folder into yiis protected folder. Now you need a download action in a controller where you check if the user is guest or logged in. If ok, simply pass the file through from your filesystem and to the users browser. phps readfile can help you here.
I am completely and utterly lost on how to do this. I have 3 different roles : Admin, Staff and Donors. My problem is that It really gets confusing(for me anyway) with permissions and as well as appropriate redirections, should an unauthorized user tries to access an action from the URL.
In my UsersController I have the following actions
admin_index
admin_add
admin_edit
admin_view
admin_delete
non-prefixed actions
login
logout
view
add
edit
The admin should be allowed to access all admin-prefixed actions as well as login and logout, whilst the staff and donor
should only be able to access the latter 5. Also note that all users are using the same login form.
In my AppControlles's component I have the following :
'Auth' => array(
'loginRedirect' => array(
'controller' => 'donors',
'action' => 'index'
),
'logoutRedirect' => array(
'controller' => 'users',
'action' => 'login'
),
'authorize' => array('Controller')
)
However, In my login action I check for the user role to change the loginRedirect accordingly :
if($this->request->is('post')){
if($this->Auth->login()){
switch($this->Auth->user('role')){
case 'admin':
$this->Auth->loginRedirect = array('controller'=>'users','action'=>'admin_index','prefix'=>'admin','admin'=>true);
break;
case 'donor':
...
break;
case .....
}
}
}
Question 1
Now, if a current user with a role of donor is logged in, and tries to access localhost/sitename/admin/users/add he is redirected to admin/donors rather then just /donors . So how am I able to remove the admin prefix ?
Question 2
Also I do not fully understand hwo $this->Auth->allow(), works.. If In my donorsController I want to control the access to the controllers action according to roles, how can I do it? So for instance, If there is the 'delete' action in my donorsController, How will I be able to permit the staff user whilst denying the donor user to access the delete action. I believe the beforeFilter is the solution, but can't find how to do it! Any pointers ?
Thanks
1) In your login() action impelement a check for the user role, if the role is admin redirect to whatever controller/action and set the admin prefix. If hes not an admin redirect him to something else.
if ($this->Auth->login()) {
if ($this->Auth->user('role') === 'admin') {
$this->redirect(array(
'admin' => true,
'controller' => 'foo',
'action' => 'bar')));
} else {
// Do something else, another redirect or whatever
}
}
There is no need to remove the /admin from the URL as it should show the user hes not authorized when he tries to access an URL he is not allowed to.
2) If you want to grant access for different roles you can use the SimpleRbacAuth I've written. Check the tests for examples of how it works. You simply define a nested array structure and add the roles you want to an action or a whole controller or grant access to everyone by using *.
This may be a solution for you.
Go to the core.php file and uncomment if present/add if not present the below line.
Configure::write('Routing.prefixes', array('admin'));
Location: app/config/core.php
Put the below code inside the beforeFilter method of AppController.php (cake version 2.X) / app_controller.php (cake version < 2.X)
function beforeFilter(){
if($this->Auth->user('role') == 'admin'){
if(!in_array($this->params['action'],array('login','logout')) && (stristr($this->params['action'], 'admin_') === FALSE)){
$this->redirect(array("controller"=>$this->params['controller'],"action"=>'admin_'.$this->params['action'],"admin" => 1));
}
}else{
if(stristr($this->params['action'], 'admin_')){
$action = explode('_',$this->params['action']);
$this->redirect(array("controller"=>$this->params['controller'],"action"=>$action[1],"admin" => false));
}
}
}
Rest of the functionality you can manage by handling the custom error page.
You can refer to Customize error pae
I have a CakePHP 2.3 setup with the following route:
Router::connect('/contact', array('controller' => 'old_layout', 'action' => 'contact'));
In my AppController, I define
public $components = array(
'Security'...
);
In OldLayoutController, in the beforeFilter() function I define:
$this->Security->allowedControllers = array('OldLayout');
In the view for old_layout/contact, I generate the form using the Form->create() and end() functions and regular Form::input()... commands.
When I submit the form at /contact, I get the following message:
The request has been black-holed
Error: The requested address '/[domain].com/contact' was not found on this server.
Thing is, I do the exact same thing for another form in a different controller which works perfectly.
After much debugging, I figured it out. It was all due to an errant 'reset' button that was being generated incorrectly.
I recently upgraded from CakePHP 1.2 to CakePHP 1.3 and now I have some code that is trapping the user in a redirect loop. This is after the user has successfully logs in and decides to click on a link to manage emails.
I have some code in a controller where the index() method will check if the current user is an admin or not. If the user is not an admin it will do the following:
function index()
{
if ($this->Session->read('is_admin') < 1) {
$this->redirect(array('controller' => 'emails', 'action' => 'view', 'id' => $this->Session->read('username')));
}
//...more code...
}
This is intended to redirect the user to a view() method and display only their email and not everyone's email. What is happening when I debug this is the redirect keeps ending up in the index() method.
Is there something new in CakePHP that I'm missing? Is it a no-no to use the name "view" as an action in a controller?
* EDIT *
Okay, I was a little premature with this post. The code in the view($username) method is being reached. But the thing is the $username is not defined and I have some client code that is then redirecting back to the index() action if it is not defined.
I did check the original redirect and the $this->Session->read('username') is populated with the username but it is just not being passed in the view()'s $username argument.
Thanks!
It turns out the redirect signature changed from 1.2 to 1.3:
http://book.cakephp.org/view/1561/Migrating-from-CakePHP-1-2-to-1-3
Library Classes > Router
// CakePHP 1.2 way
$this->redirect(array('controller' => 'emails', 'action' => 'view', 'id' => $this->Session->read('username')));
// CakePHP 1.3 way
$this->redirect(array('controller' => 'emails', 'action' => 'view', $this->Session->read('username')));
Im developing a simple application with CakePHP v1.3.7 Stable. I want to generate a simple user profile page, accessible by the url: my.domain/u/id, where id is the id of the user in database.
So i wrote this (and only this) in app/config/routes.php:
Router::connect('/u/:id',
array('controller' => 'Users', 'action' => 'profile')
,array('pass'=>array('id'),'id'=>'[0-9]+')
);
The above code works fine, when i put my.domain/u/120 in the browser, it shows the profile of user 120.
But, when i try to create a link to this page using the Html helper:
// some code in a view
$this->html->link('Test', array('controller'=>'Users', 'action'=>'profile', 120))
The html helper (doing inverse routing, i think) generates the url in the defaut cakephp form: Test
Based on the configuration in routes.php, it should be: Test, right?
I'm missing something?
Thanks.
Try with this:
$this->html->link('Test', array('controller'=>'Users', 'action'=>'profile', 'id'=>120))
I hope the missed 'id' will fix it.
Finally, thanks to dogmatic69, I deleted the id related code of the route.
I end with this in routes.php:
Router::connect('/u/*',
array('controller' => 'users', 'action' => 'profile')
);
Now, the html helper works just as expected:
echo $this->html->link('Test',array(
'controller'=>'users',
'action'=>'profile',
100
))
// renders: Test
The drawback is that I can't take advantage of the regexp filter of the router, as in the initial route code.