Skip to content

Commit

Permalink
Add upgrade task
Browse files Browse the repository at this point in the history
  • Loading branch information
Ioannis committed Mar 15, 2026
1 parent 6c9bb3a commit 961a30a
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 4 deletions.
2 changes: 1 addition & 1 deletion app/plugins/EnvSource/templates/EnvSources/fields.inc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ foreach ($spModes as $key => $label) {
}
} elseif ($key === EnvSourceSpModeEnum::Other) {
$phpDelimiterMap[$key] = '';
if ($vv_obj?->mva_delimiter != '') {
if (!in_array($vv_obj?->mva_delimiter, ['', ',', ';'])) {
$phpDelimiterMap[$key] = $vv_obj?->mva_delimiter;
$selectedValue = EnvSourceSpModeEnum::Other;
}
Expand Down
6 changes: 6 additions & 0 deletions app/resources/locales/en_US/information.po
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,18 @@ msgstr "Executing post-database tasks for version {0}"
msgid "ug.tasks.pre"
msgstr "Executing pre-database tasks for version {0}"

msgid "ug.tasks.schema.reload"
msgstr "Force a global schema reload so that post-upgrade tasks are aware of the new schema"

msgid "ug.version.current"
msgstr "Current version: {0}"

msgid "ug.version.target"
msgstr "Target version: {0}"

msgid "ug.tasks.assignEnvSourceMvaDelimiter.co"
msgstr "Map the EnvSource SP Mode to Multi Value Delimitier for CO {0}"

msgid "ug.tasks.assignUuids"
msgstr "Assigning UUIDs (this may take a while for larger deployments)"

Expand Down
107 changes: 104 additions & 3 deletions app/src/Command/UpgradeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

namespace App\Command;

use Cake\Cache\Cache;
use Cake\Console\Arguments;
use Cake\Console\BaseCommand;
use Cake\Console\ConsoleIo;
Expand All @@ -37,13 +38,29 @@
use \App\Lib\Enum\GroupTypeEnum;
use \App\Lib\Util\PaginatedSqlIterator;
use \App\Lib\Util\SearchUtilities;
use Cake\ORM\TableRegistry;
use EnvSource\Lib\Enum\EnvSourceSpModeEnum;

class UpgradeCommand extends BaseCommand
{
use \Cake\ORM\Locator\LocatorAwareTrait;

protected $io = null;

/**
* Cache of EnvSource SP Modes partitioned by CO ID.
*
* This array temporarily stores the `sp_mode` values (e.g., 'SH', 'SS', 'O')
* from the database prior to schema migration. It allows post-migration tasks
* to accurately map the deprecated `sp_mode` column data into the new
* `mva_delimiter` column structure.
*
* Format: `[ coId => [ envSourceId => 'sp_mode_value' ] ]`
*
* @var array<int, array<int, string>>
*/
private array $EnvSourceSpMode = [];

// A list of known versions, must be semantic versioning compliant. The value
// is a "blocker" if it is a version that prevents an upgrade from happening.
// For example, if a user attempts to upgrade from 1.0.0 to 1.2.0, and 1.1.0
Expand Down Expand Up @@ -76,13 +93,15 @@ class UpgradeCommand extends BaseCommand
"5.2.0" => [
'block' => false,
'pre' => [
'checkGroupNames'
'checkGroupNames',
'cacheEnvSourcespMode'
],
'post' => [
'assignUuids',
'buildGroupTree',
'createDefaultGroups',
'installMostlyStaticPages'
'installMostlyStaticPages',
'assignEnvSourceMvaDelimiter',
]
]
];
Expand All @@ -95,7 +114,9 @@ class UpgradeCommand extends BaseCommand
'buildGroupTree' => ['global' => true],
'checkGroupNames' => ['global' => true],
'createDefaultGroups' => ['perCO' => true, 'perCOU' => true],
'installMostlyStaticPages' => ['perCO' => true]
'installMostlyStaticPages' => ['perCO' => true],
'cacheEnvSourcespMode' => ['perCO' => true],
'assignEnvSourceMvaDelimiter' => ['perCO' => true]
];

/**
Expand Down Expand Up @@ -235,6 +256,19 @@ public function execute(Arguments $args, ConsoleIo $io)
if(!$args->getOption('skipdatabase')) {
// Call database command
$this->executeCommand(DatabaseCommand::class);

// Force a global schema reload so that post-upgrade tasks are aware of the new schema
$this->io->out(__d('information', 'ug.tasks.schema.reload'));

// Clear all loaded table instances so they are re-instantiated with the new schema
TableRegistry::getTableLocator()->clear();

// Clear the CakePHP file/redis cache for models (this holds the schema arrays)
Cache::clear('_cake_model_');

// Disable schema caching for this specific process going forward
$connection = ConnectionManager::get('default');
$connection->cacheMetadata(false);
}

// Run appropriate post-database steps
Expand Down Expand Up @@ -378,6 +412,73 @@ protected function assignUuids() {
}
}


/**
* Cache the SP Mode for EnvSource instances associated with a given CO.
* This is used prior to database migrations where the sp_mode column is
* removed or altered, allowing post-migration tasks to map the old value
* to the new schema structure (e.g., mva_delimiter).
*
* @since COmanage Registry v5.2.0
* @param int $coId CO ID to cache the configurations for
* @return void
*/
protected function cacheEnvSourcespMode(int $coId): void
{
$MspsTable = $this->getTableLocator()->get('EnvSource.EnvSources');

$modes = $MspsTable->find('list', [
'keyField' => 'id',
'valueField' => 'sp_mode'
])
->innerJoinWith('ExternalIdentitySources')
->where(['ExternalIdentitySources.co_id' => $coId])
->applyOptions(['archived' => true])
->toArray();

$this->EnvSourceSpMode[$coId] = $modes;
}

/**
* Cache the SP Mode for EnvSource instances associated with a given CO.
* This is used prior to database migrations where the sp_mode column is
* removed or altered, allowing post-migration tasks to map the old value
* to the new schema structure (e.g., mva_delimiter).
*
* @param int $coId CO ID to cache the configurations for
* @return void
* @throws \Exception
* @since COmanage Registry v5.2.0
*/
protected function assignEnvSourceMvaDelimiter(int $coId): void
{
if (empty($this->EnvSourceSpMode[$coId])) {
// Nothing to migrate for this CO
return;
}

$EnvSourcesTable = $this->getTableLocator()->get('EnvSource.EnvSources');

// Iterate over the cached id => sp_mode array for this CO
foreach ($this->EnvSourceSpMode[$coId] as $envSourceId => $spMode) {
$delimiter = ';';

// Map the old SP Mode to the new multi-value delimiter
if ($spMode === EnvSourceSpModeEnum::Shibboleth) {
$delimiter = ';';
} elseif ($spMode === EnvSourceSpModeEnum::SimpleSamlPhp) {
$delimiter = ',';
}

// Use updateAll to execute a raw SQL UPDATE.
// This bypasses the ORM's beforeSave event and ChangelogBehavior's lock.
$EnvSourcesTable->updateAll(
['mva_delimiter' => $delimiter], // Fields to update
['id' => $envSourceId] // Conditions
);
}
}

/**
* Establish tree metadata for Groups.
*
Expand Down

0 comments on commit 961a30a

Please sign in to comment.