/** * @dataProvider providerStoreArray */ public function testStoreArray($input, $output) { midcom::get('auth')->request_sudo('midcom.core'); $privilege = new midcom_core_privilege($input); $stat = $privilege->store(); $this->assertEquals($output['stat'], $stat, midcom_connection::get_error_string()); foreach ($output as $field => $value) { if ($field == 'stat') { continue; } $this->assertEquals($value, $privilege->{$field}, 'Difference in field ' . $field); } $stat = $privilege->drop(); $this->assertTrue($stat); midcom::get('auth')->drop_sudo(); }
/** * Writes the privilege to the DB unless the privilege member is still null (in which * case the inherited default will kick in). In all other cases the type will have * already populated storage->object with a temporary object in set_value(). */ function convert_to_storage() { if ($this->privilege) { $object = $this->storage->object; // If we have sufficient privileges, we set all privilege accordingly. // otherwise we log this and exit silently. if ($object->can_do('midgard:privileges')) { $this->privilege->store(); } else { debug_add("Could not synchronize privilege of field {$this->name}, access was denied, midgard:privileges is needed here.", MIDCOM_LOG_WARN); } } }
/** * Drop the privilege. If we are a known DB record, we delete us, otherwise * we return silently. * * @return boolean Indicating success. */ public function drop() { $this->_sync_to_db_object(); if (!$this->__guid) { debug_add('We are not stored, GUID is empty. Ignoring silently.'); return true; } if (!$this->validate()) { debug_add('This privilege failed to validate, rejecting to drop it, see the debug log for details.', MIDCOM_LOG_WARN); debug_print_r('Privilege dump:', $this); return false; } if (!$this->__privilege_object->guid) { // We created this via collector, instantiate a new one $privilege = new midcom_core_privilege($this->__guid); return $privilege->drop(); } try { if (!$this->__privilege_object->delete()) { debug_add('Failed to delete privilege record, aborting. Error: ' . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } catch (Exception $e) { debug_add('Failed to delete privilege record, aborting. Error: ' . $e->getMessage(), MIDCOM_LOG_ERROR); return false; } debug_add("Delete privilege record {$this->__guid} ({$this->__privilege_object->objectguid} {$this->__privilege_object->privilegename} {$this->__privilege_object->assignee} {$this->__privilege_object->value}"); $this->__privilege_object->purge(); $this->_invalidate_cache(); $this->value = MIDCOM_PRIVILEGE_INHERIT; return true; }
/** * Look up a specific content privilege and cache the result. This implements the same semantics * as _collect_content_privileges, but only works for one privilege at a time, which allows us to cut * a few corners and therefore be faster * * @param string $privilegename The privilege to check for * @param string $guid A Midgard GUID pointing to an object * @param string $class DBA Class of the object in question * @param string $user_id The user against which to check the privilege, defaults to the currently authenticated user. * @return boolean True when privilege was found, otherwise false */ private static function _load_content_privilege($privilegename, $guid, $class, $user_id) { $cache_id = $user_id . '::' . $guid; if (!array_key_exists($cache_id, self::$_content_privileges_cache)) { self::$_content_privileges_cache[$cache_id] = array(); } if (array_key_exists($privilegename, self::$_content_privileges_cache[$cache_id])) { return self::$_content_privileges_cache[$cache_id][$privilegename]; } $object_privileges = midcom_core_privilege::get_content_privileges($guid); $last_scope = -1; $content_privilege = null; foreach ($object_privileges as $privilege) { if ($privilege->privilegename != $privilegename || $privilege->scope <= $last_scope || !$privilege->does_privilege_apply($user_id)) { continue; } $last_scope = $privilege->scope; $content_privilege = $privilege; } //owner privileges override everything but person privileges, so we have to cross-check those here if ($privilegename != 'midgard:owner' && $last_scope < MIDCOM_PRIVILEGE_SCOPE_OWNER) { $owner_privileges = midcom::get('auth')->acl->get_owner_default_privileges(); if (array_key_exists($privilegename, $owner_privileges)) { $found = self::_load_content_privilege('midgard:owner', $guid, $class, $user_id); if ($found && self::$_content_privileges_cache[$cache_id]['midgard:owner']) { self::$_content_privileges_cache[$cache_id][$privilegename] = $owner_privileges[$privilegename]; return true; } } } if (!is_null($content_privilege)) { self::$_content_privileges_cache[$cache_id][$privilegename] = $content_privilege->value == MIDCOM_PRIVILEGE_ALLOW; return true; } //if nothing was found, we try to recurse to parent // ==> into SUDO $previous_sudo = midcom::get('auth')->acl->_internal_sudo; midcom::get('auth')->acl->_internal_sudo = true; $parent_guid = midcom::get('dbfactory')->get_parent_guid($guid, $class); midcom::get('auth')->acl->_internal_sudo = $previous_sudo; // <== out of SUDO if ($parent_guid == $guid || !mgd_is_guid($parent_guid)) { return false; } else { $parent_cache_id = $user_id . '::' . $parent_guid; if (!array_key_exists($parent_cache_id, self::$_privileges_cache)) { self::$_content_privileges_cache[$parent_cache_id] = array(); } if (self::_load_content_privilege($privilegename, $parent_guid, null, $user_id)) { self::$_content_privileges_cache[$cache_id][$privilegename] = self::$_content_privileges_cache[$parent_cache_id][$privilegename]; return true; } return false; } }
/** * This helper function will create a new privilege object for the object in question. * It will initialize the privilege with the values given in the arguments, as outlined * below. * * This call requires the <i>midgard:privileges</i> privilege. * * @param midcom_core_dbaobject $object The DBA object we're working on * @param string $name The name of the privilege to add. * @param int $value The privilege value, this defaults to MIDCOM_PRIVILEGE_ALLOW. * @param mixed $assignee A valid assignee suitable for midcom_core_privilege::set_privilege(). This defaults to the currently * active user if authenticated or to 'EVERYONE' otherwise. * @param string $classname An optional class name to which a SELF privilege gets restricted to. Only valid for SELF privileges. * @return midcom_core_privilege The newly created privilege record or false on failure. */ public static function create_new_privilege_object(midcom_core_dbaobject $object, $name, $assignee = null, $value = MIDCOM_PRIVILEGE_ALLOW, $classname = '') { if (!$object->can_do('midgard:privileges')) { debug_add('Could not create a new privilege, permission denied.', MIDCOM_LOG_WARN); return false; } if ($assignee === null) { if (midcom::get('auth')->user === null) { $assignee = 'EVERYONE'; } else { $assignee =& midcom::get('auth')->user; } } $privilege = new midcom_core_privilege(); if (!$privilege->set_assignee($assignee)) { debug_add('Failed to set the assignee, aborting.', MIDCOM_LOG_INFO); return false; } $privilege->set_object($object); $privilege->privilegename = $name; $privilege->value = $value; $privilege->classname = $classname; if (!$privilege->validate()) { debug_add('Failed to validate the newly created privilege.', MIDCOM_LOG_INFO); return false; } return $privilege; }
/** * Return a list of privileges assigned directly to the group. The default implementation * queries the GUID directly using the get_self_privileges method of the * midcom_core_privilege class, which should work fine on all MgdSchema * objects. If the storage object is null, an empty array is returned. * * @return array A list of midcom_core_privilege objects. */ function get_privileges() { if (is_null($this->_storage)) { return array(); } return midcom_core_privilege::get_self_privileges($this->_storage->guid); }
/** * Load the privileges from the database. * * This uses the inheritance chains * loaded by _load_all_groups(). */ private function _load_privileges() { static $cache = array(); if (!array_key_exists($this->id, $cache)) { debug_add("Loading privileges for user {$this->name} ({$this->id})"); if (is_null($this->_all_groups)) { $this->_load_all_groups(); } $this->_privileges = array(); $this->_per_class_privileges = array(); foreach ($this->_inheritance_chains as $inheritance_chain) { // Compute permissions based on this group line. foreach ($inheritance_chain as $group_id) { $this->_merge_privileges($this->_all_groups[$group_id]->get_privileges()); } } // Finally, apply our own privilege set to the one we got from the group $this->_merge_privileges(midcom_core_privilege::get_self_privileges($this->guid)); $cache[$this->id]['direct'] = $this->_privileges; $cache[$this->id]['class'] = $this->_per_class_privileges; } else { $this->_privileges = $cache[$this->id]['direct']; $this->_per_class_privileges = $cache[$this->id]['class']; } }