From f274d97cfeed5d6034d0cab79913114aa3ef5bca Mon Sep 17 00:00:00 2001 From: Roman Chekhaniuk Date: Thu, 14 Nov 2024 17:22:28 +0200 Subject: [PATCH] Issue #3477793: Add 'Verified' role for Flexible group, update permissions --- .../group.role.flexible_group-anonymous.yml | 2 - .../group.role.flexible_group-outsider.yml | 2 - .../group.role.flexible_group-verified.yml | 22 +++++++++ ...ial_group_flexible_group_update_130006.yml | 3 ++ .../social_group_flexible_group.install | 45 +++++++++++++++++ .../EventSubscriber/RedirectSubscriber.php | 44 ++++++++++++++++- phpstan-baseline.neon | 6 --- .../groups-flexible-page-access.feature | 48 +++++++++++++++++++ .../groups-flexible-sidebar-blocks.feature | 1 - ...exible-view-outsider-authenticated.feature | 2 +- ...ps-flexible-view-outsider-verified.feature | 2 +- 11 files changed, 162 insertions(+), 15 deletions(-) create mode 100644 modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-verified.yml create mode 100644 modules/social_features/social_group/modules/social_group_flexible_group/config/update/social_group_flexible_group_update_130006.yml create mode 100644 tests/behat/features/capabilities/groups/flexible/groups-flexible-page-access.feature diff --git a/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-anonymous.yml b/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-anonymous.yml index 989552cdbe9..8ad5d08d76e 100644 --- a/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-anonymous.yml +++ b/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-anonymous.yml @@ -13,8 +13,6 @@ global_role: anonymous group_type: flexible_group permissions: - 'view group' - - 'view group stream page' - - 'view group_membership relationship' - 'view group_node:event relationship' - 'view group_node:event entity' - 'view group_node:topic relationship' diff --git a/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-outsider.yml b/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-outsider.yml index 9d02b3dabd4..51634f54ec5 100644 --- a/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-outsider.yml +++ b/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-outsider.yml @@ -17,8 +17,6 @@ permissions: - 'update own group_node:event entity' - 'update own group_node:topic entity' - 'view group' - - 'view group stream page' - - 'view group_membership relationship' - 'view group_node:event relationship' - 'view group_node:event entity' - 'view group_node:topic relationship' diff --git a/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-verified.yml b/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-verified.yml new file mode 100644 index 00000000000..5fc80a3e9f0 --- /dev/null +++ b/modules/social_features/social_group/modules/social_group_flexible_group/config/install/group.role.flexible_group-verified.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + config: + - group.type.flexible_group +id: flexible_group-verified +label: Verified +admin: false +scope: outsider +global_role: verified +group_type: flexible_group +permissions: + - 'access comments' + - 'access posts in group' + - 'join group' + - 'update own group_node:event entity' + - 'update own group_node:topic entity' + - 'view group' + - 'view group_node:event relationship' + - 'view group_node:event entity' + - 'view group_node:topic relationship' + - 'view group_node:topic entity' diff --git a/modules/social_features/social_group/modules/social_group_flexible_group/config/update/social_group_flexible_group_update_130006.yml b/modules/social_features/social_group/modules/social_group_flexible_group/config/update/social_group_flexible_group_update_130006.yml new file mode 100644 index 00000000000..85884f9699a --- /dev/null +++ b/modules/social_features/social_group/modules/social_group_flexible_group/config/update/social_group_flexible_group_update_130006.yml @@ -0,0 +1,3 @@ +__global_actions: + import_configs: + - group.role.flexible_group-verified diff --git a/modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.install b/modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.install index aa2e6ac2183..878753a44cb 100644 --- a/modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.install +++ b/modules/social_features/social_group/modules/social_group_flexible_group/social_group_flexible_group.install @@ -250,3 +250,48 @@ function social_group_flexible_group_update_130005() : void { \Drupal::service('module_installer')->install(['social_email_broadcast']); } } + +/** + * Add 'Verified' group role for Flexible group type. + */ +function social_group_flexible_group_update_130006(): string { + /** @var \Drupal\update_helper\Updater $updater */ + $updater = \Drupal::service('update_helper.updater'); + + if (\Drupal::moduleHandler()->moduleExists('social_group_flexible_group') && + empty(\Drupal::config('group.role.flexible_group-verified')->getRawData()) + ) { + // Execute configuration update definitions with logging of success. + $updater->executeUpdate('social_group_flexible_group', __FUNCTION__); + } + // Output logged messages to related channel of update execution. + return $updater->logger()->output(); + +} + +/** + * Revoke group permissions for Outsider and Anonymous roles. + */ +function social_group_flexible_group_update_130007(): void { + $roles_permissions = [ + 'flexible_group-outsider' => [ + 'view group_membership relationship', + 'view group stream page', + ], + 'flexible_group-anonymous' => [ + 'view group_membership relationship', + 'view group stream page', + ], + ]; + + foreach ($roles_permissions as $role_id => $permissions) { + /** @var \Drupal\group\Entity\GroupRoleInterface $role */ + $role = \Drupal::entityTypeManager()->getStorage('group_role')->load($role_id); + + foreach ($permissions as $permission) { + $role->revokePermission($permission); + } + + $role->save(); + } +} diff --git a/modules/social_features/social_group/modules/social_group_flexible_group/src/EventSubscriber/RedirectSubscriber.php b/modules/social_features/social_group/modules/social_group_flexible_group/src/EventSubscriber/RedirectSubscriber.php index 3506fb6aa6b..aa026dac132 100644 --- a/modules/social_features/social_group/modules/social_group_flexible_group/src/EventSubscriber/RedirectSubscriber.php +++ b/modules/social_features/social_group/modules/social_group_flexible_group/src/EventSubscriber/RedirectSubscriber.php @@ -6,10 +6,14 @@ use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\Url; use Drupal\group\Entity\GroupInterface; +use Drupal\social_group\SocialGroupInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\Routing\Route; /** * Class RedirectSubscriber. @@ -56,6 +60,7 @@ public function __construct( */ public static function getSubscribedEvents() { $events[KernelEvents::REQUEST][] = ['checkForRedirection']; + $events[KernelEvents::EXCEPTION][] = ['onKernelException', 100]; return $events; } @@ -110,17 +115,52 @@ public function checkForRedirection(RequestEvent $event) { ) { $this->doRedirect($event, $group); } + elseif ($route_name === 'entity.group.canonical' && + $this->routeMatch->getRouteObject() instanceof Route && + ($this->routeMatch->getRouteObject()->getPath() === '/group/{group}/stream' || + $this->routeMatch->getRouteObject()->getPath() === '/group/{group}/home') && + !$group->hasPermission('view group stream page', $this->currentUser) + ) { + $this->doRedirect($event, $group); + } + } + + /** + * Redirect on exceptions. + * + * @param \Symfony\Component\HttpKernel\Event\ExceptionEvent $event + * The exception event. + */ + public function onKernelException(ExceptionEvent $event): void { + // Check if there is a group object on the current route. + $group = $this->routeMatch->getParameter('group'); + if (!$group instanceof SocialGroupInterface) { + return; + } + + $exception = $event->getThrowable(); + + // Do not redirect form access denied if user doesn't have access to + // view the group (secret group, etc.). + if (!$group->access('view', $this->currentUser) || + !$exception instanceof AccessDeniedHttpException || + $group->bundle() != 'flexible_group' + ) { + return; + } + + $this->doRedirect($event, $group); } /** * Makes redirect to the "About" group tab. * - * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event + * @param \Symfony\Component\HttpKernel\Event\RequestEvent|\Symfony\Component\HttpKernel\Event\ExceptionEvent $event * The event. * @param \Drupal\group\Entity\GroupInterface $group * The group. */ - protected function doRedirect(RequestEvent $event, GroupInterface $group) { + protected function doRedirect(RequestEvent|ExceptionEvent $event, GroupInterface $group): void { $url = Url::fromRoute('view.group_information.page_group_about', [ 'group' => $group->id(), ]); diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 39047285bab..e789553124d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -7367,12 +7367,6 @@ parameters: message: "#^Method Drupal\\\\social_group_flexible_group\\\\EventSubscriber\\\\RedirectSubscriber\\:\\:checkForRedirection\\(\\) has no return type specified\\.$#" count: 1 path: modules/social_features/social_group/modules/social_group_flexible_group/src/EventSubscriber/RedirectSubscriber.php - - - - message: "#^Method Drupal\\\\social_group_flexible_group\\\\EventSubscriber\\\\RedirectSubscriber\\:\\:doRedirect\\(\\) has no return type specified\\.$#" - count: 1 - path: modules/social_features/social_group/modules/social_group_flexible_group/src/EventSubscriber/RedirectSubscriber.php - - message: "#^Not allowed to call private function _social_group_get_current_group from module social_group_flexible_group\\.$#" count: 1 diff --git a/tests/behat/features/capabilities/groups/flexible/groups-flexible-page-access.feature b/tests/behat/features/capabilities/groups/flexible/groups-flexible-page-access.feature new file mode 100644 index 00000000000..8c7672fc069 --- /dev/null +++ b/tests/behat/features/capabilities/groups/flexible/groups-flexible-page-access.feature @@ -0,0 +1,48 @@ +@api @javascript +Feature: Validate accessibility of flexible group pages for different users + + Background: + Given I enable the module "social_group_flexible_group" + And I am logged in as an "sitemanager" + And users: + | name | mail | status | roles | + | Behat Owner | behat_owner@example.com | 1 | sitemanager | + | Non Member | non_member@example.com | 1 | | + | Member | member@example.com | 1 | | + + And groups no validation: + | label | type | author | field_flexible_group_visibility | + | Test Flexible | flexible_group | Behat Owner | public | + And group members with values: + | group | user | group_roles | + | Test Flexible | Member | flexible_group-member | + + Scenario: Anonymous user should be redirected to the About page from "Members" and "Stream" pages. + Given I am an anonymous user + + When I go to "/group/1/stream" + + Then the URL should match "^\/group\/[^\/]+\/about$" + + And I go to "/group/1/members" + And the URL should match "^\/group\/[^\/]+\/about$" + + Scenario: Verified user should be redirected to the About page from "Members" and "Stream" pages if he is non-member. + Given I am logged in as "Non Member" + + When I go to "/group/1/stream" + + Then the URL should match "^\/group\/[^\/]+\/about$" + + And I go to "/group/1/members" + And the URL should match "^\/group\/[^\/]+\/about$" + + Scenario: Group member shouldn't be redirected to the About page from "Members" and "Stream" pages. + Given I am logged in as "Member" + + When I go to "/group/1/stream" + + Then the URL should match "^\/group\/[^\/]+\/stream" + + And I go to "/group/1/members" + And the URL should match "^\/group\/[^\/]+\/members$" diff --git a/tests/behat/features/capabilities/groups/flexible/groups-flexible-sidebar-blocks.feature b/tests/behat/features/capabilities/groups/flexible/groups-flexible-sidebar-blocks.feature index f078ccdd068..0271ecf89c5 100644 --- a/tests/behat/features/capabilities/groups/flexible/groups-flexible-sidebar-blocks.feature +++ b/tests/behat/features/capabilities/groups/flexible/groups-flexible-sidebar-blocks.feature @@ -18,4 +18,3 @@ Feature: Flexible groups sidebar blocks are correctly displayed Then I should see "Upcoming events" in the "Sidebar second" And I should see "Newest topics" in the "Sidebar second" - And I should see "Newest Members" in the "Sidebar second" diff --git a/tests/behat/features/capabilities/groups/flexible/groups-flexible-view-outsider-authenticated.feature b/tests/behat/features/capabilities/groups/flexible/groups-flexible-view-outsider-authenticated.feature index 74be1060ee2..018d41b0b74 100644 --- a/tests/behat/features/capabilities/groups/flexible/groups-flexible-view-outsider-authenticated.feature +++ b/tests/behat/features/capabilities/groups/flexible/groups-flexible-view-outsider-authenticated.feature @@ -33,7 +33,7 @@ Feature: Flexible groups view access for authenticated but unverified users When I am viewing the group "Test group" - Then I should not see "Test group" + Then I should see "You are not authorized to access this page" Scenario: As unverified user I can view a public group I'm not a member of on the groups search Given groups with non-anonymous owner: diff --git a/tests/behat/features/capabilities/groups/flexible/groups-flexible-view-outsider-verified.feature b/tests/behat/features/capabilities/groups/flexible/groups-flexible-view-outsider-verified.feature index f4fdae9ef31..11fb8b62273 100644 --- a/tests/behat/features/capabilities/groups/flexible/groups-flexible-view-outsider-verified.feature +++ b/tests/behat/features/capabilities/groups/flexible/groups-flexible-view-outsider-verified.feature @@ -35,7 +35,7 @@ Feature: Flexible groups view access for verified users When I am viewing the group "Test group" - Then I should not see "Test group" + Then I should see "You are not authorized to access this page" Scenario: As verified user I can view a public group I'm not a member of on the groups search Given groups with non-anonymous owner: