using System; using JobTrackerApi.Data; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace JobTrackerApi.Migrations; /// /// Establishes one migration owner for the ASP.NET Identity aggregate while preserving all /// existing users, credentials, roles, claims, external logins, and tokens. /// [DbContext(typeof(JobTrackerContext))] [Migration("20260830134000_AdoptIdentitySchema")] public sealed class AdoptIdentitySchema : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.Sql(ActiveProvider.Contains("MySql", StringComparison.OrdinalIgnoreCase) ? MySqlDdl : SqliteDdl); } protected override void Down(MigrationBuilder migrationBuilder) { // Identity data may predate this migration; downgrade must never remove accounts. } private const string SqliteDdl = """ CREATE TABLE IF NOT EXISTS "AspNetRoles" ( "Id" TEXT NOT NULL CONSTRAINT "PK_AspNetRoles" PRIMARY KEY, "Name" TEXT NULL, "NormalizedName" TEXT NULL, "ConcurrencyStamp" TEXT NULL); CREATE TABLE IF NOT EXISTS "AspNetUsers" ( "Id" TEXT NOT NULL CONSTRAINT "PK_AspNetUsers" PRIMARY KEY, "UserName" TEXT NULL, "NormalizedUserName" TEXT NULL, "Email" TEXT NULL, "NormalizedEmail" TEXT NULL, "EmailConfirmed" INTEGER NOT NULL, "PasswordHash" TEXT NULL, "SecurityStamp" TEXT NULL, "ConcurrencyStamp" TEXT NULL, "PhoneNumber" TEXT NULL, "PhoneNumberConfirmed" INTEGER NOT NULL, "TwoFactorEnabled" INTEGER NOT NULL, "LockoutEnd" TEXT NULL, "LockoutEnabled" INTEGER NOT NULL, "AccessFailedCount" INTEGER NOT NULL, "FirstName" TEXT NULL, "LastName" TEXT NULL, "DisplayName" TEXT NULL, "ProfileCvText" TEXT NULL, "ProfileCvStructureJson" TEXT NULL, "CurrentCvUploadArtifactId" INTEGER NULL, "CurrentCvExtractionRunId" INTEGER NULL, "CurrentCvProfileVersion" INTEGER NULL, "AvatarImageDataUrl" TEXT NULL, "GoogleSubject" TEXT NULL, "GoogleEmail" TEXT NULL, "GoogleLinkedAt" TEXT NULL, "MicrosoftSubject" TEXT NULL, "MicrosoftEmail" TEXT NULL, "MicrosoftLinkedAt" TEXT NULL, "MicrosoftTenantId" TEXT NULL, "MicrosoftObjectId" TEXT NULL, "TotpSecretEncrypted" TEXT NULL, "TotpPendingSecretEncrypted" TEXT NULL, "TotpEnabledAtUtc" TEXT NULL, "PendingEmail" TEXT NULL, "PendingEmailRequestedAtUtc" TEXT NULL, "AiEnabled" INTEGER NOT NULL DEFAULT 1, "ExternalAiProcessingAllowed" INTEGER NOT NULL DEFAULT 0, "StripeCustomerId" TEXT NULL, "StripeSubscriptionId" TEXT NULL, "StripeSubscriptionStatus" TEXT NULL, "StripeLastEventCreatedUtc" TEXT NULL, "DeletionRequestedAtUtc" TEXT NULL, "DeletionStatus" TEXT NOT NULL DEFAULT 'active', "EmailFollowUpRemindersEnabled" INTEGER NOT NULL DEFAULT 1, "UiLanguage" TEXT NULL); CREATE TABLE IF NOT EXISTS "AspNetRoleClaims" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_AspNetRoleClaims" PRIMARY KEY AUTOINCREMENT, "RoleId" TEXT NOT NULL, "ClaimType" TEXT NULL, "ClaimValue" TEXT NULL, CONSTRAINT "FK_AspNetRoleClaims_AspNetRoles_RoleId" FOREIGN KEY ("RoleId") REFERENCES "AspNetRoles" ("Id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "AspNetUserClaims" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_AspNetUserClaims" PRIMARY KEY AUTOINCREMENT, "UserId" TEXT NOT NULL, "ClaimType" TEXT NULL, "ClaimValue" TEXT NULL, CONSTRAINT "FK_AspNetUserClaims_AspNetUsers_UserId" FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "AspNetUserLogins" ( "LoginProvider" TEXT NOT NULL, "ProviderKey" TEXT NOT NULL, "ProviderDisplayName" TEXT NULL, "UserId" TEXT NOT NULL, CONSTRAINT "PK_AspNetUserLogins" PRIMARY KEY ("LoginProvider", "ProviderKey"), CONSTRAINT "FK_AspNetUserLogins_AspNetUsers_UserId" FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "AspNetUserRoles" ( "UserId" TEXT NOT NULL, "RoleId" TEXT NOT NULL, CONSTRAINT "PK_AspNetUserRoles" PRIMARY KEY ("UserId", "RoleId"), CONSTRAINT "FK_AspNetUserRoles_AspNetRoles_RoleId" FOREIGN KEY ("RoleId") REFERENCES "AspNetRoles" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_AspNetUserRoles_AspNetUsers_UserId" FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE); CREATE TABLE IF NOT EXISTS "AspNetUserTokens" ( "UserId" TEXT NOT NULL, "LoginProvider" TEXT NOT NULL, "Name" TEXT NOT NULL, "Value" TEXT NULL, CONSTRAINT "PK_AspNetUserTokens" PRIMARY KEY ("UserId", "LoginProvider", "Name"), CONSTRAINT "FK_AspNetUserTokens_AspNetUsers_UserId" FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE); CREATE UNIQUE INDEX IF NOT EXISTS "RoleNameIndex" ON "AspNetRoles" ("NormalizedName"); CREATE INDEX IF NOT EXISTS "IX_AspNetRoleClaims_RoleId" ON "AspNetRoleClaims" ("RoleId"); CREATE INDEX IF NOT EXISTS "EmailIndex" ON "AspNetUsers" ("NormalizedEmail"); CREATE UNIQUE INDEX IF NOT EXISTS "UserNameIndex" ON "AspNetUsers" ("NormalizedUserName"); CREATE UNIQUE INDEX IF NOT EXISTS "IX_AspNetUsers_MicrosoftTenantId_MicrosoftObjectId" ON "AspNetUsers" ("MicrosoftTenantId", "MicrosoftObjectId"); CREATE INDEX IF NOT EXISTS "IX_AspNetUserClaims_UserId" ON "AspNetUserClaims" ("UserId"); CREATE INDEX IF NOT EXISTS "IX_AspNetUserLogins_UserId" ON "AspNetUserLogins" ("UserId"); CREATE INDEX IF NOT EXISTS "IX_AspNetUserRoles_RoleId" ON "AspNetUserRoles" ("RoleId"); """; private const string MySqlDdl = """ CREATE TABLE IF NOT EXISTS `AspNetRoles` ( `Id` varchar(255) NOT NULL, `Name` varchar(256) NULL, `NormalizedName` varchar(256) NULL, `ConcurrencyStamp` longtext NULL, PRIMARY KEY (`Id`)) CHARACTER SET=utf8mb4; CREATE TABLE IF NOT EXISTS `AspNetUsers` ( `Id` varchar(255) NOT NULL, `UserName` varchar(256) NULL, `NormalizedUserName` varchar(256) NULL, `Email` varchar(256) NULL, `NormalizedEmail` varchar(256) NULL, `EmailConfirmed` tinyint(1) NOT NULL, `PasswordHash` longtext NULL, `SecurityStamp` longtext NULL, `ConcurrencyStamp` longtext NULL, `PhoneNumber` longtext NULL, `PhoneNumberConfirmed` tinyint(1) NOT NULL, `TwoFactorEnabled` tinyint(1) NOT NULL, `LockoutEnd` datetime(6) NULL, `LockoutEnabled` tinyint(1) NOT NULL, `AccessFailedCount` int NOT NULL, `FirstName` longtext NULL, `LastName` longtext NULL, `DisplayName` longtext NULL, `ProfileCvText` longtext NULL, `ProfileCvStructureJson` longtext NULL, `CurrentCvUploadArtifactId` int NULL, `CurrentCvExtractionRunId` int NULL, `CurrentCvProfileVersion` int NULL, `AvatarImageDataUrl` longtext NULL, `GoogleSubject` longtext NULL, `GoogleEmail` longtext NULL, `GoogleLinkedAt` datetime(6) NULL, `MicrosoftSubject` longtext NULL, `MicrosoftEmail` longtext NULL, `MicrosoftLinkedAt` datetime(6) NULL, `MicrosoftTenantId` varchar(36) NULL, `MicrosoftObjectId` varchar(36) NULL, `TotpSecretEncrypted` longtext NULL, `TotpPendingSecretEncrypted` longtext NULL, `TotpEnabledAtUtc` datetime(6) NULL, `PendingEmail` varchar(320) NULL, `PendingEmailRequestedAtUtc` datetime(6) NULL, `AiEnabled` tinyint(1) NOT NULL DEFAULT 1, `ExternalAiProcessingAllowed` tinyint(1) NOT NULL DEFAULT 0, `StripeCustomerId` varchar(255) NULL, `StripeSubscriptionId` varchar(255) NULL, `StripeSubscriptionStatus` varchar(64) NULL, `StripeLastEventCreatedUtc` datetime(6) NULL, `DeletionRequestedAtUtc` datetime(6) NULL, `DeletionStatus` varchar(32) NOT NULL DEFAULT 'active', `EmailFollowUpRemindersEnabled` tinyint(1) NOT NULL DEFAULT 1, `UiLanguage` varchar(16) NULL, PRIMARY KEY (`Id`)) CHARACTER SET=utf8mb4; CREATE TABLE IF NOT EXISTS `AspNetRoleClaims` ( `Id` int NOT NULL AUTO_INCREMENT, `RoleId` varchar(255) NOT NULL, `ClaimType` longtext NULL, `ClaimValue` longtext NULL, PRIMARY KEY (`Id`), CONSTRAINT `FK_AspNetRoleClaims_AspNetRoles_RoleId` FOREIGN KEY (`RoleId`) REFERENCES `AspNetRoles` (`Id`) ON DELETE CASCADE) CHARACTER SET=utf8mb4; CREATE TABLE IF NOT EXISTS `AspNetUserClaims` ( `Id` int NOT NULL AUTO_INCREMENT, `UserId` varchar(255) NOT NULL, `ClaimType` longtext NULL, `ClaimValue` longtext NULL, PRIMARY KEY (`Id`), CONSTRAINT `FK_AspNetUserClaims_AspNetUsers_UserId` FOREIGN KEY (`UserId`) REFERENCES `AspNetUsers` (`Id`) ON DELETE CASCADE) CHARACTER SET=utf8mb4; CREATE TABLE IF NOT EXISTS `AspNetUserLogins` ( `LoginProvider` varchar(255) NOT NULL, `ProviderKey` varchar(255) NOT NULL, `ProviderDisplayName` longtext NULL, `UserId` varchar(255) NOT NULL, PRIMARY KEY (`LoginProvider`, `ProviderKey`), CONSTRAINT `FK_AspNetUserLogins_AspNetUsers_UserId` FOREIGN KEY (`UserId`) REFERENCES `AspNetUsers` (`Id`) ON DELETE CASCADE) CHARACTER SET=utf8mb4; CREATE TABLE IF NOT EXISTS `AspNetUserRoles` ( `UserId` varchar(255) NOT NULL, `RoleId` varchar(255) NOT NULL, PRIMARY KEY (`UserId`, `RoleId`), CONSTRAINT `FK_AspNetUserRoles_AspNetRoles_RoleId` FOREIGN KEY (`RoleId`) REFERENCES `AspNetRoles` (`Id`) ON DELETE CASCADE, CONSTRAINT `FK_AspNetUserRoles_AspNetUsers_UserId` FOREIGN KEY (`UserId`) REFERENCES `AspNetUsers` (`Id`) ON DELETE CASCADE) CHARACTER SET=utf8mb4; CREATE TABLE IF NOT EXISTS `AspNetUserTokens` ( `UserId` varchar(255) NOT NULL, `LoginProvider` varchar(255) NOT NULL, `Name` varchar(255) NOT NULL, `Value` longtext NULL, PRIMARY KEY (`UserId`, `LoginProvider`, `Name`), CONSTRAINT `FK_AspNetUserTokens_AspNetUsers_UserId` FOREIGN KEY (`UserId`) REFERENCES `AspNetUsers` (`Id`) ON DELETE CASCADE) CHARACTER SET=utf8mb4; CREATE UNIQUE INDEX IF NOT EXISTS `RoleNameIndex` ON `AspNetRoles` (`NormalizedName`); CREATE INDEX IF NOT EXISTS `IX_AspNetRoleClaims_RoleId` ON `AspNetRoleClaims` (`RoleId`); CREATE INDEX IF NOT EXISTS `EmailIndex` ON `AspNetUsers` (`NormalizedEmail`); CREATE UNIQUE INDEX IF NOT EXISTS `UserNameIndex` ON `AspNetUsers` (`NormalizedUserName`); CREATE UNIQUE INDEX IF NOT EXISTS `IX_AspNetUsers_MicrosoftTenantId_MicrosoftObjectId` ON `AspNetUsers` (`MicrosoftTenantId`, `MicrosoftObjectId`); CREATE INDEX IF NOT EXISTS `IX_AspNetUserClaims_UserId` ON `AspNetUserClaims` (`UserId`); CREATE INDEX IF NOT EXISTS `IX_AspNetUserLogins_UserId` ON `AspNetUserLogins` (`UserId`); CREATE INDEX IF NOT EXISTS `IX_AspNetUserRoles_RoleId` ON `AspNetUserRoles` (`RoleId`); """; }