using System; using JobTrackerApi.Data; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace JobTrackerApi.Migrations; /// /// Moves the authentication support tables from startup reconciliation into the migration chain /// without replacing tables or rows that pre-date migration ownership. /// [DbContext(typeof(JobTrackerContext))] [Migration("20260830123000_AdoptAuthenticationSupportSchema")] public sealed class AdoptAuthenticationSupportSchema : Migration { protected override void Up(MigrationBuilder migrationBuilder) { if (ActiveProvider.Contains("MySql", StringComparison.OrdinalIgnoreCase)) { migrationBuilder.Sql(""" CREATE TABLE IF NOT EXISTS `TwoFactorRecoveryCodes` ( `Id` int NOT NULL AUTO_INCREMENT, `UserId` varchar(255) NOT NULL, `CodeHash` varchar(255) NOT NULL, `CreatedAtUtc` datetime(6) NOT NULL, `UsedAtUtc` datetime(6) NULL, PRIMARY KEY (`Id`) ) CHARACTER SET=utf8mb4; CREATE INDEX IF NOT EXISTS `IX_TwoFactorRecoveryCodes_UserId_UsedAtUtc` ON `TwoFactorRecoveryCodes` (`UserId`, `UsedAtUtc`); CREATE TABLE IF NOT EXISTS `TrustedDevices` ( `Id` int NOT NULL AUTO_INCREMENT, `UserId` varchar(255) NOT NULL, `TokenHash` varchar(255) NOT NULL, `DeviceLabel` varchar(255) NULL, `CreatedAtUtc` datetime(6) NOT NULL, `LastSeenAtUtc` datetime(6) NOT NULL, `ExpiresAtUtc` datetime(6) NOT NULL, PRIMARY KEY (`Id`) ) CHARACTER SET=utf8mb4; CREATE INDEX IF NOT EXISTS `IX_TrustedDevices_UserId` ON `TrustedDevices` (`UserId`); CREATE INDEX IF NOT EXISTS `IX_TrustedDevices_TokenHash` ON `TrustedDevices` (`TokenHash`); CREATE TABLE IF NOT EXISTS `UserSessions` ( `Id` varchar(64) NOT NULL, `UserId` varchar(255) NOT NULL, `DeviceLabel` varchar(255) NULL, `CreatedAtUtc` datetime(6) NOT NULL, `LastSeenAtUtc` datetime(6) NOT NULL, `ExpiresAtUtc` datetime(6) NOT NULL, `RevokedAtUtc` datetime(6) NULL, PRIMARY KEY (`Id`) ) CHARACTER SET=utf8mb4; CREATE INDEX IF NOT EXISTS `IX_UserSessions_UserId` ON `UserSessions` (`UserId`); """); return; } migrationBuilder.Sql(""" CREATE TABLE IF NOT EXISTS "TwoFactorRecoveryCodes" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_TwoFactorRecoveryCodes" PRIMARY KEY AUTOINCREMENT, "UserId" TEXT NOT NULL, "CodeHash" TEXT NOT NULL, "CreatedAtUtc" TEXT NOT NULL, "UsedAtUtc" TEXT NULL ); CREATE INDEX IF NOT EXISTS "IX_TwoFactorRecoveryCodes_UserId_UsedAtUtc" ON "TwoFactorRecoveryCodes" ("UserId", "UsedAtUtc"); CREATE TABLE IF NOT EXISTS "TrustedDevices" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_TrustedDevices" PRIMARY KEY AUTOINCREMENT, "UserId" TEXT NOT NULL, "TokenHash" TEXT NOT NULL, "DeviceLabel" TEXT NULL, "CreatedAtUtc" TEXT NOT NULL, "LastSeenAtUtc" TEXT NOT NULL, "ExpiresAtUtc" TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS "IX_TrustedDevices_UserId" ON "TrustedDevices" ("UserId"); CREATE INDEX IF NOT EXISTS "IX_TrustedDevices_TokenHash" ON "TrustedDevices" ("TokenHash"); CREATE TABLE IF NOT EXISTS "UserSessions" ( "Id" TEXT NOT NULL CONSTRAINT "PK_UserSessions" PRIMARY KEY, "UserId" TEXT NOT NULL, "DeviceLabel" TEXT NULL, "CreatedAtUtc" TEXT NOT NULL, "LastSeenAtUtc" TEXT NOT NULL, "ExpiresAtUtc" TEXT NOT NULL, "RevokedAtUtc" TEXT NULL ); CREATE INDEX IF NOT EXISTS "IX_UserSessions_UserId" ON "UserSessions" ("UserId"); """); } protected override void Down(MigrationBuilder migrationBuilder) { // Preserve security records that may have been created before migration ownership. } }