058d13de47
Complete schema ownership by moving all ASP.NET Identity tables to an additive provider-aware migration. Preserve credentials, security state, preferences, roles, claims, external logins, tokens, indexes, and cascades.
174 lines
11 KiB
C#
174 lines
11 KiB
C#
using System;
|
|
using JobTrackerApi.Data;
|
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
using Microsoft.EntityFrameworkCore.Migrations;
|
|
|
|
#nullable disable
|
|
|
|
namespace JobTrackerApi.Migrations;
|
|
|
|
/// <summary>
|
|
/// Establishes one migration owner for the ASP.NET Identity aggregate while preserving all
|
|
/// existing users, credentials, roles, claims, external logins, and tokens.
|
|
/// </summary>
|
|
[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`);
|
|
""";
|
|
}
|