From faef50e6e9e768de57a58f596775614cd5d498bf Mon Sep 17 00:00:00 2001 From: Maximilian Kreuzkam Date: Mon, 11 Nov 2024 15:30:12 +0100 Subject: [PATCH] Add legacy migration. --- apps/server/src/infra/sync/sync.module.ts | 3 +- .../sync/tsp/tsp-legacy-migration.service.ts | 64 +++++++++++++++++++ .../src/infra/sync/tsp/tsp-sync.strategy.ts | 4 ++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 apps/server/src/infra/sync/tsp/tsp-legacy-migration.service.ts diff --git a/apps/server/src/infra/sync/sync.module.ts b/apps/server/src/infra/sync/sync.module.ts index 40e02c83966..02bff2032ab 100644 --- a/apps/server/src/infra/sync/sync.module.ts +++ b/apps/server/src/infra/sync/sync.module.ts @@ -10,6 +10,7 @@ import { LoggerModule } from '@src/core/logger'; import { ProvisioningModule } from '@src/modules/provisioning'; import { SyncConsole } from './console/sync.console'; import { SyncService } from './service/sync.service'; +import { TspLegacyMigrationService } from './tsp/tsp-legacy-migration.service'; import { TspOauthDataMapper } from './tsp/tsp-oauth-data.mapper'; import { TspSyncService } from './tsp/tsp-sync.service'; import { TspSyncStrategy } from './tsp/tsp-sync.strategy'; @@ -28,7 +29,7 @@ import { SyncUc } from './uc/sync.uc'; SyncUc, SyncService, ...((Configuration.get('FEATURE_TSP_SYNC_ENABLED') as boolean) - ? [TspSyncStrategy, TspSyncService, TspOauthDataMapper] + ? [TspSyncStrategy, TspSyncService, TspOauthDataMapper, TspLegacyMigrationService] : []), ], exports: [SyncConsole], diff --git a/apps/server/src/infra/sync/tsp/tsp-legacy-migration.service.ts b/apps/server/src/infra/sync/tsp/tsp-legacy-migration.service.ts new file mode 100644 index 00000000000..eab60f1c3e3 --- /dev/null +++ b/apps/server/src/infra/sync/tsp/tsp-legacy-migration.service.ts @@ -0,0 +1,64 @@ +import { EntityManager, ObjectId } from '@mikro-orm/mongodb'; +import { Injectable } from '@nestjs/common'; +import { SchoolProperties } from '@shared/domain/entity'; +import { EntityId } from '@shared/domain/types'; +import { Logger } from '@src/core/logger'; + +@Injectable() +export class TspLegacyMigrationService { + constructor(private readonly em: EntityManager, private readonly logger: Logger) { + logger.setContext(TspLegacyMigrationService.name); + } + + public async migrateLegacyData(newSystemId: EntityId): Promise { + console.log('starting legacy migration'); + const legacySystemId = await this.findLegacySystemId(); + + if (!legacySystemId) { + console.log('No legacy system found'); + return; + } + + const schools = await this.em.find< + SchoolProperties & { + sourceOptions: { + schoolIdentifier: number; + }; + } + >('schools', { + systems: [legacySystemId], + source: 'tsp', + }); + + const schoolIds = schools.map((school) => school.sourceOptions.schoolIdentifier); + + console.log('Number of schools', schoolIds); + + const promises = schoolIds.map((oldId) => + this.em.nativeUpdate( + 'schools', + { + systems: [legacySystemId], + source: 'tsp', + }, + { + $unset: { sourceOptions: '' }, + ldapSchoolIdentifier: oldId, + systems: [new ObjectId(newSystemId)], + } + ) + ); + + const res = await Promise.allSettled(promises); + const success = res.map((r) => r.status === 'fulfilled').length; + console.log(`Migrated ${schoolIds.length} legacy schools to new system. ${success} succeeded.`); + } + + private async findLegacySystemId() { + const tspLegacySystem = await this.em.getCollection('systems').findOne({ + type: 'tsp-school', + }); + + return tspLegacySystem?._id; + } +} diff --git a/apps/server/src/infra/sync/tsp/tsp-sync.strategy.ts b/apps/server/src/infra/sync/tsp/tsp-sync.strategy.ts index b7273d7cfdc..c889c69252c 100644 --- a/apps/server/src/infra/sync/tsp/tsp-sync.strategy.ts +++ b/apps/server/src/infra/sync/tsp/tsp-sync.strategy.ts @@ -16,6 +16,7 @@ import { TspSyncingUsersLoggable } from './loggable/tsp-syncing-users.loggable'; import { TspOauthDataMapper } from './tsp-oauth-data.mapper'; import { TspSyncConfig } from './tsp-sync.config'; import { TspSyncService } from './tsp-sync.service'; +import { TspLegacyMigrationService } from './tsp-legacy-migration.service'; @Injectable() export class TspSyncStrategy extends SyncStrategy { @@ -31,6 +32,7 @@ export class TspSyncStrategy extends SyncStrategy { private readonly logger: Logger, private readonly tspSyncService: TspSyncService, private readonly tspOauthDataMapper: TspOauthDataMapper, + private readonly tspLegacyMigrationService: TspLegacyMigrationService, configService: ConfigService, private readonly provisioningService: ProvisioningService ) { @@ -51,6 +53,8 @@ export class TspSyncStrategy extends SyncStrategy { public async sync(): Promise { const system = await this.tspSyncService.findTspSystemOrFail(); + await this.tspLegacyMigrationService.migrateLegacyData(system.id); + await this.syncSchools(system); const schools = await this.tspSyncService.findSchoolsForSystem(system);