diff --git a/src/IncidentOps.Infrastructure/Migrations/Migration0001_InitialSchema.cs b/src/IncidentOps.Infrastructure/Migrations/Migration0001_InitialSchema.cs new file mode 100644 index 0000000..71764cb --- /dev/null +++ b/src/IncidentOps.Infrastructure/Migrations/Migration0001_InitialSchema.cs @@ -0,0 +1,93 @@ +using FluentMigrator; + +namespace IncidentOps.Infrastructure.Migrations; + +[Migration(1)] +public class Migration0001_InitialSchema : Migration +{ + public override void Up() + { + Create.Table("users") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("email").AsString(255).NotNullable().Unique() + .WithColumn("password_hash").AsString(255).NotNullable() + .WithColumn("display_name").AsString(255).NotNullable() + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime) + .WithColumn("updated_at").AsDateTime().Nullable(); + + Create.Table("orgs") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("name").AsString(255).NotNullable() + .WithColumn("slug").AsString(100).NotNullable().Unique() + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime) + .WithColumn("updated_at").AsDateTime().Nullable(); + + Create.Table("org_members") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("org_id").AsGuid().NotNullable().ForeignKey("orgs", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("user_id").AsGuid().NotNullable().ForeignKey("users", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("role").AsString(50).NotNullable() + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime) + .WithColumn("updated_at").AsDateTime().Nullable(); + + Create.UniqueConstraint("uq_org_members_org_user") + .OnTable("org_members") + .Columns("org_id", "user_id"); + + Create.Table("services") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("org_id").AsGuid().NotNullable().ForeignKey("orgs", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("name").AsString(255).NotNullable() + .WithColumn("slug").AsString(100).NotNullable() + .WithColumn("description").AsString(1000).Nullable() + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime) + .WithColumn("updated_at").AsDateTime().Nullable(); + + Create.UniqueConstraint("uq_services_org_slug") + .OnTable("services") + .Columns("org_id", "slug"); + + Create.Table("incidents") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("org_id").AsGuid().NotNullable().ForeignKey("orgs", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("service_id").AsGuid().NotNullable().ForeignKey("services", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("title").AsString(500).NotNullable() + .WithColumn("description").AsString(4000).Nullable() + .WithColumn("status").AsString(50).NotNullable() + .WithColumn("version").AsInt32().NotNullable().WithDefaultValue(1) + .WithColumn("assigned_to_user_id").AsGuid().Nullable().ForeignKey("users", "id").OnDelete(System.Data.Rule.SetNull) + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime) + .WithColumn("acknowledged_at").AsDateTime().Nullable() + .WithColumn("mitigated_at").AsDateTime().Nullable() + .WithColumn("resolved_at").AsDateTime().Nullable(); + + Create.Index("ix_incidents_org_status") + .OnTable("incidents") + .OnColumn("org_id").Ascending() + .OnColumn("status").Ascending() + .OnColumn("created_at").Descending(); + + Create.Table("incident_events") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("incident_id").AsGuid().NotNullable().ForeignKey("incidents", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("event_type").AsString(50).NotNullable() + .WithColumn("actor_user_id").AsGuid().Nullable().ForeignKey("users", "id").OnDelete(System.Data.Rule.SetNull) + .WithColumn("payload").AsString(4000).Nullable() + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime); + + Create.Index("ix_incident_events_incident") + .OnTable("incident_events") + .OnColumn("incident_id").Ascending() + .OnColumn("created_at").Ascending(); + } + + public override void Down() + { + Delete.Table("incident_events"); + Delete.Table("incidents"); + Delete.Table("services"); + Delete.Table("org_members"); + Delete.Table("orgs"); + Delete.Table("users"); + } +} diff --git a/src/IncidentOps.Infrastructure/Migrations/Migration0002_RefreshTokens.cs b/src/IncidentOps.Infrastructure/Migrations/Migration0002_RefreshTokens.cs new file mode 100644 index 0000000..c4f1549 --- /dev/null +++ b/src/IncidentOps.Infrastructure/Migrations/Migration0002_RefreshTokens.cs @@ -0,0 +1,28 @@ +using FluentMigrator; + +namespace IncidentOps.Infrastructure.Migrations; + +[Migration(2)] +public class Migration0002_RefreshTokens : Migration +{ + public override void Up() + { + Create.Table("refresh_tokens") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("user_id").AsGuid().NotNullable().ForeignKey("users", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("token_hash").AsString(255).NotNullable().Unique() + .WithColumn("active_org_id").AsGuid().NotNullable().ForeignKey("orgs", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("expires_at").AsDateTime().NotNullable() + .WithColumn("revoked_at").AsDateTime().Nullable() + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime); + + Create.Index("ix_refresh_tokens_user") + .OnTable("refresh_tokens") + .OnColumn("user_id").Ascending(); + } + + public override void Down() + { + Delete.Table("refresh_tokens"); + } +} diff --git a/src/IncidentOps.Infrastructure/Migrations/Migration0003_NotificationTargets.cs b/src/IncidentOps.Infrastructure/Migrations/Migration0003_NotificationTargets.cs new file mode 100644 index 0000000..1893871 --- /dev/null +++ b/src/IncidentOps.Infrastructure/Migrations/Migration0003_NotificationTargets.cs @@ -0,0 +1,39 @@ +using FluentMigrator; + +namespace IncidentOps.Infrastructure.Migrations; + +[Migration(3)] +public class Migration0003_NotificationTargets : Migration +{ + public override void Up() + { + Create.Table("notification_targets") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("org_id").AsGuid().NotNullable().ForeignKey("orgs", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("name").AsString(255).NotNullable() + .WithColumn("target_type").AsString(50).NotNullable() + .WithColumn("configuration").AsString(4000).NotNullable() + .WithColumn("is_enabled").AsBoolean().NotNullable().WithDefaultValue(true) + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime) + .WithColumn("updated_at").AsDateTime().Nullable(); + + Create.Table("notification_attempts") + .WithColumn("id").AsGuid().PrimaryKey() + .WithColumn("incident_id").AsGuid().NotNullable().ForeignKey("incidents", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("target_id").AsGuid().NotNullable().ForeignKey("notification_targets", "id").OnDelete(System.Data.Rule.Cascade) + .WithColumn("success").AsBoolean().NotNullable() + .WithColumn("error_message").AsString(1000).Nullable() + .WithColumn("attempt_number").AsInt32().NotNullable().WithDefaultValue(1) + .WithColumn("created_at").AsDateTime().NotNullable().WithDefault(SystemMethods.CurrentUTCDateTime); + + Create.UniqueConstraint("uq_notification_attempts_incident_target") + .OnTable("notification_attempts") + .Columns("incident_id", "target_id"); + } + + public override void Down() + { + Delete.Table("notification_attempts"); + Delete.Table("notification_targets"); + } +}