diff --git a/packages/syncing-server/migrations/mysql-legacy/1606470249552-init_database.ts b/packages/syncing-server/migrations/mysql-legacy/1606470249552-init_database.ts new file mode 100644 index 000000000..54f3f3a95 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1606470249552-init_database.ts @@ -0,0 +1,50 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class initDatabase1606470249552 implements MigrationInterface { + name = 'initDatabase1606470249552' + + public async up(queryRunner: QueryRunner): Promise { + await this.fixUpdatedAtTimestampsFromLegacyMigration(queryRunner) + + await queryRunner.query( + 'CREATE TABLE IF NOT EXISTS `items` (`uuid` varchar(36) NOT NULL, `duplicate_of` varchar(36) NULL, `items_key_id` varchar(255) NULL, `content` mediumtext NULL, `content_type` varchar(255) NULL, `enc_item_key` text NULL, `auth_hash` varchar(255) NULL, `user_uuid` varchar(36) NULL, `deleted` tinyint(1) NULL DEFAULT 0, `last_user_agent` text NULL, `created_at` datetime(6) NOT NULL, `updated_at` datetime(6) NOT NULL, `created_at_timestamp` BIGINT NOT NULL, `updated_at_timestamp` BIGINT NOT NULL, INDEX `index_items_on_content_type` (`content_type`), INDEX `index_items_on_user_uuid` (`user_uuid`), INDEX `index_items_on_deleted` (`deleted`), INDEX `updated_at_timestamp` (`updated_at_timestamp`), INDEX `index_items_on_updated_at` (`updated_at`), INDEX `user_uuid_and_updated_at_timestamp_and_created_at_timestamp` (`user_uuid`, `updated_at_timestamp`, `created_at_timestamp`), INDEX `index_items_on_user_uuid_and_updated_at_and_created_at` (`user_uuid`, `updated_at`, `created_at`), INDEX `index_items_on_user_uuid_and_content_type` (`user_uuid`, `content_type`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + await queryRunner.query( + 'CREATE TABLE IF NOT EXISTS `revisions` (`uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NULL, `content` mediumtext NULL, `content_type` varchar(255) NULL, `items_key_id` varchar(255) NULL, `enc_item_key` text NULL, `auth_hash` varchar(255) NULL, `creation_date` date NULL, `created_at` datetime(6) NULL, `updated_at` datetime(6) NULL, INDEX `index_revisions_on_item_uuid` (`item_uuid`), INDEX `index_revisions_on_creation_date` (`creation_date`), INDEX `index_revisions_on_created_at` (`created_at`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + await queryRunner.query( + 'CREATE TABLE IF NOT EXISTS `item_revisions` (`uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `revision_uuid` varchar(36) NOT NULL, INDEX `index_item_revisions_on_item_uuid` (`item_uuid`), INDEX `index_item_revisions_on_revision_uuid` (`revision_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + } + + public async down(_queryRunner: QueryRunner): Promise { + return + } + + private async fixUpdatedAtTimestampsFromLegacyMigration(queryRunner: QueryRunner): Promise { + const itemsTableExistsQueryResult = await queryRunner.manager.query( + 'SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = "items"', + ) + const itemsTableExists = itemsTableExistsQueryResult[0].count === 1 + if (!itemsTableExists) { + return + } + + const updatedAtTimestampColumnExistsQueryResult = await queryRunner.manager.query( + 'SELECT COUNT(*) as count FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = "items" AND column_name = "updated_at_timestamp"', + ) + const updatedAtTimestampColumnExists = updatedAtTimestampColumnExistsQueryResult[0].count === 1 + if (updatedAtTimestampColumnExists) { + return + } + + await queryRunner.query('ALTER TABLE `items` ADD COLUMN `updated_at_timestamp` BIGINT NOT NULL') + await queryRunner.query('ALTER TABLE `items` ADD COLUMN `created_at_timestamp` BIGINT NOT NULL') + await queryRunner.query( + 'ALTER TABLE `items` ADD INDEX `user_uuid_and_updated_at_timestamp_and_created_at_timestamp` (`user_uuid`, `updated_at_timestamp`, `created_at_timestamp`)', + ) + await queryRunner.query('ALTER TABLE `items` ADD INDEX `updated_at_timestamp` (`updated_at_timestamp`)') + await queryRunner.query('UPDATE `items` SET `created_at_timestamp` = UNIX_TIMESTAMP(`created_at`) * 1000000') + await queryRunner.query('UPDATE `items` SET `updated_at_timestamp` = UNIX_TIMESTAMP(`updated_at`) * 1000000') + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1617615657558-add_extension_settings.ts b/packages/syncing-server/migrations/mysql-legacy/1617615657558-add_extension_settings.ts new file mode 100644 index 000000000..b4ceb7b9f --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1617615657558-add_extension_settings.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class addExtensionSettings1617615657558 implements MigrationInterface { + name = 'addExtensionSettings1617615657558' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + 'CREATE TABLE IF NOT EXISTS `extension_settings` (`uuid` varchar(36) NOT NULL, `extension_id` varchar(255) NULL, `mute_emails` tinyint(1) NULL DEFAULT 0, `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX `index_extension_settings_on_extension_id` (`extension_id`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + } + + public async down(_queryRunner: QueryRunner): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1629964808297-drop_unused_indexes.ts b/packages/syncing-server/migrations/mysql-legacy/1629964808297-drop_unused_indexes.ts new file mode 100644 index 000000000..888e3bdd5 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1629964808297-drop_unused_indexes.ts @@ -0,0 +1,27 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class dropUnusedIndexes1629964808297 implements MigrationInterface { + name = 'dropUnusedIndexes1629964808297' + + public async up(queryRunner: QueryRunner): Promise { + const indexItemsOnUserAndTimestamp = await queryRunner.manager.query( + 'SHOW INDEX FROM `items` where `key_name` = "index_items_on_user_uuid_and_updated_at_and_created_at"', + ) + const indexItemsOnUserAndTimestampExists = indexItemsOnUserAndTimestamp && indexItemsOnUserAndTimestamp.length > 0 + if (indexItemsOnUserAndTimestampExists) { + await queryRunner.query('ALTER TABLE `items` DROP INDEX index_items_on_user_uuid_and_updated_at_and_created_at') + } + + const indexItemsOnUpdatedAt = await queryRunner.manager.query( + 'SHOW INDEX FROM `items` where `key_name` = "index_items_on_updated_at"', + ) + const indexItemsOnUpdatedAtExists = indexItemsOnUpdatedAt && indexItemsOnUpdatedAt.length > 0 + if (indexItemsOnUpdatedAtExists) { + await queryRunner.query('ALTER TABLE `items` DROP INDEX index_items_on_updated_at') + } + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1630318893601-refactor_calculating_integrity_hash.ts b/packages/syncing-server/migrations/mysql-legacy/1630318893601-refactor_calculating_integrity_hash.ts new file mode 100644 index 000000000..9db22db83 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1630318893601-refactor_calculating_integrity_hash.ts @@ -0,0 +1,11 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class refactorCalculatingIntegrityHash1630318893601 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `items` ADD INDEX `user_uuid_and_deleted` (`user_uuid`, `deleted`)') + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1630417724617-restrict_content_type.ts b/packages/syncing-server/migrations/mysql-legacy/1630417724617-restrict_content_type.ts new file mode 100644 index 000000000..f482f9f52 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1630417724617-restrict_content_type.ts @@ -0,0 +1,12 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class restrictContentType1630417724617 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('UPDATE `items` SET content_type = "Unknown" WHERE `content_type` IS NULL') + await queryRunner.query('ALTER TABLE `items` CHANGE `content_type` `content_type` varchar(255) NOT NULL') + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1631529502150-add_revision_for_duplicated_items.ts b/packages/syncing-server/migrations/mysql-legacy/1631529502150-add_revision_for_duplicated_items.ts new file mode 100644 index 000000000..2ec621bbc --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1631529502150-add_revision_for_duplicated_items.ts @@ -0,0 +1,26 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +import { v4 } from 'uuid' + +export class addRevisionForDuplicatedItems1631529502150 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + const itemRevisions = await queryRunner.manager.query( + 'SELECT r.uuid as originalRevisionUuid, ir.item_uuid as properItemUuid, ir.uuid as relationUuid FROM revisions r INNER JOIN item_revisions ir ON ir.revision_uuid = r.uuid AND ir.item_uuid <> r.item_uuid', + ) + + for (const itemRevision of itemRevisions) { + const revisionUuid = v4() + + await queryRunner.manager.query( + `INSERT INTO revisions (uuid, item_uuid, content, content_type, items_key_id, enc_item_key, auth_hash, creation_date, created_at, updated_at) SELECT "${revisionUuid}", "${itemRevision['properItemUuid']}", content, content_type, items_key_id, enc_item_key, auth_hash, creation_date, created_at, updated_at FROM revisions WHERE uuid = "${itemRevision['originalRevisionUuid']}"`, + ) + await queryRunner.manager.query( + `UPDATE item_revisions SET revision_uuid = "${revisionUuid}" WHERE uuid = "${itemRevision['relationUuid']}"`, + ) + } + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1631530260504-drop_item_revisions_joining_table.ts b/packages/syncing-server/migrations/mysql-legacy/1631530260504-drop_item_revisions_joining_table.ts new file mode 100644 index 000000000..c6f60047a --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1631530260504-drop_item_revisions_joining_table.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class dropItemRevisionsJoiningTable1631530260504 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP TABLE `item_revisions`') + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + 'CREATE TABLE `item_revisions` (`uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `revision_uuid` varchar(36) NOT NULL, INDEX `index_item_revisions_on_item_uuid` (`item_uuid`), INDEX `index_item_revisions_on_revision_uuid` (`revision_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1632219307742-cleanup_orphan_items_and_revisions.ts b/packages/syncing-server/migrations/mysql-legacy/1632219307742-cleanup_orphan_items_and_revisions.ts new file mode 100644 index 000000000..cfec00b0f --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1632219307742-cleanup_orphan_items_and_revisions.ts @@ -0,0 +1,36 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class cleanupOrphanItemsAndRevisions1632219307742 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + const usersTableExistsQueryResult = await queryRunner.manager.query( + 'SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = "users"', + ) + const usersTableExists = usersTableExistsQueryResult[0].count === 1 + if (usersTableExists) { + const orphanedItems = await queryRunner.manager.query( + 'SELECT i.uuid as uuid FROM items i LEFT JOIN users u ON i.user_uuid = u.uuid WHERE u.uuid IS NULL', + ) + + for (const orphanedItem of orphanedItems) { + await queryRunner.manager.query(`DELETE FROM revisions WHERE item_uuid = "${orphanedItem['uuid']}"`) + await queryRunner.manager.query(`DELETE FROM items WHERE uuid = "${orphanedItem['uuid']}"`) + } + } + + await queryRunner.manager.query('DELETE FROM items WHERE user_uuid IS NULL') + + const orphanedRevisions = await queryRunner.manager.query( + 'SELECT r.uuid as uuid FROM revisions r LEFT JOIN items i ON r.item_uuid = i.uuid WHERE i.uuid IS NULL', + ) + + for (const orphanedRevision of orphanedRevisions) { + await queryRunner.manager.query(`DELETE FROM revisions WHERE uuid = "${orphanedRevision['uuid']}"`) + } + + await queryRunner.manager.query('DELETE FROM revisions WHERE item_uuid IS NULL') + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1632221263106-add_revisions_items_relation.ts b/packages/syncing-server/migrations/mysql-legacy/1632221263106-add_revisions_items_relation.ts new file mode 100644 index 000000000..1ce340ab2 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1632221263106-add_revisions_items_relation.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class addRevisionsItemsRelation1632221263106 implements MigrationInterface { + name = 'addRevisionsItemsRelation1632221263106' + + public async up(queryRunner: QueryRunner): Promise { + const indexRevisionsOnItemUuid = await queryRunner.manager.query( + 'SHOW INDEX FROM `revisions` where `key_name` = "index_revisions_on_item_uuid"', + ) + const indexRevisionsOnItemUuidExists = indexRevisionsOnItemUuid && indexRevisionsOnItemUuid.length > 0 + if (indexRevisionsOnItemUuidExists) { + await queryRunner.query('DROP INDEX `index_revisions_on_item_uuid` ON `revisions`') + } + + await queryRunner.query('ALTER TABLE `revisions` CHANGE `item_uuid` `item_uuid` varchar(36) NOT NULL') + await queryRunner.query('ALTER TABLE `items` CHANGE `user_uuid` `user_uuid` varchar(36) NOT NULL') + await queryRunner.query( + 'ALTER TABLE `revisions` ADD CONSTRAINT `FK_ab3b92e54701fe3010022a31d90` FOREIGN KEY (`item_uuid`) REFERENCES `items`(`uuid`) ON DELETE CASCADE ON UPDATE NO ACTION', + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `revisions` DROP FOREIGN KEY `FK_ab3b92e54701fe3010022a31d90`') + await queryRunner.query('ALTER TABLE `items` CHANGE `user_uuid` `user_uuid` varchar(36) NULL') + await queryRunner.query('ALTER TABLE `revisions` CHANGE `item_uuid` `item_uuid` varchar(36) NULL') + await queryRunner.query('CREATE INDEX `index_revisions_on_item_uuid` ON `revisions` (`item_uuid`)') + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1637738491169-add_item_content_size.ts b/packages/syncing-server/migrations/mysql-legacy/1637738491169-add_item_content_size.ts new file mode 100644 index 000000000..b2daff1fb --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1637738491169-add_item_content_size.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class addItemContentSize1637738491169 implements MigrationInterface { + name = 'addItemContentSize1637738491169' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `items` ADD `content_size` INT UNSIGNED NULL') + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `items` DROP COLUMN `content_size`') + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1639134926025-remove_extension_settings.ts b/packages/syncing-server/migrations/mysql-legacy/1639134926025-remove_extension_settings.ts new file mode 100644 index 000000000..7340152b5 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1639134926025-remove_extension_settings.ts @@ -0,0 +1,11 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class removeExtensionSettings1639134926025 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP TABLE `extension_settings`') + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1642073387521-remove_sf_extension_items.ts b/packages/syncing-server/migrations/mysql-legacy/1642073387521-remove_sf_extension_items.ts new file mode 100644 index 000000000..0bb1281ac --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1642073387521-remove_sf_extension_items.ts @@ -0,0 +1,11 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class removeSfExtensionItems1642073387521 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.manager.query('DELETE FROM items WHERE content_type = "SF|Extension"') + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1647501696205-remove_user_agent.ts b/packages/syncing-server/migrations/mysql-legacy/1647501696205-remove_user_agent.ts new file mode 100644 index 000000000..dcbaa042f --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1647501696205-remove_user_agent.ts @@ -0,0 +1,11 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class removeUserAgent1647501696205 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `items` DROP COLUMN `last_user_agent`') + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1654518291191-add_updated_with_session.ts b/packages/syncing-server/migrations/mysql-legacy/1654518291191-add_updated_with_session.ts new file mode 100644 index 000000000..ea6a862f7 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1654518291191-add_updated_with_session.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class addUpdatedWithSession1654518291191 implements MigrationInterface { + name = 'addUpdatedWithSession1654518291191' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `items` ADD `updated_with_session` varchar(36) NULL') + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `items` DROP COLUMN `updated_with_session`') + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1689671563304-add-notifications.ts b/packages/syncing-server/migrations/mysql-legacy/1689671563304-add-notifications.ts new file mode 100644 index 000000000..186f7d001 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1689671563304-add-notifications.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class AddNotifications1689671563304 implements MigrationInterface { + name = 'AddNotifications1689671563304' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + 'CREATE TABLE IF NOT EXISTS `notifications` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `type` varchar(36) NOT NULL, `payload` text NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `index_notifications_on_user_uuid` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX `index_notifications_on_user_uuid` ON `notifications`') + await queryRunner.query('DROP TABLE `notifications`') + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1689671563305-add-shared-vault-and-key-system-associations.ts b/packages/syncing-server/migrations/mysql-legacy/1689671563305-add-shared-vault-and-key-system-associations.ts new file mode 100644 index 000000000..1b7219d59 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1689671563305-add-shared-vault-and-key-system-associations.ts @@ -0,0 +1,25 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class AddSharedVaultAndKeySystemAssociations1689671563305 implements MigrationInterface { + name = 'AddSharedVaultAndKeySystemAssociations1689671563305' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + 'CREATE TABLE `shared_vault_associations` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `last_edited_by` varchar(36) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_shared_vault_associations` (`shared_vault_uuid`), INDEX `item_uuid_on_shared_vault_associations` (`item_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + await queryRunner.query( + 'CREATE TABLE `key_system_associations` (`uuid` varchar(36) NOT NULL, `key_system_uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `key_system_uuid_on_key_system_associations` (`key_system_uuid`), INDEX `item_uuid_on_key_system_associations` (`item_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX `item_uuid_on_key_system_associations` ON `key_system_associations`') + await queryRunner.query('DROP INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations`') + await queryRunner.query('DROP TABLE `key_system_associations`') + await queryRunner.query('DROP INDEX `item_uuid_on_shared_vault_associations` ON `shared_vault_associations`') + await queryRunner.query( + 'DROP INDEX `shared_vault_uuid_on_shared_vault_associations` ON `shared_vault_associations`', + ) + await queryRunner.query('DROP TABLE `shared_vault_associations`') + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1689677728282-add-shared-vaults-with-users-and-invites.ts b/packages/syncing-server/migrations/mysql-legacy/1689677728282-add-shared-vaults-with-users-and-invites.ts new file mode 100644 index 000000000..284fc3c94 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1689677728282-add-shared-vaults-with-users-and-invites.ts @@ -0,0 +1,29 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class AddSharedVaultsWithUsersAndInvites1689677728282 implements MigrationInterface { + name = 'AddSharedVaultsWithUsersAndInvites1689677728282' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + 'CREATE TABLE `shared_vaults` (`uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `file_upload_bytes_used` int NOT NULL, `file_upload_bytes_limit` int NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `user_uuid_on_shared_vaults` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + await queryRunner.query( + 'CREATE TABLE `shared_vault_users` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `permission` varchar(24) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_shared_vault_users` (`shared_vault_uuid`), INDEX `user_uuid_on_shared_vault_users` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + await queryRunner.query( + 'CREATE TABLE `shared_vault_invites` (`uuid` varchar(36) NOT NULL, `shared_vault_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `sender_uuid` varchar(36) NOT NULL, `encrypted_message` text NOT NULL, `permission` varchar(24) NOT NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `shared_vault_uuid_on_shared_vault_invites` (`shared_vault_uuid`), INDEX `user_uuid_on_shared_vault_invites` (`user_uuid`), INDEX `sender_uuid_on_shared_vault_invites` (`sender_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX `sender_uuid_on_shared_vault_invites` ON `shared_vault_invites`') + await queryRunner.query('DROP INDEX `user_uuid_on_shared_vault_invites` ON `shared_vault_invites`') + await queryRunner.query('DROP INDEX `shared_vault_uuid_on_shared_vault_invites` ON `shared_vault_invites`') + await queryRunner.query('DROP TABLE `shared_vault_invites`') + await queryRunner.query('DROP INDEX `user_uuid_on_shared_vault_users` ON `shared_vault_users`') + await queryRunner.query('DROP INDEX `shared_vault_uuid_on_shared_vault_users` ON `shared_vault_users`') + await queryRunner.query('DROP TABLE `shared_vault_users`') + await queryRunner.query('DROP INDEX `user_uuid_on_shared_vaults` ON `shared_vaults`') + await queryRunner.query('DROP TABLE `shared_vaults`') + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1689745128577-add-messages.ts b/packages/syncing-server/migrations/mysql-legacy/1689745128577-add-messages.ts new file mode 100644 index 000000000..772338ab0 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1689745128577-add-messages.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class AddMessages1689745128577 implements MigrationInterface { + name = 'AddMessages1689745128577' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + 'CREATE TABLE `messages` (`uuid` varchar(36) NOT NULL, `recipient_uuid` varchar(36) NOT NULL, `sender_uuid` varchar(36) NOT NULL, `encrypted_message` text NOT NULL, `replaceability_identifier` varchar(255) NULL, `created_at_timestamp` bigint NOT NULL, `updated_at_timestamp` bigint NOT NULL, INDEX `recipient_uuid_on_messages` (`recipient_uuid`), INDEX `sender_uuid_on_messages` (`sender_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB', + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX `sender_uuid_on_messages` ON `messages`') + await queryRunner.query('DROP INDEX `recipient_uuid_on_messages` ON `messages`') + await queryRunner.query('DROP TABLE `messages`') + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1689746180559-rename-key-message-identifier.ts b/packages/syncing-server/migrations/mysql-legacy/1689746180559-rename-key-message-identifier.ts new file mode 100644 index 000000000..a25f1777f --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1689746180559-rename-key-message-identifier.ts @@ -0,0 +1,27 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class RenameKeyMessageIdentifier1689746180559 implements MigrationInterface { + name = 'RenameKeyMessageIdentifier1689746180559' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations`') + await queryRunner.query( + 'ALTER TABLE `key_system_associations` CHANGE `key_system_uuid` `key_system_identifier` varchar(36) NOT NULL', + ) + await queryRunner.query( + 'CREATE INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations` (`key_system_identifier`)', + ) + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + 'DROP INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations`', + ) + await queryRunner.query( + 'ALTER TABLE `key_system_associations` CHANGE `key_system_identifier` `key_system_uuid` varchar(36) NOT NULL', + ) + await queryRunner.query( + 'CREATE INDEX `key_system_uuid_on_key_system_associations` ON `key_system_associations` (`key_system_uuid`)', + ) + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1690900526061-delete_privileges.ts b/packages/syncing-server/migrations/mysql-legacy/1690900526061-delete_privileges.ts new file mode 100644 index 000000000..0440c1a16 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1690900526061-delete_privileges.ts @@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class DeletePrivileges1690900526061 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + const itemsWithPrivilegesContentTypeQueryResult = await queryRunner.manager.query( + 'SELECT COUNT(*) as count FROM items i WHERE i.content_type = "SN|Privileges"', + ) + const itemsWithPrivilegesContentTypeCount = +itemsWithPrivilegesContentTypeQueryResult[0].count + + const batchSize = 1_000 + const batchCount = Math.ceil(itemsWithPrivilegesContentTypeCount / batchSize) + + for (let batchIndex = 0; batchIndex < batchCount; batchIndex++) { + await queryRunner.startTransaction() + await queryRunner.manager.query(`DELETE FROM items WHERE content_type = "SN|Privileges" LIMIT ${batchSize}`) + await queryRunner.commitTransaction() + } + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1690975361562-update_unknown_content.ts b/packages/syncing-server/migrations/mysql-legacy/1690975361562-update_unknown_content.ts new file mode 100644 index 000000000..7a6ba2f1b --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1690975361562-update_unknown_content.ts @@ -0,0 +1,11 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class UpdateUnknownContent1690975361562 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.manager.query('UPDATE items SET content_type = "Note" WHERE content_type = "Unknown"') + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1692176803410-remove_revisions_foreign_key.ts b/packages/syncing-server/migrations/mysql-legacy/1692176803410-remove_revisions_foreign_key.ts new file mode 100644 index 000000000..d5b1cbdd5 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1692176803410-remove_revisions_foreign_key.ts @@ -0,0 +1,22 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class RemoveRevisionsForeignKey1692176803410 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + const revisionsTableExistsQueryResult = await queryRunner.manager.query( + 'SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = "revisions"', + ) + const revisionsTableExists = revisionsTableExistsQueryResult[0].count === 1 + if (revisionsTableExists) { + try { + await queryRunner.query('ALTER TABLE `revisions` DROP FOREIGN KEY `FK_ab3b92e54701fe3010022a31d90`') + } catch (error) { + // eslint-disable-next-line no-console + console.log('Error dropping foreign key: ', (error as Error).message) + } + } + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1692264556858-remove_associations.ts b/packages/syncing-server/migrations/mysql-legacy/1692264556858-remove_associations.ts new file mode 100644 index 000000000..ad97571dd --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1692264556858-remove_associations.ts @@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class RemoveAssociations1692264556858 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + 'DROP INDEX `key_system_identifier_on_key_system_associations` ON `key_system_associations`', + ) + await queryRunner.query('DROP INDEX `item_uuid_on_key_system_associations` ON `key_system_associations`') + await queryRunner.query('DROP TABLE `key_system_associations`') + + await queryRunner.query('DROP INDEX `item_uuid_on_shared_vault_associations` ON `shared_vault_associations`') + await queryRunner.query( + 'DROP INDEX `shared_vault_uuid_on_shared_vault_associations` ON `shared_vault_associations`', + ) + await queryRunner.query('DROP TABLE `shared_vault_associations`') + } + + public async down(): Promise { + return + } +} diff --git a/packages/syncing-server/migrations/mysql-legacy/1692619430384-remove-shared-vault-limit.ts b/packages/syncing-server/migrations/mysql-legacy/1692619430384-remove-shared-vault-limit.ts new file mode 100644 index 000000000..9cfdcbef0 --- /dev/null +++ b/packages/syncing-server/migrations/mysql-legacy/1692619430384-remove-shared-vault-limit.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class RemoveSharedVaultLimit1692619430384 implements MigrationInterface { + name = 'RemoveSharedVaultLimit1692619430384' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `shared_vaults` DROP COLUMN `file_upload_bytes_limit`') + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `shared_vaults` ADD `file_upload_bytes_limit` int NOT NULL') + } +} diff --git a/packages/syncing-server/migrations/mysql/1693219736168-add-shared-vault-information.ts b/packages/syncing-server/migrations/mysql/1693219736168-add-shared-vault-information.ts new file mode 100644 index 000000000..ccd97ef49 --- /dev/null +++ b/packages/syncing-server/migrations/mysql/1693219736168-add-shared-vault-information.ts @@ -0,0 +1,19 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class AddSharedVaultInformation1693219736168 implements MigrationInterface { + name = 'AddSharedVaultInformation1693219736168' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `items` ADD `last_edited_by` varchar(36) NULL') + await queryRunner.query('ALTER TABLE `items` ADD `shared_vault_uuid` varchar(36) NULL') + await queryRunner.query('ALTER TABLE `items` ADD `key_system_identifier` varchar(36) NULL') + await queryRunner.query('CREATE INDEX `index_items_on_shared_vault_uuid` ON `items` (`shared_vault_uuid`)') + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX `index_items_on_shared_vault_uuid` ON `items`') + await queryRunner.query('ALTER TABLE `items` DROP COLUMN `key_system_identifier`') + await queryRunner.query('ALTER TABLE `items` DROP COLUMN `shared_vault_uuid`') + await queryRunner.query('ALTER TABLE `items` DROP COLUMN `last_edited_by`') + } +} diff --git a/packages/syncing-server/migrations/sqlite/1693220037441-add-shared-vault-information.ts b/packages/syncing-server/migrations/sqlite/1693220037441-add-shared-vault-information.ts new file mode 100644 index 000000000..56583c595 --- /dev/null +++ b/packages/syncing-server/migrations/sqlite/1693220037441-add-shared-vault-information.ts @@ -0,0 +1,65 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class AddSharedVaultInformation1693220037441 implements MigrationInterface { + name = 'AddSharedVaultInformation1693220037441' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX "index_items_on_user_uuid_and_content_type"') + await queryRunner.query('DROP INDEX "user_uuid_and_updated_at_timestamp_and_created_at_timestamp"') + await queryRunner.query('DROP INDEX "user_uuid_and_deleted"') + await queryRunner.query('DROP INDEX "updated_at_timestamp"') + await queryRunner.query('DROP INDEX "index_items_on_deleted"') + await queryRunner.query('DROP INDEX "index_items_on_user_uuid"') + await queryRunner.query('DROP INDEX "index_items_on_content_type"') + await queryRunner.query( + 'CREATE TABLE "temporary_items" ("uuid" varchar PRIMARY KEY NOT NULL, "duplicate_of" varchar(36), "items_key_id" varchar(255), "content" text, "content_type" varchar(255), "content_size" integer, "enc_item_key" text, "auth_hash" varchar(255), "user_uuid" varchar(36) NOT NULL, "deleted" tinyint(1) DEFAULT (0), "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL, "updated_with_session" varchar(36), "last_edited_by" varchar(36), "shared_vault_uuid" varchar(36), "key_system_identifier" varchar(36))', + ) + await queryRunner.query( + 'INSERT INTO "temporary_items"("uuid", "duplicate_of", "items_key_id", "content", "content_type", "content_size", "enc_item_key", "auth_hash", "user_uuid", "deleted", "created_at", "updated_at", "created_at_timestamp", "updated_at_timestamp", "updated_with_session") SELECT "uuid", "duplicate_of", "items_key_id", "content", "content_type", "content_size", "enc_item_key", "auth_hash", "user_uuid", "deleted", "created_at", "updated_at", "created_at_timestamp", "updated_at_timestamp", "updated_with_session" FROM "items"', + ) + await queryRunner.query('DROP TABLE "items"') + await queryRunner.query('ALTER TABLE "temporary_items" RENAME TO "items"') + await queryRunner.query( + 'CREATE INDEX "index_items_on_user_uuid_and_content_type" ON "items" ("user_uuid", "content_type") ', + ) + await queryRunner.query( + 'CREATE INDEX "user_uuid_and_updated_at_timestamp_and_created_at_timestamp" ON "items" ("user_uuid", "updated_at_timestamp", "created_at_timestamp") ', + ) + await queryRunner.query('CREATE INDEX "user_uuid_and_deleted" ON "items" ("user_uuid", "deleted") ') + await queryRunner.query('CREATE INDEX "updated_at_timestamp" ON "items" ("updated_at_timestamp") ') + await queryRunner.query('CREATE INDEX "index_items_on_deleted" ON "items" ("deleted") ') + await queryRunner.query('CREATE INDEX "index_items_on_user_uuid" ON "items" ("user_uuid") ') + await queryRunner.query('CREATE INDEX "index_items_on_content_type" ON "items" ("content_type") ') + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query('DROP INDEX "index_items_on_shared_vault_uuid"') + await queryRunner.query('DROP INDEX "user_uuid_and_deleted"') + await queryRunner.query('DROP INDEX "user_uuid_on_shared_vaults"') + await queryRunner.query('DROP INDEX "index_items_on_content_type"') + await queryRunner.query('DROP INDEX "index_items_on_user_uuid"') + await queryRunner.query('DROP INDEX "index_items_on_deleted"') + await queryRunner.query('DROP INDEX "updated_at_timestamp"') + await queryRunner.query('DROP INDEX "user_uuid_and_updated_at_timestamp_and_created_at_timestamp"') + await queryRunner.query('DROP INDEX "index_items_on_user_uuid_and_content_type"') + await queryRunner.query('ALTER TABLE "items" RENAME TO "temporary_items"') + await queryRunner.query( + 'CREATE TABLE "items" ("uuid" varchar PRIMARY KEY NOT NULL, "duplicate_of" varchar(36), "items_key_id" varchar(255), "content" text, "content_type" varchar(255), "content_size" integer, "enc_item_key" text, "auth_hash" varchar(255), "user_uuid" varchar(36) NOT NULL, "deleted" tinyint(1) DEFAULT (0), "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL, "updated_with_session" varchar(36), "last_edited_by" varchar(36), "shared_vault_uuid" varchar(36), "key_system_identifier" varchar(36))', + ) + await queryRunner.query( + 'INSERT INTO "items"("uuid", "duplicate_of", "items_key_id", "content", "content_type", "content_size", "enc_item_key", "auth_hash", "user_uuid", "deleted", "created_at", "updated_at", "created_at_timestamp", "updated_at_timestamp", "updated_with_session", "last_edited_by", "shared_vault_uuid", "key_system_identifier") SELECT "uuid", "duplicate_of", "items_key_id", "content", "content_type", "content_size", "enc_item_key", "auth_hash", "user_uuid", "deleted", "created_at", "updated_at", "created_at_timestamp", "updated_at_timestamp", "updated_with_session", "last_edited_by", "shared_vault_uuid", "key_system_identifier" FROM "temporary_items"', + ) + await queryRunner.query('DROP TABLE "temporary_items"') + await queryRunner.query('CREATE INDEX "index_items_on_content_type" ON "items" ("content_type") ') + await queryRunner.query('CREATE INDEX "index_items_on_user_uuid" ON "items" ("user_uuid") ') + await queryRunner.query('CREATE INDEX "index_items_on_deleted" ON "items" ("deleted") ') + await queryRunner.query('CREATE INDEX "updated_at_timestamp" ON "items" ("updated_at_timestamp") ') + await queryRunner.query( + 'CREATE INDEX "user_uuid_and_updated_at_timestamp_and_created_at_timestamp" ON "items" ("user_uuid", "updated_at_timestamp", "created_at_timestamp") ', + ) + await queryRunner.query( + 'CREATE INDEX "index_items_on_user_uuid_and_content_type" ON "items" ("user_uuid", "content_type") ', + ) + await queryRunner.query('CREATE INDEX "user_uuid_and_deleted" ON "items" ("user_uuid", "deleted") ') + } +} diff --git a/packages/syncing-server/src/Bootstrap/Container.ts b/packages/syncing-server/src/Bootstrap/Container.ts index 78027b069..f921df8d9 100644 --- a/packages/syncing-server/src/Bootstrap/Container.ts +++ b/packages/syncing-server/src/Bootstrap/Container.ts @@ -158,6 +158,9 @@ import { TransitionItemsFromPrimaryToSecondaryDatabaseForUser } from '../Domain/ import { SharedVaultFileMovedEventHandler } from '../Domain/Handler/SharedVaultFileMovedEventHandler' import { TransitionStatusUpdatedEventHandler } from '../Domain/Handler/TransitionStatusUpdatedEventHandler' import { TriggerTransitionFromPrimaryToSecondaryDatabaseForUser } from '../Domain/UseCase/Transition/TriggerTransitionFromPrimaryToSecondaryDatabaseForUser/TriggerTransitionFromPrimaryToSecondaryDatabaseForUser' +import { SQLItem } from '../Infra/TypeORM/SQLItem' +import { SQLItemPersistenceMapper } from '../Mapping/Persistence/SQLItemPersistenceMapper' +import { SQLItemRepository } from '../Infra/TypeORM/SQLItemRepository' export class ContainerConfigLoader { private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000 @@ -305,6 +308,9 @@ export class ContainerConfigLoader { container .bind>(TYPES.Sync_SQLLegacyItemPersistenceMapper) .toConstantValue(new SQLLegacyItemPersistenceMapper()) + container + .bind>(TYPES.Sync_SQLItemPersistenceMapper) + .toConstantValue(new SQLItemPersistenceMapper()) container .bind>(TYPES.Sync_ItemHashHttpMapper) .toConstantValue(new ItemHashHttpMapper()) @@ -362,6 +368,9 @@ export class ContainerConfigLoader { container .bind>(TYPES.Sync_ORMLegacyItemRepository) .toDynamicValue(() => appDataSource.getRepository(SQLLegacyItem)) + container + .bind>(TYPES.Sync_ORMItemRepository) + .toConstantValue(appDataSource.getRepository(SQLItem)) container .bind>(TYPES.Sync_ORMSharedVaultRepository) .toConstantValue(appDataSource.getRepository(TypeORMSharedVault)) @@ -401,19 +410,25 @@ export class ContainerConfigLoader { // Repositories container - .bind(TYPES.Sync_SQLLegacyItemRepository) + .bind(TYPES.Sync_SQLItemRepository) .toConstantValue( - new SQLLegacyItemRepository( - container.get>(TYPES.Sync_ORMLegacyItemRepository), - container.get>(TYPES.Sync_SQLLegacyItemPersistenceMapper), - container.get(TYPES.Sync_Logger), - ), + isConfiguredForHomeServer + ? new SQLItemRepository( + container.get>(TYPES.Sync_ORMItemRepository), + container.get>(TYPES.Sync_SQLItemPersistenceMapper), + container.get(TYPES.Sync_Logger), + ) + : new SQLLegacyItemRepository( + container.get>(TYPES.Sync_ORMLegacyItemRepository), + container.get>(TYPES.Sync_SQLLegacyItemPersistenceMapper), + container.get(TYPES.Sync_Logger), + ), ) container .bind(TYPES.Sync_ItemRepositoryResolver) .toConstantValue( new TypeORMItemRepositoryResolver( - container.get(TYPES.Sync_SQLLegacyItemRepository), + container.get(TYPES.Sync_SQLItemRepository), isSecondaryDatabaseEnabled ? container.get(TYPES.Sync_MongoDBItemRepository) : null, ), ) @@ -777,7 +792,7 @@ export class ContainerConfigLoader { ) .toConstantValue( new TransitionItemsFromPrimaryToSecondaryDatabaseForUser( - container.get(TYPES.Sync_SQLLegacyItemRepository), + container.get(TYPES.Sync_SQLItemRepository), isSecondaryDatabaseEnabled ? container.get(TYPES.Sync_MongoDBItemRepository) : null, container.get(TYPES.Sync_Timer), container.get(TYPES.Sync_Logger), @@ -843,7 +858,7 @@ export class ContainerConfigLoader { .bind(TYPES.Sync_DuplicateItemSyncedEventHandler) .toConstantValue( new DuplicateItemSyncedEventHandler( - container.get(TYPES.Sync_SQLLegacyItemRepository), + container.get(TYPES.Sync_SQLItemRepository), isSecondaryDatabaseEnabled ? container.get(TYPES.Sync_MongoDBItemRepository) : null, container.get(TYPES.Sync_DomainEventFactory), container.get(TYPES.Sync_DomainEventPublisher), @@ -854,7 +869,7 @@ export class ContainerConfigLoader { .bind(TYPES.Sync_AccountDeletionRequestedEventHandler) .toConstantValue( new AccountDeletionRequestedEventHandler( - container.get(TYPES.Sync_SQLLegacyItemRepository), + container.get(TYPES.Sync_SQLItemRepository), isSecondaryDatabaseEnabled ? container.get(TYPES.Sync_MongoDBItemRepository) : null, container.get(TYPES.Sync_Logger), ), @@ -863,7 +878,7 @@ export class ContainerConfigLoader { .bind(TYPES.Sync_ItemRevisionCreationRequestedEventHandler) .toConstantValue( new ItemRevisionCreationRequestedEventHandler( - container.get(TYPES.Sync_SQLLegacyItemRepository), + container.get(TYPES.Sync_SQLItemRepository), isSecondaryDatabaseEnabled ? container.get(TYPES.Sync_MongoDBItemRepository) : null, container.get(TYPES.Sync_ItemBackupService), container.get(TYPES.Sync_DomainEventFactory), @@ -918,7 +933,7 @@ export class ContainerConfigLoader { .toConstantValue( new ExtensionsHttpService( container.get(TYPES.Sync_HTTPClient), - container.get(TYPES.Sync_SQLLegacyItemRepository), + container.get(TYPES.Sync_SQLItemRepository), isSecondaryDatabaseEnabled ? container.get(TYPES.Sync_MongoDBItemRepository) : null, container.get(TYPES.Sync_ContentDecoder), container.get(TYPES.Sync_DomainEventPublisher), @@ -964,7 +979,7 @@ export class ContainerConfigLoader { .bind(TYPES.Sync_EmailBackupRequestedEventHandler) .toConstantValue( new EmailBackupRequestedEventHandler( - container.get(TYPES.Sync_SQLLegacyItemRepository), + container.get(TYPES.Sync_SQLItemRepository), isSecondaryDatabaseEnabled ? container.get(TYPES.Sync_MongoDBItemRepository) : null, diff --git a/packages/syncing-server/src/Bootstrap/DataSource.ts b/packages/syncing-server/src/Bootstrap/DataSource.ts index 1047ae514..2ce5f695c 100644 --- a/packages/syncing-server/src/Bootstrap/DataSource.ts +++ b/packages/syncing-server/src/Bootstrap/DataSource.ts @@ -9,6 +9,7 @@ import { TypeORMSharedVaultUser } from '../Infra/TypeORM/TypeORMSharedVaultUser' import { TypeORMSharedVaultInvite } from '../Infra/TypeORM/TypeORMSharedVaultInvite' import { TypeORMMessage } from '../Infra/TypeORM/TypeORMMessage' import { MongoDBItem } from '../Infra/TypeORM/MongoDBItem' +import { SQLItem } from '../Infra/TypeORM/SQLItem' export class AppDataSource { private _dataSource: DataSource | undefined @@ -67,22 +68,29 @@ export class AppDataSource { this.env.load() const isConfiguredForMySQL = this.env.get('DB_TYPE') === 'mysql' + const isConfiguredForHomeServer = this.env.get('MODE', true) === 'home-server' const maxQueryExecutionTime = this.env.get('DB_MAX_QUERY_EXECUTION_TIME', true) ? +this.env.get('DB_MAX_QUERY_EXECUTION_TIME', true) : 45_000 + const migrationsSourceDirectoryName = isConfiguredForMySQL + ? isConfiguredForHomeServer + ? 'mysql' + : 'mysql-legacy' + : 'sqlite' + const commonDataSourceOptions = { maxQueryExecutionTime, entities: [ - SQLLegacyItem, + isConfiguredForHomeServer ? SQLItem : SQLLegacyItem, TypeORMNotification, TypeORMSharedVault, TypeORMSharedVaultUser, TypeORMSharedVaultInvite, TypeORMMessage, ], - migrations: [`${__dirname}/../../migrations/${isConfiguredForMySQL ? 'mysql' : 'sqlite'}/*.js`], + migrations: [`${__dirname}/../../migrations/${migrationsSourceDirectoryName}/*.js`], migrationsRun: true, logging: this.env.get('DB_DEBUG_LEVEL', true) ?? 'info', } diff --git a/packages/syncing-server/src/Bootstrap/Types.ts b/packages/syncing-server/src/Bootstrap/Types.ts index b25dec30c..64d2802fd 100644 --- a/packages/syncing-server/src/Bootstrap/Types.ts +++ b/packages/syncing-server/src/Bootstrap/Types.ts @@ -8,7 +8,7 @@ const TYPES = { Sync_Env: Symbol.for('Sync_Env'), // Repositories Sync_ItemRepositoryResolver: Symbol.for('Sync_ItemRepositoryResolver'), - Sync_SQLLegacyItemRepository: Symbol.for('Sync_SQLLegacyItemRepository'), + Sync_SQLItemRepository: Symbol.for('Sync_SQLItemRepository'), Sync_MongoDBItemRepository: Symbol.for('Sync_MongoDBItemRepository'), Sync_SharedVaultRepository: Symbol.for('Sync_SharedVaultRepository'), Sync_SharedVaultInviteRepository: Symbol.for('Sync_SharedVaultInviteRepository'), @@ -16,6 +16,7 @@ const TYPES = { Sync_NotificationRepository: Symbol.for('Sync_NotificationRepository'), Sync_MessageRepository: Symbol.for('Sync_MessageRepository'), // ORM + Sync_ORMItemRepository: Symbol.for('Sync_ORMItemRepository'), Sync_ORMLegacyItemRepository: Symbol.for('Sync_ORMLegacyItemRepository'), Sync_ORMSharedVaultRepository: Symbol.for('Sync_ORMSharedVaultRepository'), Sync_ORMSharedVaultInviteRepository: Symbol.for('Sync_ORMSharedVaultInviteRepository'), @@ -132,6 +133,7 @@ const TYPES = { Sync_MessageHttpMapper: Symbol.for('Sync_MessageHttpMapper'), Sync_NotificationHttpMapper: Symbol.for('Sync_NotificationHttpMapper'), Sync_SQLLegacyItemPersistenceMapper: Symbol.for('Sync_SQLLegacyItemPersistenceMapper'), + Sync_SQLItemPersistenceMapper: Symbol.for('Sync_SQLItemPersistenceMapper'), Sync_MongoDBItemPersistenceMapper: Symbol.for('Sync_MongoDBItemPersistenceMapper'), Sync_ItemHttpMapper: Symbol.for('Sync_ItemHttpMapper'), Sync_ItemHashHttpMapper: Symbol.for('Sync_ItemHashHttpMapper'), diff --git a/packages/syncing-server/src/Infra/TypeORM/MongoDBItem.ts b/packages/syncing-server/src/Infra/TypeORM/MongoDBItem.ts index 028951b33..94a0a6f4d 100644 --- a/packages/syncing-server/src/Infra/TypeORM/MongoDBItem.ts +++ b/packages/syncing-server/src/Infra/TypeORM/MongoDBItem.ts @@ -58,6 +58,7 @@ export class MongoDBItem { declare lastEditedBy: string | null @Column() + @Index('index_items_on_shared_vault_uuid') declare sharedVaultUuid: string | null @Column() diff --git a/packages/syncing-server/src/Infra/TypeORM/SQLItem.ts b/packages/syncing-server/src/Infra/TypeORM/SQLItem.ts index f526541ff..04900f28c 100644 --- a/packages/syncing-server/src/Infra/TypeORM/SQLItem.ts +++ b/packages/syncing-server/src/Infra/TypeORM/SQLItem.ts @@ -1,4 +1,5 @@ -import { Column, Entity } from 'typeorm' +import { Column, Entity, Index } from 'typeorm' + import { SQLLegacyItem } from './SQLLegacyItem' @Entity({ name: 'items' }) @@ -17,6 +18,7 @@ export class SQLItem extends SQLLegacyItem { length: 36, nullable: true, }) + @Index('index_items_on_shared_vault_uuid') declare sharedVaultUuid: string | null @Column({ diff --git a/packages/syncing-server/src/Infra/TypeORM/TypeORMItemRepositoryResolver.ts b/packages/syncing-server/src/Infra/TypeORM/TypeORMItemRepositoryResolver.ts index 92f490a36..caeca537e 100644 --- a/packages/syncing-server/src/Infra/TypeORM/TypeORMItemRepositoryResolver.ts +++ b/packages/syncing-server/src/Infra/TypeORM/TypeORMItemRepositoryResolver.ts @@ -5,13 +5,13 @@ import { ItemRepositoryResolverInterface } from '../../Domain/Item/ItemRepositor export class TypeORMItemRepositoryResolver implements ItemRepositoryResolverInterface { constructor( - private SQLItemRepository: ItemRepositoryInterface, + private sqlItemRepository: ItemRepositoryInterface, private mongoDbItemRepository: ItemRepositoryInterface | null, ) {} resolve(roleNames: RoleNameCollection): ItemRepositoryInterface { if (!this.mongoDbItemRepository) { - return this.SQLItemRepository + return this.sqlItemRepository } const transitionRoleName = RoleName.create(RoleName.NAMES.TransitionUser).getValue() @@ -20,6 +20,6 @@ export class TypeORMItemRepositoryResolver implements ItemRepositoryResolverInte return this.mongoDbItemRepository } - return this.SQLItemRepository + return this.sqlItemRepository } }