Index: trunk/core/units/general/helpers/permissions_helper.php =================================================================== diff -u -N -r8369 -r8402 --- trunk/core/units/general/helpers/permissions_helper.php (.../permissions_helper.php) (revision 8369) +++ trunk/core/units/general/helpers/permissions_helper.php (.../permissions_helper.php) (revision 8402) @@ -121,6 +121,31 @@ } /** + * Returns owner + primary category for each item (used for permission checking) + * + * @param string $prefix + * @param string $ids + * @return Array + * @author Alex + */ + function GetCategoryItemData($prefix, $ids) + { + if (is_array($ids)) { + $ids = implode(',', $ids); + } + $id_field = $this->Application->getUnitOption($prefix, 'IDField'); + $table_name = $this->Application->getUnitOption($prefix, 'TableName'); + $ci_table = $this->Application->getUnitOption('ci', 'TableName'); + + $sql = 'SELECT '.$id_field.', CreatedById, ci.CategoryId + FROM '.$table_name.' item_table + LEFT JOIN '.$ci_table.' ci ON ci.ItemResourceId = item_table.ResourceId + WHERE '.$id_field.' IN ('.$ids.') AND (ci.PrimaryCat = 1)'; + return $this->Conn->Query($sql, $id_field); + } + + + /** * Checks non-system permission on event per category basis * * @param kEvent $event @@ -132,6 +157,8 @@ $top_prefix = $event->getEventParam('top_prefix'); $event_handler =& $this->Application->recallObject($event->Prefix.'_EventHandler'); + /* @var $event_handler kCatDBEventHandler */ + if ($event->Prefix != $top_prefix) { $top_event = new kEvent($top_prefix.':'.$event->Name); $id = $event_handler->getPassedID($top_event); @@ -140,11 +167,6 @@ $id = $event_handler->getPassedID($event); } - // 1. get primary category of category item - $id_field = $this->Application->getUnitOption($top_prefix, 'IDField'); - $table_name = $this->Application->getUnitOption($top_prefix, 'TableName'); - $ci_table = $this->Application->getUnitOption('ci', 'TableName'); - if (!$id) { // item being created -> check by current (before editing started, saved in OnPreCreate event) category permissions $category_id = $this->Application->IsAdmin() ? $this->Application->RecallVar('m_cat_id') : $this->Application->GetVar('m_cat_id'); @@ -154,41 +176,19 @@ } else { // item being edited -> check by it's primary category permissions - $sql = 'SELECT ci.CategoryId, main_table.CreatedById - FROM '.$table_name.' main_table - LEFT JOIN '.$ci_table.' ci ON ci.ItemResourceId = main_table.ResourceId - WHERE (main_table.'.$id_field.' = '.$id.') AND (ci.PrimaryCat = 1)'; - $item_info = $this->Conn->GetRow($sql); - $category_id = $item_info['CategoryId']; - $owner_id = $item_info['CreatedById']; + $items_info = $this->GetCategoryItemData($top_prefix, $id); + $category_id = $items_info[$id]['CategoryId']; + $owner_id = $items_info[$id]['CreatedById']; } // specific permission check for pending & owner permissions: begin - if (substr($event->Name, 0, 9) == 'OnPreSave' || $event->Name == 'OnCreate' || $event->Name == 'OnUpdate') { - if ($event_handler->isNewItemCreate($event)) { - $check_status = $this->AddCheckPermission($category_id, $top_prefix); - } - else { - $check_status = $this->AddCheckPermission($category_id, $top_prefix) || - $this->ModifyCheckPermission($owner_id, $category_id, $top_prefix); - } - - if (!$check_status) { - $event->status = erPERM_FAIL; - } + $new_item = $this->Application->IsAdmin() && $event_handler->isNewItemCreate($event) ? true : false; + $check_status = $this->checkCombinedPermissions($event, $owner_id, $category_id, $new_item); + if (isset($check_status)) { return $check_status; } - - if ($event->Name == 'OnMassDelete') { - $check_status = $this->DeleteCheckPermission($owner_id, $category_id, $top_prefix); - if (!$check_status) { - $event->status = erPERM_FAIL; - } - return $check_status; - } // specific permission check for pending & owner permissions: end - $perm_status = false; $check_perms = $this->getPermissionByEvent($event, $event_perm_mapping); @@ -205,7 +205,6 @@ continue; } $perm_name = $item_prefix.'.'.$perm_mapping[$perm_name]; - $this->showDebug('Event '.$event->Name.' permission(-s): '.$perm_name.'', Array()); $perm_status = $this->CheckPermission($perm_name, 0, $category_id); if ($perm_status) { @@ -227,12 +226,57 @@ return $perm_status; } - function showDebug($text, $params) + /** + * Allows to check combined permissions (*.owner, *.pending) for add/modify/delete operations from admin & front-end + * + * @param kEvent $event + * @param int $owner_id + * @param int $category_id + * @param bool $new_item + * @return mixed + */ + function checkCombinedPermissions(&$event, $owner_id, $category_id, $new_item = false) { - return ; - $is_ajax = $this->Application->GetVar('ajax') == 'yes' || isset($params['ajax']) || isset($params['tab_init']); - if (!$this->Application->isDebugMode() || $is_ajax) return true; - echo $text.'
'; + $ret = null; // true/false when used, null when not used + $top_prefix = $event->getEventParam('top_prefix'); + + // check admin permission + if (substr($event->Name, 0, 9) == 'OnPreSave') { + if ($new_item) { + $ret = $this->AddCheckPermission($category_id, $top_prefix); + } + else { + // add & modify because $new_item is false, when item is aready created & then saved in temp table (even with 0 id) + $ret = $this->AddCheckPermission($category_id, $top_prefix) || + $this->ModifyCheckPermission($owner_id, $category_id, $top_prefix); + } + } + + // check front-end permissions + switch ($event->Name) { + case 'OnItemLoad': + break; + + case 'OnCreate': + $ret = $this->AddCheckPermission($category_id, $top_prefix); + break; + + case 'OnUpdate': + $ret = $this->ModifyCheckPermission($owner_id, $category_id, $top_prefix); + break; + + case 'OnDelete': + case 'OnMassDelete': + $ret = $this->DeleteCheckPermission($owner_id, $category_id, $top_prefix); + break; + } + + if ($ret === 0) { + // permission check failed (user has no permission) + $event->status = erPERM_FAIL; + } + + return $ret; } function TagPermissionCheck($params, $tag_name) @@ -243,7 +287,6 @@ if ($permission_groups) { // check permissions by permission names in current category - $this->showDebug('Tag '.$tag_name.' permission(-s): '.$permission_groups.'', $params); $permission_groups = explode('|', $permission_groups); $group_has_permission = false; @@ -270,7 +313,6 @@ } elseif ($perm_event) { // check permission by event name - $this->showDebug('Tag '.$tag_name.' permission_event: '.$perm_event.'', $params); list($prefix, $event) = explode(':', $perm_event); $event_handler =& $this->Application->recallObject($prefix.'_EventHandler'); return $event_handler->CheckPermission( new kEvent($perm_event) ); @@ -414,14 +456,20 @@ // cached view permission of category: end } - if ($cat_id == 0) { + if (is_numeric($cat_id) && $cat_id == 0) { $cat_hierarchy = Array(0); } else { - $sql = 'SELECT ParentPath + if (strpos($cat_id, '|') !== false) { + $cat_hierarchy = $cat_id; + } + else { + $sql = 'SELECT ParentPath FROM '.$this->Application->getUnitOption('c', 'TableName').' WHERE CategoryId = '.$cat_id; - $cat_hierarchy = $this->Conn->GetOne($sql); + $cat_hierarchy = $this->Conn->GetOne($sql); + } + $cat_hierarchy = explode('|', substr($cat_hierarchy, 1, -1)); $cat_hierarchy = array_reverse($cat_hierarchy); array_push($cat_hierarchy, 0); @@ -479,6 +527,38 @@ } /** + * Allows to check VIEW & "OWNER.VIEW.PENDING" permission combinations on item + * + * @param int $owner_id user_id, that is owner of the item + * @param int $category_id primary category of item + * @param string $prefix prefix of item + * @return int {0 - no VIEW permission, 1 - has VIEW permission} + */ + function ViewCheckPermission($owner_id, $category_id, $prefix) + { + $perm_prefix = $this->Application->getUnitOption($prefix, 'PermItemPrefix'); + + // in progress + $use_pending_editing = $this->Application->getUnitOption($prefix, 'UsePendingEditing'); + + + $live_delete = $this->CheckPermission($perm_prefix.'.VIEW', ptCATEGORY, $category_id); + if ($live_delete) { + return 1; + } + + if ($owner_id == $this->Application->RecallVar('user_id')) { + // user is item's OWNER -> check this permissions first + $live_delete = $this->CheckPermission($perm_prefix.'.OWNER.DELETE', ptCATEGORY, $category_id); + if ($live_delete) { + return 1; + } + } + + return 0; + } + + /** * Allows to check DELETE & OWNER.DELETE permission combinations on item * * @param int $owner_id user_id, that is owner of the item