X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;ds=sidebyside;f=web%2Fcore%2Fmodules%2Ffilter%2Fsrc%2FTests%2FFilterFormatAccessTest.php;fp=web%2Fcore%2Fmodules%2Ffilter%2Fsrc%2FTests%2FFilterFormatAccessTest.php;h=a4c23b2d5531abb75edd418f3b924171a159e196;hb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;hp=0000000000000000000000000000000000000000;hpb=57c063afa3f66b07c4bbddc2d6129a96d90f0aad;p=yaffs-website diff --git a/web/core/modules/filter/src/Tests/FilterFormatAccessTest.php b/web/core/modules/filter/src/Tests/FilterFormatAccessTest.php new file mode 100644 index 000000000..a4c23b2d5 --- /dev/null +++ b/web/core/modules/filter/src/Tests/FilterFormatAccessTest.php @@ -0,0 +1,335 @@ +drupalPlaceBlock('page_title_block'); + + $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); + + // Create a user who can administer text formats, but does not have + // specific permission to use any of them. + $this->filterAdminUser = $this->drupalCreateUser([ + 'administer filters', + 'create page content', + 'edit any page content', + ]); + + // Create three text formats. Two text formats are created for all users so + // that the drop-down list appears for all tests. + $this->drupalLogin($this->filterAdminUser); + $formats = []; + for ($i = 0; $i < 3; $i++) { + $edit = [ + 'format' => Unicode::strtolower($this->randomMachineName()), + 'name' => $this->randomMachineName(), + ]; + $this->drupalPostForm('admin/config/content/formats/add', $edit, t('Save configuration')); + $this->resetFilterCaches(); + $formats[] = FilterFormat::load($edit['format']); + } + list($this->allowedFormat, $this->secondAllowedFormat, $this->disallowedFormat) = $formats; + $this->drupalLogout(); + + // Create a regular user with access to two of the formats. + $this->webUser = $this->drupalCreateUser([ + 'create page content', + 'edit any page content', + $this->allowedFormat->getPermissionName(), + $this->secondAllowedFormat->getPermissionName(), + ]); + + // Create an administrative user who has access to use all three formats. + $this->adminUser = $this->drupalCreateUser([ + 'administer filters', + 'create page content', + 'edit any page content', + $this->allowedFormat->getPermissionName(), + $this->secondAllowedFormat->getPermissionName(), + $this->disallowedFormat->getPermissionName(), + ]); + $this->drupalPlaceBlock('local_tasks_block'); + } + + /** + * Tests the Filter format access permissions functionality. + */ + public function testFormatPermissions() { + // Make sure that a regular user only has access to the text formats for + // which they were granted access. + $fallback_format = FilterFormat::load(filter_fallback_format()); + $disallowed_format_name = $this->disallowedFormat->getPermissionName(); + $this->assertTrue($this->allowedFormat->access('use', $this->webUser), 'A regular user has access to use a text format they were granted access to.'); + $this->assertEqual(AccessResult::allowed()->addCacheContexts(['user.permissions']), $this->allowedFormat->access('use', $this->webUser, TRUE), 'A regular user has access to use a text format they were granted access to.'); + $this->assertFalse($this->disallowedFormat->access('use', $this->webUser), 'A regular user does not have access to use a text format they were not granted access to.'); + $this->assertEqual(AccessResult::neutral("The '$disallowed_format_name' permission is required.")->cachePerPermissions(), $this->disallowedFormat->access('use', $this->webUser, TRUE), 'A regular user does not have access to use a text format they were not granted access to.'); + $this->assertTrue($fallback_format->access('use', $this->webUser), 'A regular user has access to use the fallback format.'); + $this->assertEqual(AccessResult::allowed(), $fallback_format->access('use', $this->webUser, TRUE), 'A regular user has access to use the fallback format.'); + + // Perform similar checks as above, but now against the entire list of + // available formats for this user. + $this->assertTrue(in_array($this->allowedFormat->id(), array_keys(filter_formats($this->webUser))), 'The allowed format appears in the list of available formats for a regular user.'); + $this->assertFalse(in_array($this->disallowedFormat->id(), array_keys(filter_formats($this->webUser))), 'The disallowed format does not appear in the list of available formats for a regular user.'); + $this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_formats($this->webUser))), 'The fallback format appears in the list of available formats for a regular user.'); + + // Make sure that a regular user only has permission to use the format + // they were granted access to. + $this->assertTrue($this->webUser->hasPermission($this->allowedFormat->getPermissionName()), 'A regular user has permission to use the allowed text format.'); + $this->assertFalse($this->webUser->hasPermission($this->disallowedFormat->getPermissionName()), 'A regular user does not have permission to use the disallowed text format.'); + + // Make sure that the allowed format appears on the node form and that + // the disallowed format does not. + $this->drupalLogin($this->webUser); + $this->drupalGet('node/add/page'); + $elements = $this->xpath('//select[@name=:name]/option', [ + ':name' => 'body[0][format]', + ':option' => $this->allowedFormat->id(), + ]); + $options = []; + foreach ($elements as $element) { + $options[(string) $element['value']] = $element; + } + $this->assertTrue(isset($options[$this->allowedFormat->id()]), 'The allowed text format appears as an option when adding a new node.'); + $this->assertFalse(isset($options[$this->disallowedFormat->id()]), 'The disallowed text format does not appear as an option when adding a new node.'); + $this->assertFalse(isset($options[filter_fallback_format()]), 'The fallback format does not appear as an option when adding a new node.'); + + // Check regular user access to the filter tips pages. + $this->drupalGet('filter/tips/' . $this->allowedFormat->id()); + $this->assertResponse(200); + $this->drupalGet('filter/tips/' . $this->disallowedFormat->id()); + $this->assertResponse(403); + $this->drupalGet('filter/tips/' . filter_fallback_format()); + $this->assertResponse(200); + $this->drupalGet('filter/tips/invalid-format'); + $this->assertResponse(404); + + // Check admin user access to the filter tips pages. + $this->drupalLogin($this->adminUser); + $this->drupalGet('filter/tips/' . $this->allowedFormat->id()); + $this->assertResponse(200); + $this->drupalGet('filter/tips/' . $this->disallowedFormat->id()); + $this->assertResponse(200); + $this->drupalGet('filter/tips/' . filter_fallback_format()); + $this->assertResponse(200); + $this->drupalGet('filter/tips/invalid-format'); + $this->assertResponse(404); + } + + /** + * Tests if text format is available to a role. + */ + public function testFormatRoles() { + // Get the role ID assigned to the regular user. + $roles = $this->webUser->getRoles(TRUE); + $rid = $roles[0]; + + // Check that this role appears in the list of roles that have access to an + // allowed text format, but does not appear in the list of roles that have + // access to a disallowed text format. + $this->assertTrue(in_array($rid, array_keys(filter_get_roles_by_format($this->allowedFormat))), 'A role which has access to a text format appears in the list of roles that have access to that format.'); + $this->assertFalse(in_array($rid, array_keys(filter_get_roles_by_format($this->disallowedFormat))), 'A role which does not have access to a text format does not appear in the list of roles that have access to that format.'); + + // Check that the correct text format appears in the list of formats + // available to that role. + $this->assertTrue(in_array($this->allowedFormat->id(), array_keys(filter_get_formats_by_role($rid))), 'A text format which a role has access to appears in the list of formats available to that role.'); + $this->assertFalse(in_array($this->disallowedFormat->id(), array_keys(filter_get_formats_by_role($rid))), 'A text format which a role does not have access to does not appear in the list of formats available to that role.'); + + // Check that the fallback format is always allowed. + $this->assertEqual(filter_get_roles_by_format(FilterFormat::load(filter_fallback_format())), user_role_names(), 'All roles have access to the fallback format.'); + $this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_get_formats_by_role($rid))), 'The fallback format appears in the list of allowed formats for any role.'); + } + + /** + * Tests editing a page using a disallowed text format. + * + * Verifies that regular users and administrators are able to edit a page, but + * not allowed to change the fields which use an inaccessible text format. + * Also verifies that fields which use a text format that does not exist can + * be edited by administrators only, but that the administrator is forced to + * choose a new format before saving the page. + */ + public function testFormatWidgetPermissions() { + $body_value_key = 'body[0][value]'; + $body_format_key = 'body[0][format]'; + + // Create node to edit. + $this->drupalLogin($this->adminUser); + $edit = []; + $edit['title[0][value]'] = $this->randomMachineName(8); + $edit[$body_value_key] = $this->randomMachineName(16); + $edit[$body_format_key] = $this->disallowedFormat->id(); + $this->drupalPostForm('node/add/page', $edit, t('Save')); + $node = $this->drupalGetNodeByTitle($edit['title[0][value]']); + + // Try to edit with a less privileged user. + $this->drupalLogin($this->webUser); + $this->drupalGet('node/' . $node->id()); + $this->clickLink(t('Edit')); + + // Verify that body field is read-only and contains replacement value. + $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), 'Text format access denied message found.'); + + // Verify that title can be changed, but preview displays original body. + $new_edit = []; + $new_edit['title[0][value]'] = $this->randomMachineName(8); + $this->drupalPostForm(NULL, $new_edit, t('Preview')); + $this->assertText($edit[$body_value_key], 'Old body found in preview.'); + + // Save and verify that only the title was changed. + $this->drupalPostForm('node/' . $node->id() . '/edit', $new_edit, t('Save')); + $this->assertNoText($edit['title[0][value]'], 'Old title not found.'); + $this->assertText($new_edit['title[0][value]'], 'New title found.'); + $this->assertText($edit[$body_value_key], 'Old body found.'); + + // Check that even an administrator with "administer filters" permission + // cannot edit the body field if they do not have specific permission to + // use its stored format. (This must be disallowed so that the + // administrator is never forced to switch the text format to something + // else.) + $this->drupalLogin($this->filterAdminUser); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), 'Text format access denied message found.'); + + // Disable the text format used above. + $this->disallowedFormat->disable()->save(); + $this->resetFilterCaches(); + + // Log back in as the less privileged user and verify that the body field + // is still disabled, since the less privileged user should not be able to + // edit content that does not have an assigned format. + $this->drupalLogin($this->webUser); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), 'Text format access denied message found.'); + + // Log back in as the filter administrator and verify that the body field + // can be edited. + $this->drupalLogin($this->filterAdminUser); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertNoFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", NULL, 'Text format access denied message not found.'); + $this->assertFieldByXPath("//select[@name='$body_format_key']", NULL, 'Text format selector found.'); + + // Verify that trying to save the node without selecting a new text format + // produces an error message, and does not result in the node being saved. + $old_title = $new_edit['title[0][value]']; + $new_title = $this->randomMachineName(8); + $edit = []; + $edit['title[0][value]'] = $new_title; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->assertText(t('@name field is required.', ['@name' => t('Text format')]), 'Error message is displayed.'); + $this->drupalGet('node/' . $node->id()); + $this->assertText($old_title, 'Old title found.'); + $this->assertNoText($new_title, 'New title not found.'); + + // Now select a new text format and make sure the node can be saved. + $edit[$body_format_key] = filter_fallback_format(); + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->assertUrl('node/' . $node->id()); + $this->assertText($new_title, 'New title found.'); + $this->assertNoText($old_title, 'Old title not found.'); + + // Switch the text format to a new one, then disable that format and all + // other formats on the site (leaving only the fallback format). + $this->drupalLogin($this->adminUser); + $edit = [$body_format_key => $this->allowedFormat->id()]; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->assertUrl('node/' . $node->id()); + foreach (filter_formats() as $format) { + if (!$format->isFallbackFormat()) { + $format->disable()->save(); + } + } + + // Since there is now only one available text format, the widget for + // selecting a text format would normally not display when the content is + // edited. However, we need to verify that the filter administrator still + // is forced to make a conscious choice to reassign the text to a different + // format. + $this->drupalLogin($this->filterAdminUser); + $old_title = $new_title; + $new_title = $this->randomMachineName(8); + $edit = []; + $edit['title[0][value]'] = $new_title; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->assertText(t('@name field is required.', ['@name' => t('Text format')]), 'Error message is displayed.'); + $this->drupalGet('node/' . $node->id()); + $this->assertText($old_title, 'Old title found.'); + $this->assertNoText($new_title, 'New title not found.'); + $edit[$body_format_key] = filter_fallback_format(); + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $this->assertUrl('node/' . $node->id()); + $this->assertText($new_title, 'New title found.'); + $this->assertNoText($old_title, 'Old title not found.'); + } + + /** + * Rebuilds text format and permission caches in the thread running the tests. + */ + protected function resetFilterCaches() { + filter_formats_reset(); + } + +}