Index: core/kernel/processors/main_processor.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/processors/main_processor.php (revision 15775) +++ core/kernel/processors/main_processor.php (revision ) @@ -829,99 +829,31 @@ } /** - * Checks if user is logged in and if not redirects it to template passed + * Checks if user is logged in and if not redirects it to template passed. * * @param Array $params */ - function RequireLogin($params) + protected function RequireLogin($params) { - $t = $this->Application->GetVar('t'); - $next_t = getArrayValue($params, 'next_template'); + $page_access_validator = $this->Application->makeClass('PageAccessValidator', array($params)); + /* @var $page_access_validator PageAccessValidator */ - if ( $next_t ) { - $t = $next_t; + if ( isset($params['dry_run']) && $params['dry_run'] ) { + try { + $ret = !$page_access_validator->check(); - } + } - - // check by permissions: begin - if ((isset($params['perm_event']) && $params['perm_event']) || - (isset($params['perm_prefix']) && $params['perm_prefix']) || - (isset($params['permissions']) && $params['permissions'])) { - - $perm_helper = $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ - - $perm_status = $perm_helper->TagPermissionCheck($params); - if (!$perm_status) { - list($redirect_template, $redirect_params) = $perm_helper->getPermissionTemplate($params); - $this->Application->Redirect($redirect_template, $redirect_params); + catch (kRedirectException $e) { + return true; } - else { - return ; - } - } - // check by permissions: end - // check by configuration value: begin - $condition = getArrayValue($params, 'condition'); - if (!$condition) { - $condition = true; + return $ret; } - else { - if (substr($condition, 0, 1) == '!') { - $condition = !$this->Application->ConfigValue(substr($condition, 1)); - } - else { - $condition = $this->Application->ConfigValue($condition); - } - } - // check by configuration value: end - // check by belonging to group: begin - $group = $this->SelectParam($params, 'group'); - $group_access = true; - if ($group) { - $sql = 'SELECT GroupId - FROM '.TABLE_PREFIX.'UserGroups - WHERE Name = '.$this->Conn->qstr($group); - $group_id = $this->Conn->GetOne($sql); + $page_access_validator->check(); - if ($group_id) { - $groups = explode(',', $this->Application->RecallVar('UserGroups')); - $group_access = in_array($group_id, $groups); + return ''; - } + } - } - // check by belonging to group: end - if ((!$this->Application->LoggedIn() || !$group_access) && $condition) { - $redirect_params = $this->Application->HttpQuery->getRedirectParams(true); - - if (MOD_REWRITE) { - // TODO: $next_t variable is ignored !!! (is anyone using m_RequireLogin tag with "next_template" parameter?) - $redirect_params = Array ( - 'm_cat_id' => 0, - 'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']), - ); - } - else { - $redirect_params['next_template'] = $t; - } - - if (array_key_exists('pass_category', $params)) { - $redirect_params['pass_category'] = $params['pass_category']; - } - - if (array_key_exists('use_section', $params)) { - $redirect_params['use_section'] = $params['use_section']; - } - - if ( $this->Application->LoggedIn() && !$group_access) { - $this->Application->Redirect($params['no_group_perm_template'], $redirect_params); - } - - $this->Application->Redirect($params['login_template'], $redirect_params); - } - } - /** * Checks, that user belongs to a group with a given name * @@ -951,7 +883,10 @@ * If called without params forces https right away. If called with by_config="1" checks the * Require SSL setting from General Config and if it is ON forces https * - * @param Array $params + * @param Array $params Tag params. + * + * @return boolean|string + * @access protected */ protected function CheckSSL($params) { Index: core/kernel/utility/page_access_validator.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/utility/page_access_validator.php (revision ) +++ core/kernel/utility/page_access_validator.php (revision ) @@ -0,0 +1,447 @@ +tagParams = $tag_params; + } + + /** + * Checks, that user has rights to see current template. + * + * @return boolean + * @access public + */ + public function check() + { + if ( !$this->checkEnabled() ) { + return true; + } + + if ( $this->permissionCheckOnly() ) { + return $this->checkPermissions(); + } + + $ret = true; + $ret = $ret && $this->checkGroupMembership(); + $ret = $ret && $this->checkLoginStatus(); + + return $ret; + } + + /** + * Verify, that system variable specified in 'condition' attribute + * (if specified) allow further checks to be performed. + * + * @return boolean + * @access protected + */ + protected function checkEnabled() + { + $setting_name = $this->getParam('condition', ''); + + if ( !strlen($setting_name) ) { + return true; + } + + if ( substr($setting_name, 0, 1) == '!' ) { + return !$this->Application->ConfigValue(substr($setting_name, 1)); + } + + return $this->Application->ConfigValue($setting_name); + } + + /** + * Tells, that only user permissions should be checked. + * + * @return boolean + * @access protected + */ + protected function permissionCheckOnly() + { + return $this->getParam('perm_event') || $this->getParam('perm_prefix') || $this->getParam('permissions'); + } + + /** + * Checks, that user has the permissions. + * + * @return boolean + * @access protected + * @throws kRedirectException When user don't have a requested permissions. + */ + protected function checkPermissions() + { + $perm_helper = $this->Application->recallObject('PermissionsHelper'); + /* @var $perm_helper kPermissionsHelper */ + + $perm_status = $perm_helper->TagPermissionCheck($this->tagParams); + + if ( $perm_status ) { + return true; + } + + $redirect_params = $this->getCommonRedirectParams(); + + if ( $this->isSelfRedirect() ) { + $redirect_template = $this->getOriginTemplate(); + + if ( $this->Application->LoggedIn() ) { + $this->setAccessViolation($redirect_params, 'no_permission'); + } + else { + $this->setAccessViolation($redirect_params, 'login_required'); + } + } + else { + if ( $this->Application->LoggedIn() ) { + $redirect_template = $this->getNoPermissionTemplate(); + } + else { + $redirect_template = $this->getLoginTemplate(); + } + } + + if ( $this->Application->LoggedIn() && $this->Application->isDebugMode(false) ) { + $redirect_params = kUtil::array_merge_recursive($redirect_params, $this->getNoPermissionRedirectParams()); + } + + return $this->redirect('Insufficient permissions to access the page', $redirect_template, $redirect_params); + } + + /** + * Checks, that user is a member of given group (only if already logged-in). + * + * @return boolean + * @access protected + * @throws kRedirectException When user isn't a member of given group. + */ + protected function checkGroupMembership() + { + if ( !$this->Application->LoggedIn() || $this->isGroupMember() ) { + return true; + } + + $redirect_params = $this->getCommonRedirectParams(); + + if ( $this->isSelfRedirect() ) { + $redirect_template = $this->getOriginTemplate(); + $this->setAccessViolation($redirect_params, 'membership_missing'); + } + else { + $redirect_template = $this->getMembershipMissingTemplate(); + } + + return $this->redirect('Special group membership required to access the page', $redirect_template, $redirect_params); + } + + /** + * Checks, that user is member of given group. + * + * @return boolean + * @access protected + * @throws InvalidArgumentException When specified group not found. + */ + protected function isGroupMember() + { + $group_name = $this->getParam('group', ''); + + if ( !strlen($group_name) ) { + return true; + } + + $sql = 'SELECT GroupId + FROM ' . TABLE_PREFIX . 'UserGroups + WHERE Name = ' . $this->Conn->qstr($group_name); + $group_id = (int)$this->Conn->GetOne($sql); + + if ( $group_id ) { + $groups = explode(',', $this->Application->RecallVar('UserGroups')); + + return in_array($group_id, $groups); + } + + throw new InvalidArgumentException('Group "' . $group_name . '" not found'); + } + + /** + * Checks, that user is logged in. + * + * @return boolean + * @access protected + * @throws kRedirectException When user isn't logged-in. + */ + protected function checkLoginStatus() + { + if ( $this->Application->LoggedIn() ) { + return true; + } + + $redirect_params = $this->getCommonRedirectParams(); + + if ( $this->isSelfRedirect() ) { + $redirect_template = $this->getOriginTemplate(); + $this->setAccessViolation($redirect_params, 'login_required'); + } + else { + $redirect_template = $this->getLoginTemplate(); + } + + return $this->redirect('Login required to access the page', $redirect_template, $redirect_params); + } + + /** + * Returns redirect parameters common for all cases. + * + * @return array + * @access protected + */ + protected function getCommonRedirectParams() + { + $redirect_params = $this->Application->HttpQuery->getRedirectParams(true); + + if ( MOD_REWRITE ) { + // TODO: 'next_template' tag parameter is ignored !!! + $redirect_params = array( + 'm_cat_id' => 0, + 'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']), + ); + } + else { + $redirect_params['next_template'] = $this->getOriginTemplate(); + } + + if ( $this->hasParam('pass_category') ) { + $redirect_params['pass_category'] = $this->getParam('pass_category'); + } + + if ( $this->hasParam('use_section') ) { + $redirect_params['use_section'] = $this->getParam('use_section'); + } + + if ( $this->hasParam('index_file') ) { + $redirect_params['index_file'] = $this->getParam('index_file'); + } + + if ( $this->Application->isAdmin ) { + $redirect_params['m_wid'] = ''; // remove wid, otherwise parent window may add wid to its name breaking all the frameset (for targets) + $redirect_params['pass'] = 'm'; // don't pass any other (except "m") prefixes to admin login template + } + + return $redirect_params; + } + + /** + * Adds some debug info to url, that allows to figure out from where redirect was made. + * + * @return array + * @access protected + */ + protected function getNoPermissionRedirectParams() + { + $ret = array('from_template' => 1); + + if ( $this->hasParam('permissions') ) { + $ret['perms'] = $this->getParam('permissions'); + } + else { + $ret['perms'] = $this->getParam('perm_event'); + } + + return $ret; + } + + /** + * Returns template where access check was initiated. + * + * @return string + * @access protected + */ + protected function getOriginTemplate() + { + $template = $this->Application->GetVar('t'); + $next_template = $this->getParam('next_template'); + + if ( $next_template ) { + // already redirected - use template before redirect + return $next_template; + } + + return $template; + } + + /** + * Return "login" template. + * + * @return string + * @access protected + */ + protected function getLoginTemplate() + { + $template = $this->getParam('login_template', ''); + + if ( !$template /*&& $this->Application->isAdmin*/ ) { + return 'login'; + } + + return $template; + } + + /** + * Returns "no_permission" template. + * + * @return string + * @access protected + */ + protected function getNoPermissionTemplate() + { + $template = $this->getParam('no_permissions_template', ''); + + if ( !$template ) { + return $this->Application->isAdmin ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate'); + } + + return $template; + } + + /** + * Returns "no_group_perm_template" template with fallback to "login" template. + * + * @return string + * @access protected + */ + protected function getMembershipMissingTemplate() + { + $template = $this->getParam('no_group_perm_template'); + + return $template ? $template : $this->getLoginTemplate(); + } + + /** + * Mode, where redirect to same page is made with an 'access_violation' + * parameter instead of redirect to dedicated template. + * + * @return boolean + * @access protected + */ + protected function isSelfRedirect() + { + return $this->getParam('self_redirect'); + } + + /** + * Returns tag parameter value. + * + * @param string $name Parameter name. + * @param mixed $default Default parameter value, when not set. + * + * @return boolean + * @access protected + */ + protected function getParam($name, $default = false) + { + return isset($this->tagParams[$name]) ? $this->tagParams[$name] : $default; + } + + /** + * Checks, that parameter has been passed. + * + * @param string $name Parameter name. + * + * @return boolean + * @access protected + */ + protected function hasParam($name) + { + return $this->getParam($name) !== false; + } + + /** + * Sets given access violation to redirect params. + * + * @param array $redirect_params Redirect parameters. + * @param string $access_violation Access violation code. + * + * @return void + * @access protected + */ + protected function setAccessViolation(&$redirect_params, $access_violation) + { + $redirect_params[$this->accessViolation] = $access_violation; + } + + /** + * Checks, that access violation is already set. + * + * @return boolean + * @access protected + */ + protected function hasAccessViolation() + { + return $this->isSelfRedirect() && ($this->Application->GetVar($this->accessViolation) !== false); + } + + /** + * Throws an exception, that would perform redirect. + * + * @param string $message Exception message. + * @param string $template Template. + * @param array $params Url params. + * + * @return boolean + * @throws kRedirectException Always. + */ + protected function redirect($message, $template, $params) + { + if ( $this->hasAccessViolation() ) { + // already on correct page, don't repeat redirect + return false; + } + + $exception = new kRedirectException($message); + $exception->setup($template, $params); + + throw $exception; + } + +} Index: core/units/helpers/permissions_helper.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/units/helpers/permissions_helper.php (revision 15775) +++ core/units/helpers/permissions_helper.php (revision ) @@ -476,71 +476,6 @@ } /** - * Returns no permission template to redirect to - * - * @param Array $params - * @return Array - */ - function getPermissionTemplate($params) - { - $t = $this->Application->GetVar('t'); - $next_t = getArrayValue($params, 'next_template'); - - if ( $next_t ) { - $t = $next_t; - } - - $redirect_params = $this->Application->HttpQuery->getRedirectParams(true); - - if (array_key_exists('pass_category', $params)) { - $redirect_params['pass_category'] = $params['pass_cateogry']; - } - - if (MOD_REWRITE) { - // TODO: $next_t variable is ignored !!! (is anyone using m_RequireLogin tag with "next_template" parameter?) - $redirect_params = Array ( - 'm_cat_id' => 0, // category means nothing on admin login screen - 'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']), - ); - } - else { - $redirect_params['next_template'] = $t; - } - - if ($this->Application->isAdmin) { - $redirect_params['m_wid'] = ''; // remove wid, otherwise parent window may add wid to its name breaking all the frameset (for targets) - $redirect_params['pass'] = 'm'; // don't pass any other (except "m") prefixes to admin login template - } - - if (!$this->Application->LoggedIn()) { - $redirect_template = array_key_exists('login_template', $params) ? $params['login_template'] : ''; - - if (!$redirect_template && $this->Application->isAdmin) { - $redirect_template = 'login'; - } - } - else { - if (array_key_exists('no_permissions_template', $params)) { - $redirect_template = $params['no_permissions_template']; - } - else { - $redirect_template = $this->Application->isAdmin ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate'); - } - - if ($this->Application->isDebugMode()) { - $redirect_params['from_template'] = 1; - $redirect_params['perms'] = $params[ isset($params['permissions']) ? 'permissions' : 'perm_event' ]; - } - } - - if (isset($params['index_file']) && $params['index_file']) { - $redirect_params['index_file'] = $params['index_file']; - } - - return Array ($redirect_template, $redirect_params); - } - - /** * Check current user permissions based on it's group permissions in specified category (for non-system permissions) or just checks if system permission is set * * @param string $name permission name \ No newline at end of file Index: core/kernel/application.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- core/kernel/application.php (revision 15775) +++ core/kernel/application.php (revision ) @@ -730,6 +730,7 @@ $this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php'); $this->registerClass('PasswordHash', KERNEL_PATH . '/utility/php_pass.php'); + $this->registerClass('PageAccessValidator', KERNEL_PATH . '/utility/page_access_validator.php'); // Params class descendants $this->registerClass('kArray', KERNEL_PATH . '/utility/params.php'); \ No newline at end of file