id) { //open for superuser or registered and thats all what is needed //level = -1 all registered users //level = -2 disabled if ((($level == -1) && $this->id) || (($level == -2) && ($this->authorise('core.manage')))) { return true; } } // User has no permissions return false; } /** * Checks if the user is allowed to edit an item * * * @param int $allowowner * @param int $ownerid * @param int $recurse * @param int $level * @return boolean True on success */ public function editaccess($allowowner, $ownerid, $recurse, $level) { $generalaccess = $this->validate_user($recurse, $level); if ((($allowowner == 1) || $this->authorise('core.edit.own','com_jem')) && ($this->id == $ownerid) && ($ownerid != 0)) { return true; } elseif (($generalaccess == 1) || $this->authorise('core.edit','com_jem')) { return true; } return false; } /** * Checks if the user is a superuser * A superuser will allways have access if the feature is activated * * @return boolean True on success * * @deprecated since version 2.1.5 */ static function superuser() { $user = Factory::getApplication()->getIdentity(); if ($user->authorise('core.manage', 'com_jem')) { return true; } else { return false; } } /** * Checks if the user has the privileges to use the wysiwyg editor * * We could use the validate_user method instead of this to allow to set a groupid * Not sure if this is a good idea * * @return boolean True on success * * @deprecated since version 2.1.5 */ static function editoruser() { return false; } /** * Checks if the user is a maintainer of a category * * @return NULL int of maintained categories or null * * @deprecated Use JemUser::can($action, 'event', $eventid) instead. */ public function ismaintainer($action, $eventid = false) { // lets look if the user is a maintainer $db = Factory::getContainer()->get('DatabaseDriver'); $query = 'SELECT gr.id' . ' FROM #__jem_groups AS gr' . ' LEFT JOIN #__jem_groupmembers AS g ON g.group_id = gr.id' . ' WHERE g.member = ' . (int)$this->id . ' AND ' . $db->quoteName('gr.' . $action . 'event') . ' = 1 ' . ' AND g.member NOT LIKE 0'; $db->setQuery($query); $groupnumber = $db->loadColumn(); // no results, the user is not within a group with the required right if (!$groupnumber) { return false; } // the user is in a group with the required right but is there a // published category where he is allowed to post in? $categories = implode(' OR groupid = ', $groupnumber); if ($action == 'edit') { $query = 'SELECT a.catid' . ' FROM #__jem_cats_event_relations AS a' . ' LEFT JOIN #__jem_categories AS c ON c.id = a.catid' . ' WHERE c.published = 1' . ' AND (c.groupid = ' . $categories . ')' . ' AND a.itemid = ' . $eventid; $db->setQuery($query); } else { $query = 'SELECT id' . ' FROM #__jem_categories' . ' WHERE published = 1' . ' AND (groupid = ' . $categories . ')'; $db->setQuery($query); } $maintainer = $db->loadResult(); if (!$maintainer) { return false; } else { return true; } } /** * Checks if an user is a groupmember and if so * if the group is allowed for $action on venues * */ public function venuegroups($action) { /* * just a basic check to see if the current user is in an usergroup with * access for submitting venues. if a result then return true, otherwise false * * Actions: addvenue, publishvenue, editvenue * * views: venues, venue, editvenue */ $db = Factory::getContainer()->get('DatabaseDriver'); $query = 'SELECT gr.id' . ' FROM #__jem_groups AS gr' . ' LEFT JOIN #__jem_groupmembers AS g ON g.group_id = gr.id' . ' AND '.$db->quoteName('gr.'.$action.'venue').' = 1 ' . ' WHERE g.member = ' . (int)$this->id . ' AND g.member NOT LIKE 0'; ; $db->setQuery($query); $groupnumber = $db->loadResult(); return !empty($groupnumber); } /** * Returns all JEM groups user is member of. * The array returned is keyed by group id where the value is * an assoziative array of ['field_name' => 'row_value'] pairs. * * @param $asset mixed false, string or array of strings to restrict to groups * with at least one of this asset(s) set; * must be valid field names of #__jem_groups table. (optional) * @return mixed List of JEM groups or null */ public function getJemGroups($asset = false) { $userId = (int)$this->id; // no registered user -> no groups if (empty($userId)) { return false; } $db = Factory::getContainer()->get('DatabaseDriver'); if (is_array($asset) && !empty($asset)) { array_walk($asset, function(&$v, $k, $db) { $v = $db->quoteName($v); }, $db); $field = ' AND (' . implode(' > 0 OR ', $asset) . ' > 0)'; } else { $field = empty($asset) ? '' : ' AND ' . $db->quoteName($asset) . ' > 0'; } $query = 'SELECT gr.*' . ' FROM #__jem_groups AS gr' . ' LEFT JOIN #__jem_groupmembers AS gm ON gm.group_id = gr.id' . ' WHERE gm.member = '. $userId . $field . ' GROUP BY gr.id'; $db->setQuery($query); $groups = $db->loadAssocList('id'); return $groups; } /** * Method to return a list of all JEM categories that a user has permission for a given action * * @param mixed $action One or array of 'add', 'edit', 'publish' * @param string $type One of 'event', 'venue' * @param array $options additional options as 'option' => value, supported are: * 'ignore_access' (bool) true if access level should be ignored * 'use_disable' (bool) true to include non-allowed categories with attribute 'disable' set to true * 'owner' (bbol) true if 'edit.own' can be used * * @return array List of categories that this user can do this action (empty array if none). * Other categories will be returned too (with disable = true) if option 'disable' is set. */ public function getJemCategories($action, $type, $options = array()) { $action = (array)$action; $ignore_access = array_key_exists('ignore_access', $options) ? (bool)$options['ignore_access'] : false; $use_disable = array_key_exists('use_disable', $options) ? (bool)$options['use_disable'] : false; $owner = array_key_exists('owner', $options) ? (bool)$options['owner'] : false; $jemsettings = JemHelper::config(); $asset = 'com_jem'; $all = (bool)$this->authorise('core.manage', $asset); if (!$all) { foreach ($action as $act) { switch ($act) { case 'add': $all = (bool)$this->authorise('core.create', $asset); break; case 'edit': $all = (bool)$this->authorise('core.edit', $asset) || (bool)$this->authorise('core.edit.own', $asset); break; case 'publish': $all = (bool)$this->authorise('core.edit.state', $asset); break; default: break; } } } $jemgroups = array(); if (!$all && (($type == 'event') || ($type == 'venue'))) { $fields = array(); foreach ($action as $act) { switch ($act) { case 'add': $fields[] = $act . $type; break; case 'edit': $fields[] = $act . $type; break; case 'publish': $fields[] = $act . $type; break; default: break; } } switch ($type) { case 'event': $create = ($jemsettings->delivereventsyes == -1); $edit = ($jemsettings->eventedit == -1); $edit_own = ($jemsettings->eventowner == 1) && $owner; break; case 'venue': $create = ($jemsettings->deliverlocsyes == -1); $edit = ($jemsettings->venueedit == -1); $edit_own = ($jemsettings->venueowner == 1) && $owner; break; default: $create = $edit = $edit_own = false; break; } // Get all JEM groups with requested permissions and user is member of. $jemgroups = empty($fields) ? array() : $this->getJemGroups($fields); // If registered users are generally allowed (by JEM Settings) to edit events/venues // add JEM group 0 and make category check if (($create && in_array('add', $action)) || (($edit || $edit_own) && in_array('edit', $action))) { $jemgroups[0] = true; } } $disable = ''; $where = $ignore_access ? '' : ' AND c.access IN (' . implode(',', $this->getAuthorisedViewLevels()) . ')'; if (!empty($jemgroups)) { if ($use_disable) { $disable = ', IF (c.groupid IN (' . implode(',', array_keys($jemgroups)) . '), 0, 1) AS disable'; } else { $where .= ' AND c.groupid IN (' . implode(',', array_keys($jemgroups)) . ')'; } } // We have to check ALL categories, also those not seen by user. $db = Factory::getContainer()->get('DatabaseDriver'); $query = 'SELECT DISTINCT c.*' . $disable . ' FROM #__jem_categories AS c' . ' WHERE c.published = 1' . $where . ' ORDER BY c.lft'; $db->setQuery( $query ); $cats = $db->loadObjectList('id'); return $cats; } /** * Checks if user is allowed to do actions on objects. * Respects Joomla and JEM group permissions. * * @param $action mixed One or array of 'add', 'edit', 'publish', 'delete' * @param $type string One of 'event', 'venue' * @param $id mixed The event or venue id or false (default) * @param $created_by mixed User id of creator or false (default) * @param $categoryIds mixed List of category IDs to limit for or false (default) * @return true if allowed, false otherwise * @note If nno categoryIds are given this functions checks if there is any potential way * to allow requested action. To prevent this check set categoryIds to 1 (root category) */ public function can($action, $type, $id = false, $created_by = false, $categoryIds = false) { $userId = (int)$this->id; // guests are not allowed to do anything except looking if (empty($userId) || $this->get('guest', 0)) { return false; } $action = (array)$action; if (!empty($categoryIds)) { $categoryIds = (array)$categoryIds; $catIds = array(); foreach ($categoryIds as $catId) { if ((int)$catId > 0) { // allow 'root' category with which caller can skip "potentially allowed" check $catIds[] = (int)$catId; } } $categoryIds = $catIds; // non-zero integers } else { $categoryIds = array(); } $created_by = (int)$created_by; $id = ($id === false) ? $id : (int)$id; $asset = 'com_jem'; $jemsettings = JemHelper::config(); switch ($type) { case 'event': $create = ($jemsettings->delivereventsyes == -1); $edit = ($jemsettings->eventedit == -1); $edit_own = ($jemsettings->eventowner == 1); $autopubl = ($jemsettings->autopubl == -1); // auto-publish new events // not supported yet //if (!empty($id)) { // $asset .= '.event.' . $id; //} break; case 'venue': $create = ($jemsettings->deliverlocsyes == -1); $edit = ($jemsettings->venueedit == -1); $edit_own = ($jemsettings->venueowner == 1); $autopubl = ($jemsettings->autopublocate == -1); // auto-publish new venues // not supported yet //if (!empty($id)) { // $asset .= '.venue.' . $id; //} break; default: $create = $edit = $edit_own = $autopubl = false; break; } $assets[] = $asset; // not supported yet //foreach($categoryIds as $catId) { // $assets[] = 'com_jem.category.'.$catId; //} // Joomla ACL system, JEM global settings $authorised = false; foreach ($assets as $asset) { if ($authorised) { break; } $authorised |= (boolean)$this->authorise('core.manage', $asset); foreach ($action as $act) { if ($authorised) { break; } switch ($act) { case 'add': $authorised |= $create || $this->authorise('core.create', $asset); break; case 'edit': $authorised |= $this->authorise('core.edit', $asset); // $edit is limited to events not attached to jem groups // user is owner and edit-own is enabled $authorised |= ($edit_own || $this->authorise('core.edit.own', $asset)) && !empty($created_by) && ($userId == $created_by); break; case 'publish': $authorised |= $this->authorise('core.edit.state', $asset); // user is creator of new item and auto-publish is enabled $authorised |= $autopubl && ($id === 0) && (empty($created_by) || ($userId == $created_by)); // user is creator, can edit this item and auto-publish is enabled // (that's because we allowed user to not publish new item with auto-puplish enabled) $authorised |= $autopubl && ($edit || $edit_own) && ($id !== 0) && !empty($created_by) && ($userId == $created_by); break; case 'delete': $authorised |= $this->authorise('core.delete', $asset); break; } } } // JEM User groups if (!$authorised) { if (($type == 'event') || ($type == 'venue')) { $fields = array(); foreach ($action as $act) { switch ($act) { case 'add': case 'edit': case 'publish': $fields[] = $act.$type; break; default: break; } } // Get all JEM groups with requested permissions and user is member of. $jemgroups = empty($fields) ? array() : $this->getJemGroups($fields); // If registered users are generally allowed (by JEM Settings) to edit events/venues // add JEM group 0 and make category check if ($edit && (in_array('edit', $action))) { $jemgroups[0] = true; } if (!empty($jemgroups)) { if (empty($categoryIds) && (($type != 'event') || (empty($id) && (!in_array('publish', $action))))) { $authorised = true; // new events and venues have no limiting categories, so generally authorised } else { // we have a valid event object so check event's categories against jem groups $whereCats = empty($categoryIds) ? '' : ' AND c.id IN ('.implode(',', $categoryIds).')'; $levels = $this->getAuthorisedViewLevels(); // We have to check ALL categories, also those not seen by user. $db = Factory::getContainer()->get('DatabaseDriver'); $query = 'SELECT DISTINCT c.id, c.groupid, c.access' . ' FROM #__jem_categories AS c'; if (!empty($id)) { $query .= ' LEFT JOIN #__jem_cats_event_relations AS rel ON rel.catid = c.id' . ' WHERE rel.itemid = ' . $id . ' AND c.published = 1'; } else { $query .= ' WHERE c.published = 1'; } $query .= $whereCats; $db->setQuery( $query ); $cats = $db->loadObjectList(); } if (!empty($cats)) { $unspecific = in_array('publish', $action) ? -1 : 0; // publish requires jemgroup foreach($cats as $cat) { if (empty($cat->groupid)) { if ($unspecific === 0) { $unspecific = 1; } } else { $unspecific = -1; // at least one group assigned so group permissions take precedence if (in_array($cat->access, $levels) && array_key_exists($cat->groupid, $jemgroups)) { // user can "see" this category and is member of connected jem group granting permission $authorised = true; break; // foreach cats } } } if ($unspecific === 1) { // only categories without connected JEM group found, so user is authorised $authorised = true; } } } } } return (bool)$authorised; } } /** * JEM user class with additional functions. * Compatible with Joomla since 3.4.0. * * @package JEM * * @see JemUserAbstract */ class JemUser extends JemUserAbstract { static function getInstance($id = 0, JUserWrapperHelper $userHelper = null) { // we don't need this helper return parent::_getInstance($id); } }