From 1bf42c5ba0230ceba7913591bd625ca0d8d83026 Mon Sep 17 00:00:00 2001 From: Arlen Johnson Date: Wed, 11 Feb 2026 12:48:39 -0500 Subject: [PATCH 1/2] Provide Person-centric Group management; includes subnavigation refactoring (CFM-291) --- .../ApiSourceEndpointsController.php | 8 + .../src/Controller/ApiSourcesController.php | 22 ++ .../src/Model/Table/ApiSourcesTable.php | 1 - .../templates/ApiSourceEndpoints/fields.inc | 9 + .../templates/ApiSources/fields.inc | 10 + .../Controller/FileProvisionersController.php | 22 ++ .../src/Model/Table/FileSourcesTable.php | 18 -- .../templates/FileProvisioners/fields.inc | 11 +- .../templates/FileSources/fields.inc | 10 + .../Controller/KerberosServersController.php | 22 ++ .../templates/KerberosServers/fields.inc | 8 + .../PasswordAuthenticatorsController.php | 22 ++ .../PasswordAuthenticators/fields.inc | 9 + .../Controller/SqlProvisionersController.php | 22 ++ .../src/Model/Table/SqlSourcesTable.php | 18 -- .../templates/SqlProvisioners/fields.inc | 9 + .../templates/SqlSources/fields.inc | 10 + .../Controller/MatchCallbacksController.php | 9 +- .../templates/MatchCallbacks/fields.inc | 11 +- .../Controller/FormatAssignersController.php | 22 ++ .../src/Controller/SqlAssignersController.php | 22 ++ .../templates/FormatAssigners/fields.inc | 10 + .../templates/SqlAssigners/fields.inc | 9 + .../Model/Table/ApprovalCollectorsTable.php | 17 -- .../Model/Table/AttributeCollectorsTable.php | 18 -- .../Table/BasicAttributeCollectorsTable.php | 17 -- .../src/Model/Table/EmailVerifiersTable.php | 17 -- .../Model/Table/EnrollmentAttributesTable.php | 19 -- .../Model/Table/IdentifierCollectorsTable.php | 17 -- .../Model/Table/InvitationAcceptersTable.php | 17 -- .../templates/ApprovalCollectors/fields.inc | 9 + .../templates/AttributeCollectors/fields.inc | 12 +- .../BasicAttributeCollectors/fields.inc | 9 + .../templates/EmailVerifiers/fields.inc | 9 + .../EnrollmentAttributes/columns.inc | 10 + .../templates/EnrollmentAttributes/fields.inc | 10 + .../templates/IdentifierCollectors/fields.inc | 9 + .../templates/InvitationAccepters/fields.inc | 9 + .../src/Controller/HttpServersController.php | 22 ++ .../MatchServerAttributesController.php | 8 + .../src/Controller/MatchServersController.php | 22 ++ .../Controller/Oauth2ServersController.php | 12 +- .../src/Controller/SmtpServersController.php | 22 ++ .../src/Controller/SqlServersController.php | 22 ++ .../templates/HttpServers/fields.inc | 9 + .../MatchServerAttributes/columns.inc | 10 + .../MatchServerAttributes/fields.inc | 10 + .../templates/MatchServers/fields.inc | 10 + .../templates/Oauth2Servers/fields.inc | 12 +- .../templates/SmtpServers/fields.inc | 9 + .../templates/SqlServers/fields.inc | 9 + .../Model/Table/EnvSourceCollectorsTable.php | 17 -- .../src/Model/Table/EnvSourcesTable.php | 18 -- .../templates/EnvSourceCollectors/fields.inc | 9 + .../EnvSource/templates/EnvSources/fields.inc | 10 + .../Table/OrcidSourceCollectorsTable.php | 17 -- .../src/Model/Table/OrcidSourcesTable.php | 18 -- .../OrcidSourceCollectors/fields.inc | 9 + .../templates/OrcidSources/fields.inc | 10 + .../SshKeyAuthenticatorsController.php | 24 +++ .../templates/SshKeyAuthenticators/fields.inc | 9 + .../Model/Table/AgreementCollectorsTable.php | 17 -- .../templates/AgreementCollectors/fields.inc | 9 + app/resources/locales/en_US/operation.po | 3 + app/src/Lib/Traits/TabTrait.php | 71 ------- app/src/Lib/Util/StringUtilities.php | 2 +- .../Model/Table/EnrollmentFlowStepsTable.php | 38 ---- app/src/Model/Table/EnrollmentFlowsTable.php | 19 -- .../Table/ExtIdentitySourceRecordsTable.php | 33 --- .../Model/Table/ExternalIdentitiesTable.php | 34 --- .../Table/ExternalIdentityRolesTable.php | 33 --- .../Table/ExternalIdentitySourcesTable.php | 18 -- app/src/Model/Table/GroupMembersTable.php | 41 ++-- app/src/Model/Table/GroupNestingsTable.php | 13 -- app/src/Model/Table/GroupsTable.php | 19 -- app/src/Model/Table/PeopleTable.php | 19 -- app/src/Model/Table/PersonRolesTable.php | 19 -- app/src/Model/Table/PetitionsTable.php | 19 -- app/src/View/Helper/TabHelper.php | 7 +- app/templates/AdHocAttributes/columns.inc | 14 -- app/templates/Addresses/columns.inc | 14 -- app/templates/ApiUsers/columns.inc | 8 - app/templates/Apis/columns.inc | 8 - app/templates/Apis/fields.inc | 4 +- app/templates/Authenticators/columns.inc | 8 +- app/templates/Authenticators/fields.inc | 2 + app/templates/Cos/columns.inc | 8 - app/templates/Cous/columns.inc | 8 - app/templates/EmailAddresses/columns.inc | 14 -- app/templates/EnrollmentFlowSteps/columns.inc | 11 +- app/templates/EnrollmentFlowSteps/fields.inc | 3 + app/templates/EnrollmentFlows/fields.inc | 2 + .../ExtIdentitySourceRecords/fields.inc | 12 -- app/templates/ExternalIdentities/columns.inc | 15 +- app/templates/ExternalIdentities/fields.inc | 8 +- .../ExternalIdentityRoles/columns.inc | 14 +- .../ExternalIdentityRoles/fields.inc | 6 +- .../ExternalIdentitySources/columns.inc | 8 - .../ExternalIdentitySources/fields.inc | 4 +- .../ExternalIdentitySources/search.php | 5 + app/templates/Flanges/columns.inc | 8 - app/templates/GroupMembers/columns.inc | 200 +++++++++++------- app/templates/GroupNestings/columns.inc | 8 +- app/templates/Groups/columns.inc | 3 - app/templates/Groups/fields.inc | 2 + .../IdentifierAssignments/columns.inc | 8 - .../IdentifierAssignments/fields.inc | 3 + app/templates/Identifiers/columns.inc | 14 -- app/templates/Names/columns.inc | 14 -- app/templates/People/columns.inc | 8 - app/templates/People/fields.inc | 8 +- app/templates/PersonRoles/columns.inc | 13 +- app/templates/PersonRoles/fields.inc | 8 +- app/templates/Petitions/columns.inc | 2 + app/templates/Pipelines/columns.inc | 7 - app/templates/Pronouns/columns.inc | 14 -- app/templates/ProvisioningTargets/columns.inc | 8 - app/templates/ProvisioningTargets/fields.inc | 6 +- app/templates/Servers/columns.inc | 8 - app/templates/Servers/fields.inc | 18 +- app/templates/Standard/add-edit-view.php | 21 +- app/templates/Standard/index.php | 11 +- app/templates/Standard/subnavigation.inc | 150 ++++++++++++- app/templates/TelephoneNumbers/columns.inc | 14 -- app/templates/TrafficDetours/columns.inc | 8 - app/templates/Types/columns.inc | 11 - app/templates/Urls/columns.inc | 14 -- .../element/subnavigation/navBar.php | 5 +- .../element/subnavigation/tabList.php | 10 +- .../element/subnavigation/tabTitle.php | 4 +- 130 files changed, 976 insertions(+), 1053 deletions(-) delete mode 100644 app/src/Lib/Traits/TabTrait.php diff --git a/app/availableplugins/ApiConnector/src/Controller/ApiSourceEndpointsController.php b/app/availableplugins/ApiConnector/src/Controller/ApiSourceEndpointsController.php index f9fe4da31..119202628 100644 --- a/app/availableplugins/ApiConnector/src/Controller/ApiSourceEndpointsController.php +++ b/app/availableplugins/ApiConnector/src/Controller/ApiSourceEndpointsController.php @@ -48,6 +48,14 @@ class ApiSourceEndpointsController extends StandardPluginController { */ public function beforeRender(\Cake\Event\EventInterface $event) { + $link = $this->getPrimaryLink(true); + + if(!empty($link->value)) { + $this->set('vv_bc_parent_obj', $this->ApiSourceEndpoints->Apis->get($link->value)); + $this->set('vv_bc_parent_displayfield', $this->ApiSourceEndpoints->Apis->getDisplayField()); + $this->set('vv_bc_parent_primarykey', $this->ApiSourceEndpoints->Apis->getPrimaryKey()); + } + $vv_obj = $this->viewBuilder()->getVar('vv_obj'); if(!empty($vv_obj->external_identity_source->api_source->id)) { diff --git a/app/availableplugins/ApiConnector/src/Controller/ApiSourcesController.php b/app/availableplugins/ApiConnector/src/Controller/ApiSourcesController.php index 75ff700c5..b779a9a65 100644 --- a/app/availableplugins/ApiConnector/src/Controller/ApiSourcesController.php +++ b/app/availableplugins/ApiConnector/src/Controller/ApiSourcesController.php @@ -29,6 +29,7 @@ namespace ApiConnector\Controller; +use Cake\Event\EventInterface; use Cake\Routing\Router; use App\Controller\StandardPluginController; @@ -38,4 +39,25 @@ class ApiSourcesController extends StandardPluginController { 'ApiSources.id' => 'asc' ] ]; + + /** + * Callback run prior to the request render. + * + * @param EventInterface $event Cake Event + * + * @return Response|void + * @since COmanage Registry v5.0.0 + */ + + public function beforeRender(EventInterface $event) { + $link = $this->getPrimaryLink(true); + + if(!empty($link->value)) { + $this->set('vv_bc_parent_obj', $this->ApiSources->ExternalIdentitySources->get($link->value)); + $this->set('vv_bc_parent_displayfield', $this->ApiSources->ExternalIdentitySources->getDisplayField()); + $this->set('vv_bc_parent_primarykey', $this->ApiSources->ExternalIdentitySources->getPrimaryKey()); + } + + return parent::beforeRender($event); + } } diff --git a/app/availableplugins/ApiConnector/src/Model/Table/ApiSourcesTable.php b/app/availableplugins/ApiConnector/src/Model/Table/ApiSourcesTable.php index 0cb1f6d72..07bfdfdfa 100644 --- a/app/availableplugins/ApiConnector/src/Model/Table/ApiSourcesTable.php +++ b/app/availableplugins/ApiConnector/src/Model/Table/ApiSourcesTable.php @@ -42,7 +42,6 @@ class ApiSourcesTable extends Table { use \App\Lib\Traits\PrimaryLinkTrait; use \App\Lib\Traits\TableMetaTrait; use \App\Lib\Traits\ValidationTrait; - use \App\Lib\Traits\TabTrait; /** * Perform Cake Model initialization. diff --git a/app/availableplugins/ApiConnector/templates/ApiSourceEndpoints/fields.inc b/app/availableplugins/ApiConnector/templates/ApiSourceEndpoints/fields.inc index 909625d5f..64fd79507 100644 --- a/app/availableplugins/ApiConnector/templates/ApiSourceEndpoints/fields.inc +++ b/app/availableplugins/ApiConnector/templates/ApiSourceEndpoints/fields.inc @@ -38,3 +38,12 @@ if(!empty($vv_push_endpoint)) { $fields = [ 'external_identity_source_id' ]; + +$subnav = 'local'; +$subnavLocal = [ + 'tabs' => ['Apis', 'ApiConnector.ApiSourceEndpoints'], + 'action' => [ + 'Apis' => ['edit'], + 'ApiConnector.ApiSourceEndpoints' => ['edit'] + ] +]; diff --git a/app/availableplugins/ApiConnector/templates/ApiSources/fields.inc b/app/availableplugins/ApiConnector/templates/ApiSources/fields.inc index 32722bfa7..34c21dd7e 100644 --- a/app/availableplugins/ApiConnector/templates/ApiSources/fields.inc +++ b/app/availableplugins/ApiConnector/templates/ApiSources/fields.inc @@ -38,3 +38,13 @@ $fields = [ 'subtitle' => __d('api_connector', 'field.ApiSources.push_mode') ] ]; + +$subnav = 'local'; +$subnavLocal = [ + 'tabs' => ['ExternalIdentitySources', 'ApiConnector.ApiSources', 'ExternalIdentitySources@action.search'], + 'action' => [ + 'ExternalIdentitySources' => ['edit', 'view', 'search'], + 'ApiConnector.ApiSources' => ['edit'], + 'ExternalIdentitySources@action.search' => [], + ], +]; diff --git a/app/availableplugins/FileConnector/src/Controller/FileProvisionersController.php b/app/availableplugins/FileConnector/src/Controller/FileProvisionersController.php index 3fe2ebd9e..fed47b8e2 100644 --- a/app/availableplugins/FileConnector/src/Controller/FileProvisionersController.php +++ b/app/availableplugins/FileConnector/src/Controller/FileProvisionersController.php @@ -30,6 +30,7 @@ namespace FileConnector\Controller; use App\Controller\StandardPluginController; +use Cake\Event\EventInterface; class FileProvisionersController extends StandardPluginController { protected array $paginate = [ @@ -37,4 +38,25 @@ class FileProvisionersController extends StandardPluginController { 'FileProvisioners.id' => 'asc' ] ]; + + /** + * Callback run prior to the request render. + * + * @param EventInterface $event Cake Event + * + * @return Response|void + * @since COmanage Registry v5.0.0 + */ + + public function beforeRender(EventInterface $event) { + $link = $this->getPrimaryLink(true); + + if(!empty($link->value)) { + $this->set('vv_bc_parent_obj', $this->FileProvisioners->ProvisioningTargets->get($link->value)); + $this->set('vv_bc_parent_displayfield', $this->FileProvisioners->ProvisioningTargets->getDisplayField()); + $this->set('vv_bc_parent_primarykey', $this->FileProvisioners->ProvisioningTargets->getPrimaryKey()); + } + + return parent::beforeRender($event); + } } diff --git a/app/availableplugins/FileConnector/src/Model/Table/FileSourcesTable.php b/app/availableplugins/FileConnector/src/Model/Table/FileSourcesTable.php index 5010d7267..ee57ddd7a 100644 --- a/app/availableplugins/FileConnector/src/Model/Table/FileSourcesTable.php +++ b/app/availableplugins/FileConnector/src/Model/Table/FileSourcesTable.php @@ -47,7 +47,6 @@ class FileSourcesTable extends Table { use \App\Lib\Traits\PrimaryLinkTrait; use \App\Lib\Traits\TableMetaTrait; use \App\Lib\Traits\ValidationTrait; - use \App\Lib\Traits\TabTrait; // Cache of the field configuration protected $fieldCfg = null; @@ -89,23 +88,6 @@ public function initialize(array $config): void { ] ]); - // All the tabs share the same configuration in the ModelTable file - $this->setTabsConfig( - [ - // Ordered list of Tabs - 'tabs' => ['ExternalIdentitySources', 'FileConnector.FileSources', 'ExternalIdentitySources@action.search'], - // What actions will include the subnavigation header - 'action' => [ - // If a model renders in a subnavigation mode in edit/view mode, it cannot - // render in index mode for the same use case/context - // XXX edit should go first. - 'ExternalIdentitySources' => ['edit', 'view', 'search'], - 'FileConnector.FileSources' => ['edit'], - 'ExternalIdentitySources@action.search' => [], - ], - ] - ); - $this->setPermissions([ // Actions that operate over an entity (ie: require an $id) 'entity' => [ diff --git a/app/availableplugins/FileConnector/templates/FileProvisioners/fields.inc b/app/availableplugins/FileConnector/templates/FileProvisioners/fields.inc index ffecf0e93..0eb4a67e2 100644 --- a/app/availableplugins/FileConnector/templates/FileProvisioners/fields.inc +++ b/app/availableplugins/FileConnector/templates/FileProvisioners/fields.inc @@ -27,4 +27,13 @@ $fields = [ 'filename' -]; \ No newline at end of file +]; + +$subnav = 'local'; +$subnavLocal = [ + 'tabs' => ['ProvisioningTargets', 'FileConnector.FileProvisioners'], + 'action' => [ + 'ProvisioningTargets' => ['edit'], + 'FileConnector.FileProvisioners' => ['edit'] + ] +]; diff --git a/app/availableplugins/FileConnector/templates/FileSources/fields.inc b/app/availableplugins/FileConnector/templates/FileSources/fields.inc index 3fbde4e40..ce401091b 100644 --- a/app/availableplugins/FileConnector/templates/FileSources/fields.inc +++ b/app/availableplugins/FileConnector/templates/FileSources/fields.inc @@ -32,3 +32,13 @@ $fields = [ 'threshold_check', 'threshold_override', ]; + +$subnav = 'local'; +$subnavLocal = [ + 'tabs' => ['ExternalIdentitySources', 'FileConnector.FileSources', 'ExternalIdentitySources@action.search'], + 'action' => [ + 'ExternalIdentitySources' => ['edit', 'view', 'search'], + 'FileConnector.FileSources' => ['edit'], + 'ExternalIdentitySources@action.search' => [], + ], +]; diff --git a/app/availableplugins/KerberosConnector/src/Controller/KerberosServersController.php b/app/availableplugins/KerberosConnector/src/Controller/KerberosServersController.php index 089b2ef8e..e818c8cb8 100644 --- a/app/availableplugins/KerberosConnector/src/Controller/KerberosServersController.php +++ b/app/availableplugins/KerberosConnector/src/Controller/KerberosServersController.php @@ -30,6 +30,7 @@ namespace KerberosConnector\Controller; use App\Controller\StandardPluginController; +use Cake\Event\EventInterface; class KerberosServersController extends StandardPluginController { protected array $paginate = [ @@ -37,4 +38,25 @@ class KerberosServersController extends StandardPluginController { 'KerberosServers.hostname' => 'asc' ] ]; + + /** + * Callback run prior to the request render. + * + * @param EventInterface $event Cake Event + * + * @return Response|void + * @since COmanage Registry v5.0.0 + */ + + public function beforeRender(EventInterface $event) { + $link = $this->getPrimaryLink(true); + + if(!empty($link->value)) { + $this->set('vv_bc_parent_obj', $this->KerberosServers->Servers->get($link->value)); + $this->set('vv_bc_parent_displayfield', $this->KerberosServers->Servers->getDisplayField()); + $this->set('vv_bc_parent_primarykey', $this->KerberosServers->Servers->getPrimaryKey()); + } + + return parent::beforeRender($event); + } } diff --git a/app/availableplugins/KerberosConnector/templates/KerberosServers/fields.inc b/app/availableplugins/KerberosConnector/templates/KerberosServers/fields.inc index d4f28daf4..7f0c72f5d 100644 --- a/app/availableplugins/KerberosConnector/templates/KerberosServers/fields.inc +++ b/app/availableplugins/KerberosConnector/templates/KerberosServers/fields.inc @@ -33,3 +33,11 @@ $fields = [ 'keytab_path' ]; +$subnav = 'local'; +$subnavLocal = [ + 'tabs' => ['Servers', 'KerberosConnector.KerberosServers'], + 'action' => [ + 'Servers' => ['edit'], + 'KerberosConnector.KerberosServers' => ['edit'] + ] +]; diff --git a/app/availableplugins/PasswordAuthenticator/src/Controller/PasswordAuthenticatorsController.php b/app/availableplugins/PasswordAuthenticator/src/Controller/PasswordAuthenticatorsController.php index 06dba901f..cf0692b5b 100644 --- a/app/availableplugins/PasswordAuthenticator/src/Controller/PasswordAuthenticatorsController.php +++ b/app/availableplugins/PasswordAuthenticator/src/Controller/PasswordAuthenticatorsController.php @@ -30,6 +30,7 @@ namespace PasswordAuthenticator\Controller; use App\Controller\StandardPluginController; +use Cake\Event\EventInterface; class PasswordAuthenticatorsController extends StandardPluginController { protected array $paginate = [ @@ -37,4 +38,25 @@ class PasswordAuthenticatorsController extends StandardPluginController { 'PasswordAuthenticators.id' => 'asc' ] ]; + + /** + * Callback run prior to the request render. + * + * @param EventInterface $event Cake Event + * + * @return Response|void + * @since COmanage Registry v5.0.0 + */ + + public function beforeRender(EventInterface $event) { + $link = $this->getPrimaryLink(true); + + if(!empty($link->value)) { + $this->set('vv_bc_parent_obj', $this->PasswordAuthenticators->Authenticators->get($link->value)); + $this->set('vv_bc_parent_displayfield', $this->PasswordAuthenticators->Authenticators->getDisplayField()); + $this->set('vv_bc_parent_primarykey', $this->PasswordAuthenticators->Authenticators->getPrimaryKey()); + } + + return parent::beforeRender($event); + } } diff --git a/app/availableplugins/PasswordAuthenticator/templates/PasswordAuthenticators/fields.inc b/app/availableplugins/PasswordAuthenticator/templates/PasswordAuthenticators/fields.inc index bf1640b56..a85f03dc0 100644 --- a/app/availableplugins/PasswordAuthenticator/templates/PasswordAuthenticators/fields.inc +++ b/app/availableplugins/PasswordAuthenticator/templates/PasswordAuthenticators/fields.inc @@ -34,6 +34,15 @@ $fields = [ 'format_plaintext' ]; +$subnav = 'local'; +$subnavLocal = [ + 'tabs' => ['Authenticators', 'PasswordAuthenticator.PasswordAuthenticators'], + 'action' => [ + 'Authenticators' => ['edit'], + 'PasswordAuthenticator.PasswordAuthenticators' => ['edit'] + ] +] + ?>