Up to this point we have been granting and denying access to some views in the following way:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->deny('add','edit','index','view', 'delete', 'translate');
}
It worked perfectly, but now as requirements have changed, we need to do a conditional filter and give an appropriate message. It should take User's role, which can be get at $user['role'], and then depending on action it should grant/deny it with providing appropriate message.
Any help or guidance is much appreciated.
For example,
user's role are buyer & seller.
Seller can perform the following action add , update & delete & Buyers can perform the following action view, translate
public function beforeFilter() {
parent::beforeFilter();
if($user['role'] == 'buyers') {
$actions = array('view','translate');
} else {
$actions = array('add','update','delete');
}
$this->Auth->deny($actions);
}
For more details go to flowing link
That's it.
You can also look into ACL here is a short tutorial on ACL in cakephp
http://mark-story.com/posts/view/auth-and-acl-an-end-to-end-tutorial-pt-1
Related
I have a website where all the pages are accessible to the public except for one Releases page which is user specific or maybe to a specific group .I have a seperate login page to gain access to 'Releases' page based on authentication.How do I go about this?Using Acl or Authorize function?I am very confused..Also do i need to use the same users table for authenticating this page, in that case do I use this User login page as an elemnt in my other login page.Could somebody please hint me on how to proceed?
ACL is overkill for many situations.
What I normally do is something like this in my controller:
public function releases() {
$this->_allowedGroups(array(1,2,3));
// rest of code here
}
Then in my app controller:
public function _allowedGroups($groups=array()) {
if( !in_array($this->Auth->user('group_id'), $groups) ) {
$this->redirect(array('controller'=>'users', 'action'=>'login'));
}
}
Acl should do your work.
And is there any specific need that you are using a separate login page??
A single login page and and a single users table should suffice your needs if you implement acl. Only those users who have rights to view the Requests page will be allowed to do so.
you may do something like this..
on core.php, put
Configure::write('Routing.prefixes', array('release'));
and do the verification on the AppController:
class AppController extends Controller{
public function beforeFilter(){
if (isset($this->params['prefix']) and $this->params['prefix'] == 'release'){
if ($this->Session->read("User.type") != 'admin'){
//redirect the user or throw an error...
}
}
}
}
so, youdomain.com/release/* will only be accesible by your administrators...
also, i don't see why you need two logins pages... you could just put a flag on your users table saying if the user is or not an admin... and on the login, set the User.type property on session.
if you don't need of complex permissions control, i think you don't need use ACL.
Iam writing an application with cakephp where i will have admin and agents where they can login to the system. Admin will have different layout from the agents. I have already create the the users table where i added a role field (admin,agent) ,i added the prefixes in core.php
Configure::write('Routing.prefixes', array('admin','agent'));
I managed to create the login and the logout for admin, but still iam confused how i should proceed with the rest. For Example i dont understand how beforeFilter() and isAuthorized() functions works. How i can check if user has access to that function or not. Also the redirections if a someone try to access this page domain.com/admin to be redirected to admin/login page .
Thanks.
Use the beforeFilter() to control access to each action, the below example will only allow access to the view and index action - any other action will be blocked :
$this->Auth->allow('view', 'index');
if you want to allow access to all the actions in your controller , try this in your before filter:
$this->Auth->allow();
To control who has access to what you could use a simple function in your app controller like so:
protected function _isAuthorized($role_required) {
if ($this->Auth->user('role') != $role_required) {
$this->Session->setFlash("your message here...");
$this->redirect("wherever you want the user to go to...");
}
}
In your controller action, eg. admin_delete on the first line you would do the following:
$this->_isAuthorized('admin');
Finally the redirect works like so:
$this->redirect(array('controller' => 'home', 'action' => 'dashboard'));
if you are redirecting within the same controller simply do the following:
$this->redirect('dashboard');
Hope this helps.
What i usually do is extend my App controller into an AdminAppController and SiteController , in the AdminAppController I have the following code in my beforeFilter:
$controller = strtolower($this->params["controller"]);
$action = strtolower($this->params["action"]);
$crole = $this->Auth->user("role");
$allowed = false;
$roles = array(
"all"=>array("user#login","user#register","user#forgot"),
"admin"=>array("pages#index","pages#view")
);
if(in_array($controller."#".$action,$roles["all"])){
$allowed = true;
}else{
if(in_array($controller."#".$action,$roles[$crole])){
$allowed = true;
}
}
if($allowed==false){
$this->setFlash("Access denied message...");
$this->redirect("...");
}
Don't know if this is the best practice but it works just fine. I normally hate CakePHP's built in Authorization system.
To check for allowance per role, I think it's best to use the Auth->allow([...]) in a per controller basis.
I find it best to check in Controller::beforeFilter() with a:
switch ($role) {
case 'admin':
$this->Auth->allow(...); //Allow delete
//notice no break; statement, so next case will execute too if admin
case 'manager':
$this->Auth->allow(...); //Allow edit
case default:
$this->Auth->allow(...); //Allow index
}
While you can check in AppController, I don't want to remember to change two files when I edit just one.
I've installed CakeDC Users plugin and I found out that role, is_admin don't function by default. If I login with regular username role=registered and is_admin=0, I can still go to /admin/users/add/. Why are there two types of checks, role and is_admin, what if role=administrator and is_admin=0, or vice-versa?
I am looking for a preferred solution to this problem so I could secure admin section and make use of user roles on different pages. Still, can't understand why is_admin is present, when role=administrator could take care of it all.
I solved the very same issue by adding the following piece of code in "app/Controller/AppController.php" in method "beforeFilter()" :
if (isset($this->params['prefix']) && $this->params['prefix'] == 'admin') {
if ($this->Session->check('Auth.User.role') and 'admin' !== $this->Session->read('Auth.User.role')) {
$this->Auth->deny('*');
return $this->flash('Non admin access unauthorized', '/');
}
}
While I admit this solution is not optimal, it sure does the trick!
This is not an issue of the plugin: You have to implement your auth application wide on your own. The plugin just gives you the basics but does not your job of customizing the app based on the requirements of your client. I recommend you to read this chapter http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
The is_admin check AND role field are there for multiple reasons: Your user can have any role but only if they have is_admin checked they can access an admin area for example. is_admin alone does not allow you to have roles. Both fields are there to cover different scenarios. Again, the plugin is thought to be a kick start and base you can build on. That's what you have to do when you want to customize it.
There is an example that shows pretty much how to use whatever you need:
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#using-controllerauthorize
class AppController extends Controller {
public $components = array(
'Auth' => array('authorize' => 'Controller'),
);
public function isAuthorized($user = null) {
// Any registered user can access public functions
if (empty($this->request->params['admin'])) {
return true;
}
// Only admins can access admin functions
if (isset($this->request->params['admin'])) {
return (bool)($user['role'] === 'admin');
}
// Default deny
return false;
}
}
For my project I have three types of users. Admins, members and Others.
There are certain functions that both admin and members could perform.
I know how to do routing and check for admin, and calling admin methods. But am not sure how to share a function between user types.
Any hint?
Best,
R
You could simply do it using Auth component.
Uncomment Routing.prefixes = array('admin', 'manager'); in your app/Config/core.php file.
Setup an Auth component with the help of this link.
Now if your controller's method is common with two user roles 'admin' and 'manager', then it is simple to define a method for any role and invoke it in another method.
Lets say in your UsersController.php
public function admin_list()
{
/*.... define here ..... */
}
public function manager_list()
{
$this->admin_list();
}
This technique will also help you to manage if you want to show some other things with user list for the manager user role.
Use isAuthorized() from Auth component. Let's say that your users is in table users.
In your AppController.php put:
public function isAuthorized($user){
return true;
}
In your UsersController, lets say that you want method1 and method2 to be visible only for admins and members, not for others.
public function isAuthorized($user){
if(in_array($this->action, array('method1', 'method2'))){
if($user['role'] != 'admin' || $user['role'] != 'user'){
return false;
}
}
return true;
}
And, of course, include your AuthComponent in AppController:
public $components = array('Session', 'Auth');
If you have any further questions, feel free to ask. :)
I'm trying to use roles in the CakePHP Auth component. The roles would be user, admin, super-admin, etc. I'm having difficulty with placing a conditional in each controller based off the user role. I tried the following and it didn't work:
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('add');
if($this->Auth->user('roles') == 'admin') {
$this->Auth->allow('index', 'add', 'edit', 'delete');
}
elseif($this->Auth->user('roles') == 'super-admin') {
$this->Auth->allow('index', 'add', 'edit', 'delete', 'make_super_admin', 'privileges'); //Note difference in superadmin priviledges
}
The problem is with the conditional. I want the function to go in each controller (UsersController, PatientsController, AdmissionsController, etc.) and based off the user role, give different permissions.
Placing this logic in the beforeFilter() of the AppController class should do the trick.
Another thought that I had was that maybe you should consider using the Acl component in conjunction with the Auth component. The Acl component will give you out-of-the-box granular control over every action in every controller. If used correctly, you'd only have to set permissions on the actions for each role and the type of access-control checking that you are currently trying to do will be automated.
The book has an excellent tutorial on how to make this work. I'm using it in my application and it's well worth the time invested to setup and understand how it all works. Reference below.
CakePHP Book :: Simple Acl controlled Application
I don't know if this is your problem, but if you want to allow every action you have to use * instead of nothing:
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('add');
if($this->Auth->user('roles') == 'admin') {
$this->Auth->allow('*');
} elseif($this->Auth->user('roles') == 'super-admin') {
$this->Auth->allow('*');
}
}
If you want to set those permissions for every controller it would be the best to put it in your AppController so it will affect everything.