Created
December 31, 2011 20:12
Revisions
-
hrach created this gist
Dec 31, 2011 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,216 @@ <?php /** * Signály.cz – JP2 * ---------------- * * @license MIT License http://en.wikipedia.org/wiki/MIT_License * @link http://signaly.cz */ use Nette; use Nette\Debug; use Nette\Logger; use Nette\Logger\ILogger; use Nette\Environment as Env; use Nette\Application\AppForm; use Nette\Application\BadRequestException; use Nette\Application\ForbiddenRequestException; use Nette\Application\Presenter; use Nette\Security\AuthenticationException; use DateTime; abstract class BasePresenter extends Presenter { /** * Zkontroluje zda má uživatel potřebné oznámení oprávnení a pokud ne, podnikne patřičné kroky * * @author Jan Tvrdík * @param string|IRowResource * @param string * @return void * @throws ForbiddenRequestException */ public function requirePrivilege($resource, $action = NULL) { if (!$this->actor->isAllowed($resource, $action)) { $this->requireLogin(); throw new ForbiddenRequestException('Nemáš tady co dělat!'); } } /** * Vynutí přihlášenost uživatele. * * @author Jan Tvrdík * @return void */ public function requireLogin() { if (!$this->actor->isLoggedIn()) { $storedRequest = $this->getApplication()->storeRequest(); $this->redirect(':Auth:requireLogin', array('backlink' => $storedRequest)); } } /** * Zpracuje anotace u dané metody * * Podporované anotace: * - @privilege(resource, action) * - @requireLogin * - @allowedAction(edit) * - @secured * - @onlyAjax * * @author Jan Tvrdík * @param string název metody * @return void */ private function processMethodAnnotations($method) { if (!method_exists($this, $method)) return; // přeskočí zpracování, pokud metoda neexistuje $reflection = $this->getReflection()->getMethod($method); $annotations = $reflection->getAnnotations(); if (isset($annotations['privilege'])) { foreach ($annotations['privilege'] as $privilige) { $this->requirePrivilege($privilige[0], $privilige[1]); } } if (isset($annotations['requireLogin'])) { $this->requireLogin(); } if (isset($annotations['allowedAction'])) { $allowedActions = $annotations['allowedAction']; if (!in_array($this->action, $allowedActions)) { throw new ForbiddenRequestException('Volání metody ' . $method . ' není pro akci ' . $this->action . ' povoleno. Zkontrolujte anotaci @allowedAction.'); } } if (isset($annotations['secured'])) { $protectedParams = array(); foreach ($reflection->getParameters() as $param) { if ($param->isOptional()) continue; $protectedParams[$param->name] = $this->getParam($param->name); } if ($this->getParam('__secu') !== $this->createSecureHash($protectedParams)) { throw new ForbiddenRequestException('Secured parameters are not valid.'); } } if (isset($annotations['onlyAjax'])) { if (!$this->isAjax()) { throw new ForbiddenRequestException("Metoda $method přijímá pouze AJAXové požadavky. Viz anotace @onlyAjax"); } } } // === Zabezpečení signalů ===================================================== /** * Zajistí vyhodnocení anotací nad handlerem signálu. * * @author Jan Skrasek, Jan Tvrdík * @param string název signálu * @return void * @throws BadSignalException */ public function signalReceived($signal) { $this->processMethodAnnotations($this->formatSignalMethod($signal)); parent::signalReceived($signal); } /** * Generates link. If links points to @secure annotated signal handler method, additonal * parameter preventing changing parameters will be added. * * @author Jan Skrasek * @param string $destination * @param array|mixed $args * @return string */ public function link($destination, $args = array()) { if (!is_array($args)) { $args = func_get_args(); array_shift($args); } $link = parent::link($destination, $args); $lastRequest = $this->presenter->lastCreatedRequest; // spatny link if ($lastRequest === NULL) return $link; // neni signal if (substr($destination, - 1) !== '!') return $link; // jen na stejny presenter if ($this->getPresenter()->getName() !== $lastRequest->getPresenterName()) return $link; $destination = str_replace(':', '-', $destination); if (strpos($destination, '-') !== FALSE) { $pos = strrpos($destination, '-'); $signal = substr($destination, $pos + 1, -1); $component = substr($destination, 0, $pos); $component = $this->getComponent($component); } else { $signal = substr($destination, 0, -1); $component = $this; } // jen komponenty if (!$component instanceof Nette\Application\PresenterComponent) return $link; $method = $component->formatSignalMethod($signal); $reflection = Nette\Reflection\MethodReflection::from($component, $method); // nema anotaci if (!$reflection->hasAnnotation('secured')) return $link; $origParams = $lastRequest->getParams(); $protectedParams = array(); foreach ($reflection->getParameters() as $key => $param) { if ($param->isOptional()) continue; $protectedParams[$param->name] = $origParams[$component->getParamId($param->name)]; } $uniqueId = $this->getUniqueId(); if (empty($uniqueId)) { $paramName = $component->getParamId('__secu'); } else { $paramName = substr($component->getParamId('__secu'), strlen($uniqueId) + 1); } $args[$paramName] = $this->createSecureHash($protectedParams); return parent::link($destination, $args); } /** * Creates secure hash from array of arguments. * * @author Jan Skrasek * @param array $param * @return string */ protected function createSecureHash($params) { $ns = $this->getSession('securedlinks'); if ($ns->key === NULL) { $ns->key = uniqid(); } $s = implode('|', array_keys($params)) . '|' . implode('|', array_values($params)) . $ns->key; return substr(md5($s), 4, 8); } }