Skip to content

Instantly share code, notes, and snippets.

@savannah
Created December 27, 2009 19:45
Show Gist options
  • Save savannah/264376 to your computer and use it in GitHub Desktop.
Save savannah/264376 to your computer and use it in GitHub Desktop.
<?php
/**
* Base auth presenter, provides support for annotation based authorization checks.
*
* @author Ondrej Skalicka
*/
abstract class BaseAuthPresenter extends Presenter {
public $oldLayoutMode = FALSE;
protected function startup() {
$this->authCheck();
parent::startup();
}
/**
* Search for annotations on presenter render/action and performs auth check if necessary.
*
* If user fails to authorize, redirects to login page.
*
* Recognized annotations are:
* <ul>
* <li>@loginRequired - only requires user to be logged in (eg. not a guest). Accepts
* optional loginUrl attribute (default 'Auth:login') where to redirect if user fails
* to authorize
* </li>
* <li>@permissionRequired - requires user to has access to certain resource/privilege and/or
* to be member of a role. Accepts optional arguments (however at least one of 'role',
* 'resource' and 'privilege' should be present):
* <ul>
* <li>'role' if supplied, user must pass $user->isInRole($role) to be authorized</li>
* <li>'resource' if supplied, user must pass either $user->isAllowed($resource)
* (if 'privilege' is not set) or $user->isAllowed($resource, $privilege) (if both
* 'resource' and 'privilege' is set)
* </li>
* <li>'privilege' if supplied, user must pass either $user->isAllowed(null, $privilege)
* (if 'resource' is not set) or $user->isAllowed($resource, $privilege) (if both
* 'resource' and 'privilege' is set)</li>
* <li>'loginUrl' (defaults to 'Auth:login')if user don't authorize, redirect there</li>
* </ul>
* </ul>
*
* Annotations could be set both on Presenter level and Render/Action level. If both are
* present, Render overrides Presenter.
*
*
* @return void
*/
protected function authCheck() {
$loginRequired = false;
$roleRequired = null;
$resourceRequired = false;
$privilegeRequired = false;
$loginUrl = 'Auth:login';
// check view level for annotations
if ($an = $this -> getAnnotation('permissionRequired')) {
if ($an->offsetExists('role')) $roleRequired = $an['role'];
if ($an->offsetExists('resource')) $resourceRequired = $an['resource'];
if ($an->offsetExists('privilege')) $privilegeRequired = $an['privilege'];
if ($an->offsetExists('loginUrl')) $loginUrl = $an['loginUrl'];
} elseif ($an = $this -> getAnnotation('loginRequired')) {
if ($an->offsetExists('loginUrl')) $loginUrl = $an['loginUrl'];
$loginRequired = true;
}
// check signal for annotations
/**
* @todo buggy as of now, won't get signalMethodName correctly
*/
/*if ($this -> signal !== NULL) {
$signalMethod = $this->formatSignalMethod($this->signal);
var_dump($this->signal);
if ($an = $this -> getMethodAnnotation($signalMethod, 'permissionRequired')) {
var_dump($an);
if ($an->offsetExists('role')) $roleRequired = $an['role'];
if ($an->offsetExists('resource')) $resourceRequired = $an['resource'];
if ($an->offsetExists('privilege')) $privilegeRequired = $an['privilege'];
if ($an->offsetExists('loginUrl')) $loginUrl = $an['loginUrl'];
} elseif ($an = $this -> getMethodAnnotation($signalMethod, 'loginRequired')) {
if ($an->offsetExists('loginUrl')) $loginUrl = $an['loginUrl'];
$loginRequired = true;
}
}*/
// check render for annotations
$renderMethod = $this->formatRenderMethod($this->view);
if ($an = $this -> getMethodAnnotation($renderMethod, 'permissionRequired')) {
if ($an->offsetExists('role')) $roleRequired = $an['role'];
if ($an->offsetExists('resource')) $resourceRequired = $an['resource'];
if ($an->offsetExists('privilege')) $privilegeRequired = $an['privilege'];
if ($an->offsetExists('loginUrl')) $loginUrl = $an['loginUrl'];
} elseif ($an = $this -> getMethodAnnotation($renderMethod, 'loginRequired')) {
if ($an->offsetExists('loginUrl')) $loginUrl = $an['loginUrl'];
$loginRequired = true;
}
$user = Environment::getUser();
if (($loginRequired && !$user->isAuthenticated()) ||
($roleRequired && !$user->isInRole($roleRequired)) ||
($resourceRequired && $privilegeRequired && !$user->isAllowed($resourceRequired, $privilegeRequired)) ||
($resourceRequired && !$privilegeRequired && $user->isAllowed($resourceRequired)) ||
($privilegeRequired && !$resourceRequired && $user->isAllowed(null, $privilegeRequired))) {
$this -> redirect($loginUrl, array('backlink' => $this -> getApplication() -> storeRequest()));
}
}
/**
* Returns annotation.
* @param string $annotation
* @return array
*/
protected function getAnnotation($annotation) {
return Annotations::get($this->getReflection(), $annotation);
}
/**
* Returns given method's annotation.
* @param string $method
* @param string $annotation
* @return array
*/
protected function getMethodAnnotation($method, $annotation) {
if (!$this->getReflection()->hasMethod($method)) return false;
return Annotations::get(new ReflectionMethod($this->getClass(), $method), $annotation);
}
}
<?php
class DemoPresenter extends BaseAuthPresenter {
/**
* This render is public
*/
public function renderDefault () {
// ...
}
/**
* This render is public as well
*
* @permissionRequired(role=guest)
*/
public function renderGuest () {
// ...
}
/**
* This render requires user->isAuthenticated() == true
*
* @loginRequired
*/
public function renderRequiresLogin () {
// ...
}
/**
* This render requires user->isAllowed('article', 'add')
*
* @permissionRequired(resource=article, privilege=add)
*/
public function renderAddArticle () {
// ...
}
/**
* This render requires user->isAllowed('article', 'edit') and
* be in 'admin' role as well.
*
* @permissionRequired(resource=article, privilege=add, role=admin)
*/
public function renderAdminEditArticle () {
// ...
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment