parent
9bfe05322a
commit
dd55e0ab63
@ -0,0 +1,203 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Authorize or deny calls. |
||||
* |
||||
* |
||||
* Note: |
||||
* |
||||
* This class stores locally the security token so that the current call |
||||
* can still be validated after generating the new token. |
||||
* |
||||
* The new security token is generated only on first call. Successive calls |
||||
* return the same token. This ensure that different parts of the application |
||||
* (form, javascript for javascript, etc) can get access to the same token. |
||||
* |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Geneva |
||||
* @license /license.txt |
||||
*/ |
||||
abstract class Access |
||||
{ |
||||
|
||||
const SEC_TOKEN = 'sec_token'; |
||||
|
||||
/** |
||||
* Return view and edit access. |
||||
* |
||||
* @return \Access |
||||
*/ |
||||
public static function all() |
||||
{ |
||||
return AccessAll::instance(); |
||||
} |
||||
|
||||
/** |
||||
* Return no access. |
||||
* |
||||
* @return \Access |
||||
*/ |
||||
public static function forbidden() |
||||
{ |
||||
AccessForbidden::instance(); |
||||
} |
||||
|
||||
protected $session_token; |
||||
protected $token; |
||||
|
||||
/** |
||||
* Returns true if security token is valid, false otherwise. |
||||
* |
||||
* @return bool |
||||
*/ |
||||
public function is_token_valid() |
||||
{ |
||||
$call_token = Request::get_security_token(); |
||||
if (empty($call_token)) { |
||||
return false; |
||||
} |
||||
$session_token = $this->get_session_token(); |
||||
return $session_token == $call_token; |
||||
} |
||||
|
||||
/** |
||||
* Returns the token contained in the session. |
||||
* Stores the token for further reuse so that it can be changed in session. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function get_session_token() |
||||
{ |
||||
if (empty($this->session_token)) { |
||||
$key = self::SEC_TOKEN; |
||||
$this->session_token = isset($_SESSION[$key]) ? $_SESSION[$key] : ''; |
||||
} |
||||
return $this->session_token; |
||||
} |
||||
|
||||
/* |
||||
* On first call generate a new security token and save it in session. |
||||
* On successful calls returns the same (new) token (function is repeatable). |
||||
* If user do not have the right to edit, returns a blank (invalid) token. |
||||
* |
||||
* Stores the existing session token before saving the new one so that |
||||
* the current call can still be validated after calling this function. |
||||
*/ |
||||
|
||||
public function get_token() |
||||
{ |
||||
if (!$this->can_edit()) { |
||||
return ''; |
||||
} |
||||
if ($this->token) { |
||||
return $this->token; |
||||
} |
||||
$this->session_token = $this->get_session_token(); |
||||
|
||||
|
||||
$this->token = \Security::get_token(); |
||||
} |
||||
|
||||
/** |
||||
* Returns true if the user has the right to edit. |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
public abstract function can_edit(); |
||||
|
||||
/** |
||||
* Returns true if the current user has the right to view |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
public abstract function can_view(); |
||||
|
||||
public function authorize() |
||||
{ |
||||
return $this->can_view(); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Authorize access and view access. |
||||
*/ |
||||
class AccessAll extends Access |
||||
{ |
||||
|
||||
/** |
||||
* Return the instance. |
||||
* |
||||
* @return \Access |
||||
*/ |
||||
public static function instance() |
||||
{ |
||||
static $result = null; |
||||
if (empty($result)) { |
||||
$result = new self(); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
private function __construct() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public function can_edit() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
public function can_view() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
public function authorize() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Authorizev view access only |
||||
*/ |
||||
class AccessForbidden extends Access |
||||
{ |
||||
|
||||
/** |
||||
* Return the instance. |
||||
* |
||||
* @return \AccessView |
||||
*/ |
||||
public static function instance() |
||||
{ |
||||
static $result = null; |
||||
if (empty($result)) { |
||||
$result = new self(); |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
private function __construct() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public function can_edit() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public function can_view() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
public function authorize() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,198 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* Controller |
||||
* |
||||
* |
||||
* |
||||
* @author Laurent Opprecht <laurent@opprecht.info> for the Univesity of Genevas |
||||
* @license see /license.txt |
||||
*/ |
||||
class Controller |
||||
{ |
||||
|
||||
const PARAM_ACTION = 'action'; |
||||
|
||||
protected $access; |
||||
|
||||
protected function __construct($access = null) |
||||
{ |
||||
$access = $access ? $access : Access::all(); |
||||
$this->access = $access; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return \Access |
||||
*/ |
||||
public function access() |
||||
{ |
||||
return $this->access; |
||||
} |
||||
|
||||
/** |
||||
* List of actions accepted by the controller. |
||||
* |
||||
* @return array |
||||
*/ |
||||
public function get_actions() |
||||
{ |
||||
$reflector = new ReflectionClass($this); |
||||
$constants = $reflector->getConstants(); |
||||
$result = array(); |
||||
foreach ($constants as $key => $value) { |
||||
if (strpos($key, 'ACTION') !== false) { |
||||
$result[$key] = $value; |
||||
} |
||||
} |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Action to perform. |
||||
* Returns the request parameter. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function get_action() |
||||
{ |
||||
$result = Request::get(self::PARAM_ACTION); |
||||
$actions = $this->get_actions(); |
||||
$result = in_array($result, $actions) ? $result : ''; |
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* Set up the environment. Set up breadcrumps, raise tracking event, etc. |
||||
*/ |
||||
protected function prolog() |
||||
{ |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Whether the call is authorized or not. |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
public function authorize() |
||||
{ |
||||
return $this->access()->authorize(); |
||||
} |
||||
|
||||
/** |
||||
* Returns a string containing dynamic javascript to be included in the template. |
||||
* This requires a {{javascript}} tag in a twigg template to appear. |
||||
* |
||||
* Note: |
||||
* |
||||
* A better approach to this method is to create a twigg "javascript" |
||||
* template and to include it where required. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function javascript() |
||||
{ |
||||
return ''; |
||||
} |
||||
|
||||
// public function check_token() |
||||
// { |
||||
// return (bool) Security::check_token('get'); |
||||
// } |
||||
|
||||
/** |
||||
* Run the controller. Dispatch action and execute requested tasks. |
||||
*/ |
||||
public function run() |
||||
{ |
||||
if (!$this->authorize()) { |
||||
$this->forbidden(); |
||||
return false; |
||||
} |
||||
|
||||
$this->prolog(); |
||||
$action = $this->get_action(); |
||||
if (empty($action)) { |
||||
$this->unknown(); |
||||
return; |
||||
} |
||||
$f = array($this, $action); |
||||
if (is_callable($f)) { |
||||
call_user_func($f); |
||||
} else { |
||||
$this->missing(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Unknown action. I.e. the action has not been registered. |
||||
* Possibly missing action declaration: |
||||
* |
||||
* const ACTION_XXX = 'XXX'; |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
public function unknown() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return boolean |
||||
*/ |
||||
public function forbidden() |
||||
{ |
||||
api_not_allowed(); |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Action exists but implementation is missing. |
||||
*/ |
||||
public function missing() |
||||
{ |
||||
echo 'No implementation'; |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Render a template using data. Adds a few common parameters to data. |
||||
* |
||||
* @see /main/template/default/course_description/ |
||||
* @param string $template |
||||
* @param array $data |
||||
*/ |
||||
protected function render($template_name, $data) |
||||
{ |
||||
$data = (object) $data; |
||||
$data->www = \Chamilo::url(); |
||||
$data->messages = isset($data->messages) ? $data->messages : array(); |
||||
$javascript = $this->javascript(); |
||||
if ($javascript) { |
||||
$data->javascript = $javascript; |
||||
} |
||||
|
||||
$tpl = new Template(); |
||||
foreach ($data as $key => $value) { |
||||
$tpl->assign($key, $value); |
||||
} |
||||
$template = $tpl->get_template($template_name); |
||||
$content = $tpl->fetch($template); |
||||
$tpl->assign('content', $content); |
||||
$tpl->display_one_col_template(); |
||||
} |
||||
|
||||
/** |
||||
* Render data as JSON |
||||
* |
||||
* @param any $data |
||||
*/ |
||||
protected function render_json($data) |
||||
{ |
||||
Header::content_type_json(); |
||||
echo json_encode($data); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue