access.test in Access Control Kit 7
Tests for the access control kit module.
File
access.testView source
<?php
/**
* @file
* Tests for the access control kit module.
*/
/**
* Provides common helper methods for access control kit module tests.
*/
class AccessWebTestCase extends DrupalWebTestCase {
/**
* Creates and returns a new access scheme with random properties.
*
* @param string $type
* (optional) The scheme type. Defaults to 'boolean'.
* @param array $settings
* (optional) The scheme settings. Defaults to array().
*
* @return object
* An access scheme.
*/
public function createScheme($type = 'boolean', $settings = array()) {
$machine_name = drupal_strtolower($this
->randomName());
$name = $this
->randomName();
$description = $this
->randomName();
// Create a scheme.
$scheme = entity_get_controller('access_scheme')
->create(array(
'machine_name' => $machine_name,
'name' => $name,
'type' => $type,
'description' => $description,
));
$scheme->settings = $settings;
$this
->assertNull($scheme->sid);
// Save the scheme and confirm that values come back correct.
$this
->assertIdentical(access_scheme_save($scheme), SAVED_NEW, 'New scheme saved.');
$this
->assertNotNull($scheme->sid);
$this
->assertIdentical($scheme->machine_name, $machine_name);
$this
->assertIdentical($scheme->name, $name);
$this
->assertIdentical($scheme->type, $type);
$this
->assertIdentical($scheme->description, $description);
$this
->assertIdentical($scheme->settings, $settings);
return $scheme;
}
/**
* Creates a list-based scheme with generic realms.
*
* @param string $type
* The list type: 'integer', 'float', or 'text'.
*
* @return object
* An access scheme.
*/
public function createListScheme($type) {
switch ($type) {
case 'integer':
$realms = array(
1 => '1 day',
7 => '1 week',
31 => '1 month',
);
break;
case 'float':
$realms = array(
'0' => '0',
'.25' => '1/4',
'.75' => '3/4',
'1' => '1',
);
break;
case 'text':
$realms = array(
'IL' => 'Illinois',
'IA' => 'Iowa',
'IN' => 'Indiana',
);
break;
default:
$realms = array();
}
field_create_field(array(
'field_name' => 'field_' . $type,
'type' => 'list_' . $type,
'settings' => array(
'allowed_values' => $realms,
),
));
$scheme = $this
->createScheme('list_' . $type, array(
'field_name' => 'field_' . $type,
));
return access_scheme_load($scheme->sid);
}
/**
* Creates a taxonomy-based scheme with randomly named realms.
*
* @param string $machine_name
* The vocabulary machine name.
*
* @return object
* An access scheme.
*/
public function createTaxonomyTermScheme($machine_name) {
$vocabulary = new stdClass();
$vocabulary->name = $this
->randomName();
$vocabulary->machine_name = $machine_name;
$vocabulary->hierarchy = 0;
taxonomy_vocabulary_save($vocabulary);
for ($i = 0; $i < 3; $i++) {
$term = new stdClass();
$term->vid = $vocabulary->vid;
$term->name = $this
->randomName();
taxonomy_term_save($term);
}
$scheme = $this
->createScheme('taxonomy_term', array(
'vocabulary' => $vocabulary->machine_name,
));
return access_scheme_load($scheme->sid);
}
/**
* Creates and returns a new access grant for the given scheme.
*
* @param object $scheme
* An access scheme.
* @param object $role
* (optional) A user role. If omitted, uses the first available scheme role.
* If no role is available, creates one using drupalCreateRole().
* @param object $account
* (optional) A user account. If omitted, uses drupalCreateUser() and adds
* the user to the role.
*
* @return object
* An access grant.
*/
public function createGrant($scheme, $role = NULL, $account = NULL) {
// Make sure we have a user role to assign.
if (!isset($role)) {
// Get the list of roles enabled for this scheme.
$scheme_roles = variable_get('access_scheme_roles_' . $scheme->machine_name, array());
// If the scheme has no enabled roles, create one for it.
if (empty($scheme_roles)) {
$rid = $this
->drupalCreateRole(array(
'access content',
));
$role = user_role_load($rid);
$scheme_roles = array(
$role->rid => $role->name,
);
variable_set('access_scheme_roles_' . $scheme->machine_name, $scheme_roles);
}
else {
$rid = key($scheme_roles);
$role = user_role_load($rid);
}
}
// Make sure we have a user to assign.
if (!isset($account)) {
// Create an account and add it to the role.
$account = $this
->drupalCreateUser(array(
'access content',
));
$account->original = clone $account;
$user_roles = $account->roles + array(
$role->rid => $role->name,
);
user_save($account, array(
'roles' => $user_roles,
));
}
// Create an access grant.
$grant = entity_get_controller('access_grant')
->create(array(
'scheme' => $scheme->machine_name,
'rid' => $role->rid,
'uid' => $account->uid,
));
$this
->assertNull($grant->gid);
// Save the grant and confirm that values come back correct.
$this
->assertIdentical(access_grant_save($grant), SAVED_NEW, 'New grant saved.');
$this
->assertNotNull($grant->gid);
$this
->assertIdentical($grant->scheme, $scheme->machine_name);
$this
->assertIdentical($grant->rid, $role->rid);
$this
->assertIdentical($grant->uid, $account->uid);
return $grant;
}
}
/**
* Tests the access scheme interface.
*/
class AccessSchemeInterfaceTest extends AccessWebTestCase {
/**
* A user with administrative access.
*
* @var object
*/
protected $adminUser;
/**
* The role ID of an ACK-enabled role.
*
* @var int
*/
protected $ackRoleRid;
/**
* Implements getInfo(), required method for SimpleTest.
*/
public static function getInfo() {
return array(
'name' => 'Access scheme interface',
'description' => 'Tests the access scheme admin interface.',
'group' => 'Access control kit',
);
}
/**
* Overrides DrupalWebTestCase::setUp().
*/
public function setUp() {
// Enable the access control kit module.
parent::setUp(array(
'access',
));
// Create and log in our admin user.
$this->adminUser = $this
->drupalCreateUser(array(
'administer access schemes',
));
$this
->drupalLogin($this->adminUser);
// Create a user role for use in the access scheme.
$this->ackRoleRid = $this
->drupalCreateRole(array(
'access content',
));
}
/**
* Create and edit an access scheme via the user interface.
*/
public function testSchemeInterface() {
// Visit the scheme admin overview page.
$this
->drupalGet('admin/structure/access');
// Create a new scheme through the admin form.
$this
->clickLink(t('Add access scheme'));
$this
->clickLink(t('Boolean'));
$this
->assertText(t('Add access scheme: @type', array(
'@type' => t('Boolean'),
)));
$edit = array();
$machine_name = drupal_strtolower($this
->randomName());
$edit['machine_name'] = $machine_name;
$edit['name'] = $this
->randomName();
$edit['description'] = $this
->randomName();
$edit['roles[' . $this->ackRoleRid . ']'] = TRUE;
$this
->drupalPost(NULL, $edit, t('Save access scheme and continue'));
$this
->assertRaw(t('Added access scheme %name.', array(
'%name' => $edit['name'],
)), 'Scheme created successfully.');
$this
->drupalGet('admin/structure/access');
$this
->assertText(t('@name (Machine name: @machine_name)', array(
'@name' => $edit['name'],
'@machine_name' => $machine_name,
)), 'Scheme found in the scheme admin overview listing.');
// Confirm that all submitted values were saved.
$this
->clickLink(t('edit'));
$this
->assertFieldByName('name', $edit['name'], 'The name field is correctly set to ' . $edit['name']);
$this
->assertFieldByName('machine_name', $edit['machine_name'], 'The machine_name field is correctly set to ' . $edit['machine_name']);
$machine_name_disabled = $this
->xpath('//input[@id=:id and @disabled="disabled"]', array(
':id' => 'edit-machine-name',
));
$this
->assertTrue($machine_name_disabled, 'The machine name cannot be changed.');
$this
->assertFieldByName('description', $edit['description'], 'The description field is correctly set to ' . $edit['description']);
$this
->assertFieldChecked('edit-roles-' . $this->ackRoleRid, 'The role is correctly selected.');
$this
->assertText(t('No access-controllable objects available.'), 'Informs that no access-controllable object types have been defined.');
// Edit the scheme.
$edit = array();
$edit['name'] = $this
->randomName();
$this
->drupalPost(NULL, $edit, t('Save access scheme'));
$this
->assertRaw(t('Updated access scheme %name.', array(
'%name' => $edit['name'],
)), 'Scheme updated successfully.');
$this
->assertText(t('@name (Machine name: @machine_name)', array(
'@name' => $edit['name'],
'@machine_name' => $machine_name,
)), 'Updated scheme found in the scheme admin overview listing.');
// Check integration with the Field UI.
$this
->clickLink(t('manage fields'));
$this
->assertText(t('Manage fields'));
$this
->assertText(t('Access control kit user reference'));
$this
->assertText(t('Access control kit role reference'));
$this
->assertText('ack_' . $machine_name);
$this
->drupalGet('admin/structure/access');
$this
->clickLink(t('manage display'));
$this
->assertText(t('Manage display'));
$this
->assertText(t('User'));
$this
->assertText(t('Role'));
// Try to submit a new scheme with a duplicate human-readable name.
$edit['machine_name'] = drupal_strtolower($this
->randomName());
$this
->drupalPost('admin/structure/access/add/boolean', $edit, t('Save access scheme and continue'));
$this
->assertRaw(t('The name %name is already in use.', array(
'%name' => $edit['name'],
)));
// Try to submit a new scheme with a duplicate machine name.
$edit['name'] = $this
->randomName();
$edit['machine_name'] = $machine_name;
$this
->drupalPost('admin/structure/access/add/boolean', $edit, t('Save access scheme and continue'));
$this
->assertText(t('The machine-readable name is already in use. It must be unique.'));
// Try to submit an invalid machine name.
$edit['machine_name'] = '!&^%';
$this
->drupalPost('admin/structure/access/add/boolean', $edit, t('Save access scheme and continue'));
$this
->assertText(t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
// Try to submit some disallowed machine names.
foreach (array(
'add',
'0',
) as $bad_name) {
$edit['machine_name'] = $bad_name;
$this
->drupalPost('admin/structure/access/add/boolean', $edit, t('Save access scheme and continue'));
$this
->assertText(t('Invalid machine-readable name. Enter a name other than @invalid.', array(
'@invalid' => $bad_name,
)));
}
// Ensure that scheme names and descriptions are escaped properly.
$edit = array();
$description = '<strong>' . $this
->randomName() . '</strong>';
$edit['machine_name'] = 'don_t_panic';
$edit['name'] = 'Don\'t Panic & Carry a Towel';
$edit['description'] = '<script>' . $description . '</script>';
$this
->drupalPost('admin/structure/access/add/boolean', $edit, t('Save access scheme and continue'));
// Check that the name isn't double-filtered when used as the page title.
$site_name = variable_get('site_name', 'Drupal');
$this
->assertTitle(t("Don't Panic & Carry a Towel | @site-name", array(
'@site-name' => $site_name,
)));
$this
->assertNoTitle(t('Don't Panic & Carry a Towel | @site-name', array(
'@site-name' => $site_name,
)));
// Check that the name is sanitized in overview.
$this
->drupalGet('admin/structure/access');
$this
->assertRaw('Don't Panic & Carry a Towel');
$this
->assertNoRaw($edit['name']);
// Check that the description is sanitized in overview.
$this
->assertRaw($description);
$this
->assertNoRaw($edit['description']);
}
/**
* Confirm that realm fields are hidden from the scheme UI and Field UI.
*/
public function testSchemeRealmFieldsHidden() {
// Confirm that we're starting clean.
$this
->drupalGet('admin/structure/access/add');
$this
->assertNoText(t('List (integer) field'), 'The list (integer) scheme type is not available.');
// Create a user account scheme, which uses a list_integer realm field.
$edit = array();
$machine_name = drupal_strtolower($this
->randomName());
$edit['machine_name'] = $machine_name;
$edit['name'] = $this
->randomName();
$this
->drupalPost('admin/structure/access/add/user', $edit, t('Save access scheme and continue'));
$this
->drupalGet('admin/structure/access');
$this
->assertText(t('@name (Machine name: @machine_name)', array(
'@name' => $edit['name'],
'@machine_name' => $machine_name,
)), 'Scheme found in the scheme admin overview listing.');
// Confirm that realm fields cannot be deleted through the Field UI.
$this
->drupalGet('admin/structure/access/' . $machine_name . '/fields/ack_' . $machine_name . '/delete');
$this
->assertText(t('This field is locked and cannot be deleted.'), 'Realm fields are locked.');
// Confirm that the presence of a scheme with a list_integer realm field
// does not make the list_integer scheme type available.
$this
->drupalGet('admin/structure/access/add');
$this
->assertNoText(t('List (integer) field'), 'Realm fields are ignored when determining whether a list-based scheme can be created.');
// Create a valid list_integer field and confirm that the scheme type does
// become available.
$field = array(
'field_name' => 'field_valid_list',
'type' => 'list_integer',
);
field_create_field($field);
$this
->drupalGet('admin/structure/access/add');
$this
->assertText(t('List (integer) field'), 'List-based schemes become available when usable fields are present.');
// Confirm that the scheme's realm field is hidden from the scheme UI.
$this
->clickLink(t('List (integer) field'));
$this
->assertNoRaw('ack_' . $machine_name, 'Realm fields are hidden when selecting the base field for a list-based scheme.');
$this
->assertRaw($field['field_name'], 'Usable list fields are selectable on a list-based scheme.');
// Confirm that realm fields are hidden from the Field UI.
$scheme = $this
->createScheme();
$this
->drupalGet('admin/structure/access/' . $scheme->machine_name . '/fields');
$this
->assertNoRaw('ack_' . $machine_name, 'Realm fields are hidden from the Field UI.');
}
/**
* Test the scheme overview with no schemes.
*/
public function testSchemeOverviewEmpty() {
// Delete all schemes.
$schemes = access_scheme_load_multiple(FALSE);
foreach ($schemes as $sid => $scheme) {
access_scheme_delete($sid);
}
// Confirm that no schemes remain in the database.
$this
->assertFalse(access_scheme_load_multiple(FALSE), 'No access schemes found in the database.');
// Check the default message for no schemes.
$this
->drupalGet('admin/structure/access');
$this
->assertText(t('No access schemes available.'), 'No access schemes were found.');
}
/**
* Delete an access scheme via the user interface.
*/
public function testSchemeDelete() {
// Create an access scheme.
$scheme = $this
->createScheme();
$scheme = access_scheme_load($scheme->sid, TRUE);
$this
->assertTrue($scheme, 'Access scheme found in the database.');
// Create an access grant in the scheme.
$grant = $this
->createGrant($scheme);
$grant = access_grant_load($grant->gid, TRUE);
$this
->assertTrue($grant, 'Access grant found in the database.');
// Check deleting from the overview page.
$this
->drupalGet('admin/structure/access');
$this
->clickLink(t('delete'));
$this
->assertRaw(t('Are you sure you want to delete the access scheme %name?', array(
'%name' => $scheme->name,
)), '[confirm deletion] Asks for confirmation.');
// Delete the scheme.
$edit = array();
$this
->drupalPost('admin/structure/access/' . $scheme->machine_name, $edit, t('Delete access scheme'));
$this
->assertRaw(t('Are you sure you want to delete the access scheme %name?', array(
'%name' => $scheme->name,
)), '[confirm deletion] Asks for confirmation.');
$this
->assertRaw(t('All access grants within the scheme will also be deleted. %scheme currently contains 1 access grant on your site. If you remove this scheme, the user may not be able to exercise the permissions assigned by that grant.', array(
'%scheme' => $scheme->name,
)), '[confirm deletion] Informs that all grants will be deleted.');
$this
->assertText(t('This action cannot be undone.'), '[confirm deletion] Informs that deletion is permanent.');
// Confirm deletion.
$this
->drupalPost(NULL, NULL, t('Delete'));
$this
->assertRaw(t('Deleted access scheme %name.', array(
'%name' => $scheme->name,
)), 'Access scheme deleted.');
$this
->assertFalse(access_grant_load($grant->gid, TRUE), 'Access grant is not found in the database.');
$this
->assertFalse(access_scheme_load($scheme->sid, TRUE), 'Access scheme is not found in the database.');
}
}
/**
* Tests for access scheme functions.
*/
class AccessSchemeFunctionTest extends AccessWebTestCase {
/**
* An array of access schemes.
*
* @var array
*/
protected $schemes;
/**
* Implements getInfo(), required method for SimpleTest.
*/
public static function getInfo() {
return array(
'name' => 'Access schemes',
'description' => 'Tests loading, saving and deleting access schemes.',
'group' => 'Access control kit',
);
}
/**
* Overrides DrupalWebTestCase::setUp().
*/
public function setUp() {
// Enable the access control kit module.
parent::setUp(array(
'access',
));
// Create two schemes for testing.
$this->schemes = array();
$this->schemes[] = $this
->createScheme();
$this->schemes[] = $this
->createScheme();
// Attach a handler to each.
foreach ($this->schemes as $scheme) {
entity_get_controller('access_scheme')
->attachHandler($scheme, 'node', 'ACKEntityField');
access_scheme_save($scheme);
}
}
/**
* Test basic create, read, update, and delete functions.
*/
public function testSchemeCRUD() {
$loaded_schemes = access_scheme_load_multiple(FALSE, TRUE);
$this
->assertTrue(count($loaded_schemes), 'Access schemes exist in the database.');
$i = 0;
$count = count($this->schemes);
$names = access_scheme_names();
$bundles = field_info_bundles('access_grant');
foreach ($this->schemes as $scheme) {
$i++;
// Find the test scheme in the name list.
$this
->assertTrue(isset($names[$scheme->machine_name]) && $names[$scheme->machine_name] == $scheme->name, "[scheme {$i} of {$count}] Found the scheme in the name list.");
// Find the test scheme in the bundle list.
$this
->assertTrue(isset($bundles[$scheme->machine_name]), "[scheme {$i} of {$count}] Found the scheme in the bundle list.");
// Confirm that the loaded scheme matches expected values.
$loaded_scheme = $loaded_schemes[$scheme->sid];
$this
->assertEqual($scheme->sid, $loaded_scheme->sid, "[scheme {$i} of {$count}] ID is OK.");
$this
->assertEqual($scheme->machine_name, $loaded_scheme->machine_name, "[scheme {$i} of {$count}] Machine name is OK.");
$this
->assertEqual($scheme->name, $loaded_scheme->name, "[scheme {$i} of {$count}] Human-readable name is OK.");
$this
->assertEqual($scheme->type, $loaded_scheme->type, "[scheme {$i} of {$count}] Scheme type is OK.");
$this
->assertEqual($scheme->description, $loaded_scheme->description, "[scheme {$i} of {$count}] Description is OK.");
// Confirm that the scheme's access realm field exists.
$this
->assertTrue(isset($loaded_scheme->realm_field) && isset($loaded_scheme->realm_field['field_name']) && $loaded_scheme->realm_field['field_name'] == $scheme->realm_field_name, "[scheme {$i} of {$count}] Realm field exists.");
// Confirm that scheme type and realm information were attached.
$this
->assertTrue(isset($loaded_scheme->info) && isset($loaded_scheme->info['type']) && $loaded_scheme->info['type'] == 'boolean', "[scheme {$i} of {$count}] Scheme type info was attached.");
$this
->assertTrue(isset($loaded_scheme->realms) && is_array($loaded_scheme->realms) && $loaded_scheme->realms[0] == t('False') && $loaded_scheme->realms[1] == t('True'), "[scheme {$i} of {$count}] Realm values were attached.");
// Confirm that role information was attached.
$this
->assertTrue(isset($loaded_scheme->roles) && is_array($loaded_scheme->roles), "[scheme {$i} of {$count}] Roles were attached.");
// Confirm that handlers were attached.
$this
->assertTrue(isset($loaded_scheme->handlers) && isset($loaded_scheme->handlers['node']), "[scheme {$i} of {$count}] Handlers were attached.");
$this
->assertEqual(get_class($loaded_scheme->handlers['node']), 'ACKEntityField');
}
// Attempt to load a scheme that doesn't exist.
$sid = count($loaded_schemes) + 1;
$scheme = access_scheme_load($sid);
$this
->assertFalse($scheme, 'Invalid scheme ID does not load.');
// Create a new scheme, which should end up with $sid as its ID.
$this
->createScheme();
// Make sure that the previously invalid ID now loads properly.
$scheme = access_scheme_load($sid);
$this
->assertTrue(!empty($scheme) && is_object($scheme), 'Newly created access scheme loads properly.');
$this
->assertEqual($scheme->sid, $sid, 'Loaded scheme ID is the same as the previously invalid ID.');
// Confirm that schemes can be loaded by machine name.
$loaded_scheme = access_scheme_machine_name_load(str_replace('_', '-', $scheme->machine_name));
$this
->assertEqual($scheme->sid, $loaded_scheme->sid, 'Scheme loads by machine name.');
// Confirm that the scheme can be updated.
$new_name = $this
->randomName();
$loaded_scheme->name = $new_name;
$this
->assertEqual(access_scheme_save($loaded_scheme), SAVED_UPDATED, 'Scheme updated.');
$loaded_scheme = access_scheme_load($scheme->sid, TRUE);
$this
->assertEqual($loaded_scheme->name, $new_name);
// Confirm that the scheme can be deleted.
entity_get_controller('access_scheme')
->attachHandler($loaded_scheme, 'node', 'ACKEntityField');
access_scheme_save($loaded_scheme);
$handlers = db_query('SELECT * FROM {access_handler} WHERE scheme = :scheme', array(
':scheme' => $loaded_scheme->machine_name,
));
$handler = $handlers
->fetch();
$this
->assertFalse(empty($handler), 'Handlers were attached.');
$this
->assertEqual(access_scheme_delete($loaded_scheme->sid), SAVED_DELETED, 'Scheme deleted.');
$this
->assertFalse(access_scheme_load($loaded_scheme->sid));
$handlers = db_query('SELECT * FROM {access_handler} WHERE scheme = :scheme', array(
':scheme' => $loaded_scheme->machine_name,
));
$this
->assertFalse($handlers
->fetch(), 'Handlers were detached.');
$this
->assertNull(variable_get('access_scheme_roles_' . $loaded_scheme->machine_name), 'Role configuration was deleted.');
$bundles = field_info_bundles('access_grant');
$this
->assertFalse(isset($bundles[$loaded_scheme->machine_name]), 'Bundle was deleted.');
// Confirm that the scheme can be recreated.
unset($loaded_scheme->sid);
$this
->assertEqual(access_scheme_save($loaded_scheme), SAVED_NEW, 'Scheme created.');
$this
->assertNotNull($loaded_scheme->sid);
}
/**
* Test deleting an access scheme that contains grants.
*/
public function testSchemeDeleteWithGrants() {
$this
->assertEqual(2, count($this->schemes));
// Create five access grants each for the two test schemes.
foreach ($this->schemes as $scheme) {
// Assert that there are no existing grants for the access scheme.
$has_rows = (bool) db_query_range('SELECT 1 FROM {access_grant} WHERE scheme = :scheme', 0, 1, array(
':scheme' => $scheme->machine_name,
))
->fetchField();
$this
->assertFalse($has_rows);
for ($i = 0; $i < 5; $i++) {
$this
->createGrant($scheme);
}
// Assert that there are now five grants for the access scheme.
$this
->assertEqual(5, db_query('SELECT COUNT(*) FROM {access_grant} WHERE scheme = :scheme', array(
':scheme' => $scheme->machine_name,
))
->fetchField());
}
// Delete the first scheme.
$scheme = reset($this->schemes);
access_scheme_delete($scheme->sid);
// Assert that there are no grants left for the deleted scheme.
$has_rows = (bool) db_query_range('SELECT 1 FROM {access_grant} WHERE scheme = :scheme', 0, 1, array(
':scheme' => $scheme->machine_name,
))
->fetchField();
$this
->assertFalse($has_rows);
// Assert that there are still five grants for the remaining scheme.
$scheme = array_pop($this->schemes);
$this
->assertEqual(5, db_query('SELECT COUNT(*) FROM {access_grant} WHERE scheme = :scheme', array(
':scheme' => $scheme->machine_name,
))
->fetchField());
}
/**
* Ensure that the access scheme static reset works correctly.
*/
public function testSchemeStaticReset() {
$original_scheme = access_scheme_load($this->schemes[0]->sid);
$this
->assertTrue(is_object($original_scheme) && $original_scheme->name == $this->schemes[0]->name, 'Scheme loaded successfully.');
// Change the name and description.
$scheme = $original_scheme;
$scheme->name = $this
->randomName();
$scheme->description = $this
->randomName();
access_scheme_save($scheme);
// Load the scheme.
$new_scheme = access_scheme_load($original_scheme->sid);
$this
->assertEqual($new_scheme->name, $scheme->name);
$this
->assertEqual($new_scheme->description, $scheme->description);
// Delete the scheme.
access_scheme_delete($this->schemes[0]->sid);
$schemes = access_scheme_load_multiple(FALSE);
$this
->assertTrue(!isset($schemes[$this->schemes[0]->sid]), 'The scheme was deleted.');
}
}
/**
* Tests the access grant interface.
*/
class AccessGrantInterfaceTest extends AccessWebTestCase {
/**
* A user with administrative access.
*
* @var object
*/
protected $adminUser;
/**
* An ACK-enabled role.
*
* @var object
*/
protected $ackRole;
/**
* A user to whom access will be granted during the test.
*
* @var object
*/
protected $ackUser;
/**
* Implements getInfo(), required method for SimpleTest.
*/
public static function getInfo() {
return array(
'name' => 'Access grant interface',
'description' => 'Tests the access grant admin interface.',
'group' => 'Access control kit',
);
}
/**
* Overrides DrupalWebTestCase::setUp().
*/
public function setUp() {
// Enable the access control kit module.
parent::setUp(array(
'access',
));
// Create and log in our admin user.
$this->adminUser = $this
->drupalCreateUser(array(
'administer access grants',
));
$this
->drupalLogin($this->adminUser);
// Create a user role for use in an access scheme.
$rid = $this
->drupalCreateRole(array(
'access content',
));
$this->ackRole = user_role_load($rid);
// Create a user account for use in access grants.
$this->ackUser = $this
->drupalCreateUser(array(
'access content',
));
}
/**
* Create and edit an access grant via the user interface.
*/
public function testGrantInterface() {
// Visit the grant admin overview page.
$this
->drupalGet('admin/access');
// Check that the add grant page responds to the presence of access schemes.
$this
->clickLink(t('Add access grant'));
$this
->assertText(t('You have not created any access schemes yet.'), 'Informs that an access scheme must exist before grants can be created.');
$scheme = $this
->createScheme();
$this
->drupalGet('admin/access/add');
$this
->assertNoLink(check_plain($scheme->name), 'The "add grant" list page is bypassed when only one scheme exists.');
$this
->assertText(t('Grant access to @scheme', array(
'@scheme' => $scheme->name,
)));
$deleted_scheme = $this
->createScheme();
$this
->drupalGet('admin/access/add');
$this
->assertLink(check_plain($scheme->name), 0, 'The "add grant" list page is shown when more than one scheme exists.');
$this
->clickLink(check_plain($deleted_scheme->name));
$this
->assertText(t('Grant access to @scheme', array(
'@scheme' => $deleted_scheme->name,
)));
access_scheme_delete($deleted_scheme->sid);
$this
->drupalGet('admin/access/add');
$this
->assertNoLink(check_plain($deleted_scheme->name), 'Deleted schemes are not shown when adding a grant.');
// Set the scheme to use the test role.
$this
->assertText(t('No roles are available for new access grants.'));
$scheme = access_scheme_load($scheme->sid);
$scheme->roles = array(
$this->ackRole->rid => $this->ackRole->name,
);
variable_set('access_scheme_roles_' . $scheme->machine_name, $scheme->roles);
$this
->drupalGet('admin/access/add');
$this
->assertNoText(t('No roles are available for new access grants.'));
// Attempt to create an access grant through the admin form for a role that
// the test user does not yet have.
$this
->assertText(t('Grant access to @scheme', array(
'@scheme' => $scheme->name,
)));
$edit = array();
$edit['user'] = $this->ackUser->name;
$edit['role'] = $this->ackRole->rid;
$field_name = $scheme->realm_field['field_name'];
$edit[$field_name . '[und][1]'] = TRUE;
$this
->drupalPost(NULL, $edit, t('Save'));
$this
->assertText(t('@user is not a member of the @role role.', array(
'@user' => $this->ackUser->name,
'@role' => $this->ackRole->name,
)), 'Cannot add users to roles without access to administer users.');
$this->ackUser = user_load($this->ackUser->uid, TRUE);
$this
->assertFalse(isset($this->ackUser->roles[$this->ackRole->rid]), 'User is not a member of the role.');
// Give the admin user access to grant new roles and try again.
$this->adminUser->original = clone $this->adminUser;
$rid = $this
->drupalCreateRole(array(
'administer users',
));
$role = user_role_load($rid);
$roles = $this->adminUser->roles + array(
$role->rid => $role->name,
);
user_save($this->adminUser, array(
'roles' => $roles,
));
$this
->drupalGet('admin/access/add');
$this
->assertText(t('The user will be added to this role, if not already a member.'), 'User administrators are notified that they can add new roles.');
$this
->drupalPost(NULL, $edit, t('Save'));
$this
->assertRaw(t("Added %scheme for %user's access as %role.", array(
'%scheme' => $scheme->name,
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), 'Grant created successfully.');
$this->ackUser = user_load($this->ackUser->uid, TRUE);
$this
->assertTrue(isset($this->ackUser->roles[$this->ackRole->rid]), 'User has become a member of the role.');
$this
->drupalGet('admin/access');
// Check that all grant fields are correctly shown in the overview.
$this
->assertText(check_plain($this->ackUser->name), 'Grant found in the grant admin overview listing.');
$this
->assertText(check_plain($this->ackRole->name));
$this
->assertText(t('True'));
$this
->assertText(check_plain($scheme->name));
// Test operations links.
$this
->clickLink(t('edit'));
$this
->assertRaw(t('<em>Edit @scheme for</em> @grant', array(
'@scheme' => $scheme->name,
'@grant' => t("@user's access as @role", array(
'@user' => $this->ackUser->name,
'@role' => $this->ackRole->name,
)),
)));
$this
->clickLink(t('Cancel'));
$this
->clickLink(t('delete'));
$this
->assertText(t("Are you sure you want to revoke all @scheme for @user's access as @role?", array(
'@scheme' => $scheme->name,
'@user' => $this->ackUser->name,
'@role' => $this->ackRole->name,
)));
$this
->clickLink(t('Cancel'));
// View the grant.
$this
->clickLink(t('view'));
$this
->assertRaw(t("@user's access as @role", array(
'@user' => $this->ackUser->name,
'@role' => $this->ackRole->name,
)), 'Grant can be rendered.');
$this
->assertText(check_plain($this->ackUser->name));
$this
->assertText(check_plain($this->ackRole->name));
$this
->assertText(t('True'));
$this
->assertText(check_plain($scheme->name));
// Edit the grant.
$this
->clickLink(t('Edit'));
$this
->assertRaw('<label for="edit-user-display">User </label>', 'User field is display only.');
$this
->assertRaw('<label for="edit-role-display">Role </label>', 'Role field is display only.');
$edit = array();
$edit[$field_name . '[und][0]'] = TRUE;
$edit[$field_name . '[und][1]'] = FALSE;
$this
->drupalPost(NULL, $edit, t('Save'));
$this
->assertRaw(t("Updated %scheme for %user's access as %role.", array(
'%scheme' => $scheme->name,
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), 'Grant updated successfully.');
$this
->assertFieldChecked('edit-' . strtr($field_name, '_', '-') . '-und-0', 'New realm assigned.');
$this
->assertNoFieldChecked('edit-' . strtr($field_name, '_', '-') . '-und-1', 'Old realm removed.');
$this
->drupalGet('admin/access');
$this
->assertText(t('False'), 'Updated grant found in the grant admin overview listing.');
$this
->assertNoText(t('True'));
// Try to submit a duplicate grant for this user-role-scheme combination.
$this
->drupalGet('admin/access/add');
$edit = array();
$edit['user'] = $this->ackUser->name;
$edit['role'] = $this->ackRole->rid;
$field_name = $scheme->realm_field['field_name'];
$edit[$field_name . '[und][1]'] = TRUE;
$this
->drupalPost(NULL, $edit, t('Save'));
$this
->assertRaw(t('%user has already been granted access as %role in @scheme.', array(
'@scheme' => $scheme->name,
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), 'Duplicate access grants are not permitted.');
// Attempt to create a grant for an unknown user.
$edit['user'] = $this
->randomName();
$this
->drupalPost(NULL, $edit, t('Save'));
$this
->assertRaw(t('The username %name does not exist.', array(
'%name' => $edit['user'],
)), 'Invalid user references are not permitted.');
// Create a user with an unsafe username.
$new_user = $this
->drupalCreateUser();
$new_user->name = 'Don\'t';
user_save($new_user);
$new_user = user_load($new_user->uid, TRUE);
// Create a role with an unsafe name.
$new_rid = $this
->drupalCreateRole(array(
'access content',
));
$new_role = user_role_load($new_rid);
$new_role->name = 'Panic & Carry';
user_role_save($new_role);
$new_role = user_role_load($new_role->rid);
// Create a scheme with an unsafe name.
$new_scheme = $this
->createScheme();
$new_scheme = access_scheme_load($new_scheme->sid);
$new_scheme->roles = array(
$new_role->rid => $new_role->name,
);
variable_set('access_scheme_roles_' . $new_scheme->machine_name, $new_scheme->roles);
$new_scheme_name = 'a Towel';
$new_scheme->name = '<script>' . $new_scheme_name . '</script>';
access_scheme_save($new_scheme);
$new_scheme = access_scheme_load($new_scheme->sid, TRUE);
// Create a grant with the unsafe values.
$new_grant = $this
->createGrant($new_scheme, $new_role, $new_user);
$field_name = $new_scheme->realm_field['field_name'];
$new_grant->{$field_name} = array(
'und' => array(
array(
'value' => 1,
),
),
);
access_grant_save($new_grant);
// Ensure that grant values are escaped properly in displays.
for ($i = 0; $i < 2; $i++) {
switch ($i) {
case 0:
// Overview.
$this
->drupalGet('admin/access');
// Check the scheme name.
$this
->assertRaw('<script>a Towel</script>');
$this
->assertNoRaw($new_scheme->name);
break;
case 1:
// Rendered view.
$this
->drupalGet('admin/access/grant/' . $new_grant->gid);
// Check that the name isn't double-filtered in the page title.
$site_name = variable_get('site_name', 'Drupal');
$this
->assertTitle(t("Don't's access as Panic & Carry | @site-name", array(
'@site-name' => $site_name,
)));
$this
->assertNoTitle(t("Don't's access as Panic & Carry | @site-name", array(
'@site-name' => $site_name,
)));
break;
}
// Checks common to all displays.
$this
->assertRaw('Don't');
$this
->assertNoRaw($new_user->name);
$this
->assertRaw('Panic & Carry');
$this
->assertNoRaw($new_role->name);
}
}
/**
* Test the grant overview with no grants.
*/
public function testGrantOverviewEmpty() {
// Delete all grants.
$grants = access_grant_load_multiple(FALSE);
foreach ($grants as $gid => $grant) {
access_grant_delete($gid);
}
// Confirm that no grants remain in the database.
$this
->assertFalse(access_grant_load_multiple(FALSE), 'No access grants found in the database.');
// Check the default message for no grants.
$this
->drupalGet('admin/access');
$this
->assertText(t('No access grants available.'), 'No access grants were found.');
}
/**
* Test the grant overview filters.
*/
public function testGrantOverviewFilters() {
// Create two schemes for testing the scheme filter.
$schemes = array(
'good' => $this
->createScheme(),
'bad' => $this
->createScheme(),
);
// Create two roles for testing the role filter.
$rid = $this
->drupalCreateRole(array(
'access content',
));
$roles = array(
'good' => $this->ackRole,
'bad' => user_role_load($rid),
);
// Enable both roles for both schemes.
$scheme_roles = array(
$roles['good']->rid => $roles['good']->name,
$roles['bad']->rid => $roles['bad']->name,
);
variable_set('access_scheme_roles_' . $schemes['good']->machine_name, $scheme_roles);
variable_set('access_scheme_roles_' . $schemes['bad']->machine_name, $scheme_roles);
// Create two users for testing the user filter.
$users = array(
'good' => $this->ackUser,
'bad' => $this
->drupalCreateUser(array(
'access content',
)),
);
// Create two grants for filtering.
$good = $this
->createGrant($schemes['good'], $roles['good'], $users['good']);
$bad = $this
->createGrant($schemes['bad'], $roles['bad'], $users['bad']);
$this
->drupalGet('admin/access');
foreach (array(
'role',
'scheme',
'username',
) as $filter) {
// Make sure that both grants are displayed on the unfiltered display.
$this
->assertLinkByHref('admin/access/grant/' . $good->gid, 0);
$this
->assertLinkByHref('admin/access/grant/' . $bad->gid, 0);
// Filter the display.
$edit = array();
$value = '';
switch ($filter) {
case 'role':
$edit = array(
'rid' => $roles['good']->rid,
);
$value = $roles['good']->name;
break;
case 'scheme':
$edit = array(
'scheme' => $schemes['good']->machine_name,
);
$value = $schemes['good']->name;
break;
case 'username':
$edit = array(
'username' => $users['good']->name,
);
$value = $users['good']->name;
break;
}
$this
->drupalPost(NULL, $edit, 'Filter');
$this
->assertText(t('where @filter is @value', array(
'@filter' => $filter,
'@value' => $value,
)), 'Applied filter for ' . $filter . '.');
// Make sure that only the matching grant is displayed.
$this
->assertLinkByHref('admin/access/grant/' . $good->gid, 0, 'Matching grants were displayed.');
$this
->assertNoLinkByHref('admin/access/grant/' . $bad->gid, 'Non-matching grants were not displayed.');
// Clear the filters.
$this
->drupalPost(NULL, array(), 'Reset');
$this
->assertNoText(t('where @filter is @value', array(
'@filter' => $filter,
'@value' => $value,
)), 'Filter text was removed on reset.');
}
// Test multiple filters.
$this
->drupalPost(NULL, array(
'username' => $users['good']->name,
), 'Filter');
$this
->drupalPost(NULL, array(
'scheme' => $schemes['good']->machine_name,
), 'Refine');
$this
->assertText(t('where @filter is @value', array(
'@filter' => 'username',
'@value' => $users['good']->name,
)), 'Applied filter for username.');
$this
->assertText(t('and where @filter is @value', array(
'@filter' => 'scheme',
'@value' => $schemes['good']->name,
)), 'Applied filter for scheme.');
$this
->assertLinkByHref('admin/access/grant/' . $good->gid, 0, 'Matching grants were displayed.');
$this
->assertNoLinkByHref('admin/access/grant/' . $bad->gid, 'Non-matching grants were not displayed.');
$this
->drupalPost(NULL, array(), 'Undo');
$this
->assertText(t('where @filter is @value', array(
'@filter' => 'username',
'@value' => $users['good']->name,
)), 'Retained filter for username.');
$this
->assertNoText(t('and where @filter is @value', array(
'@filter' => 'scheme',
'@value' => $schemes['good']->name,
)), 'Removed filter for scheme.');
$this
->assertLinkByHref('admin/access/grant/' . $good->gid, 0, 'Matching grants were displayed.');
$this
->assertNoLinkByHref('admin/access/grant/' . $bad->gid, 'Non-matching grants were not displayed.');
$this
->drupalPost(NULL, array(
'scheme' => $schemes['bad']->machine_name,
), 'Refine');
$this
->assertNoLinkByHref('admin/access/grant/' . $good->gid, 'Non-matching grants were not displayed.');
$this
->assertNoLinkByHref('admin/access/grant/' . $bad->gid, 'Non-matching grants were not displayed.');
$this
->assertText(t('No access grants available.'));
// Clear all filters.
$this
->drupalPost(NULL, array(), 'Reset');
$this
->assertLinkByHref('admin/access/grant/' . $good->gid, 0);
$this
->assertLinkByHref('admin/access/grant/' . $bad->gid, 0);
}
/**
* Delete an access grant via the user interface.
*/
public function testGrantDelete() {
// Create an access scheme that uses the test role.
$scheme = $this
->createScheme();
$scheme = access_scheme_load($scheme->sid, TRUE);
$scheme->roles = array(
$this->ackRole->rid => $this->ackRole->name,
);
variable_set('access_scheme_roles_' . $scheme->machine_name, $scheme->roles);
// Add the test user to the test role.
$this->ackUser->original = clone $this->ackUser;
$roles = $this->ackUser->roles + array(
$this->ackRole->rid => $this->ackRole->name,
);
user_save($this->ackUser, array(
'roles' => $roles,
));
$this->ackUser = user_load($this->ackUser->uid, TRUE);
// Create an access grant.
$grant = $this
->createGrant($scheme, $this->ackRole, $this->ackUser);
$field_name = $scheme->realm_field['field_name'];
$grant->{$field_name} = array(
'und' => array(
array(
'value' => 1,
),
),
);
access_grant_save($grant);
$grant = access_grant_load($grant->gid, TRUE);
$this
->assertTrue($grant, 'Access grant found in the database.');
// Check deleting from the overview page.
$this
->drupalGet('admin/access');
$this
->clickLink(t('delete'));
$this
->assertRaw(t("Are you sure you want to revoke all %scheme for %user's access as %role?", array(
'%scheme' => $scheme->name,
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), '[confirm deletion] Asks for confirmation.');
// Delete the grant without removing the user's role.
$edit = array();
$this
->drupalPost('admin/access/grant/' . $grant->gid . '/edit', $edit, t('Delete'));
$this
->assertRaw(t("Are you sure you want to revoke all %scheme for %user's access as %role?", array(
'%scheme' => $scheme->name,
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), '[confirm deletion] Asks for confirmation.');
$this
->assertNoRaw(t("Also revoke %user's membership in the %role role?", array(
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), 'Prompt to revoke the role is not shown when user lacks user admin access.');
// Give the admin user access to administer users and try again.
$this->adminUser->original = clone $this->adminUser;
$rid = $this
->drupalCreateRole(array(
'administer users',
));
$role = user_role_load($rid);
$roles = $this->adminUser->roles + array(
$role->rid => $role->name,
);
user_save($this->adminUser, array(
'roles' => $roles,
));
$this
->drupalGet('admin/access/grant/' . $grant->gid . '/delete');
$this
->assertRaw(t("Also revoke %user's membership in the %role role?", array(
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), 'Prompt to revoke the role is shown when user has user admin access.');
$this
->assertText(t('This action cannot be undone.'), '[confirm deletion] Informs that deletion is permanent.');
$this
->drupalPost(NULL, NULL, t('Delete'));
// Confirm deletion.
$this
->assertRaw(t("Deleted %scheme for %user's access as %role.", array(
'%scheme' => $scheme->name,
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), 'Access grant deleted.');
$this
->assertFalse(access_grant_load($grant->gid, TRUE), 'Access grant is not found in the database.');
$this->ackUser = user_load($this->ackUser->uid, TRUE);
$this
->assertTrue(isset($this->ackUser->roles[$this->ackRole->rid]), 'User is still a member of the role.');
// Repeat with a new grant and the revoke role option checked.
$grant = $this
->createGrant($scheme, $this->ackRole, $this->ackUser);
$grant->{$field_name} = array(
'und' => array(
array(
'value' => 1,
),
),
);
access_grant_save($grant);
$grant = access_grant_load($grant->gid, TRUE);
$this
->assertTrue($grant, 'Access grant found in the database.');
$edit = array();
$edit['revoke_role'] = TRUE;
$this
->drupalPost('admin/access/grant/' . $grant->gid . '/delete', $edit, t('Delete'));
// Confirm deletion and role removal.
$this
->assertRaw(t("Deleted %scheme for %user's access as %role.", array(
'%scheme' => $scheme->name,
'%user' => $this->ackUser->name,
'%role' => $this->ackRole->name,
)), 'Access grant deleted.');
$this
->assertFalse(access_grant_load($grant->gid, TRUE), 'Access grant is not found in the database.');
$this->ackUser = user_load($this->ackUser->uid, TRUE);
$this
->assertFalse(isset($this->ackUser->roles[$this->ackRole->rid]), 'User was removed from the role.');
// Check multiple deletion.
$grant_a = $this
->createGrant($scheme);
$grant_b = $this
->createGrant($scheme);
$edit = array();
$this
->drupalPost('admin/access', $edit, t('Delete selected grants'));
$this
->assertText(t('No items selected'));
$key = 'grants[' . $grant_a->gid . ']';
$edit[$key] = TRUE;
$this
->drupalPost('admin/access', $edit, t('Delete selected grants'));
$this
->assertText('Are you sure you want to delete this access grant?', '[confirm deletion] Asks for confirmation.');
$this
->assertText(access_grant_label($grant_a));
$this
->clickLink(t('Cancel'));
$this
->assertLinkByHref('admin/access/grant/' . $grant_a->gid);
$this
->assertLinkByHref('admin/access/grant/' . $grant_b->gid);
$key = 'grants[' . $grant_b->gid . ']';
$edit[$key] = TRUE;
$this
->drupalPost('admin/access', $edit, t('Delete selected grants'));
$this
->assertText('Are you sure you want to delete these access grants?', '[confirm deletion] Asks for confirmation.');
$this
->assertText(access_grant_label($grant_a));
$this
->assertText(access_grant_label($grant_b));
$this
->assertText(t('This action cannot be undone.'), '[confirm deletion] Informs that deletion is permanent.');
$this
->drupalPost(NULL, array(), t('Delete'));
$this
->assertText('Deleted 2 access grants.');
$this
->assertNoLinkByHref('admin/access/grant/' . $grant_a->gid);
$this
->assertNoLinkByHref('admin/access/grant/' . $grant_b->gid);
$this
->assertFalse(access_grant_load($grant_a->gid, TRUE), 'Access grant is not found in the database.');
$this
->assertFalse(access_grant_load($grant_b->gid, TRUE), 'Access grant is not found in the database.');
}
}
/**
* Tests for access grant functions.
*/
class AccessGrantFunctionTest extends AccessWebTestCase {
/**
* An access scheme.
*
* @var object
*/
protected $scheme;
/**
* An array of access grants.
*
* @var array
*/
protected $grants;
/**
* Implements getInfo(), required method for SimpleTest.
*/
public static function getInfo() {
return array(
'name' => 'Access grants',
'description' => 'Tests loading, saving and deleting access grants.',
'group' => 'Access control kit',
);
}
/**
* Overrides DrupalWebTestCase::setUp().
*/
public function setUp() {
// Enable the access control kit module.
parent::setUp(array(
'access',
));
// Create the test scheme.
$this->scheme = $this
->createScheme();
$this->scheme = access_scheme_load($this->scheme->sid, TRUE);
// Create two grants for testing.
$this->grants = array();
$this->grants[] = $this
->createGrant($this->scheme);
$this->grants[] = $this
->createGrant($this->scheme);
}
/**
* Test basic create, read, update, and delete functions.
*/
public function testGrantCRUD() {
$loaded_grants = access_grant_load_multiple(FALSE, TRUE);
$this
->assertTrue(count($loaded_grants), 'Access grants exist in the database.');
$i = 0;
$count = count($this->grants);
$field_name = $this->scheme->realm_field['field_name'];
foreach ($this->grants as $grant) {
$i++;
// Confirm that the loaded grant matches expected values.
$loaded_grant = $loaded_grants[$grant->gid];
$this
->assertEqual($grant->gid, $loaded_grant->gid, "[grant {$i} of {$count}] ID is OK.");
$this
->assertEqual($grant->scheme, $loaded_grant->scheme, "[grant {$i} of {$count}] Scheme is OK.");
$this
->assertEqual($grant->uid, $loaded_grant->uid, "[grant {$i} of {$count}] User reference is OK.");
$this
->assertEqual($grant->rid, $loaded_grant->rid, "[grant {$i} of {$count}] Role reference is OK.");
// Confirm that the realm field was attached.
$this
->assertTrue(isset($loaded_grant->{$field_name}), "[grant {$i} of {$count}] Realm field is attached.");
}
// Attempt to load a grant that doesn't exist.
$gid = count($loaded_grants) + 1;
$grant = access_grant_load($gid);
$this
->assertFalse($grant, 'Invalid grant ID does not load.');
// Create a new grant, which should end up with $gid as its ID.
$this
->createGrant($this->scheme);
// Make sure that the previously invalid ID now loads properly.
$grant = access_grant_load($gid);
$this
->assertTrue(!empty($grant) && is_object($grant), 'Newly created access grant loads properly.');
$this
->assertEqual($grant->gid, $gid, 'Loaded grant ID is the same as the previously invalid ID.');
// Confirm that the grant can be updated.
if (!empty($grant) && is_object($grant)) {
$grant->{$field_name} = array(
'und' => array(
array(
'value' => 1,
),
),
);
$this
->assertEqual(access_grant_save($grant), SAVED_UPDATED, 'Grant updated.');
$loaded_grant = access_grant_load($grant->gid, TRUE);
$field = $loaded_grant->{$field_name};
$this
->assertEqual($field['und'][0]['value'], 1);
$realms = $loaded_grant->realms;
$this
->assertFalse(isset($realms[0]));
$this
->assertTrue(isset($realms[1]), 'Grant realms found.');
// Confirm that the grant can be deleted.
$this
->assertEqual(access_grant_delete($grant->gid), SAVED_DELETED, 'Grant deleted.');
$this
->assertFalse(access_grant_load($grant->gid));
// Confirm that the grant can be recreated.
unset($grant->gid);
$this
->assertEqual(access_grant_save($grant), SAVED_NEW, 'Grant created.');
}
// Test conditional loading.
$scheme = $this
->createListScheme('integer');
$field_name = $scheme->realm_field['field_name'];
$grant = $this
->createGrant($scheme);
$grant->{$field_name} = array(
'und' => array(
array(
'value' => 7,
),
),
);
access_grant_save($grant);
$grant = $this
->createGrant($scheme);
$grant->{$field_name} = array(
'und' => array(
array(
'value' => 31,
),
),
);
access_grant_save($grant);
$conditions = array(
// Load by scheme.
'scheme' => array(
'condition' => $scheme->machine_name,
'count' => 2,
),
// Load by user.
'uid' => array(
'condition' => $grant->uid,
'count' => 1,
),
// Load by role.
'rid' => array(
'condition' => $grant->rid,
'count' => 2,
),
);
foreach ($conditions as $key => $tests) {
$match = TRUE;
$loaded_grants = access_grant_load_by_condition(array(
$key => $tests['condition'],
));
foreach ($loaded_grants as $loaded_grant) {
$match = $match && $loaded_grant->{$key} == $tests['condition'];
}
$this
->assertTrue($match && count($loaded_grants) == $tests['count'], 'Loaded all grants for ' . $key . ' ' . $tests['condition']);
}
// Load by realms.
$conditions = array(
'scheme' => $scheme->machine_name,
'realms' => array(
31,
),
);
$loaded_grants = access_grant_load_by_condition($conditions);
$loaded_grant = reset($loaded_grants);
$this
->assertTrue(count($loaded_grants) == 1 && $loaded_grant->gid == $grant->gid, 'Loaded only one grant with matching realms.');
$conditions['realms'] = array(
1,
);
$loaded_grants = access_grant_load_by_condition($conditions);
$this
->assertTrue(count($loaded_grants) == 0, 'Did not load grants with mismatching realms.');
}
/**
* Test the access grant rendering functions.
*/
public function testGrantRender() {
$gids = array(
$this->grants[0]->gid,
$this->grants[1]->gid,
);
$loaded_grants = access_grant_load_multiple($gids);
$render = access_grant_view_multiple($loaded_grants, 'full', 3);
// Check weight and sorting.
$this
->assertEqual($render['grants'][$gids[0]]['#weight'], 3, 'Rendered weight is correct.');
$this
->assertEqual($render['grants'][$gids[1]]['#weight'], 4, 'Rendered weight increments.');
$this
->assertTrue($render['grants']['#sorted'], 'Rendered grants are sorted.');
// Check the renderable array.
$this
->assertEqual($render['grants'][$gids[0]]['#theme'], 'access_grant', 'Rendered grants are themed.');
$this
->assertEqual($render['grants'][$gids[0]]['#view_mode'], 'full', 'Grants are rendered in full mode.');
$this
->assertEqual($render['grants'][$gids[0]]['#access_grant']->gid, $gids[0], 'Grant object is included in the renderable array.');
// Check attached fields and pseudo-fields.
$this
->assertEqual($render['grants'][$gids[0]]['#bundle'], $this->scheme->machine_name, 'The bundle property is attached.');
$this
->assertTrue(isset($render['grants'][$gids[0]]['user']), 'The user property is attached.');
$this
->assertTrue(isset($render['grants'][$gids[0]]['role']), 'The role property is attached.');
}
/**
* Ensure that the access grant static reset works correctly.
*/
public function testGrantStaticReset() {
// Set the grant's realm value.
$field_name = $this->scheme->realm_field['field_name'];
$this->grants[0]->{$field_name} = array(
'und' => array(
array(
'value' => 0,
),
),
);
access_grant_save($this->grants[0]);
// Load the grant.
$original_grant = access_grant_load($this->grants[0]->gid);
$this
->assertTrue(is_object($original_grant) && $original_grant->gid == $this->grants[0]->gid, 'Grant loaded successfully.');
$this_grant_field = $this->grants[0]->{$field_name};
$original_grant_field = $original_grant->{$field_name};
$this
->assertEqual($original_grant_field['und'][0]['value'], $this_grant_field['und'][0]['value']);
// Change the grant's realm value.
$grant = $original_grant;
$grant->{$field_name} = array(
'und' => array(
array(
'value' => 1,
),
),
);
access_grant_save($grant);
// Reload the grant.
$new_grant = access_grant_load($original_grant->gid);
$grant_field = $grant->{$field_name};
$new_grant_field = $new_grant->{$field_name};
$this
->assertEqual($new_grant_field['und'][0]['value'], $grant_field['und'][0]['value']);
// Delete the grant.
$grants = access_grant_load_multiple(FALSE);
$this
->assertTrue(isset($grants[$this->grants[0]->gid]), 'The grant exists.');
access_grant_delete($this->grants[0]->gid);
$grants = access_grant_load_multiple(FALSE);
$this
->assertTrue(!isset($grants[$this->grants[0]->gid]), 'The grant was deleted.');
}
}
/**
* Tests the access control kit API.
*/
class AccessAPITest extends AccessWebTestCase {
/**
* An ACK-enabled role.
*
* @var object
*/
protected $ackRole;
/**
* An access scheme.
*
* @var object
*/
protected $scheme;
/**
* Implements getInfo(), required method for SimpleTest.
*/
public static function getInfo() {
return array(
'name' => 'Access control kit API',
'description' => 'Tests the access control kit API and handler interface.',
'group' => 'Access control kit',
);
}
/**
* Overrides DrupalWebTestCase::setUp().
*/
public function setUp() {
// Enable the access control kit module and our dummy test module.
parent::setUp(array(
'access',
'access_test',
));
// Create a role that uses the permission defined in access_test.module.
$rid = $this
->drupalCreateRole(array(
'meow',
));
$this->ackRole = user_role_load($rid);
// Create an access scheme that uses the test role.
$scheme = $this
->createScheme();
$scheme->roles = array(
$this->ackRole->rid => $this->ackRole->name,
);
variable_set('access_scheme_roles_' . $scheme->machine_name, $scheme->roles);
$this->scheme = $scheme;
}
/**
* Attach a handler to the test scheme through the UI.
*
* Checks that the ACK hooks and their alter hooks fire correctly as we go.
*/
public function testHandlerInterface() {
// Create and log in an admin user.
$admin_user = $this
->drupalCreateUser(array(
'administer access schemes',
));
$this
->drupalLogin($admin_user);
// Go to the "add access scheme" page and check that the boolean scheme type
// label was successfully altered.
$this
->drupalGet('admin/structure/access/add');
$this
->assertNoText(t('Boolean'), 'hook_access_scheme_info_alter(): The boolean scheme type info was changed.');
$this
->clickLink(t('Yes or no'));
// Check that the settings callback fired.
$this
->assertText(t('The scheme does not have grants.'), 'Scheme settings callback was called.');
// Check that the access-controllable object types and handlers were
// successfully registered and altered.
$this
->drupalGet('admin/structure/access/' . $this->scheme->machine_name);
$this
->assertText(t('Cat'), 'hook_access_info(): The object type was registered.');
$this
->assertNoText(t('Kitten'), 'hook_access_info_alter(): The access-controllable object type info was changed.');
$this
->assertFieldChecked('edit-handlers-cat-handler');
$this
->assertNoFieldChecked('edit-handlers-cat-handler--2');
$this
->assertFieldByName('handlers[cat][handler]', 'ACKTestMeowHandler', 'hook_access_handler_info(): The handler was registered.');
$this
->assertText(t('Dog'), 'hook_access_info(): The object type was registered.');
$this
->assertFieldChecked('edit-handlers-dog-handler');
$this
->assertNoFieldChecked('edit-handlers-dog-handler--2');
$this
->assertFieldByName('handlers[dog][handler]', 'ACKTestMeowHandler', 'hook_access_handler_info_alter(): The supported object types for the handler were changed.');
$this
->assertText(t('No object access handlers are available to manage @object_type objects in a @scheme_type scheme.', array(
'@object_type' => t('Bird'),
'@scheme_type' => t('Yes or no'),
)), 'The handler UI notifies the user when there are no available handlers.');
// Attach the handler and confirm that the attachment was saved.
$edit = array(
'handlers[cat][handler]' => 'ACKTestMeowHandler',
);
$this
->drupalPost(NULL, $edit, t('Save access scheme'));
$this
->clickLink(t('edit'));
$this
->assertNoFieldChecked('edit-handlers-cat-handler');
$this
->assertFieldChecked('edit-handlers-cat-handler--2', 'The handler was attached to the correct object type.');
$this
->assertFieldChecked('edit-handlers-dog-handler');
$this
->assertNoFieldChecked('edit-handlers-dog-handler--2', 'The handler was not attached to the incorrect object type.');
$this
->assertText(t('The meow handler assigns the boolean TRUE realm to cats and the boolean FALSE realm to everything else.'), 'The handler description was displayed.');
$this
->assertText(t('Meow handler settings would go here.'), 'The handler settings method was called.');
// Detach the handler and confirm that the attachment was deleted.
$edit = array(
'handlers[cat][handler]' => '',
);
$this
->drupalPost(NULL, $edit, t('Save access scheme'));
$this
->clickLink(t('edit'));
$this
->assertFieldChecked('edit-handlers-cat-handler');
$this
->assertNoFieldChecked('edit-handlers-cat-handler--2', 'The handler was detached.');
// Check that the scheme settings form changes when grants are present.
$this
->createGrant($this->scheme, $this->ackRole);
$this
->drupalGet('admin/structure/access/' . $this->scheme->machine_name);
$this
->assertText(t('The scheme has grants.'), 'Scheme form detects existing grants.');
}
/**
* Test access arbitration through our dummy handler.
*/
public function testHandlerMethods() {
$dummy_object = new stdClass();
// Attach the test "meow" handler for dummy "cat" and "dog" object types.
entity_get_controller('access_scheme')
->attachHandler($this->scheme, 'cat', 'ACKTestMeowHandler');
entity_get_controller('access_scheme')
->attachHandler($this->scheme, 'dog', 'ACKTestMeowHandler');
access_scheme_save($this->scheme);
// Reset the scheme cache.
$this->scheme = access_scheme_load($this->scheme->sid, TRUE);
// Create an access grant in the scheme for a test user.
$grant = $this
->createGrant($this->scheme, $this->ackRole);
// Assign access in the TRUE realm.
$fieldname = $this->scheme->realm_field_name;
$grant->{$fieldname} = array(
LANGUAGE_NONE => array(
array(
'value' => TRUE,
),
),
);
access_grant_save($grant);
// Reset grant cache.
access_grant_load($grant->gid, TRUE);
// Get the test user.
$test_user = user_load($grant->uid, TRUE);
// Check access.
$this
->assertTrue(access_user_object_access('meow', 'cat', $dummy_object, $test_user), 'User has access to an object in an assigned realm.');
$this
->assertFalse(access_user_object_access('meow', 'dog', $dummy_object, $test_user), 'User does not have access to an object in an unassigned realm.');
}
/**
* Test clean-up functions.
*/
public function testHandlerCleanup() {
// Attach a handler provided by the access_test module.
entity_get_controller('access_scheme')
->attachHandler($this->scheme, 'cat', 'ACKTestMeowHandler');
access_scheme_save($this->scheme);
$this->scheme = access_scheme_load($this->scheme->sid, TRUE);
// Create and log in an admin user.
$admin_user = $this
->drupalCreateUser(array(
'administer access schemes',
));
$this
->drupalLogin($admin_user);
// Confirm that the handler is attached.
$this
->drupalGet('admin/structure/access/' . $this->scheme->machine_name);
$this
->assertFieldChecked('edit-handlers-cat-handler--2', 'The handler is attached.');
// Disable the access_test module.
module_disable(array(
'access_test',
), FALSE);
drupal_flush_all_caches();
$this->scheme = access_scheme_load($this->scheme->sid, TRUE);
$this
->drupalGet('admin/structure/access/' . $this->scheme->machine_name);
$this
->assertNoText('Meow', 'The handler is not listed.');
// Uninstall the access_test module, then re-enable and check handlers.
drupal_uninstall_modules(array(
'access_test',
), FALSE);
drupal_flush_all_caches();
module_enable(array(
'access_test',
), FALSE);
drupal_flush_all_caches();
$this->scheme = access_scheme_load($this->scheme->sid, TRUE);
$this
->drupalGet('admin/structure/access/' . $this->scheme->machine_name);
$this
->assertNoFieldChecked('edit-handlers-cat-handler--2', 'The handler did not reattach after uninstall.');
}
}
/**
* Tests the bundled scheme types and handlers.
*/
class AccessPluginTest extends AccessWebTestCase {
/**
* Implements getInfo(), required method for SimpleTest.
*/
public static function getInfo() {
return array(
'name' => 'Access control kit plugins',
'description' => 'Tests the scheme type and handler plugins.',
'group' => 'Access control kit',
);
}
/**
* Overrides DrupalWebTestCase::setUp().
*/
public function setUp() {
parent::setUp(array(
'access',
'taxonomy',
));
// We need to start without any defined vocabularies.
foreach (taxonomy_vocabulary_get_names() as $vocabulary) {
taxonomy_vocabulary_delete($vocabulary->vid);
}
}
/**
* Check that scheme types are defined correctly.
*/
public function testSchemeInfo() {
$info = access_scheme_info();
// The boolean type should always be available.
$this
->assertTrue(isset($info['boolean']), 'The boolean scheme type is defined.');
$scheme = $this
->createScheme('boolean');
$scheme = access_scheme_load($scheme->sid);
$realms = array(
0 => t('False'),
1 => t('True'),
);
$diff_a = array_diff_assoc($scheme->realms, $realms);
$diff_b = array_diff_assoc($realms, $scheme->realms);
$this
->assertTrue(empty($diff_a) && empty($diff_b), 'The boolean realms were found.');
// The user type should always be available.
$this
->assertTrue(isset($info['user']), 'The user scheme type is defined.');
$scheme = $this
->createScheme('user');
$scheme = access_scheme_load($scheme->sid);
$realms = db_query('SELECT uid, name FROM {users} WHERE uid > 0')
->fetchAllKeyed();
$diff_a = array_diff_assoc($scheme->realms, $realms);
$diff_b = array_diff_assoc($realms, $scheme->realms);
$this
->assertTrue(empty($diff_a) && empty($diff_b), 'The user realms were found.');
// The list types should not be available until a field exists.
foreach (array(
'integer',
'float',
'text',
) as $type) {
$list = 'list_' . $type;
$field_name = 'field_' . $type;
$this
->assertFalse(isset($info[$list]), 'The ' . $list . ' scheme type is not available without a usable field.');
$scheme = $this
->createListScheme($type);
$info = access_scheme_info();
$this
->assertTrue(isset($info[$list]), 'The ' . $list . ' scheme type is available when a usable field exists.');
$field = field_info_field($field_name);
$realms = list_allowed_values($field);
$diff_a = array_diff_assoc($scheme->realms, $realms);
$diff_b = array_diff_assoc($realms, $scheme->realms);
$this
->assertTrue(empty($diff_a) && empty($diff_b), 'The ' . $list . ' realms were found.');
$settings_form = call_user_func_array($scheme->info['settings callback'], array(
$scheme,
FALSE,
));
$this
->assertTrue(isset($settings_form['field_name']), 'The ' . $list . ' settings form was found.');
$this
->assertTrue(isset($settings_form['field_name']['#options'][$field_name]), 'The usable ' . $list . ' field appears as an option.');
}
// The taxonomy type should not be available until a vocabulary exists.
$this
->assertFalse(isset($info['taxonomy_term']), 'The taxonomy_term scheme type is not available without a usable vocabulary.');
$scheme = $this
->createTaxonomyTermScheme('vocabulary_taxonomy_term');
$info = access_scheme_info();
$this
->assertTrue(isset($info['taxonomy_term']), 'The taxonomy_term scheme type is available when a usable vocabulary exists.');
$vocabulary = taxonomy_vocabulary_machine_name_load('vocabulary_taxonomy_term');
$realms = db_query('SELECT tid, name FROM {taxonomy_term_data} WHERE vid = :vid', array(
':vid' => $vocabulary->vid,
))
->fetchAllKeyed();
$diff_a = array_diff_assoc($scheme->realms, $realms);
$diff_b = array_diff_assoc($realms, $scheme->realms);
$this
->assertTrue(empty($diff_a) && empty($diff_b), 'The taxonomy_term realms were found.');
$settings_form = call_user_func_array($scheme->info['settings callback'], array(
$scheme,
FALSE,
));
$this
->assertTrue(isset($settings_form['vocabulary']), 'The taxonomy_term settings form was found.');
$this
->assertTrue(isset($settings_form['vocabulary']['#options'][$vocabulary->machine_name]), 'The usable vocabulary appears as an option.');
}
/**
* Check that handlers are defined correctly.
*/
public function testHanderInfo() {
$info = access_handler_info();
// We need schemes and a representative entity to test the handlers.
$scheme_list = $this
->createListScheme('integer');
$scheme_term = $this
->createTaxonomyTermScheme('vocabulary_taxonomy_term');
$content_type = $this
->drupalCreateContentType();
// Add a list field to the content type.
$instance = array(
'field_name' => 'field_integer',
'entity_type' => 'node',
'bundle' => $content_type->type,
);
field_create_instance($instance);
// Add a term reference field to the content type.
$field = array(
'field_name' => 'field_term',
'type' => 'taxonomy_term_reference',
'settings' => array(
'allowed_values' => array(
array(
'vocabulary' => 'vocabulary_taxonomy_term',
'parent' => '0',
),
),
),
);
field_create_field($field);
$instance = array(
'field_name' => 'field_term',
'entity_type' => 'node',
'bundle' => $content_type->type,
'required' => TRUE,
);
field_create_instance($instance);
// Create the test node.
$node = $this
->drupalCreateNode(array(
'type' => $content_type->type,
));
$node = node_load($node->nid);
$node->field_integer[LANGUAGE_NONE][]['value'] = 7;
$node->field_term[LANGUAGE_NONE][]['tid'] = 3;
node_save($node);
// Get the node form for later reference.
$node_form_state = array();
$node_form_state['build_info']['args'] = array(
$node,
);
module_load_include('inc', 'node', 'node.pages');
$node_form = drupal_build_form($node->type . '_node_form', $node_form_state);
// Test the generic field handler.
$this
->assertTrue(isset($info['ACKEntityField']), 'Found the generic field handler.');
$handler = new ACKEntityField($scheme_list);
$description = $handler
->description();
$this
->assertIdentical($description, t('The value of %field_name will determine realm membership.', array(
'%field_name' => 'field_integer',
)), 'Generic handler has the correct description.');
$form = $handler
->settingsForm();
$this
->assertIdentical($form, array(), 'Generic handler has no settings.');
$realms = $handler
->objectRealms('node', $node);
$this
->assertIdentical($realms, array(
7,
), 'Generic handler can find realm values on a node.');
// Test altering the node form.
$this
->assertTrue(empty($node_form['field_integer'][LANGUAGE_NONE]['#disabled']), 'List field is accessible before handler is applied.');
$handler
->objectFormAlter('node', $node, $node_form, $node_form_state, $node->type . '_node_form');
$this
->assertTrue($node_form['field_integer'][LANGUAGE_NONE]['#disabled'], 'List field is locked after handler is applied.');
$this
->assertTrue(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['_none']), 'List field contains the _none option.');
$this
->assertTrue(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['1']), 'List field contains option 1.');
$this
->assertTrue(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['7']), 'List field contains option 7.');
$this
->assertTrue(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['31']), 'List field contains option 31.');
$handler
->objectFormAlter('node', $node, $node_form, $node_form_state, $node->type . '_node_form', array(
'7',
'31',
'365',
));
$this
->assertTrue(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['_none']), 'The _none option was not removed from the list.');
$this
->assertFalse(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['1']), 'Option 1 was removed from the the list.');
$this
->assertTrue(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['7']), 'Option 7 remains in the list.');
$this
->assertTrue(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['31']), 'Option 31 remains in the list.');
$this
->assertFalse(isset($node_form['field_integer'][LANGUAGE_NONE]['#options']['365']), 'Option 365 was not added to the list.');
// Test the taxonomy term reference handler.
$this
->assertTrue(isset($info['ACKEntityTaxonomyTermReference']), 'Found the term reference field handler.');
$handler = new ACKEntityTaxonomyTermReference($scheme_term, array(
'field_name' => 'field_term',
));
$description = $handler
->description();
$this
->assertIdentical($description, t('The value of the selected term reference field will determine realm membership.'), 'Term handler has the correct description.');
$form = $handler
->settingsForm();
$this
->assertTrue(isset($form['field_name']['#default_value']), 'Term handler has settings.');
$this
->assertIdentical($form['field_name']['#default_value'], 'field_term', 'Term handler settings default to the saved value.');
$realms = $handler
->objectRealms('node', $node);
$this
->assertIdentical($realms, array(
3,
), 'Term handler can find realm values on a node.');
$this
->assertTrue(empty($node_form['field_term'][LANGUAGE_NONE]['#disabled']), 'Term field is accessible before handler is applied.');
$this
->assertTrue(isset($node_form['field_term'][LANGUAGE_NONE]['#options']['1']), 'Term field contains option 1.');
$this
->assertTrue(isset($node_form['field_term'][LANGUAGE_NONE]['#options']['2']), 'Term field contains option 2.');
$this
->assertTrue(isset($node_form['field_term'][LANGUAGE_NONE]['#options']['3']), 'Term field contains option 3.');
$this
->assertEqual($node_form['field_term'][LANGUAGE_NONE]['#default_value'], array(
'3',
), 'Term field defaults to the saved value.');
$handler
->objectFormAlter('node', $node, $node_form, $node_form_state, $node->type . '_node_form', array(
'2',
));
$this
->assertFalse(isset($node_form['field_term'][LANGUAGE_NONE]['#options']['_none']), 'The _none option was not added to the term field.');
$this
->assertFalse(isset($node_form['field_term'][LANGUAGE_NONE]['#options']['1']), 'Option 1 was removed from the term field.');
$this
->assertTrue(isset($node_form['field_term'][LANGUAGE_NONE]['#options']['2']), 'Option 2 remains in the term field.');
$this
->assertFalse(isset($node_form['field_term'][LANGUAGE_NONE]['#options']['3']), 'Option 3 was removed from the term field.');
$this
->assertTrue($node_form['field_term'][LANGUAGE_NONE]['#disabled'], 'Term field is locked after the handler is applied.');
$this
->assertEqual($node_form['field_term'][LANGUAGE_NONE]['#default_value'], array(
'2',
), 'Only allowable term value is preselected by the handler.');
}
}
Classes
Name | Description |
---|---|
AccessAPITest | Tests the access control kit API. |
AccessGrantFunctionTest | Tests for access grant functions. |
AccessGrantInterfaceTest | Tests the access grant interface. |
AccessPluginTest | Tests the bundled scheme types and handlers. |
AccessSchemeFunctionTest | Tests for access scheme functions. |
AccessSchemeInterfaceTest | Tests the access scheme interface. |
AccessWebTestCase | Provides common helper methods for access control kit module tests. |