i am a newbie in programming with cakephp, so i have implemented an simple user-game application. There is an "hasMany" relation between users and game. A game is created exactly by one user. Therefore there is a field in the model of game, named "user_id". I am already using the auth component and it is possible that user can login to the system. Now, i want that user can add games to the model, but the user_id should be added automatically( by acessing to session data). How i can achieve that ?
stannis :)
Now, i want that user can add games to the model, but the user_id should be added automatically( by acessing to session data). How i can achieve that ?
First, I highly recommend you to do the official blog tutorial, because it will cover questions like this for you.
In the controller:
public function add() {
if ($this->request->is('post') {
$this->request->data['Game']['user_id'] = $this->Auth->user('id');
$this->Game->save($this->request->data);
}
}
But this can and definitely should be done better by moving the logic into the model, remember: fat models, skinny controllers. Here is a broken down and short example:
// Controller
public function add() {
if ($this->request->is('post') {
$this->Game->add($this->Auth->user('id'), $this->request->data);
}
}
// Model
public function add($userId, $postData) {
$postData[$this->alias]['user_id'] = $userId;
return $this->save($this->request->data);
}
}
Usually you don't want to access the session directly in a model because it requires you to use a static or singleton call to the auth component or the session object, which we want to avoid as much as we can.
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.
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 have setup a CRUD area on my frontendAPI.php file (testing my models)... and I even managed to secure it. I would like to do this the proper way... I would like to establish a separate directory/ Page for the Admins. Please advise on this.
Still new at this but I'm trying to do the same for a news page, think i've got the login part working but having problems with the CRUD (will post a question on it shortly) - i have a table to populate with data from an rss feed (but will be manually populated with a CRUD to start with) and then have a page on the front end to pull out the details using views to format each news story.
Create a new directory called /page/Admin
Create a new file here based on the function e.g. news.php containing
class page_admin_news extends Page {
function init(){
parent::init();
$p=$this;
$crud=$p->add('CRUD');
$g=$crud->setModel('News');
if($crud->grid)
$crud->grid->addPaginator(30);
}
}
In Frontend.php, you need to enable the login - for an admin only access, the BasicAuth may be sufficient but there are also classes to use a database to obtain username and password infromation e.g. for a membership site - heres the basic one.
// If you wish to restrict access to your pages, use BasicAuth class
$auth=$this->add('BasicAuth')
->allow('demo','demo')
;
You need to modify Frontend.php to enable pages that can be viewed
without being logged in
$auth->allowPage('index');
$auth->allowPage('news');
$auth->allowPage('links');
$auth->allowPage('About');
if (!$auth->isPageAllowed($this->api->page))
{
$auth->check();
}
And also in Frontend.php, you need to create a different menu if logged in. Note the login and logout pages dont actually exist.
if ($auth->isLoggedIn())
{
$this->add('Menu',null,'Menu')
->addMenuitem('News','admin_news')
->addMenuitem('logout')
;
} else {
$this->add('Menu',null,'Menu')
->addMenuitem('News','news')
->addMenuitem('Links','links')
->addMenuItem('About')
->addMenuItem('Login')
;
}
When you login, it goes to page/index.php by default so if you want it to redirect to a particular page when you log in so you can add this to page/index.php
class page_index extends Page {
function init(){
parent::init();
$p=$this;
if($this->api->auth->isLoggedIn())
$this->api->redirect('admin_news');
Hope that helps.
Trev
======================================== EDIT ====================================
Per charles suggestion, I accomplished the Offline/Online feature using the following code, based on Charles code:
<?php
Class AppController extends Controller{
// prevents unauthorized access
public $components = array('Auth');
// the name of the model storing site_offline boolean
public $uses = array('Configuration');
// callback invoked before every controller action
public function beforeFilter() {
// returns your site_offline status assuming 0 is offline
if ($this->Configuration->get_site_status() == 1) {
$this->Auth->allow('*');
}else {
if(($this->Configuration->get_site_status() == 0) and (!$this->Auth->user() == null)){
// I set it up like this for now to allow access to any authenticated user,
//but later will change it to only allow admins access thru a login form
$this->Auth->allow('*');
}else{
//If site is offline and user is not authenticated, sent them to
// the a screen using the OFFLINE layout and provide a screen for login.
$this->layout = 'offline';
$this->setFlash('Maintenance Mode. Check back shortly.');
$this->Auth->deny('*');
}
}
}
}
?>
Then I used jQuery to hide my login form. An admin clicks on the message to show the login form. This is an attempt to prevent any login tryouts.
============================ END EDIT ==========================================
I would like to know what is the best way to create a "site offline/online" feature in CakePHP. Basically, I would like to allow an administrator to turn off access to the site to everyone registered or not. The offline page should have a login access thru which only admins can login.
The idea I have is to create some kind of dashboard controller, where as soon as the administrator is logged in he/she will be redirected to this dashboard from where he can access the other controller actions (admin_edit, etc). This dashboard and all admin actions (admin_delete, etc) should use the admin layout.
Is this a good approach? For the offline/online feature should I create a settings table with a site_offline field that can be turned on or off? Where in app_controller and what code should I use to check for it before allowing or not access to the site?
Thanks a lot for your help,
first add a config in the core.config
/*
* This is the site maintenance
* The built in defaults are:
*
* - '1' - Site works
* - '0' - site down for maintenance.
*/
Configure::write('Site.status', 1);
in the AppController you'll check it in the beforeRender function
if (Configure::read('Site.status') == 0) {
$this->layout = 'maintenance';
$this->set('title_for_layout', __('Site_down_for_maintenance_title'));
} else {
// do something
}
i'm here load a separate layout form the maintenance to let me add whatever layout i want
If you were going to save site_offline boolean value in a database table you should be able to easily do this with a callback in AppController and the Auth component.
<?php
AppController extends Object {
// prevents unauthorized access
public $components = array('Auth');
// the name of the model storing site_offline boolean
public $uses = array('NameOfModel');
// callback invoked before every controller action
public function beforeFilter() {
// returns your site_offline status assuming 0 is offline
if ($this->NameOfModel->get_status() === 0) {
$this->Auth->deny('*');
} else {
$this->Auth->allow('*');
}
}
}
I've always liked the idea of the DashboardsController for admin functions. That's actually the exact name of the class I use and the same general idea.
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.