Skip to content

Commit

Permalink
VAGAOV-TEAM-97941: Adds Form Builder role and permission (#20192)
Browse files Browse the repository at this point in the history
* Changes module name to include VA.gov prefix.

* Adds `access form builder` permission.

* Adds `Form Builder user` (form_builder_user) role with `access form builder` permission.

* Adds unit test for permissions.yml

* Updates annotation on existing test to be more accurate.

* Updates routing:
 - Use RouteSubscriber rather than repeating same permission on every route.
 - Update to use new permission.

* Updates existing tests to align with new permission. Note that these existing tests effectively test the RouteSubscriber functionality.

* Small fix to `hasRequirement` check. Cannot take a specific permission as a second parameter. We'll set the permission whenever one is not set.
  • Loading branch information
ryguyk authored Jan 7, 2025
1 parent a0a78c9 commit 0993b35
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 26 deletions.
16 changes: 16 additions & 0 deletions config/sync/user.role.form_builder_user.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
uuid: 2793e5e4-37aa-49b3-9c29-5e1c7ddc3772
langcode: en
status: true
dependencies:
module:
- va_gov_backend
- va_gov_form_builder
third_party_settings:
va_gov_backend:
vgb_description: "A user of the VA.gov Form Builder tool."
id: form_builder_user
label: "Form Builder user"
weight: 14
is_admin: null
permissions:
- "access form builder"
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Drupal\va_gov_form_builder\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
* Listens to the dynamic route events to alter routes.
*/
class RouteSubscriber extends RouteSubscriberBase {

/**
* {@inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
foreach ($collection->all() as $route_name => $route) {
if (strpos($route_name, 'va_gov_form_builder.') === 0) {
if (!$route->hasRequirement('_permission')) {
$route->setRequirement('_permission', 'access form builder');
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "Form Builder"
name: "VA.gov Form Builder"
type: module
description: "A module that builds a custom experience for creating and editing Digital Form nodes."
core_version_requirement: ^9 || ^10
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
access form builder:
title: "Access Form Builder"
description: "Allows the user to access the VA.gov Form Builder tool."
restrict access: FALSE
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,15 @@ va_gov_form_builder.entry:
path: "/form-builder"
defaults:
_controller: '\Drupal\va_gov_form_builder\Controller\VaGovFormBuilderController::entry'
requirements:
_permission: "edit any digital_form content"
va_gov_form_builder.intro:
path: "/form-builder/intro"
defaults:
_controller: '\Drupal\va_gov_form_builder\Controller\VaGovFormBuilderController::intro'
requirements:
_permission: "edit any digital_form content"
va_gov_form_builder.start_conversion:
path: "/form-builder/start-conversion"
defaults:
_controller: '\Drupal\va_gov_form_builder\Controller\VaGovFormBuilderController::startConversion'
requirements:
_permission: "edit any digital_form content"
va_gov_form_builder.name_and_dob:
path: "/form-builder/{nid}/name-and-dob"
defaults:
_controller: '\Drupal\va_gov_form_builder\Controller\VaGovFormBuilderController::nameAndDob'
requirements:
_permission: "edit any digital_form content"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
va_gov_form_builder.route_subscriber:
class: Drupal\va_gov_form_builder\Routing\RouteSubscriber
tags:
- { name: "event_subscriber" }
6 changes: 3 additions & 3 deletions tests/phpunit/va_gov_form_builder/Traits/TestFormLoads.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ trait TestFormLoads {
/**
* Logs-in a user with appropriate privileges.
*/
private function loginDigitalFormUser() {
private function loginFormBuilderUser() {
$this->drupalLogin($this->createUser([
'edit any digital_form content',
'access form builder',
]));
}

Expand All @@ -26,7 +26,7 @@ private function loginDigitalFormUser() {
*/
private function sharedTestFormLoads($url, $expectedText) {
// Log in a user with permission.
$this->loginDigitalFormUser();
$this->loginFormBuilderUser();

// Navigate to page.
$this->drupalGet($url);
Expand Down
22 changes: 13 additions & 9 deletions tests/phpunit/va_gov_form_builder/functional/Form/IntroTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace tests\phpunit\va_gov_form_builder\functional\Form;

use tests\phpunit\va_gov_form_builder\Traits\TestFormLoads;
use Tests\Support\Classes\VaGovExistingSiteBase;

/**
Expand All @@ -13,39 +14,42 @@
* @coversDefaultClass \Drupal\va_gov_form_builder\Form\Intro
*/
class IntroTest extends VaGovExistingSiteBase {
use TestFormLoads;

/**
* {@inheritdoc}
*/
private static $modules = ['va_gov_form_builder'];

/**
* Returns the url for this form (for the given node)
*/
private function getFormPageUrl() {
return '/form-builder/intro';
}

/**
* Set up the environment for each test.
*/
public function setUp(): void {
parent::setUp();

$this->drupalLogin($this->createUser(['edit any digital_form content']));
$this->drupalGet('/form-builder/intro');
$this->loginFormBuilderUser();
$this->drupalGet($this->getFormPageUrl());
}

/**
* Test that the form is accessible to a user with the correct privilege.
*/
public function testFormLoads() {
$this->assertSession()->statusCodeEquals(200);
$this->assertSession()->pageTextContains('Working with the Form Builder');
$this->sharedTestFormLoads($this->getFormPageUrl(), 'Working with the Form Builder');
}

/**
* Test that the form is not accessible to a user without privilege.
*/
public function testFormDoesNotLoad() {
// Log out the good user and log in a user without permission.
$this->drupalLogin($this->createUser([]));
$this->drupalGet('/form-builder/intro');

$this->assertSession()->statusCodeNotEquals(200);
$this->sharedTestFormDoesNotLoad($this->getFormPageUrl());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private function reloadNode() {
public function setUp(): void {
parent::setUp();

$this->loginDigitalFormUser();
$this->loginFormBuilderUser();

// Create a node that doesn't have any chapters.
$this->node = $this->createNode([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ private function getFormPageUrl() {
public function setUp(): void {
parent::setUp();

$this->loginDigitalFormUser();
$this->loginFormBuilderUser();
$this->drupalGet($this->getFormPageUrl());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class FormBuilderPageTemplateTest extends VaGovExistingSiteBase {
public function setUp(): void {
parent::setUp();

$this->drupalLogin($this->createUser(['edit any digital_form content']));
$this->drupalLogin($this->createUser(['access form builder']));

// Form Builder entry.
$this->drupalGet('/form-builder');
Expand Down
4 changes: 2 additions & 2 deletions tests/phpunit/va_gov_form_builder/unit/LibrariesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ class LibrariesTest extends VaGovUnitTestBase {
/**
* The libraries defined in libraries.yml.
*
* @var array{
* @var array<string, array{
* css?: array{
* theme?: array<string, mixed>
* },
* js?: array<string, mixed>,
* dependencies?: array<string>
* }
* }>
*/
private $libraries;

Expand Down
68 changes: 68 additions & 0 deletions tests/phpunit/va_gov_form_builder/unit/PermissionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace tests\phpunit\va_gov_form_builder\unit;

use DrupalFinder\DrupalFinder;
use Symfony\Component\Yaml\Yaml;
use Tests\Support\Classes\VaGovUnitTestBase;

/**
* Unit tests for va_gov_form_builder.permissions.yml.
*
* @group unit
* @group all
*/
class PermissionsTest extends VaGovUnitTestBase {

/**
* The path to the module being tested.
*
* @var string
*/
private $modulePath = 'modules/custom/va_gov_form_builder';

/**
* The permissions defined in permissions.yml.
*
* @var array<string, array{
* title: string,
* description?: string,
* restrict access?: bool,
* }>
*/
private $permissions;

/**
* Set up the environment for each test.
*/
protected function setUp(): void {
parent::setUp();

// Find Drupal root.
$drupalFinder = new DrupalFinder();
$drupalFinder->locateRoot(__DIR__);
$drupalRoot = $drupalFinder->getDrupalRoot();

$yamlFile = $drupalRoot . '/' . $this->modulePath . '/va_gov_form_builder.permissions.yml';

$this->permissions = Yaml::parseFile($yamlFile);
}

/**
* Tests that the `access form builder` permission is present.
*/
public function testPermissionPresent() {
$this->assertArrayHasKey('access form builder', $this->permissions);

// Assert expected keys are present.
$formBuilderPermission = $this->permissions['access form builder'];
$this->assertArrayHasKey('title', $formBuilderPermission);
$this->assertArrayHasKey('description', $formBuilderPermission);
$this->assertArrayHasKey('restrict access', $formBuilderPermission);

// Assert `restrict access` is false.
$restrictAccess = $formBuilderPermission['restrict access'];
$this->assertFalse($restrictAccess);
}

}

0 comments on commit 0993b35

Please sign in to comment.