Skip to content

Commit

Permalink
SQL Provisioner fixes (CFM-74)
Browse files Browse the repository at this point in the history
  • Loading branch information
Benn Oshrin committed Feb 18, 2024
1 parent ed3a2d4 commit f969b37
Showing 1 changed file with 52 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,16 @@ class SqlProvisionersTable extends Table {
'source' => 'People',
'source_table' => 'people',
'related' => [
// We need to process PersonRoles first (last on delete) in case an
// MVEA refers to it
'PersonRoles',
'AdHocAttributes',
'Addresses',
'EmailAddresses',
'ExternalIdentities',
'GroupMembers',
'Identifiers',
'Names',
'PersonRoles',
'Pronouns',
'TelephoneNumbers',
'Urls'
Expand Down Expand Up @@ -417,8 +419,15 @@ protected function syncEntity(
try {
$curEntity = $SpTable->get($data->id);

if($eligibility == ProvisioningEligibilityEnum::Eligible) {
// We have a currently provisioned record and the subject is Eligible,
// We treat Eligible and Ineligible the same, meaning we provision the records.
// marshalProvisioningData() filters Ineligible records so that entitlement
// oriented attributes (such as Group Memberships and Person Roles) are removed,
// which allows us to provision enough of a record that referential integrity is
// maintained.

if($eligibility == ProvisioningEligibilityEnum::Eligible
|| $eligibility == ProvisioningEligibilityEnum::Ineligible) {
// We have a currently provisioned record and the subject is not Deleted,
// patch it with $data and try saving.
$patchedEntity = $SpTable->patchEntity($curEntity, $data->toArray(), ['validate' => false]);

Expand Down Expand Up @@ -450,12 +459,15 @@ protected function syncEntity(
'identifier' => null
];
} else {
// The subject record is deleted or otherwise Ineligible, remove the
// current entity. Remove the related models before the entity.
// The subject record is Deleted, remove the current entity.
// Remove the related models before the entity.
// We process related models backwards so Person Role is deleted last
// (in case other MVEAs point to it) (though we also manually cascade
// deletes in syncRelatedEntities()).

if(!empty($mconfig['related'])) {
// Process related models
foreach($mconfig['related'] as $rmodel) {
foreach(array_reverse($mconfig['related']) as $rmodel) {
$this->syncRelatedEntities(
SqlProvisioner: $SqlProvisioner,
parentEntityName: $entityName,
Expand All @@ -478,8 +490,9 @@ protected function syncEntity(
}
catch(\Cake\Datasource\Exception\RecordNotFoundException $e) {
// The record is not yet in the SP table (probably a new record)
if($eligibility == ProvisioningEligibilityEnum::Eligible) {
// The subject is eligible, so provision the record
if($eligibility == ProvisioningEligibilityEnum::Eligible
|| $eligibility == ProvisioningEligibilityEnum::Ineligible) {
// The subject is not Deleted, so provision the record
$newEntity = $SpTable->newEntity($data->toArray(), ['validate' => false]);

$SpTable->saveOrFail(
Expand Down Expand Up @@ -510,11 +523,11 @@ protected function syncEntity(
'identifier' => null
];
} else {
// The subject record is deleted or otherwise Ineligible, nothing to do
// The subject record is deleted, nothing to do

return [
'status' => ProvisioningStatusEnum::NotProvisioned,
'comment' => __d('sql_connector', 'result.prov.ineligible'),
'comment' => __d('sql_connector', 'result.prov.deleted'),
'identifier' => null
];
}
Expand Down Expand Up @@ -665,15 +678,16 @@ protected function syncRelatedEntities(
->where([$parentFk => $parentData->id])
->all();

if($eligibility == ProvisioningEligibilityEnum::Eligible) {
if($eligibility == ProvisioningEligibilityEnum::Eligible
|| $eligibility == ProvisioningEligibilityEnum::Ineligible) {
// Patch the target with the source. Note this will handle add and
// insert correctly, but will ignore any records from $curEntities that
// are not in $srcEntities.
$patchedEntities = $SpTable->patchEntities($curEntities, $srcEntities, ['validate' => false]);

$SpTable->saveManyOrFail($patchedEntities, ['validate' => false, 'checkRules' => false]);
} else {
// Delete all currently provisioned entries, which will force by
// Delete all currently provisioned entries, which we'll force by
// clearing $srcEntities

$srcEntities = [];
Expand Down Expand Up @@ -715,6 +729,32 @@ protected function syncRelatedEntities(
}

if(!empty($toDelete)) {
if(!empty($this->secondaryModels[$relatedEntityName]['related'])) {
// This model has additional related models that we may need to cascade deletes to.
// We can't leverage Cake's "dependent => true" because the related models don't
// exist in a well defined way that Cake can properly set them up on the fly.
// So we manually process deleteAlls.

$parentKey = StringUtilities::ClassNameToForeignKey($relatedEntityName);

foreach($this->secondaryModels[$relatedEntityName]['related'] as $subModelName) {
$subconfig = $this->secondaryModels[$subModelName];

$options = [
'table' => $SqlProvisioner->table_prefix . $subconfig['table'],
'alias' => $subconfig['name'],
'connection' => ConnectionManager::get($dataSource)
];

$SubTable = TableRegistry::get(alias: $subconfig['name'], options: $options);

foreach($toDelete as $d) {
// We shouldn't get here if either $parentKey or $d->id is null...
$SubTable->deleteAll([$parentKey => $d->id]);
}
}
}

$SpTable->deleteMany($toDelete);
}

Expand Down

0 comments on commit f969b37

Please sign in to comment.