commit 5046bb8e72e4781e887d06914eb6317ac39f244e Author: Pieter Frenssen Date: Wed Aug 12 09:15:52 2015 +0200 77 diff --git a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php index 91547c4..f0e01dd 100644 --- a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php +++ b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php @@ -99,7 +99,7 @@ function testNodeAccessBasic() { // Array of nids marked private. $private_nodes = []; for ($i = 0; $i < $num_simple_users; $i++) { - $simple_users[$i] = $this->drupalCreateUser(array('access content', 'create article content')); + $simple_users[$i] = $this->drupalCreateUser(array('access content', 'create article content', 'create terms in tags')); } foreach ($simple_users as $this->webUser) { $this->drupalLogin($this->webUser); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyOverviewAccessCheck.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyOverviewAccessCheck.php new file mode 100644 index 0000000..db73156 --- /dev/null +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyOverviewAccessCheck.php @@ -0,0 +1,36 @@ +hasPermission('administer taxonomy') || $account->hasPermission('access taxonomy overview'); + + return $access ? static::ALLOW : static::DENY; + } + +} diff --git a/core/modules/taxonomy/src/Form/OverviewTerms.php b/core/modules/taxonomy/src/Form/OverviewTerms.php index 556e79b..45d1e3a 100644 --- a/core/modules/taxonomy/src/Form/OverviewTerms.php +++ b/core/modules/taxonomy/src/Form/OverviewTerms.php @@ -204,14 +204,23 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular $destination = $this->getDestinationArray(); $row_position = 0; // Build the actual form. + $access_controller = \Drupal::entityManager()->getAccessController('taxonomy_term'); + if ($access_controller->createAccess($taxonomy_vocabulary->id())) { + $empty = $this->t('No terms available. Add term.', ['@link' => $this->url('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $taxonomy_vocabulary->id()])]), + } + else { + $empty = $this->t('No terms available.'); + } $form['terms'] = array( '#type' => 'table', '#header' => array($this->t('Name'), $this->t('Weight'), $this->t('Operations')), - '#empty' => $this->t('No terms available. Add term.', array('@link' => $this->url('entity.taxonomy_term.add_form', array('taxonomy_vocabulary' => $taxonomy_vocabulary->id())))), + '#empty' => $empty, '#attributes' => array( 'id' => 'taxonomy', ), ); + $change_weight_access = TRUE; + $operations_access = TRUE; foreach ($current_page as $key => $term) { /** @var $term \Drupal\Core\Entity\EntityInterface */ $form['terms'][$key]['#term'] = $term; @@ -256,28 +265,36 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular ), ); } - $form['terms'][$key]['weight'] = array( - '#type' => 'weight', - '#delta' => $delta, - '#title' => $this->t('Weight for added term'), - '#title_display' => 'invisible', - '#default_value' => $term->getWeight(), - '#attributes' => array( - 'class' => array('term-weight'), - ), - ); - $operations = array( - 'edit' => array( + $edit_access = $term->access('update'); + $change_weight_access &= $edit_access; + + if ($edit_access) { + $form['terms'][$key]['weight'] = [ + '#type' => 'weight', + '#delta' => $delta, + '#title' => $this->t('Weight for added term'), + '#title_display' => 'invisible', + '#default_value' => $term->getWeight(), + '#attributes' => ['class' => ['term-weight']], + '#access' => $edit_access, + ]; + } + $operations = array(); + + if ($edit_access) { + $operations['edit'] = [ 'title' => $this->t('Edit'), 'query' => $destination, 'url' => $term->urlInfo('edit-form'), - ), - 'delete' => array( + ]; + } + if ($term->access('delete')) { + $operations['delete'] = [ 'title' => $this->t('Delete'), 'query' => $destination, 'url' => $term->urlInfo('delete-form'), - ), - ); + ]; + } if ($this->moduleHandler->moduleExists('content_translation') && content_translation_translate_access($term)->isAllowed()) { $operations['translate'] = array( 'title' => $this->t('Translate'), @@ -285,10 +302,14 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular 'url' => $term->urlInfo('drupal:content-translation-overview'), ); } - $form['terms'][$key]['operations'] = array( - '#type' => 'operations', - '#links' => $operations, - ); + + $operations_access &= count($operations) > 0; + if (count($operations)) { + $form['terms'][$key]['operations'] = array( + '#type' => 'operations', + '#links' => $operations, + ); + } $form['terms'][$key]['#attributes']['class'] = array(); if ($parent_fields) { @@ -318,32 +339,40 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular $row_position++; } - if ($parent_fields) { - $form['terms']['#tabledrag'][] = array( - 'action' => 'match', - 'relationship' => 'parent', - 'group' => 'term-parent', - 'subgroup' => 'term-parent', - 'source' => 'term-id', - 'hidden' => FALSE, - ); - $form['terms']['#tabledrag'][] = array( - 'action' => 'depth', - 'relationship' => 'group', - 'group' => 'term-depth', - 'hidden' => FALSE, - ); - $form['terms']['#attached']['library'][] = 'taxonomy/drupal.taxonomy'; - $form['terms']['#attached']['drupalSettings']['taxonomy'] = [ - 'backStep' => $back_step, - 'forwardStep' => $forward_step, + $form['terms']['#header'] = array($this->t('Name')); + if ($change_weight_access) { + $form['terms']['#header'][] = $this->t('Weight'); + if ($parent_fields) { + $form['terms']['#tabledrag'][] = [ + 'action' => 'match', + 'relationship' => 'parent', + 'group' => 'term-parent', + 'subgroup' => 'term-parent', + 'source' => 'term-id', + 'hidden' => FALSE, + ]; + $form['terms']['#tabledrag'][] = [ + 'action' => 'depth', + 'relationship' => 'group', + 'group' => 'term-depth', + 'hidden' => FALSE, + ]; + $form['terms']['#attached']['library'][] = 'taxonomy/drupal.taxonomy'; + $form['terms']['#attached']['drupalSettings']['taxonomy'] = [ + 'backStep' => $back_step, + 'forwardStep' => $forward_step, + ]; + } + $form['terms']['#tabledrag'][] = [ + 'action' => 'order', + 'relationship' => 'sibling', + 'group' => 'term-weight', ]; } - $form['terms']['#tabledrag'][] = array( - 'action' => 'order', - 'relationship' => 'sibling', - 'group' => 'term-weight', - ); + + if ($operations_access) { + $form['terms']['#header'][] = $this->t('Operations'); + } if ($taxonomy_vocabulary->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) { $form['actions'] = array('#type' => 'actions', '#tree' => FALSE); @@ -351,11 +380,13 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular '#type' => 'submit', '#value' => $this->t('Save'), '#button_type' => 'primary', + '#access' => $change_weight_access, ); $form['actions']['reset_alphabetical'] = array( '#type' => 'submit', '#submit' => array('::submitReset'), '#value' => $this->t('Reset to alphabetical'), + '#access' => $change_weight_access, ); } diff --git a/core/modules/taxonomy/src/Tests/VocabularyPermissionsTest.php b/core/modules/taxonomy/src/Tests/VocabularyPermissionsTest.php index 00df789..1827cb0 100644 --- a/core/modules/taxonomy/src/Tests/VocabularyPermissionsTest.php +++ b/core/modules/taxonomy/src/Tests/VocabularyPermissionsTest.php @@ -15,6 +15,33 @@ class VocabularyPermissionsTest extends TaxonomyTestBase { /** + * Create, edit and delete a vocabulary via the user interface. + */ + function testVocabularyPermissionsVocabulary() { + // VocabularyTest.php already tests for user with "administer taxonomy" permissions. + + // Test as user without proper permissions. + $authenticated_user = $this->drupalCreateUser(array()); + $this->drupalLogin($authenticated_user); + + // Visit the main taxonomy administration page. + $this->drupalGet('admin/structure/taxonomy'); + $this->assertResponse(403, 'Vocabulary overview open failed.'); + + // Test as user with "access taxonomy overview" permissions. + $proper_user = $this->drupalCreateUser(array('access taxonomy overview')); + $this->drupalLogin($proper_user); + + // Visit the main taxonomy administration page. + $this->drupalGet('admin/structure/taxonomy'); + $this->assertResponse(200); + $this->assertText(t('Vocabulary name'), 'Vocabulary overview opened successfully.'); + + // Create a new vocabulary. + $this->assertNoLink(t('Add vocabulary')); + } + + /** * Create, edit and delete a taxonomy term via the user interface. */ function testVocabularyPermissionsTaxonomyTerm() { @@ -57,8 +84,35 @@ function testVocabularyPermissionsTaxonomyTerm() { $this->drupalPostForm(NULL, NULL, t('Delete')); $this->assertRaw(t('Deleted term %name.', array('%name' => $edit['name[0][value]'])), 'Term deleted.'); + // Test as user with "create" permissions. + $user = $this->drupalCreateUser(array("access taxonomy overview", "create terms in {$vocabulary->id()}")); + $this->drupalLogin($user); + + // Visit the main taxonomy administration page. + $this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add'); + $this->assertResponse(200); + $this->assertField('edit-name', 'Add taxonomy term form opened successfully.'); + + // Submit the term. + $edit = array(); + $edit['name'] = $this->randomName(); + + $this->drupalPost(NULL, $edit, t('Save')); + $this->assertRaw(t('Created new term %name.', array('%name' => $edit['name'])), 'Term created successfully.'); + + $terms = taxonomy_term_load_multiple_by_name($edit['name']); + $term = reset($terms); + + // Edit the term. + $this->drupalGet('taxonomy/term/' . $term->id() . '/edit'); + $this->assertResponse(403, 'Edit taxonomy term form open failed.'); + + // Delete the vocabulary. + $this->drupalGet('taxonomy/term/' . $term->id() . '/delete'); + $this->assertResponse(403, 'Delete taxonomy term form open failed.'); + // Test as user with "edit" permissions. - $user = $this->drupalCreateUser(array("edit terms in {$vocabulary->id()}")); + $user = $this->drupalCreateUser(array("access taxonomy overview", "edit terms in {$vocabulary->id()}")); $this->drupalLogin($user); // Visit the main taxonomy administration page. @@ -82,7 +136,7 @@ function testVocabularyPermissionsTaxonomyTerm() { $this->assertResponse(403, 'Delete taxonomy term form open failed.'); // Test as user with "delete" permissions. - $user = $this->drupalCreateUser(array("delete terms in {$vocabulary->id()}")); + $user = $this->drupalCreateUser(array("access taxonomy overview", "delete terms in {$vocabulary->id()}")); $this->drupalLogin($user); // Visit the main taxonomy administration page. diff --git a/core/modules/taxonomy/src/VocabularyListBuilder.php b/core/modules/taxonomy/src/VocabularyListBuilder.php index fe196c9..08cfaca 100644 --- a/core/modules/taxonomy/src/VocabularyListBuilder.php +++ b/core/modules/taxonomy/src/VocabularyListBuilder.php @@ -46,11 +46,14 @@ public function getDefaultOperations(EntityInterface $entity) { 'weight' => 0, 'url' => $entity->urlInfo('overview-form'), ); - $operations['add'] = array( - 'title' => t('Add terms'), - 'weight' => 10, - 'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]), - ); + $access_controller = \Drupal::entityManager()->getAccessController('taxonomy_term'); + if ($access_controller->createAccess($entity->bundle())) { + $operations['add'] = array( + 'title' => t('Add terms'), + 'weight' => 10, + 'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]), + ); + } unset($operations['delete']); return $operations; @@ -61,6 +64,11 @@ public function getDefaultOperations(EntityInterface $entity) { */ public function buildHeader() { $header['label'] = t('Vocabulary name'); + + if (user_access('administer vocabularies')) { + $header['weight'] = t('Weight'); + } + return $header + parent::buildHeader(); } @@ -83,7 +91,14 @@ public function render() { unset($this->weightKey); } $build = parent::render(); - $build['table']['#empty'] = t('No vocabularies available. Add vocabulary.', array('@link' => \Drupal::url('entity.taxonomy_vocabulary.add_form'))); + + if (user_access('administer vocabularies')) { + $build['table']['#empty'] = t('No vocabularies available. Add vocabulary.', array('@link' => \Drupal::url('entity.taxonomy_vocabulary.add_form'))); + } + else { + $build['table']['#empty'] = t('No vocabularies available.'); + } + return $build; } diff --git a/core/modules/taxonomy/taxonomy.routing.yml b/core/modules/taxonomy/taxonomy.routing.yml index a7a75f3..bd00f33 100644 --- a/core/modules/taxonomy/taxonomy.routing.yml +++ b/core/modules/taxonomy/taxonomy.routing.yml @@ -4,7 +4,7 @@ entity.taxonomy_vocabulary.collection: _entity_list: 'taxonomy_vocabulary' _title: 'Taxonomy' requirements: - _permission: 'administer taxonomy' + _access_taxonomy_overview: 'TRUE' entity.taxonomy_term.add_form: path: '/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/add' diff --git a/core/modules/taxonomy/taxonomy.services.yml b/core/modules/taxonomy/taxonomy.services.yml index a8153ed..ea11954 100644 --- a/core/modules/taxonomy/taxonomy.services.yml +++ b/core/modules/taxonomy/taxonomy.services.yml @@ -4,3 +4,7 @@ services: arguments: ['@entity.manager'] tags: - { name: breadcrumb_builder, priority: 1002 } + access_check.taxonomy.taxonomy_overview: + class: Drupal\taxonomy\Access\TaxonomyOverviewAccessCheck + tags: + - { name: access_check } diff --git a/core/modules/views/src/Tests/Wizard/WizardTestBase.php b/core/modules/views/src/Tests/Wizard/WizardTestBase.php index f610a5f..686d6cb 100644 --- a/core/modules/views/src/Tests/Wizard/WizardTestBase.php +++ b/core/modules/views/src/Tests/Wizard/WizardTestBase.php @@ -15,6 +15,13 @@ abstract class WizardTestBase extends ViewTestBase { /** + * Permissions for this user to test with. + * + * @var array + */ + protected $permissions = array(); + + /** * Modules to enable. * * @var array @@ -24,8 +31,10 @@ protected function setUp() { parent::setUp(); + $this->permissions = array_merge($this->permissions, array('administer views', 'administer blocks', 'bypass node access', 'access user profiles', 'view all revisions')); + // Create and log in a user with administer views permission. - $views_admin = $this->drupalCreateUser(array('administer views', 'administer blocks', 'bypass node access', 'access user profiles', 'view all revisions')); + $views_admin = $this->drupalCreateUser($this->permissions); $this->drupalLogin($views_admin); }