views:

81

answers:

3

I'm writing an admin section to a site using CodeIgniter. I am writing an Admin class that extends the Controller class, and then controllers for admin pages will extend Admin. I do this because I want the Admin class to check the user's session to make sure he is logged in -- and if not, to show the login page and abort initialization of the class.

To me, that seems like a nice abstraction -- not worrying about the user being logged in for any of the administration pages and functions, just writing them and letting the super class worry about it. But how should I do this?

If I throw an exception from the Admin constructor, will that stop the sub class extending it from being created? is there a better way to do this? @anyone who has used MVC before, have you dealt with something like this before?

+1  A: 

In the constructor of your Admin class, check if the user is logged in and redirect to the login page if not.

public function __construct() {
  // assuming you have your user authentication handled by UserLogin class
  if (!UserLogin::is_logged_in()) {
    redirect("/uri/to/login/page");
    die;
  }

  // do normal stuff
  parent::__construct();
}
Lukman
the URI helper class has to be loaded for this to work, correct?
Carson Myers
yup, you need to load URL helper to get the `redirect()` function
Lukman
A: 

I would suggest that you apply the "is a" test here. "Is a(n)" admin a controller? I would say no. Rather, a controller providing access to administrative pages might have the property of "requires admin authentication". Therefore, it seems like you should use a decorator on the controller class to do access control. For the admin sections you can set an "Admin access controller" and for non-admin sections you can set it to null or a base class that has a default action of doing nothing.

Your way probably will work fine, I'm just kind of approaching it more from the "how should the design look" kind of angle.

Zak
Can you sort of clarify a little bit? I was meaning for the Admin subclass to be a "decorator" for the controller class as it would extend controller. I was going to have it auto-authenticate for its subclasses and add a view function for displaying content which would add a header and footer to the site, among other things.
Carson Myers
I was trying to find the source for the base controller class to see if/what the easy way to add authentication/access control decorators would be, but I'm coming up short.
Zak
Sorry, this gives a more complete description of what I was saying: Unfortuneately it doesn't look like the default CI Controller class has the ability to do simple decorator adds for pre-controller method running, but you can use hooks before the controller ever runs. See this page for more details:http://www.echovsprint.com/2009/04/role-based-access-control-in-codeigniter-using-hooks/
Zak
+2  A: 

show_error() words similarly to die() in native PHP. It will immediately halt execution and display the error string, no matter where it's called: a view, a model, or (more commonly) a controller. Keep in mind though that any state manipulation that occurs up to the call won't be reversed.

As for best practice to perform rights checking, other folks here have and will recommend other solutions, but I can give you the approach I usually take.

If the admin is going to be just another non-comp savvy end user in a site with multiple non-admin users, I would just create a flag in the users database table, and the user's row is loaded in a custom controller MY_Controller. Then, I'd just attach a check on each function in a controller class if different functions have different rights restrictions. If they all have the same rights restrictions, I'd put it in the controller, as @Lukman suggests.

If the admin is going to be completely separate from the user experience, you might consider creating an admin subdomain and installing CI on it. That way you don't have to worry about anything other than setting up a global custom controller that manages rights.

In your case, the approach I'd take is a bit different. I'd create a custom controller and extend EVERY controller on the site from it (this is just good practice in my opinion since there almost always winds up stuff that is best done in one place). In that controller, I would run:

if(strcasecmp($this->uri->segment(1) , 'admin') === 0)
    if($this->session->userdata('admin') !== 1)
        show_error('Access Prohibited');
Steven Xu