From e1c2e4e9c98df183162d5ac71aa1c63add1a01b6 Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Wed, 14 Jul 2021 14:35:57 -0300 Subject: [PATCH] Add a constraint for field_member_of for entity references. (#1) * Add a constraint for field_member_of for entity references. * Adds php test for this --- composer.json | 3 +- idc_defaults.info.yml | 8 + idc_defaults.module | 17 ++ .../Validation/Constraint/WorkbenchAccess.php | 32 ++++ .../Constraint/WorkbenchAccessValidator.php | 32 ++++ tests/src/Kernel/ConstraintTest.php | 145 ++++++++++++++++++ 6 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 idc_defaults.info.yml create mode 100644 idc_defaults.module create mode 100644 src/Plugin/Validation/Constraint/WorkbenchAccess.php create mode 100644 src/Plugin/Validation/Constraint/WorkbenchAccessValidator.php create mode 100644 tests/src/Kernel/ConstraintTest.php diff --git a/composer.json b/composer.json index 38ca73c..8a02b79 100644 --- a/composer.json +++ b/composer.json @@ -3,6 +3,7 @@ "type": "drupal-module", "description": "Customizations for the Islandora integration at JHU's Sheridan Libraries.", "require": { - "islandora/islandora": "dev-8.x-1.x" + "islandora/islandora": "dev-8.x-1.x", + "drupal/workbench_access": "^1.0@beta" } } diff --git a/idc_defaults.info.yml b/idc_defaults.info.yml new file mode 100644 index 0000000..9ec8f16 --- /dev/null +++ b/idc_defaults.info.yml @@ -0,0 +1,8 @@ +name: iDC Defaults +description: Customizations for the Islandora integration at JHU's Sheridan Libraries. +package: iDC +type: module +core_version_requirement: ^8 || ^9 +dependencies: + - islandora:islandora + - drupal:workbench_access diff --git a/idc_defaults.module b/idc_defaults.module new file mode 100644 index 0000000..7d21be9 --- /dev/null +++ b/idc_defaults.module @@ -0,0 +1,17 @@ +addConstraint('WorkbenchAccess'); + } +} diff --git a/src/Plugin/Validation/Constraint/WorkbenchAccess.php b/src/Plugin/Validation/Constraint/WorkbenchAccess.php new file mode 100644 index 0000000..268b3e1 --- /dev/null +++ b/src/Plugin/Validation/Constraint/WorkbenchAccess.php @@ -0,0 +1,32 @@ +entity) || !$item->entity instanceof NodeInterface) { + $this->context->addViolation($constraint->badType); + } + else { + // Use the "update" op as it applies to an already existing entity and + // not a new entity being created. + if (!$item->entity->access('update')) { + $this->context->addViolation($constraint->noAccess); + } + } + } + } + +} diff --git a/tests/src/Kernel/ConstraintTest.php b/tests/src/Kernel/ConstraintTest.php new file mode 100644 index 0000000..f26e65f --- /dev/null +++ b/tests/src/Kernel/ConstraintTest.php @@ -0,0 +1,145 @@ +installConfig('workbench_access'); + $this->installEntitySchema('taxonomy_term'); + $this->installEntitySchema('section_association'); + $this->installSchema('system', 'key_value'); + + $node_type = $this->createContentType(['type' => 'repository_item']); + $this->vocabulary = $this->setUpVocabulary(); + $this->accessHandler = $this->container->get('entity_type.manager')->getAccessControlHandler('node'); + $this->state = $this->container->get('state'); + $this->setUpTaxonomyFieldForEntityType('node', $node_type->id(), $this->vocabulary->id()); + $this->scheme = $this->setUpTaxonomyScheme($node_type, $this->vocabulary); + $this->userStorage = $this->container->get('workbench_access.user_section_storage'); + $this->createEntityReferenceField('node', 'repository_item', 'field_member_of', 'Member Of', 'node', 'default', [], 2); + } + + /** + * Tests the WorkbenchAccess constraint. + */ + public function testConstraint() { + // Permissions matching the collection level and global admins for repo + // items. + $permissions = [ + 'create repository_item content', + 'edit any repository_item content', + 'edit own repository_item content', + 'access content', + ]; + + // Create a section. + $term = Term::create([ + 'vid' => $this->vocabulary->id(), + 'name' => 'Some collection', + ]); + $term->save(); + + // Create two collection_admin users with the same permissions but one will + // be part of a community. + $collection_admin_community_user = $this->createUser($permissions); + $this->userStorage->addUser($this->scheme, $collection_admin_community_user, [$term->id()]); + + $collection_admin_user = $this->createUser($permissions); + + // Global admin can bypass workbench. + $permissions[] = 'bypass workbench access'; + $global_admin_user = $this->createUser($permissions); + + // Node that belongs to a community. + $community_node = $this->drupalCreateNode([ + 'type' => 'repository_item', + WorkbenchAccessManagerInterface::FIELD_NAME => $term->id(), + ]); + + // Switch to the collection admin community user. + $this->setCurrentUser($collection_admin_community_user); + $node_referencing_a_community_node = $this->drupalCreateNode([ + 'type' => 'repository_item', + 'field_member_of' => $community_node->id(), + ]); + + $violations = $node_referencing_a_community_node->validate(); + $this->assertCount(0, $violations, 'Collection admin within a community able to add to a node within a community.'); + + // Switch to the collection admin user. + $this->setCurrentUser($collection_admin_user); + $node_referencing_a_community_node_no_access = $this->drupalCreateNode([ + 'type' => 'repository_item', + 'field_member_of' => $community_node->id(), + ]); + $violations = $node_referencing_a_community_node_no_access->validate(); + $this->assertCount(1, $violations, 'Collection admin not part of a community unable to add to a node.'); + $this->assertEquals('The user does not have access to ingest into this object.', $violations->get(0)->getMessage(), 'Incorrect constraint validation message found'); + + // Switch to the global admin user. + $this->setCurrentUser($global_admin_user); + $node_referencing_a_community_global_admin = $this->drupalCreateNode([ + 'type' => 'repository_item', + 'field_member_of' => $community_node->id(), + ]); + $violations = $node_referencing_a_community_global_admin->validate(); + $this->assertCount(0, $violations, 'Global admin can add to whatever collection they want.'); + + } + +}