Created
May 9, 2011 13:42
-
-
Save zombor/962539 to your computer and use it in GitHub Desktop.
Controller/Action ACL logic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Extension to Controller_Website that enforces authentication | |
* | |
* @package | |
* @author Jeremy Bush | |
* @copyright (c) 2011 Jeremy Bush | |
*/ | |
class Controller_Website_Authenticated extends Controller_Website | |
{ | |
/** | |
* Overload before to force authentication | |
* | |
* @return null | |
*/ | |
public function before() | |
{ | |
parent::before(); | |
try | |
{ | |
// We need to be at least authenticated to see this | |
Auth::instance()->get_user()->assert('use_authenticated'); | |
// Otherwise fall back to auth checks | |
$this->check_auth(); | |
} | |
catch (Policy_Exception $e) | |
{ | |
// See if we have a specific place to go first | |
$directory = Request::current()->directory() | |
? Request::current()->directory().'_' : ''; | |
$message = $directory. | |
Request::current()->controller(). | |
'_'.Request::current()->action(); | |
$message = Kohana::message('policy', $message.'.'.Model_ACL_Role::LOGIN); | |
if ($message AND is_array($message)) | |
{ | |
Session::instance()->set('requested_page', $this->request->uri()); | |
Session::instance()->set('flash_message', $message['message']); | |
$this->request->redirect($message['route']); | |
} | |
$this->request->action('unauthorized'); | |
Session::instance()->set('requested_page', $this->request->uri()); | |
} | |
catch (Authorization_Exception $e) | |
{ | |
// See if we have a specific place to go first | |
$directory = Request::current()->directory() | |
? Request::current()->directory().'_' : ''; | |
$message = $directory. | |
Request::current()->controller(). | |
'_'.Request::current()->action(); | |
$message = Kohana::message('policy', $message.'.'.Model_ACL_Role::LOGIN); | |
if ($message AND is_array($message)) | |
{ | |
Session::instance()->set('requested_page', $this->request->uri()); | |
Session::instance()->set('flash_message', $message['message']); | |
$this->request->redirect($message['route']); | |
} | |
$this->request->action('unauthorized'); | |
Session::instance()->set('requested_page', $this->request->uri()); | |
} | |
} | |
/** | |
* Prompts a user to login if they don't have access | |
* | |
* @return null | |
*/ | |
public function action_unauthorized() | |
{ | |
$this->response->status('403'); | |
Session::instance()->set( | |
'flash_error', 'Please login to view this page.' | |
); | |
$this->view = NULL; | |
$this->template = Request::factory('users/login')->execute()->body(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
return array( | |
'message_compose' => array( | |
Model_ACL_Role::LOGIN => array( | |
'route' => Route::get('user login')->uri(), | |
'message' => 'Please login to view your messages.', | |
), | |
), | |
'users_lists_create' => array( | |
Model_ACL_Role::LOGIN => array( | |
'route' => Route::get('user register')->uri(), | |
'message' => 'Please create an account to make a list.', | |
), | |
), | |
'users_account' => array( | |
Model_ACL_Role::LOGIN => TRUE, | |
), | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
abstract class Controller_Website extends Controller | |
{ | |
protected $prompt_login = TRUE; | |
public function before() | |
{ | |
parent::before(); | |
// Make sure they can even use this website | |
Auth::instance()->get_user()->assert('use_website'); | |
$this->user = Auth::instance()->get_user(); | |
$directory = Request::current()->directory() ? Request::current()->directory().'_' : ''; | |
$view_name = 'View_'.$directory.Request::current()->controller().'_'.Request::current()->action(); | |
if(Kohana::find_file('classes', strtolower(str_replace('_', '/', $view_name)))) | |
{ | |
$this->template = $this->view = new $view_name; | |
} | |
} | |
public function after() | |
{ | |
if (isset($this->view)) | |
{ | |
$this->view->errors = Session::instance()->get_once('flash_error'); | |
$this->view->flash_message = Session::instance()->get_once('flash_message'); | |
$this->response->body($this->view->render()); | |
} | |
else | |
$this->response->body($this->template); | |
} | |
/** | |
* Authorization method for all controller classes. | |
* | |
* @throws Authorization_Exception | |
* | |
* @return null | |
*/ | |
public function check_auth() | |
{ | |
// The parent call is always right | |
if ( ! $this->request->is_initial()) | |
{ | |
return; | |
} | |
$status = TRUE; | |
$user = Auth::instance()->get_user(); | |
$policy_name = Request::current()->controller(). | |
'_'.Request::current()->action(); | |
// This can be a blacklist or whitelist method, depending on how the | |
// policy class is setup | |
try | |
{ | |
try | |
{ | |
// look for the specific method | |
$refl = new ReflectionClass('Policy_'.$policy_name); | |
$class = $refl->newInstanceArgs(); | |
$status = $class->execute($user); | |
if (TRUE === $status) | |
return; | |
} | |
catch (ReflectionException $ex) | |
{ | |
// otherwise try and look for one for the whole controller | |
$refl = new ReflectionClass( | |
'Policy_'.Request::current()->controller() | |
); | |
$class = $refl->newInstanceArgs(); | |
$status = $class->execute($user); | |
if (TRUE === $status) | |
return; | |
} | |
} | |
// try and find a message based policy | |
// This is basically a blacklist method | |
catch (ReflectionException $ex) | |
{ | |
$status = FALSE; | |
$no_policy = FALSE; | |
// If there's no policy message file, assume there's no auth needed | |
if ( ! Kohana::message('policy', $policy_name, FALSE)) | |
{ | |
$no_policy = TRUE; | |
} | |
// If there's no policy message file, assume there's no auth needed | |
if ( | |
$no_policy | |
AND ! Kohana::message( | |
'policy', Request::current()->controller(), FALSE | |
) | |
) | |
{ | |
$no_policy = TRUE; | |
} | |
else | |
{ | |
$no_policy = FALSE; | |
} | |
if ($no_policy) | |
{ | |
return; | |
} | |
// Try each of this user's roles to match a policy | |
if ( ! Auth::instance()->logged_in()) | |
{ | |
if (Kohana::message( | |
'policy', | |
$policy_name.'.'.Model_ACL_Role::LOGGED_OUT, | |
FALSE | |
) | |
) | |
{ | |
$status = TRUE; | |
} | |
if (Kohana::message( | |
'policy', | |
Request::current()->controller(). | |
'.'.Model_ACL_Role::LOGGED_OUT, | |
FALSE | |
) | |
) | |
{ | |
$status = TRUE; | |
} | |
if ($status) | |
return; | |
} | |
foreach ($user->find_related('roles') as $role) | |
{ | |
if (Kohana::message( | |
'policy', | |
$policy_name.'.'.$role->id, | |
FALSE | |
)) | |
{ | |
$status = TRUE; | |
} | |
if (Kohana::message( | |
'policy', | |
Request::current()->controller().'.'.$role->id, | |
FALSE | |
) | |
) | |
{ | |
$status = TRUE; | |
} | |
if ($status) | |
return; | |
} | |
} | |
if (TRUE === $status) | |
return; | |
// We don't know what kind of specific error this was | |
if (FALSE === $status) | |
{ | |
$status = Policy::GENERAL_FAILURE; | |
} | |
Policy::$last_code = $status; | |
throw new Authorization_Exception( | |
'Could not authorize policy :policy', | |
array(':policy' => $policy_name), | |
$status | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment