diff --git a/islandora.module b/islandora.module index f800cf6d..05a3a57b 100644 --- a/islandora.module +++ b/islandora.module @@ -357,6 +357,88 @@ function islandora_forms($form_id) { return $forms; } +/** + * Checks whether the user can access the given object. + * + * Checks for repository access, object/datastream existance, namespace access, + * user permissions, content models. + * + * Will check the given user or the user repersented by the GET token parameter, + * failing that it will use the global user. + * + * @global $user + * + * @param mixed $object + * The FedoraObject or FedoraDatastream to test for accessibility, if NULL + * is given the object is assumed to not exist or be inaccessible. + * @param array $permissions + * The required user permissions. + * @param array $content_models + * The required content models. + * @param bool $access_any + * (optional) TRUE to grant access if any single requirement is met from both + * the permissions and content models parameters. FALSE if all requirements + * must be met from both the permissions and content model parameters. + * @param object $account + * (optional) The account to check, if not given check the GET parameters for + * a token to restore the user. If no GET parameter is present use currently + * logged in user. + * + * @return bool + * TRUE if the user is allowed to access this object/datastream, FALSE + * otherwise. + */ +function islandora_user_access($object, array $permissions, $content_models = array(), $access_any = TRUE, $account = NULL) { + module_load_include('inc', 'islandora', 'includes/utilities'); + $is_repository_accessible = &drupal_static(__FUNCTION__); + // If the repository is inaccessible then access always fails. + if (!isset($is_repository_accessible)) { + $is_repository_accessible = islandora_describe_repository(); + if (!$is_repository_accessible) { + // Only display the inaccessible message once. + islandora_display_repository_inaccessible_message(); + return FALSE; + } + } + if (!$is_repository_accessible || !is_object($object)) { + return FALSE; + } + // Determine the user account to test against. + if (!isset($account)) { + $token = filter_input(INPUT_GET, 'token', FILTER_SANITIZE_STRING); + if ($token) { + module_load_include('inc', 'islandora', 'includes/authtokens'); + $user = islandora_validate_object_token($object->id, $datastream->id, $token); + if ($user) { + $account = user_load($user->uid); + } + } + else { + global $user; + $account = $user; + } + } + // Determine what has been passed as $object. + if (is_subclass_of($object, 'FedoraObject')) { + $object = $object; + } + elseif (is_subclass_of($object, 'FedoraDatastream')) { + $datastream = $object; + $object = $datastream->parent; + } + // Check for access. + $accessible_namespace = islandora_namespace_accessible($object->id); + if ($access_any) { + $has_required_permissions = islandora_user_access_any($permissions, $account); + $has_required_content_models = empty($content_models) ? TRUE : count(array_intersect($object->models, $content_models)) > 0; + } + else { + $has_required_permissions = islandora_user_access_all($permissions, $account); + $has_required_content_models = count(array_diff($content_models, $object->models)) == 0; + } + return $accessible_namespace && $has_required_permissions && $has_required_content_models; +} + /** * Checks whether the user can access the given object. * diff --git a/tests/islandora_manage_permissions.test b/tests/islandora_manage_permissions.test index 76f43a6d..72aebd89 100644 --- a/tests/islandora_manage_permissions.test +++ b/tests/islandora_manage_permissions.test @@ -1,7 +1,17 @@ 'Islandora Manage Permissions', @@ -10,69 +20,117 @@ class IslandoraPermissionsTestCase extends IslandoraWebTestCase { ); } + /** + * Prepares enviroment for testing. + * + * @see IslandoraWebTestCase::setUp() + */ public function setUp() { parent::setUp(array('islandora')); } + /** + * Test manage permissions. + */ public function testManagePermissions() { - - - // permission FEDORA_VIEW_OBJECTS - // create a user with permission + // Test permission FEDORA_VIEW_OBJECTS. + // Create a user with permission. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); - // log the user in + // Log the user in. $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertNoLink('Manage', 'Manage tab is not on current page.'); - - - // permission FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES + + // Test permission FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES)); - // log the user in $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertLink('Manage', 0, 'Manage tab is on current page.'); $this->clickLink(t('Manage')); $this->assertLink('Properties', 0, 'Properties tab is on current page.'); $this->assertNoLink('Datastreams', 'Datastreams tab is not on current page.'); - $this->assertNoLink('Collection','Collection tab is not on current page.'); + $this->assertNoLink('Collection', 'Collection tab is not on current page.'); - - // permission FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS + // Test permission FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS)); - // log the user in $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertLink('Manage', 0, 'Manage tab is on current page.'); $this->clickLink(t('Manage')); $this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.'); $this->assertNoLink('Properties', 'Properties tab is not on current page.'); - $this->assertNoLink('Collection','Collection tab is not on current page.'); - - - // permission FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT + $this->assertNoLink('Collection', 'Collection tab is not on current page.'); + + // Test permission FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT)); - // log the user in - $this->drupalLogin($user); + $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertLink('Manage', 0, 'Manage tab is on current page.'); $this->clickLink(t('Manage')); $this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.'); $this->assertNoLink('Properties', 'Properties tab is not on current page.'); - $this->assertNoLink('Collection','Collection tab is not on current page.'); - - - // permission FEDORA_VIEW_OBJECTS, FEDORA_PURGE + $this->assertNoLink('Collection', 'Collection tab is not on current page.'); + + // Test permission FEDORA_VIEW_OBJECTS, FEDORA_PURGE. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE)); - // log the user in $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertLink('Manage', 0, 'Manage tab is on current page.'); $this->clickLink(t('Manage')); $this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.'); $this->assertNoLink('Properties', 'Properties tab is not on current page.'); - $this->assertNoLink('Collection','Collection tab is not on current page.'); - + $this->assertNoLink('Collection', 'Collection tab is not on current page.'); } - } \ No newline at end of file + /** + * Test generic access functions. + * + * Note that we can't test with the Global user as SimpleTest doesn't support + * it. Therefore we can't test the authtoken support. + */ + public function testAccessFunctions() { + $object = islandora_object_load(variable_get('islandora_repository_pid', 'islandora:root')); + // Test islandora_user_access(); + // Test no object/permissions. + $ret = islandora_user_access(NULL, array()); + $this->assertFalse($ret, 'User access denied when no object/permissions are provided.'); + // Test with object no permissions. + $ret = islandora_user_access($object, array()); + $this->assertFalse($ret, 'User access denied when no permissions are provided.'); + // Test access with matching permission. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user); + $this->assertTrue($ret, 'User access granted when permissions match.'); + // Test access with matching permission but access any is FALSE. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array(), FALSE, $user); + $this->assertFalse($ret, 'User access denied for matching permission but with access any set to FALSE.'); + // Test access with non-matching permission. + $user = $this->drupalCreateUser(array(FEDORA_PURGE)); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user); + $this->assertFalse($ret, 'User access denied when permissions did not match.'); + // Test access with both permissions and content model. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); + $model = $object->models; + $model = reset($model); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array($model), TRUE, $user); + $this->assertTrue($ret, 'User access granted for matching permission and model.'); + // Test access with matching permissions and non-matching content model. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array('islandora:obviouslyNotACModel'), TRUE, $user); + $this->assertFalse($ret, 'User access denied for matching permission and non-matching model.'); + // Test access with all matching permissions and one matching model but + // access any is FALSE. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE)); + $model = $object->models; + $model = reset($model); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array($model, 'islandora:obviouslyNotACModel'), FALSE, $user); + $this->assertFalse($ret, 'User access denied for all matching permissions and one matching model but with access any set to FALSE.'); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array($model), FALSE, $user); + $this->assertTrue($ret, 'User access granted for all matching permissions and matching models with access any set to FALSE.'); + // Test passing in a Datastream. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE)); + $ret = islandora_user_access($object['DC'], array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user); + $this->assertTrue($ret, 'User access granted for matching permissions, with a datastream given instead of an object.'); + } +}