From 3aa685ac78f1e907cbd6346c55c4dfd430b68c33 Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Wed, 20 Aug 2025 12:54:18 +0300 Subject: [PATCH] Move enable people picker in Enrollment Flow step configuration --- app/resources/locales/en_US/field.po | 6 +- app/src/Controller/ApiV2Controller.php | 56 ++++++++++++++++++- .../Component/RegistryAuthComponent.php | 36 ------------ app/src/Controller/PeopleController.php | 1 + app/src/View/Helper/FieldHelper.php | 32 +++++++++++ app/src/View/Helper/PetitionHelper.php | 2 +- app/templates/CoSettings/fields.inc | 52 ++++++++--------- app/templates/EnrollmentFlowSteps/fields.inc | 16 ++++++ app/templates/EnrollmentFlows/fields.inc | 1 - 9 files changed, 132 insertions(+), 70 deletions(-) diff --git a/app/resources/locales/en_US/field.po b/app/resources/locales/en_US/field.po index 44d063edc..e9c99c678 100644 --- a/app/resources/locales/en_US/field.po +++ b/app/resources/locales/en_US/field.po @@ -456,6 +456,9 @@ msgstr "Limit Global Search Scope" msgid "CoSettings.search_global_limited_models.desc" msgstr "If true, Global Search will only search Names, Email Addresses, and Identifiers. This may result in faster searches for larger deployments." +msgid "EnrollmentFlowSteps.enable_person_find" +msgstr "Enable People Picker for Self Service" + msgid "EnrollmentFlowSteps.actor_type" msgstr "Actor Type" @@ -498,9 +501,6 @@ msgstr "Petitioner Authorization" msgid "EnrollmentFlows.collect_enrollee_email" msgstr "Collect Enrollee Email" -msgid "EnrollmentFlows.enable_person_find" -msgstr "Enable People Picker for Self Service" - msgid "EnrollmentFlows.enable_person_find.desc" msgstr "Enable people picker for self-service enrollments, see Registry Technical Manual for privacy considerations" diff --git a/app/src/Controller/ApiV2Controller.php b/app/src/Controller/ApiV2Controller.php index 435b156f7..d41eef857 100644 --- a/app/src/Controller/ApiV2Controller.php +++ b/app/src/Controller/ApiV2Controller.php @@ -29,14 +29,15 @@ namespace App\Controller; -use Cake\Controller\Controller; -use InvalidArgumentException; +use App\Lib\Enum\EnrollmentAuthzEnum; use Cake\Chronos\Chronos; +use Cake\Controller\Controller; +use Cake\Event\EventInterface; use Cake\Http\Exception\BadRequestException; use Cake\Log\Log; use Cake\ORM\TableRegistry; use Cake\Utility\Inflector; - +use InvalidArgumentException; use \App\Lib\Enum\ProvisioningContextEnum; use \App\Lib\Enum\SuspendableStatusEnum; @@ -410,4 +411,53 @@ public function view($id = null) { public function pick() { $this->dispatchIndex(mode: 'picker'); } + + /** + * Indicate whether this Controller will handle some or all authnz. + * + * @param EventInterface $event Cake event, ie: from beforeFilter + * @return string "no", "open", "authz", "yes", or "notauth" + * @since COmanage Registry v5.2.0 + */ + public function willHandleAuth(\Cake\Event\EventInterface $event): string + { + $request = $this->getRequest(); + $reqAction = $request->getParam('action'); + $session = $request->getSession(); + $mode = 'no'; + + $auth = $session->read('Auth'); + + // Calculate people picker permissions on the fly for an enrollment flow/petition + if( + $this->name == 'People' + && $reqAction == 'pick' + && !empty($request->getQuery('petition_id')) + ) { + $petitionId = (int)$request->getQuery('petition_id'); + // We need to check if this is part of an Enrollment Flow + $Petitions = TableRegistry::getTableLocator()->get('Petitions'); + + // Pull the Petition to find its CO + $petition = $Petitions->get($petitionId, ['contain' => ['EnrollmentFlows' => ['EnrollmentFlowSteps']]]); + + // We need to check the Petitioner Authorization. + $hasAuthorizedUser = false; + if ($petition->enrollment_flow->authz_type == EnrollmentAuthzEnum::AuthUser) { + $hasAuthorizedUser = !empty($auth['external']['user']); + } else { + // This will be the no authorization use case. + $hasAuthorizedUser = true; + } + + foreach ($petition->enrollment_flow->enrollment_flow_steps as $step) { + if ($step->plugin == 'CoreEnroller.AttributeCollectors') { + $mode = $hasAuthorizedUser && $step->enable_person_find ? 'yes' : 'no'; + } + } + } + + // Apply standard behavior + return $mode; + } } \ No newline at end of file diff --git a/app/src/Controller/Component/RegistryAuthComponent.php b/app/src/Controller/Component/RegistryAuthComponent.php index 861447400..f1098d43e 100644 --- a/app/src/Controller/Component/RegistryAuthComponent.php +++ b/app/src/Controller/Component/RegistryAuthComponent.php @@ -386,19 +386,6 @@ protected function calculatePermissions(?int $id=null): array { // Pull the table's permission definitions $permissions = $this->getTablePermissions($table, $id); - - // Calculate people picker permissions on the fly for an enrollment flow/petition - if( - $reqAction == 'pick' - && $modelsName == 'People' - && !empty($controller->getRequest()->getQuery('petition_id')) - ) { - // We need to check if this is part of an Enrollment Flow - $isPicker = $this->isAuthenticatedUserPicker((int)$controller->getRequest()->getQuery('petition_id')); - if($isPicker) { - $permissions['table']['pick'][] = 'authenticatedUser'; - } - } if($id) { $readOnlyActions = ['view']; @@ -865,29 +852,6 @@ public function isApprover(int $petitionId): bool { public function isAuthenticatedUser(): bool { return !empty($this->authenticatedUser); } - - /** - * Determine if the current authenticated user is allowed to use the person picker functionality - * for a given petition. - * - * @param int $petitionId ID of the petition to check - * @return bool True if the user can use the person picker, false otherwise - * @since COmanage Registry v5.2.0 - */ - - protected function isAuthenticatedUserPicker(int $petitionId): bool - { - if (empty($petitionId)) { - return false; - } - - $Petitions = TableRegistry::getTableLocator()->get('Petitions'); - - // Pull the Petition to find its CO - $petition = $Petitions->get($petitionId, ['contain' => 'EnrollmentFlows']); - - return $this->authenticatedUser && $petition->enrollment_flow->enable_person_find; - } /** * Determine if the current user is a CO Administrator. diff --git a/app/src/Controller/PeopleController.php b/app/src/Controller/PeopleController.php index 5d529a590..f88d7fbcb 100644 --- a/app/src/Controller/PeopleController.php +++ b/app/src/Controller/PeopleController.php @@ -30,6 +30,7 @@ namespace App\Controller; // XXX not doing anything with Log yet +use Cake\Event\EventInterface; use Cake\Log\Log; use Cake\ORM\TableRegistry; use http\QueryString; diff --git a/app/src/View/Helper/FieldHelper.php b/app/src/View/Helper/FieldHelper.php index 5e674a06c..12e3a508f 100644 --- a/app/src/View/Helper/FieldHelper.php +++ b/app/src/View/Helper/FieldHelper.php @@ -32,6 +32,8 @@ use App\Lib\Enum\DateTypeEnum; use App\Lib\Util\StringUtilities; use Cake\I18n\FrozenTime; +use Cake\ORM\Table; +use Cake\ORM\TableRegistry; use Cake\Utility\Inflector; use Cake\View\Helper; use DOMDocument; @@ -548,6 +550,36 @@ public function getReqFields(): array return $this->reqFields; } + /** + * Get reference to the Table Object + * + * @param string $tableName + * + * @return Table + * @since COmanage Registry v5.2.0 + */ + public function getTable(string $tableName): Table + { + return TableRegistry::getTableLocator()->get($tableName); + } + + /** + * Get attribute collectors configuration for a specific enrollment flow step + * + * @param int $stepId The ID of the enrollment flow step + * @return array The attribute collectors configuration array containing enrollment attributes + * @since COmanage Registry v5.2.0 + */ + public function getAttributeCollectorsForStep(int $stepId): array + { + $AttributeCollectors = $this->getTable('CoreEnroller.AttributeCollectors'); + return $AttributeCollectors->find() + ->where(['enrollment_flow_step_id' => $stepId]) + ->contain(['EnrollmentAttributes']) + ->first() + ->toArray(); + } + /** * For the records that have a value like co_x.value, and we want to handle * the value separate from the field diff --git a/app/src/View/Helper/PetitionHelper.php b/app/src/View/Helper/PetitionHelper.php index be426a30d..c4ac48521 100644 --- a/app/src/View/Helper/PetitionHelper.php +++ b/app/src/View/Helper/PetitionHelper.php @@ -76,7 +76,7 @@ public function populateAutoViewVars(): void { // XXX Find the co id foreach ( - $this->enrollmentAttributesTable->calculateAutoViewVars($this->petition?->enrollment_flow?->co_id,$this->entity) as $vvar => $value + $this->enrollmentAttributesTable->calculateAutoViewVars($this->petition?->enrollment_flow?->co_id, $this->entity) as $vvar => $value ) { $this->getView()->set($vvar, $value); } diff --git a/app/templates/CoSettings/fields.inc b/app/templates/CoSettings/fields.inc index 4b51f4165..75231447b 100644 --- a/app/templates/CoSettings/fields.inc +++ b/app/templates/CoSettings/fields.inc @@ -96,32 +96,32 @@ if($vv_action == 'edit') { 'fieldName' => 'search_global_limited_models' ]]); - print $this->element('form/listItem', [ - 'arguments' => [ - 'fieldName' => 'person_picker_display_fields', - 'labelIsTextOnly' => true, - 'groupedControls' => [ - // each key is the fieldName of the control we are going to create - 'person_picker_email_address_type_id' => [ - 'fieldOptions' => [ - 'label' => __d('field', 'mail'), - 'empty' => '(' . __d('operation', 'all') . ')', -// 'all' => '(' . __d('operation', 'all') . ')' - ], - ], - 'person_picker_identifier_type_id' => [ - 'fieldOptions' => [ - 'label' => __d('field', 'identifier'), - 'empty' => '(' . __d('operation', 'all') . ')', -// 'all' => '(' . __d('operation', 'all') . ')', - ], - ], - 'person_picker_display_types' => [ - 'singleRowItem' => true, - 'fieldLabel' => __d('field', 'CoSettings.person_picker_display_types') - ] - ], - ]]); +// print $this->element('form/listItem', [ +// 'arguments' => [ +// 'fieldName' => 'person_picker_display_fields', +// 'labelIsTextOnly' => true, +// 'groupedControls' => [ +// // each key is the fieldName of the control we are going to create +// 'person_picker_email_address_type_id' => [ +// 'fieldOptions' => [ +// 'label' => __d('field', 'mail'), +// 'empty' => '(' . __d('operation', 'all') . ')', +//// 'all' => '(' . __d('operation', 'all') . ')' +// ], +// ], +// 'person_picker_identifier_type_id' => [ +// 'fieldOptions' => [ +// 'label' => __d('field', 'identifier'), +// 'empty' => '(' . __d('operation', 'all') . ')', +//// 'all' => '(' . __d('operation', 'all') . ')', +// ], +// ], +// 'person_picker_display_types' => [ +// 'singleRowItem' => true, +// 'fieldLabel' => __d('field', 'CoSettings.person_picker_display_types') +// ] +// ], +// ]]); print $this->element('form/listItem', [ 'arguments' => [ diff --git a/app/templates/EnrollmentFlowSteps/fields.inc b/app/templates/EnrollmentFlowSteps/fields.inc index ffe5137ec..8b831543b 100644 --- a/app/templates/EnrollmentFlowSteps/fields.inc +++ b/app/templates/EnrollmentFlowSteps/fields.inc @@ -69,6 +69,22 @@ if($vv_action == 'add' || $vv_action == 'edit') { ]]); } + // The people picker enable checkbox is only useful for the attribute collection plugin. + if ($vv_obj->plugin === 'CoreEnroller.AttributeCollectors') { + $attributeCollectorConfig = $this->Field->getAttributeCollectorsForStep( $vv_obj->id); + $sponsorAttribute = array_filter( + $attributeCollectorConfig["enrollment_attributes"], + fn($enrollmentAttribute) => $enrollmentAttribute['attribute'] == 'sponsor_person_id' + ); + print $this->element('form/listItem', [ + 'arguments' => [ + 'fieldName' => 'enable_person_find', + 'fieldOptions' => [ + 'readonly' => empty($sponsorAttribute) + ] + ]]); + } + print $this->element('form/listItem', [ 'arguments' => [ 'fieldName' => 'actor_type', diff --git a/app/templates/EnrollmentFlows/fields.inc b/app/templates/EnrollmentFlows/fields.inc index 33d25752c..411633f7c 100644 --- a/app/templates/EnrollmentFlows/fields.inc +++ b/app/templates/EnrollmentFlows/fields.inc @@ -90,7 +90,6 @@ if($vv_action == 'add' || $vv_action == 'edit') { foreach (['authz_cou_id', 'authz_group_id', 'collect_enrollee_email', - 'enable_person_find', 'redirect_on_duplicate', 'redirect_on_finalize', 'finalization_message_template_id'