mirror of
https://gitlab.unicamp.br/infimecc_drupal11_modules/ldap_groups_sync.git
synced 2026-03-11 02:37:41 -03:00
Centraliza configuração de access rules no módulo pai
- Adiciona rota, menu e abas unificados em ldap_groups_sync
- Cria LdapGroupsSyncController (overview dos submódulos)
- Cria UnifiedAccessRulesForm: tabela combinada de regras de todos os
submódulos habilitados, com único botão "Add Rule"
- Cria GlobalAccessRuleForm: estende AccessRuleFormBase com parâmetro
{group_type} na rota; exibe select "Group Type" com AJAX rebuild ao
criar novas regras (desabilitado ao editar)
- Remove rotas access_rules e access_rule_form dos submódulos
- Remove entradas de menu dos submódulos (módulo pai fornece a entrada)
- Atualiza abas dos submódulos para base_route: ldap_groups_sync.config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1 @@
|
|||||||
ldap_departments_sync.config:
|
# Menu entry removed: the parent module ldap_groups_sync provides the unified menu entry.
|
||||||
title: 'LDAP Departments Sync'
|
|
||||||
description: 'Configurar sincronização de departamentos do LDAP'
|
|
||||||
route_name: ldap_departments_sync.config
|
|
||||||
parent: site_tools.admin_config
|
|
||||||
weight: 5
|
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
ldap_departments_sync.tab.config:
|
ldap_departments_sync.tab.config:
|
||||||
title: 'Configuration'
|
title: 'Departments Sync'
|
||||||
route_name: ldap_departments_sync.config
|
route_name: ldap_departments_sync.config
|
||||||
base_route: ldap_departments_sync.config
|
base_route: ldap_groups_sync.config
|
||||||
weight: 0
|
|
||||||
|
|
||||||
ldap_departments_sync.tab.access_rules:
|
|
||||||
title: 'Access Rules'
|
|
||||||
route_name: ldap_departments_sync.access_rules
|
|
||||||
base_route: ldap_departments_sync.config
|
|
||||||
weight: 10
|
weight: 10
|
||||||
|
|||||||
@@ -5,21 +5,3 @@ ldap_departments_sync.config:
|
|||||||
_title: 'LDAP Departments Sync'
|
_title: 'LDAP Departments Sync'
|
||||||
requirements:
|
requirements:
|
||||||
_permission: 'administer ldap departments sync'
|
_permission: 'administer ldap departments sync'
|
||||||
|
|
||||||
ldap_departments_sync.access_rules:
|
|
||||||
path: '/admin/config/local-modules/ldap-departments-sync/access-rules'
|
|
||||||
defaults:
|
|
||||||
_form: '\Drupal\ldap_departments_sync\Form\AccessRulesForm'
|
|
||||||
_title: 'Access Rules'
|
|
||||||
requirements:
|
|
||||||
_permission: 'administer ldap departments sync'
|
|
||||||
|
|
||||||
ldap_departments_sync.access_rule_form:
|
|
||||||
path: '/admin/config/local-modules/ldap-departments-sync/access-rule/{rule_index}'
|
|
||||||
defaults:
|
|
||||||
_form: '\Drupal\ldap_departments_sync\Form\AccessRuleForm'
|
|
||||||
_title: 'Access Rule'
|
|
||||||
rule_index: 'new'
|
|
||||||
requirements:
|
|
||||||
_permission: 'administer ldap departments sync'
|
|
||||||
rule_index: 'new|\d+'
|
|
||||||
|
|||||||
6
ldap_groups_sync.links.menu.yml
Normal file
6
ldap_groups_sync.links.menu.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
ldap_groups_sync.config:
|
||||||
|
title: 'LDAP Groups Sync'
|
||||||
|
description: 'Configurar sincronização de grupos do LDAP'
|
||||||
|
route_name: ldap_groups_sync.config
|
||||||
|
parent: site_tools.admin_config
|
||||||
|
weight: 4
|
||||||
11
ldap_groups_sync.links.task.yml
Normal file
11
ldap_groups_sync.links.task.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
ldap_groups_sync.tab.overview:
|
||||||
|
title: 'Overview'
|
||||||
|
route_name: ldap_groups_sync.config
|
||||||
|
base_route: ldap_groups_sync.config
|
||||||
|
weight: 0
|
||||||
|
|
||||||
|
ldap_groups_sync.tab.access_rules:
|
||||||
|
title: 'Access Rules'
|
||||||
|
route_name: ldap_groups_sync.access_rules
|
||||||
|
base_route: ldap_groups_sync.config
|
||||||
|
weight: 100
|
||||||
4
ldap_groups_sync.permissions.yml
Normal file
4
ldap_groups_sync.permissions.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
administer ldap groups sync:
|
||||||
|
title: 'Administrar LDAP Groups Sync'
|
||||||
|
description: 'Acesso à página unificada de configuração e regras de acesso.'
|
||||||
|
restrict access: true
|
||||||
26
ldap_groups_sync.routing.yml
Normal file
26
ldap_groups_sync.routing.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
ldap_groups_sync.config:
|
||||||
|
path: '/admin/config/local-modules/ldap-groups-sync'
|
||||||
|
defaults:
|
||||||
|
_controller: '\Drupal\ldap_groups_sync\Controller\LdapGroupsSyncController::overview'
|
||||||
|
_title: 'LDAP Groups Sync'
|
||||||
|
requirements:
|
||||||
|
_permission: 'administer ldap groups sync'
|
||||||
|
|
||||||
|
ldap_groups_sync.access_rules:
|
||||||
|
path: '/admin/config/local-modules/ldap-groups-sync/access-rules'
|
||||||
|
defaults:
|
||||||
|
_form: '\Drupal\ldap_groups_sync\Form\UnifiedAccessRulesForm'
|
||||||
|
_title: 'Access Rules'
|
||||||
|
requirements:
|
||||||
|
_permission: 'administer ldap groups sync'
|
||||||
|
|
||||||
|
ldap_groups_sync.access_rule_form:
|
||||||
|
path: '/admin/config/local-modules/ldap-groups-sync/access-rule/{group_type}/{rule_index}'
|
||||||
|
defaults:
|
||||||
|
_form: '\Drupal\ldap_groups_sync\Form\GlobalAccessRuleForm'
|
||||||
|
_title: 'Access Rule'
|
||||||
|
rule_index: 'new'
|
||||||
|
requirements:
|
||||||
|
_permission: 'administer ldap groups sync'
|
||||||
|
rule_index: 'new|\d+'
|
||||||
|
group_type: 'departments|research_groups'
|
||||||
@@ -1,6 +1 @@
|
|||||||
ldap_research_groups_sync.config:
|
# Menu entry removed: the parent module ldap_groups_sync provides the unified menu entry.
|
||||||
title: 'LDAP Research Groups Sync'
|
|
||||||
description: 'Configurar sincronização de grupos de pesquisa do LDAP'
|
|
||||||
route_name: ldap_research_groups_sync.config
|
|
||||||
parent: site_tools.admin_config
|
|
||||||
weight: 6
|
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
ldap_research_groups_sync.tab.config:
|
ldap_research_groups_sync.tab.config:
|
||||||
title: 'Configuration'
|
title: 'Research Groups Sync'
|
||||||
route_name: ldap_research_groups_sync.config
|
route_name: ldap_research_groups_sync.config
|
||||||
base_route: ldap_research_groups_sync.config
|
base_route: ldap_groups_sync.config
|
||||||
weight: 0
|
weight: 20
|
||||||
|
|
||||||
ldap_research_groups_sync.tab.access_rules:
|
|
||||||
title: 'Access Rules'
|
|
||||||
route_name: ldap_research_groups_sync.access_rules
|
|
||||||
base_route: ldap_research_groups_sync.config
|
|
||||||
weight: 10
|
|
||||||
|
|||||||
@@ -5,21 +5,3 @@ ldap_research_groups_sync.config:
|
|||||||
_title: 'LDAP Research Groups Sync'
|
_title: 'LDAP Research Groups Sync'
|
||||||
requirements:
|
requirements:
|
||||||
_permission: 'administer ldap research groups sync'
|
_permission: 'administer ldap research groups sync'
|
||||||
|
|
||||||
ldap_research_groups_sync.access_rules:
|
|
||||||
path: '/admin/config/local-modules/ldap-research-groups-sync/access-rules'
|
|
||||||
defaults:
|
|
||||||
_form: '\Drupal\ldap_research_groups_sync\Form\AccessRulesForm'
|
|
||||||
_title: 'Access Rules'
|
|
||||||
requirements:
|
|
||||||
_permission: 'administer ldap research groups sync'
|
|
||||||
|
|
||||||
ldap_research_groups_sync.access_rule_form:
|
|
||||||
path: '/admin/config/local-modules/ldap-research-groups-sync/access-rule/{rule_index}'
|
|
||||||
defaults:
|
|
||||||
_form: '\Drupal\ldap_research_groups_sync\Form\AccessRuleForm'
|
|
||||||
_title: 'Access Rule'
|
|
||||||
rule_index: 'new'
|
|
||||||
requirements:
|
|
||||||
_permission: 'administer ldap research groups sync'
|
|
||||||
rule_index: 'new|\d+'
|
|
||||||
|
|||||||
50
src/Controller/LdapGroupsSyncController.php
Normal file
50
src/Controller/LdapGroupsSyncController.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\ldap_groups_sync\Controller;
|
||||||
|
|
||||||
|
use Drupal\Core\Controller\ControllerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the overview page for the LDAP Groups Sync unified configuration.
|
||||||
|
*/
|
||||||
|
class LdapGroupsSyncController extends ControllerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders an overview listing the enabled LDAP group sync submodules.
|
||||||
|
*/
|
||||||
|
public function overview(): array {
|
||||||
|
$submodules = [
|
||||||
|
'ldap_departments_sync' => [
|
||||||
|
'label' => $this->t('LDAP Departments Sync'),
|
||||||
|
'description' => $this->t('Synchronizes department groups from LDAP.'),
|
||||||
|
],
|
||||||
|
'ldap_research_groups_sync' => [
|
||||||
|
'label' => $this->t('LDAP Research Groups Sync'),
|
||||||
|
'description' => $this->t('Synchronizes research group entities from LDAP.'),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$rows = [];
|
||||||
|
foreach ($submodules as $module => $info) {
|
||||||
|
$enabled = $this->moduleHandler()->moduleExists($module);
|
||||||
|
$rows[] = [
|
||||||
|
(string) $info['label'],
|
||||||
|
(string) $info['description'],
|
||||||
|
$enabled
|
||||||
|
? ['data' => ['#markup' => '<span style="color:green">✓ ' . $this->t('Enabled') . '</span>']]
|
||||||
|
: ['data' => ['#markup' => '<span style="color:gray">✗ ' . $this->t('Disabled') . '</span>']],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'#type' => 'table',
|
||||||
|
'#header' => [
|
||||||
|
$this->t('Module'),
|
||||||
|
$this->t('Description'),
|
||||||
|
$this->t('Status'),
|
||||||
|
],
|
||||||
|
'#rows' => $rows,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
155
src/Form/GlobalAccessRuleForm.php
Normal file
155
src/Form/GlobalAccessRuleForm.php
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\ldap_groups_sync\Form;
|
||||||
|
|
||||||
|
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||||
|
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||||
|
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||||
|
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||||
|
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||||
|
use Drupal\Core\Form\FormStateInterface;
|
||||||
|
use Drupal\Core\Routing\RouteMatchInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global modal form for creating or editing a single access rule.
|
||||||
|
*
|
||||||
|
* When adding a new rule (rule_index = 'new'), a "Group Type" select field is
|
||||||
|
* shown at the top; changing it triggers an AJAX rebuild so the groups and
|
||||||
|
* roles options reflect the chosen submodule config.
|
||||||
|
*
|
||||||
|
* When editing an existing rule the field is shown as disabled (the group type
|
||||||
|
* is already determined by the route's {group_type} segment).
|
||||||
|
*/
|
||||||
|
class GlobalAccessRuleForm extends AccessRuleFormBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The group type key for the current request.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected string $groupType = 'departments';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||||
|
*/
|
||||||
|
protected $moduleHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ConfigFactoryInterface $config_factory,
|
||||||
|
EntityTypeManagerInterface $entity_type_manager,
|
||||||
|
EntityTypeBundleInfoInterface $bundle_info,
|
||||||
|
EntityFieldManagerInterface $entity_field_manager,
|
||||||
|
RouteMatchInterface $route_match,
|
||||||
|
ModuleHandlerInterface $module_handler
|
||||||
|
) {
|
||||||
|
parent::__construct($config_factory, $entity_type_manager, $bundle_info, $entity_field_manager, $route_match);
|
||||||
|
$this->moduleHandler = $module_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function create(ContainerInterface $container) {
|
||||||
|
return new static(
|
||||||
|
$container->get('config.factory'),
|
||||||
|
$container->get('entity_type.manager'),
|
||||||
|
$container->get('entity_type.bundle.info'),
|
||||||
|
$container->get('entity_field.manager'),
|
||||||
|
$container->get('current_route_match'),
|
||||||
|
$container->get('module_handler')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFormId(): string {
|
||||||
|
return 'ldap_groups_sync_global_access_rule_form';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function buildForm(array $form, FormStateInterface $form_state, $group_type = 'departments', $rule_index = 'new'): array {
|
||||||
|
// Priority for group type:
|
||||||
|
// 1. User's current selection submitted via AJAX (getValue).
|
||||||
|
// 2. Previously stored value across AJAX rebuilds (get).
|
||||||
|
// 3. Route parameter (initial page load).
|
||||||
|
$selected = $form_state->getValue('group_type');
|
||||||
|
if ($selected !== NULL) {
|
||||||
|
$this->groupType = $selected;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->groupType = $form_state->get('group_type') ?? $group_type;
|
||||||
|
}
|
||||||
|
$form_state->set('group_type', $this->groupType);
|
||||||
|
|
||||||
|
// Resolve rule index the same way the parent will, so we know whether
|
||||||
|
// this is a new rule before calling parent::buildForm().
|
||||||
|
$is_new = ($form_state->get('rule_index') ?? $rule_index) === 'new';
|
||||||
|
|
||||||
|
$form = parent::buildForm($form, $form_state, $rule_index);
|
||||||
|
|
||||||
|
// Build options from enabled submodules only.
|
||||||
|
$options = [];
|
||||||
|
if ($this->moduleHandler->moduleExists('ldap_departments_sync')) {
|
||||||
|
$options['departments'] = $this->t('Departments');
|
||||||
|
}
|
||||||
|
if ($this->moduleHandler->moduleExists('ldap_research_groups_sync')) {
|
||||||
|
$options['research_groups'] = $this->t('Research Groups');
|
||||||
|
}
|
||||||
|
|
||||||
|
$form['group_type'] = [
|
||||||
|
'#type' => 'select',
|
||||||
|
'#title' => $this->t('Group Type'),
|
||||||
|
'#options' => $options,
|
||||||
|
'#default_value' => $this->groupType,
|
||||||
|
'#required' => TRUE,
|
||||||
|
'#disabled' => !$is_new,
|
||||||
|
'#weight' => -100,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Only attach AJAX when the field is editable (new rules).
|
||||||
|
if ($is_new) {
|
||||||
|
$form['group_type']['#ajax'] = [
|
||||||
|
'callback' => '::updateDependentFields',
|
||||||
|
'wrapper' => 'access-rule-form-wrapper',
|
||||||
|
'effect' => 'fade',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function getConfigName(): string {
|
||||||
|
return match($this->groupType) {
|
||||||
|
'research_groups' => 'ldap_research_groups_sync.settings',
|
||||||
|
default => 'ldap_departments_sync.settings',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function getDefaultGroupTypeId(): string {
|
||||||
|
return match($this->groupType) {
|
||||||
|
'research_groups' => 'research_group',
|
||||||
|
default => 'departments',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function getAccessRulesRoute(): string {
|
||||||
|
return 'ldap_groups_sync.access_rules';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
283
src/Form/UnifiedAccessRulesForm.php
Normal file
283
src/Form/UnifiedAccessRulesForm.php
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\ldap_groups_sync\Form;
|
||||||
|
|
||||||
|
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||||
|
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||||
|
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||||
|
use Drupal\Core\Form\FormBase;
|
||||||
|
use Drupal\Core\Form\FormStateInterface;
|
||||||
|
use Drupal\Core\Url;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unified access rules listing for all LDAP group sync submodules.
|
||||||
|
*
|
||||||
|
* Shows a combined table of access rules from every enabled submodule and
|
||||||
|
* allows removing individual rules. New rules and edits open a modal using
|
||||||
|
* GlobalAccessRuleForm routed through ldap_groups_sync.access_rule_form.
|
||||||
|
*/
|
||||||
|
class UnifiedAccessRulesForm extends FormBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps group_type key → [config_name, module, label].
|
||||||
|
*/
|
||||||
|
protected const GROUP_TYPES = [
|
||||||
|
'departments' => [
|
||||||
|
'config' => 'ldap_departments_sync.settings',
|
||||||
|
'module' => 'ldap_departments_sync',
|
||||||
|
'label' => 'Departments',
|
||||||
|
],
|
||||||
|
'research_groups' => [
|
||||||
|
'config' => 'ldap_research_groups_sync.settings',
|
||||||
|
'module' => 'ldap_research_groups_sync',
|
||||||
|
'label' => 'Research Groups',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||||
|
*/
|
||||||
|
protected $configFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||||
|
*/
|
||||||
|
protected $entityTypeManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||||
|
*/
|
||||||
|
protected $moduleHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ConfigFactoryInterface $config_factory,
|
||||||
|
EntityTypeManagerInterface $entity_type_manager,
|
||||||
|
ModuleHandlerInterface $module_handler
|
||||||
|
) {
|
||||||
|
$this->configFactory = $config_factory;
|
||||||
|
$this->entityTypeManager = $entity_type_manager;
|
||||||
|
$this->moduleHandler = $module_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public static function create(ContainerInterface $container) {
|
||||||
|
return new static(
|
||||||
|
$container->get('config.factory'),
|
||||||
|
$container->get('entity_type.manager'),
|
||||||
|
$container->get('module_handler')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getFormId(): string {
|
||||||
|
return 'ldap_groups_sync_unified_access_rules_form';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function buildForm(array $form, FormStateInterface $form_state): array {
|
||||||
|
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
|
||||||
|
|
||||||
|
$form['description'] = [
|
||||||
|
'#type' => 'markup',
|
||||||
|
'#markup' => '<p>' . $this->t(
|
||||||
|
'Define rules that restrict or grant entity operations based on group membership.<br>'
|
||||||
|
. '<strong>Restrictive</strong>: if a matching rule exists and the user does not satisfy it, access is denied.<br>'
|
||||||
|
. '<strong>Additive</strong>: the rule only grants extra access; other users keep their default permissions.'
|
||||||
|
) . '</p>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$form['summary'] = [
|
||||||
|
'#type' => 'table',
|
||||||
|
'#header' => [
|
||||||
|
$this->t('Type'),
|
||||||
|
$this->t('Label'),
|
||||||
|
$this->t('Entity type / Bundle'),
|
||||||
|
$this->t('Operations'),
|
||||||
|
$this->t('Groups / Roles'),
|
||||||
|
$this->t('Mode'),
|
||||||
|
$this->t('Status'),
|
||||||
|
$this->t('Edit'),
|
||||||
|
$this->t('Remove'),
|
||||||
|
],
|
||||||
|
'#empty' => $this->t('No access rules defined. Use the "Add Rule" buttons below to create the first one.'),
|
||||||
|
'#attributes' => ['class' => ['access-rules-summary-table']],
|
||||||
|
'#tree' => TRUE,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach (self::GROUP_TYPES as $group_type => $info) {
|
||||||
|
if (!$this->moduleHandler->moduleExists($info['module'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rules = $this->configFactory->get($info['config'])->get('access_rules') ?? [];
|
||||||
|
|
||||||
|
foreach ($rules as $i => $rule) {
|
||||||
|
$row_key = $group_type . '__' . $i;
|
||||||
|
|
||||||
|
$bundle_part = !empty($rule['bundle'])
|
||||||
|
? ' / <em>' . $rule['bundle'] . '</em>'
|
||||||
|
: ' / <em>' . $this->t('all bundles') . '</em>';
|
||||||
|
|
||||||
|
$form['summary'][$row_key]['type'] = [
|
||||||
|
'#markup' => $info['label'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$form['summary'][$row_key]['label'] = [
|
||||||
|
'#markup' => '<strong>' . ($rule['label'] ?: $this->t('(no label)')) . '</strong>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$form['summary'][$row_key]['entity_bundle'] = [
|
||||||
|
'#markup' => ($rule['entity_type'] ?? '?') . $bundle_part,
|
||||||
|
];
|
||||||
|
|
||||||
|
$form['summary'][$row_key]['operations'] = [
|
||||||
|
'#markup' => implode(', ', $rule['operations'] ?? []),
|
||||||
|
];
|
||||||
|
|
||||||
|
$membership_lines = [];
|
||||||
|
foreach ($rule['memberships'] ?? [] as $mem) {
|
||||||
|
try {
|
||||||
|
$group = $this->entityTypeManager->getStorage('group')->load($mem['group_id'] ?? 0);
|
||||||
|
$group_label = $group ? $group->label() : '#' . ($mem['group_id'] ?? '?');
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
$group_label = '#' . ($mem['group_id'] ?? '?');
|
||||||
|
}
|
||||||
|
$roles = implode(', ', $mem['roles'] ?? []);
|
||||||
|
$membership_lines[] = $group_label . ($roles ? ' <em>(' . $roles . ')</em>' : '');
|
||||||
|
}
|
||||||
|
$form['summary'][$row_key]['memberships_summary'] = [
|
||||||
|
'#markup' => $membership_lines
|
||||||
|
? implode('<br>', $membership_lines)
|
||||||
|
: '<em>' . $this->t('none') . '</em>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$form['summary'][$row_key]['mode'] = [
|
||||||
|
'#markup' => ($rule['mode'] ?? 'restrictive') === 'additive'
|
||||||
|
? $this->t('Additive')
|
||||||
|
: $this->t('Restrictive'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$form['summary'][$row_key]['enabled'] = [
|
||||||
|
'#markup' => ($rule['enabled'] ?? TRUE)
|
||||||
|
? '<span style="color:green">✓ ' . $this->t('On') . '</span>'
|
||||||
|
: '<span style="color:gray">✗ ' . $this->t('Off') . '</span>',
|
||||||
|
];
|
||||||
|
|
||||||
|
$form['summary'][$row_key]['edit'] = [
|
||||||
|
'#type' => 'link',
|
||||||
|
'#title' => $this->t('Edit'),
|
||||||
|
'#url' => Url::fromRoute('ldap_groups_sync.access_rule_form', [
|
||||||
|
'group_type' => $group_type,
|
||||||
|
'rule_index' => $i,
|
||||||
|
]),
|
||||||
|
'#attributes' => [
|
||||||
|
'class' => ['use-ajax', 'button', 'button--small'],
|
||||||
|
'data-dialog-type' => 'modal',
|
||||||
|
'data-dialog-options' => json_encode([
|
||||||
|
'width' => 860,
|
||||||
|
'title' => $this->t('Edit Access Rule'),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$form['summary'][$row_key]['remove'] = [
|
||||||
|
'#type' => 'checkbox',
|
||||||
|
'#default_value' => FALSE,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$form['actions'] = ['#type' => 'actions'];
|
||||||
|
|
||||||
|
// Find the first enabled submodule to use as the initial group_type in the
|
||||||
|
// modal URL. The modal itself exposes a "Group Type" select so the user can
|
||||||
|
// switch to any enabled type without closing and re-opening the dialog.
|
||||||
|
$default_group_type = NULL;
|
||||||
|
foreach (self::GROUP_TYPES as $group_type => $info) {
|
||||||
|
if ($this->moduleHandler->moduleExists($info['module'])) {
|
||||||
|
$default_group_type = $group_type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($default_group_type !== NULL) {
|
||||||
|
$form['actions']['add_rule'] = [
|
||||||
|
'#type' => 'link',
|
||||||
|
'#title' => $this->t('Add Rule'),
|
||||||
|
'#url' => Url::fromRoute('ldap_groups_sync.access_rule_form', [
|
||||||
|
'group_type' => $default_group_type,
|
||||||
|
'rule_index' => 'new',
|
||||||
|
]),
|
||||||
|
'#attributes' => [
|
||||||
|
'class' => ['use-ajax', 'button', 'button--primary'],
|
||||||
|
'data-dialog-type' => 'modal',
|
||||||
|
'data-dialog-options' => json_encode([
|
||||||
|
'width' => 860,
|
||||||
|
'title' => $this->t('New Access Rule'),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$form['actions']['remove_selected'] = [
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => $this->t('Remove Selected'),
|
||||||
|
'#limit_validation_errors' => [['summary']],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function submitForm(array &$form, FormStateInterface $form_state): void {
|
||||||
|
$summary_values = $form_state->getValue('summary') ?? [];
|
||||||
|
|
||||||
|
// Collect indices to remove per group type.
|
||||||
|
$to_remove = [];
|
||||||
|
foreach ($summary_values as $row_key => $row) {
|
||||||
|
if (empty($row['remove'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// row_key format: {group_type}__{rule_index}
|
||||||
|
[$group_type, $rule_index] = explode('__', $row_key, 2);
|
||||||
|
$to_remove[$group_type][] = (int) $rule_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (self::GROUP_TYPES as $group_type => $info) {
|
||||||
|
if (!isset($to_remove[$group_type])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!$this->moduleHandler->moduleExists($info['module'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = $this->configFactory->getEditable($info['config']);
|
||||||
|
$rules = $config->get('access_rules') ?? [];
|
||||||
|
|
||||||
|
$kept = [];
|
||||||
|
foreach ($rules as $i => $rule) {
|
||||||
|
if (!in_array($i, $to_remove[$group_type], TRUE)) {
|
||||||
|
$kept[] = $rule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$config->set('access_rules', array_values($kept))->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->messenger()->addStatus($this->t('Access rules updated.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user