From f326b5cdabb5a61d74c3d81105f8102ff3c41b82 Mon Sep 17 00:00:00 2001 From: Benn Oshrin Date: Sun, 14 Jul 2024 20:49:01 -0400 Subject: [PATCH] Fix handling of Pipelined attributes with multiple External Identities (NOJIRA) --- app/resources/locales/en_US/field.po | 3 ++ app/src/Model/Table/AdHocAttributesTable.php | 4 +-- app/src/Model/Table/AddressesTable.php | 4 +++ app/src/Model/Table/EmailAddressesTable.php | 4 +-- app/src/Model/Table/IdentifiersTable.php | 4 +-- app/src/Model/Table/NamesTable.php | 4 +-- app/src/Model/Table/PipelinesTable.php | 32 +++++++++++++------ app/src/Model/Table/PronounsTable.php | 4 +++ app/src/Model/Table/TelephoneNumbersTable.php | 4 +-- app/src/Model/Table/UrlsTable.php | 4 +++ .../ExternalIdentitySources/fields.inc | 3 +- 11 files changed, 48 insertions(+), 22 deletions(-) diff --git a/app/resources/locales/en_US/field.po b/app/resources/locales/en_US/field.po index 83ed93afb..2a00ffeca 100644 --- a/app/resources/locales/en_US/field.po +++ b/app/resources/locales/en_US/field.po @@ -396,6 +396,9 @@ msgstr "If true, Global Search will only search Names, Email Addresses, and Iden msgid "ExternalIdentitySources.hash_source_record" msgstr "Hash Source Records" +msgid "ExternalIdentitySources.sor_label" +msgstr "System of Record Label" + msgid "ExternalIdentitySources.source_record.empty" msgstr "The source record is empty. This suggests the record is no longer available from the datasource." diff --git a/app/src/Model/Table/AdHocAttributesTable.php b/app/src/Model/Table/AdHocAttributesTable.php index 7822a3e0f..d88a58254 100644 --- a/app/src/Model/Table/AdHocAttributesTable.php +++ b/app/src/Model/Table/AdHocAttributesTable.php @@ -77,8 +77,8 @@ public function initialize(array $config): void { $this->belongsTo('PersonRoles'); $this->belongsTo('ExternalIdentities'); $this->belongsTo('ExternalIdentityRoles'); - $this->belongsTo('ExtIdentitySourceRecords') - ->setClassName('ExtIdentitySourceRecords') + $this->belongsTo('SourceAdHocAttributes') + ->setClassName('AdHocAttributes') ->setForeignKey('source_ad_hoc_attribute_id') ->setProperty('source_ad_hoc_attribute'); diff --git a/app/src/Model/Table/AddressesTable.php b/app/src/Model/Table/AddressesTable.php index 6ddd34615..d1be7bd73 100644 --- a/app/src/Model/Table/AddressesTable.php +++ b/app/src/Model/Table/AddressesTable.php @@ -91,6 +91,10 @@ public function initialize(array $config): void { $this->belongsTo('ExternalIdentities'); $this->belongsTo('ExternalIdentityRoles'); $this->belongsTo('Types'); + $this->belongsTo('SourceAddresses') + ->setClassName('Addresses') + ->setForeignKey('source_address_id') + ->setProperty('source_address'); $this->setDisplayField('street'); diff --git a/app/src/Model/Table/EmailAddressesTable.php b/app/src/Model/Table/EmailAddressesTable.php index 2bd309af3..c4b449fe1 100644 --- a/app/src/Model/Table/EmailAddressesTable.php +++ b/app/src/Model/Table/EmailAddressesTable.php @@ -98,8 +98,8 @@ public function initialize(array $config): void { $this->belongsTo('People'); $this->belongsTo('ExternalIdentities'); $this->belongsTo('Types'); - $this->belongsTo('ExtIdentitySourceRecords') - ->setClassName('ExtIdentitySourceRecords') + $this->belongsTo('SourceEmailAddresses') + ->setClassName('EmailAddresses') ->setForeignKey('source_email_address_id') ->setProperty('source_email_address'); diff --git a/app/src/Model/Table/IdentifiersTable.php b/app/src/Model/Table/IdentifiersTable.php index 144ad8d7c..1a3aa6576 100644 --- a/app/src/Model/Table/IdentifiersTable.php +++ b/app/src/Model/Table/IdentifiersTable.php @@ -108,8 +108,8 @@ public function initialize(array $config): void { $this->belongsTo('People'); $this->belongsTo('ProvisioningTargets'); $this->belongsTo('Types'); - $this->belongsTo('ExtIdentitySourceRecords') - ->setClassName('ExtIdentitySourceRecords') + $this->belongsTo('SourceIdentifiers') + ->setClassName('Identifiers') ->setForeignKey('source_identifier_id') ->setProperty('source_identifier'); diff --git a/app/src/Model/Table/NamesTable.php b/app/src/Model/Table/NamesTable.php index d43d5eff5..de71825aa 100644 --- a/app/src/Model/Table/NamesTable.php +++ b/app/src/Model/Table/NamesTable.php @@ -97,8 +97,8 @@ public function initialize(array $config): void { $this->belongsTo('People'); $this->belongsTo('ExternalIdentities'); $this->belongsTo('Types'); - $this->belongsTo('ExtIdentitySourceRecords') - ->setClassName('ExtIdentitySourceRecords') + $this->belongsTo('SourceNames') + ->setClassName('Names') ->setForeignKey('source_name_id') ->setProperty('source_name'); diff --git a/app/src/Model/Table/PipelinesTable.php b/app/src/Model/Table/PipelinesTable.php index 084f91ff8..f3471e96d 100644 --- a/app/src/Model/Table/PipelinesTable.php +++ b/app/src/Model/Table/PipelinesTable.php @@ -48,6 +48,7 @@ use \App\Lib\Enum\ProvisioningContextEnum; use \App\Lib\Enum\StatusEnum; use \App\Lib\Enum\SuspendableStatusEnum; +use \App\Lib\Util\StringUtilities; class PipelinesTable extends Table { use \App\Lib\Traits\AutoViewVarsTrait; @@ -1458,6 +1459,10 @@ protected function syncPerson( $amodel = Inflector::underscore($model); // sourcefk = eg source_name_id $sourcefk = $this->Cos->People->$model->sourceForeignKey(); + // sourceModel = eg SourceName + $sourceModel = StringUtilities::foreignKeyToClassName($sourcefk); + // sourceEntity = eg source_name + $sourceEntity = "source_" . $amodel; // Pull the current set of associated records for this model. // We can filter down to those that came from _any_ source (ie @@ -1471,6 +1476,7 @@ protected function syncPerson( $model.'.person_id' => $person->id, $model.'.'.$sourcefk." IS NOT" => null ]) + ->contain([$sourceModel]) ->all(); // Track which IDs we've seen to facilitate deletes. @@ -1555,20 +1561,26 @@ protected function syncPerson( // Now walk through the Person entities, and delete any that we didn't see. // In theory we could make Cake do this automatically via a HasOne // relation, but it's a bit tricky to make Cake handle relations within - // the same object correctly to cascade the delete. + // the same object correctly to cascade the delete. Also, we need to + // filter entities that aren't associated with this EIS. if(!empty($curentities)) { foreach($curentities as $aentity) { - // $aentity is an entity attached to the Person, we search through the - // source attributes for one with a corresponding source key ID - $found = Hash::extract($externalIdentity[$amodel], '{n}[id='.$aentity->$sourcefk.']'); + if(!empty($aentity->$sourceEntity->external_identity_id) + && $aentity->$sourceEntity->external_identity_id == $externalIdentityId) { + // $aentity is an entity attached to the Person and was sourced from + // an attribute associated with the current External Identity (as opposed + // to another EI associated with the Person); we search through the + // source attributes for one with a corresponding source key ID + $found = Hash::extract($externalIdentity[$amodel], '{n}[id='.$aentity->$sourcefk.']'); - if(!$found) { - if(isset($aentity->frozen) && $aentity->frozen) { - $this->llog('trace', "Refusing to delete frozen $model " . $aentity->id . " on Person from External Identity " . $externalIdentity->id); - } else { - $this->llog('trace', "Deleted $model " . $aentity->id . " for Person " . $person->id); - $this->Cos->People->$model->deleteOrFail($aentity); + if(!$found) { + if(isset($aentity->frozen) && $aentity->frozen) { + $this->llog('trace', "Refusing to delete frozen $model " . $aentity->id . " on Person from External Identity " . $externalIdentity->id); + } else { + $this->llog('trace', "Deleted $model " . $aentity->id . " for Person " . $person->id); + $this->Cos->People->$model->deleteOrFail($aentity); + } } } } diff --git a/app/src/Model/Table/PronounsTable.php b/app/src/Model/Table/PronounsTable.php index e02753daf..23ba6c4dd 100644 --- a/app/src/Model/Table/PronounsTable.php +++ b/app/src/Model/Table/PronounsTable.php @@ -85,6 +85,10 @@ public function initialize(array $config): void { $this->belongsTo('People'); $this->belongsTo('ExternalIdentities'); $this->belongsTo('Types'); + $this->belongsTo('SourcePronouns') + ->setClassName('Pronouns') + ->setForeignKey('source_pronoun_id') + ->setProperty('source_pronoun'); $this->setDisplayField('pronouns'); diff --git a/app/src/Model/Table/TelephoneNumbersTable.php b/app/src/Model/Table/TelephoneNumbersTable.php index 11da53dde..d770ccf05 100644 --- a/app/src/Model/Table/TelephoneNumbersTable.php +++ b/app/src/Model/Table/TelephoneNumbersTable.php @@ -92,8 +92,8 @@ public function initialize(array $config): void { $this->belongsTo('ExternalIdentities'); $this->belongsTo('ExternalIdentityRoles'); $this->belongsTo('Types'); - $this->belongsTo('ExtIdentitySourceRecords') - ->setClassName('ExtIdentitySourceRecords') + $this->belongsTo('SourceTelephoneNumbers') + ->setClassName('TelephoneNumbers') ->setForeignKey('source_telephone_number_id') ->setProperty('source_telephone_number'); diff --git a/app/src/Model/Table/UrlsTable.php b/app/src/Model/Table/UrlsTable.php index ab2550d9b..6ed3d9ca0 100644 --- a/app/src/Model/Table/UrlsTable.php +++ b/app/src/Model/Table/UrlsTable.php @@ -85,6 +85,10 @@ public function initialize(array $config): void { $this->belongsTo('People'); $this->belongsTo('ExternalIdentities'); $this->belongsTo('Types'); + $this->belongsTo('SourceUrls') + ->setClassName('Urls') + ->setForeignKey('source_url_id') + ->setProperty('source_url'); $this->setDisplayField('url'); diff --git a/app/templates/ExternalIdentitySources/fields.inc b/app/templates/ExternalIdentitySources/fields.inc index 1f35ac8c4..f0a7fb645 100644 --- a/app/templates/ExternalIdentitySources/fields.inc +++ b/app/templates/ExternalIdentitySources/fields.inc @@ -33,8 +33,7 @@ if($vv_action == 'add' || $vv_action == 'edit') { 'status', 'plugin', 'pipeline_id', -// Not yet implemented -// 'sor_label', + 'sor_label', 'hash_source_record', 'suppress_noop_logs' ] as $field) {