cerebrate/config/Migrations/20210311084258_UniqUUIDAndC...

209 lines
8.1 KiB
PHP

<?php
declare(strict_types=1);
use Migrations\AbstractMigration;
class UniqUUIDAndConstraints extends AbstractMigration
{
private $tablesRequiringUUIDMigration = [
'auth_keys',
'broods',
'encryption_keys',
'individuals',
'meta_fields',
'meta_templates',
'organisations',
'roles',
'sharing_groups',
'users',
];
public function up()
{
foreach ($this->tablesRequiringUUIDMigration as $table) {
$table = $this->table($table);
$this->migrateUUID($table)->update();
}
// We don't need these table as we'll move to a more generic approach
$this->table('alignment_tags')->drop()->save();
$this->table('individual_encryption_keys')->drop()->save();
$this->table('organisation_encryption_keys')->drop()->save();
// If a user is deleted, so you its auth_keys
$this->table('auth_keys')
->addForeignKey('user_id', 'users', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
->update();
// Should an encryption_keys be tied to a user? In the UI it says to individuals/organisations but you can only set it from the user profile.
$this->table('encryption_keys')
->renameColumn('owner_type', 'owner_model') // less confusing name & make it its length future-proof
->changeColumn('owner_model', 'string', [
'length' => 40,
'default' => null,
'null' => false,
])
->update();
// A meta_field belongs to both a template & a template field. If one of them is removed, so should the meta field
// (We don't want floating meta_fields as there is no way to link it back to its corresponding template)
$this->table('meta_fields')
->addForeignKey('meta_template_id', 'meta_templates', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
->addForeignKey('meta_template_field_id', 'meta_template_fields', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
->update();
// sgo being an mapping table, we don't need an ID. We can use the two other FK as a composed PK
$sgo = $this->table('sgo');
if ($sgo->hasColumn('id')) {
$sgo
->changePrimaryKey(['sharing_group_id', 'organisation_id'])
->removeColumn('id')
->update();
}
// A sharing group belongs to both a user & an organisation. If one of them is removed, so should the sharing group
// (A sharing group without owner should not exists)
$this->table('sharing_groups')
->addForeignKey('user_id', 'users', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
->addForeignKey('organisation_id', 'organisations', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
->update();
}
public function down()
{
/**
* Operations not recoverable during a rollback:
* - Dropped tables (alignment_tags, individual_encryption_keys, organisation_encryption_keys)
* - sgo's `ID` primary key
*/
foreach ($this->tablesRequiringUUIDMigration as $table) {
$table = $this->table($table);
$this->roolbackUUID($table)->update();
}
$this->table('auth_keys')
->dropForeignKey('user_id')
->update();
$this->table('encryption_keys')
->renameColumn('owner_model', 'owner_type')
->changeColumn('owner_type', 'string', [
'length' => 20,
'default' => null,
'null' => false,
])
->update();
$this->table('meta_fields')
->dropForeignKey('meta_template_id')
->dropForeignKey('meta_template_field_id')
->update();
$this->table('sharing_groups')
->dropForeignKey('user_id')
->dropForeignKey('organisation_id')
->update();
}
// public function change()
// {
// if ($this->isMigratingUp()) {
// foreach ($this->tablesRequiringUUIDMigration as $table) {
// $table = $this->table($table);
// $this->migrateUUID($table)->update();
// }
// } else {
// foreach ($this->tablesRequiringUUIDMigration as $table) {
// $table = $this->table($table);
// $this->roolbackUUID($table)->update();
// }
// }
// if ($this->isMigratingUp()) {
// // We don't need these table as we'll move to a more generic approach
// $this->table('alignment_tags')->drop()->save();
// $this->table('individual_encryption_keys')->drop()->save();
// $this->table('organisation_encryption_keys')->drop()->save();
// }
// // If a user is deleted, so you its auth_keys
// $this->table('auth_keys')
// ->addForeignKey('user_id', 'users', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
// ->update();
// // Should an encryption_keys be tied to a user? In the UI it says to individuals/organisations but you can only set it from the user profile.
// $encryption_keys = $this->table('encryption_keys');
// $encryption_keys->renameColumn('owner_type', 'owner_model');
// if ($this->isMigratingUp()) {
// $encryption_keys->changeColumn('owner_model', 'string', [
// 'length' => 40,
// 'default' => null,
// 'null' => false,
// ])->update();
// } else {
// $encryption_keys->changeColumn('owner_type', 'string', [
// 'length' => 20,
// 'default' => null,
// 'null' => false,
// ])->update();
// }
// // A meta_field belongs to both a template & a template field. If one of them is removed, so should the meta field
// // (We don't want floating meta_fields as there is no way to link it back to its corresponding template)
// $this->table('meta_fields')
// ->addForeignKey('meta_template_id', 'meta_templates', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
// ->addForeignKey('meta_template_field_id', 'meta_template_fields', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
// ->update();
// // sgo being an mapping table, we don't need an ID. We can use the two other FK as a composed PK
// $sgo = $this->table('sgo');
// if ($this->isMigratingUp()) {
// $sgo->changePrimaryKey(['sharing_group_id', 'organisation_id'])
// ->removeColumn('id')
// ->update();
// } else {
// $sgo->addColumn('id', 'integer', [
// 'autoIncrement' => true,
// 'limit' => 10,
// 'signed' => false,
// ])
// ->changePrimaryKey('id')
// ->update();
// }
// // A sharing group belongs to both a user & an organisation. If one of them is removed, so should the sharing group
// // (A sharing group without owner should not exists)
// $this->table('sharing_groups')
// ->addForeignKey('user_id', 'users', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
// ->addForeignKey('organisation_id', 'organisations', 'id', ['delete'=> 'CASCADE', 'update'=> 'CASCADE'])
// ->update();
// }
// Use cake's built-in uuid type and ensure unicity
private function migrateUUID($table)
{
$table->changeColumn('uuid', 'uuid', [
'default' => null,
'null' => false,
]);
if ($table->hasIndex('uuid')) {
$table->removeIndex(['uuid']); // remove existing non-unique index
}
$table->addIndex(['uuid'], ['unique' => true]);
return $table;
}
private function roolbackUUID($table)
{
$table->changeColumn('uuid', 'string', [
'limit' => 40,
'null' => true,
])->removeIndex(['uuid']);
return $table;
}
}