feat: complete release readiness work
- consolidate API ownership and remove dead vendor code - add Stripe billing, learning paths, and public CV hardening - add migration, recovery, security, audit, and browser gates
This commit is contained in:
@@ -4,6 +4,8 @@ using JobTrackerApi.Models;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace JobTrackerApi.Services;
|
||||
|
||||
@@ -529,6 +531,10 @@ public static class StartupInitializationExtensions
|
||||
EnsureColumn(conn, "AspNetUsers", "TotpSecretEncrypted", "ALTER TABLE AspNetUsers ADD COLUMN TotpSecretEncrypted TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "TotpPendingSecretEncrypted", "ALTER TABLE AspNetUsers ADD COLUMN TotpPendingSecretEncrypted TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "TotpEnabledAtUtc", "ALTER TABLE AspNetUsers ADD COLUMN TotpEnabledAtUtc TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "StripeCustomerId", "ALTER TABLE AspNetUsers ADD COLUMN StripeCustomerId TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "StripeSubscriptionId", "ALTER TABLE AspNetUsers ADD COLUMN StripeSubscriptionId TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "StripeSubscriptionStatus", "ALTER TABLE AspNetUsers ADD COLUMN StripeSubscriptionStatus TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "StripeLastEventCreatedUtc", "ALTER TABLE AspNetUsers ADD COLUMN StripeLastEventCreatedUtc TEXT NULL;");
|
||||
|
||||
static void EnsureUserRuleSettingsTable(DbConnection c)
|
||||
{
|
||||
@@ -1115,12 +1121,11 @@ public static class StartupInitializationExtensions
|
||||
EnsureCoverLetterVersionsTable(conn);
|
||||
EnsureInterviewPrepItemsTable(conn);
|
||||
|
||||
// Legacy DB signature: migration history exists (AddCorrespondence applied), but 20260310195000 not recorded,
|
||||
// and at least one of the new columns already exists.
|
||||
// Once the base app tables exist, provision this reconciler-owned schema set and
|
||||
// stamp its historical migration before later migrations rebuild JobApplications.
|
||||
var isLegacy =
|
||||
HasMigration(conn, "20260310174114_AddCorrespondence") &&
|
||||
!HasMigration(conn, legacyMigrationId) &&
|
||||
(HasColumn(conn, "Companies", "Source") || HasColumn(conn, "JobApplications", "IsDeleted"));
|
||||
!HasMigration(conn, legacyMigrationId);
|
||||
|
||||
if (isLegacy)
|
||||
{
|
||||
@@ -1427,6 +1432,10 @@ public static class StartupInitializationExtensions
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "TotpSecretEncrypted", "ALTER TABLE `AspNetUsers` ADD COLUMN `TotpSecretEncrypted` longtext NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "TotpPendingSecretEncrypted", "ALTER TABLE `AspNetUsers` ADD COLUMN `TotpPendingSecretEncrypted` longtext NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "TotpEnabledAtUtc", "ALTER TABLE `AspNetUsers` ADD COLUMN `TotpEnabledAtUtc` datetime NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "StripeCustomerId", "ALTER TABLE `AspNetUsers` ADD COLUMN `StripeCustomerId` varchar(255) NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "StripeSubscriptionId", "ALTER TABLE `AspNetUsers` ADD COLUMN `StripeSubscriptionId` varchar(255) NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "StripeSubscriptionStatus", "ALTER TABLE `AspNetUsers` ADD COLUMN `StripeSubscriptionStatus` varchar(64) NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "StripeLastEventCreatedUtc", "ALTER TABLE `AspNetUsers` ADD COLUMN `StripeLastEventCreatedUtc` datetime(6) NULL;");
|
||||
|
||||
// RuleSettings is MIGRATION-owned — the initial migration creates it. The reconciler
|
||||
// used to create it too, which made a clean install fail with "Table 'RuleSettings'
|
||||
@@ -1997,13 +2006,19 @@ public static class StartupInitializationExtensions
|
||||
// table is skipped here (the parent does not exist yet) and picked up in pass 3.
|
||||
ReconcileSchema();
|
||||
|
||||
// 2. Migrations create every migration-owned table. On a brand-new database this is what
|
||||
// actually builds the schema; the pass above found nothing to reconcile.
|
||||
// 2. Apply one migration at a time, reconciling after each. Some historical migrations
|
||||
// rebuild tables using columns owned by the reconciler, so a fresh database needs
|
||||
// those columns added after the base table appears and before a later migration reads it.
|
||||
try
|
||||
{
|
||||
using var migrationScope = app.Services.CreateScope();
|
||||
var migrationDb = migrationScope.ServiceProvider.GetRequiredService<JobTrackerContext>();
|
||||
migrationDb.Database.Migrate();
|
||||
var migrator = migrationDb.Database.GetService<IMigrator>();
|
||||
while (migrationDb.Database.GetPendingMigrations().FirstOrDefault() is { } migration)
|
||||
{
|
||||
migrator.Migrate(migration);
|
||||
ReconcileSchema();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user