forked from gongxuegit/tiku-backend.net
feat(saas): implement marketplace and tenant onboarding
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,213 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddCommerceAdjustmentVouchers : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commerce_adjustment_vouchers",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
issue_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
batch_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
item_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
order_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
payment_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
refund_request_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
reviewed_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
voucher_no = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
direction = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
amount_cents = table.Column<int>(type: "integer", nullable: false),
|
||||
currency = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: false),
|
||||
reason = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: false),
|
||||
proof_asset_key = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: true),
|
||||
reviewed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
closed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commerce_adjustment_vouchers", x => x.id);
|
||||
table.UniqueConstraint("ak_commerce_adjustment_vouchers_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_commerce_adjustment_vouchers_amount", "amount_cents > 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_commerce_reconciliation_batche~",
|
||||
columns: x => new { x.tenant_id, x.batch_id },
|
||||
principalTable: "commerce_reconciliation_batches",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_commerce_reconciliation_issues~",
|
||||
columns: x => new { x.tenant_id, x.issue_id },
|
||||
principalTable: "commerce_reconciliation_issues",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_commerce_reconciliation_items_~",
|
||||
columns: x => new { x.tenant_id, x.item_id },
|
||||
principalTable: "commerce_reconciliation_items",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_commerce_refund_requests_tenan~",
|
||||
columns: x => new { x.tenant_id, x.refund_request_id },
|
||||
principalTable: "commerce_refund_requests",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_orders_tenant_id_order_id",
|
||||
columns: x => new { x.tenant_id, x.order_id },
|
||||
principalTable: "orders",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_payments_tenant_id_payment_id",
|
||||
columns: x => new { x.tenant_id, x.payment_id },
|
||||
principalTable: "payments",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_users_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_vouchers_users_reviewed_by",
|
||||
column: x => x.reviewed_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "commerce_adjustment_voucher_events",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
voucher_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
from_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
to_status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
actor_user_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
note = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
details = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_commerce_adjustment_voucher_events", x => x.id);
|
||||
table.UniqueConstraint("ak_commerce_adjustment_voucher_events_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_voucher_events_commerce_adjustment_vouc~",
|
||||
columns: x => new { x.tenant_id, x.voucher_id },
|
||||
principalTable: "commerce_adjustment_vouchers",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_voucher_events_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_commerce_adjustment_voucher_events_users_actor_user_id",
|
||||
column: x => x.actor_user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_voucher_events_actor_user_id",
|
||||
table: "commerce_adjustment_voucher_events",
|
||||
column: "actor_user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_voucher_events_tenant_id_voucher_id_cre~",
|
||||
table: "commerce_adjustment_voucher_events",
|
||||
columns: new[] { "tenant_id", "voucher_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_created_by",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_reviewed_by",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
column: "reviewed_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_tenant_id_batch_id",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
columns: new[] { "tenant_id", "batch_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_tenant_id_issue_id_created_at",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
columns: new[] { "tenant_id", "issue_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_tenant_id_item_id",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
columns: new[] { "tenant_id", "item_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_tenant_id_order_id",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
columns: new[] { "tenant_id", "order_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_tenant_id_payment_id",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
columns: new[] { "tenant_id", "payment_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_tenant_id_refund_request_id",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
columns: new[] { "tenant_id", "refund_request_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_tenant_id_status_created_at",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
columns: new[] { "tenant_id", "status", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_commerce_adjustment_vouchers_tenant_id_voucher_no",
|
||||
table: "commerce_adjustment_vouchers",
|
||||
columns: new[] { "tenant_id", "voucher_no" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "commerce_adjustment_voucher_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "commerce_adjustment_vouchers");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,111 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddVideoPlaybackProgress : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "video_playback_progress",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
video_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
question_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
position_seconds = table.Column<int>(type: "integer", nullable: false),
|
||||
duration_seconds = table.Column<int>(type: "integer", nullable: true),
|
||||
watched_seconds = table.Column<int>(type: "integer", nullable: false),
|
||||
is_completed = table.Column<bool>(type: "boolean", nullable: false),
|
||||
completed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
last_played_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
play_count = table.Column<int>(type: "integer", nullable: false),
|
||||
metadata = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_video_playback_progress", x => x.id);
|
||||
table.UniqueConstraint("ak_video_playback_progress_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_video_playback_progress_duration", "duration_seconds is null or duration_seconds >= 0");
|
||||
table.CheckConstraint("ck_video_playback_progress_play_count", "play_count >= 0");
|
||||
table.CheckConstraint("ck_video_playback_progress_position", "position_seconds >= 0");
|
||||
table.CheckConstraint("ck_video_playback_progress_watched", "watched_seconds >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_video_playback_progress_questions_tenant_id_question_id",
|
||||
columns: x => new { x.tenant_id, x.question_id },
|
||||
principalTable: "questions",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_video_playback_progress_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_video_playback_progress_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_video_playback_progress_video_explanations_tenant_id_video_~",
|
||||
columns: x => new { x.tenant_id, x.video_id },
|
||||
principalTable: "video_explanations",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_playback_progress_tenant_id_question_id",
|
||||
table: "video_playback_progress",
|
||||
columns: new[] { "tenant_id", "question_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_playback_progress_tenant_id_user_id_last_played_at",
|
||||
table: "video_playback_progress",
|
||||
columns: new[] { "tenant_id", "user_id", "last_played_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_playback_progress_tenant_id_user_id_video_id",
|
||||
table: "video_playback_progress",
|
||||
columns: new[] { "tenant_id", "user_id", "video_id" },
|
||||
unique: true,
|
||||
filter: "question_id is null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_playback_progress_tenant_id_user_id_video_id_question~",
|
||||
table: "video_playback_progress",
|
||||
columns: new[] { "tenant_id", "user_id", "video_id", "question_id" },
|
||||
unique: true,
|
||||
filter: "question_id is not null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_playback_progress_tenant_id_video_id",
|
||||
table: "video_playback_progress",
|
||||
columns: new[] { "tenant_id", "video_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_video_playback_progress_user_id",
|
||||
table: "video_playback_progress",
|
||||
column: "user_id");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "video_playback_progress");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class RemoveMfaAuthentication : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "mfa_satisfied",
|
||||
table: "auth_sessions");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "mfa_satisfied",
|
||||
table: "auth_sessions",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddDistributedSecurityFoundation : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddUniqueConstraint(
|
||||
name: "ak_platform_saas_plans_code",
|
||||
table: "platform_saas_plans",
|
||||
column: "code");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "inbox_state",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
message_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
consumer_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
lock_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
row_version = table.Column<byte[]>(type: "bytea", rowVersion: true, nullable: true),
|
||||
received = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
receive_count = table.Column<int>(type: "integer", nullable: false),
|
||||
expiration_time = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
consumed = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
delivered = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
last_sequence_number = table.Column<long>(type: "bigint", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_inbox_state", x => x.id);
|
||||
table.UniqueConstraint("ak_inbox_state_message_id_consumer_id", x => new { x.message_id, x.consumer_id });
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "outbox_state",
|
||||
columns: table => new
|
||||
{
|
||||
outbox_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
lock_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
row_version = table.Column<byte[]>(type: "bytea", rowVersion: true, nullable: true),
|
||||
created = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
delivered = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
last_sequence_number = table.Column<long>(type: "bigint", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_outbox_state", x => x.outbox_id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "product_modules",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
description = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_product_modules", x => x.id);
|
||||
table.UniqueConstraint("ak_product_modules_code", x => x.code);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_auth_policies",
|
||||
columns: table => new
|
||||
{
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
allow_external_student_self_registration = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_auth_policies", x => x.tenant_id);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_auth_policies_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
// Existing tenants retain the historical external-login behavior. New tenants
|
||||
// receive an explicit fail-closed policy when created by PlatformAdminService.
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO tenant_auth_policies
|
||||
(tenant_id, allow_external_student_self_registration, created_at, updated_at)
|
||||
SELECT id, TRUE, now(), now()
|
||||
FROM tenants
|
||||
ON CONFLICT (tenant_id) DO NOTHING;
|
||||
""");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "outbox_message",
|
||||
columns: table => new
|
||||
{
|
||||
sequence_number = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
enqueue_time = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
sent_time = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
headers = table.Column<string>(type: "text", nullable: true),
|
||||
properties = table.Column<string>(type: "text", nullable: true),
|
||||
inbox_message_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
inbox_consumer_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
outbox_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
message_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
content_type = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
|
||||
message_type = table.Column<string>(type: "text", nullable: false),
|
||||
body = table.Column<string>(type: "text", nullable: false),
|
||||
conversation_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
correlation_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
initiator_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
request_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
source_address = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||
destination_address = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||
response_address = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||
fault_address = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
||||
expiration_time = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_outbox_message", x => x.sequence_number);
|
||||
table.ForeignKey(
|
||||
name: "fk_outbox_message_inbox_state_inbox_message_id_inbox_consumer_~",
|
||||
columns: x => new { x.inbox_message_id, x.inbox_consumer_id },
|
||||
principalTable: "inbox_state",
|
||||
principalColumns: new[] { "message_id", "consumer_id" });
|
||||
table.ForeignKey(
|
||||
name: "fk_outbox_message_outbox_state_outbox_id",
|
||||
column: x => x.outbox_id,
|
||||
principalTable: "outbox_state",
|
||||
principalColumn: "outbox_id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "plan_module_entitlements",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
plan_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
module_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
enabled = table.Column<bool>(type: "boolean", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_plan_module_entitlements", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_plan_module_entitlements_platform_saas_plans_plan_code",
|
||||
column: x => x.plan_code,
|
||||
principalTable: "platform_saas_plans",
|
||||
principalColumn: "code",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_plan_module_entitlements_product_modules_module_code",
|
||||
column: x => x.module_code,
|
||||
principalTable: "product_modules",
|
||||
principalColumn: "code",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_module_overrides",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
module_code = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
mode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
expires_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
reason = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_tenant_module_overrides", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_module_overrides_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_module_overrides_product_modules_module_code",
|
||||
column: x => x.module_code,
|
||||
principalTable: "product_modules",
|
||||
principalColumn: "code",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_module_overrides_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_inbox_state_delivered",
|
||||
table: "inbox_state",
|
||||
column: "delivered");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_outbox_message_enqueue_time",
|
||||
table: "outbox_message",
|
||||
column: "enqueue_time");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_outbox_message_expiration_time",
|
||||
table: "outbox_message",
|
||||
column: "expiration_time");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_outbox_message_inbox_message_id_inbox_consumer_id_sequence_~",
|
||||
table: "outbox_message",
|
||||
columns: new[] { "inbox_message_id", "inbox_consumer_id", "sequence_number" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_outbox_message_outbox_id_sequence_number",
|
||||
table: "outbox_message",
|
||||
columns: new[] { "outbox_id", "sequence_number" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_outbox_state_created",
|
||||
table: "outbox_state",
|
||||
column: "created");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_plan_module_entitlements_module_code",
|
||||
table: "plan_module_entitlements",
|
||||
column: "module_code");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_plan_module_entitlements_plan_code_module_code",
|
||||
table: "plan_module_entitlements",
|
||||
columns: new[] { "plan_code", "module_code" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_product_modules_code",
|
||||
table: "product_modules",
|
||||
column: "code",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_module_overrides_module_code",
|
||||
table: "tenant_module_overrides",
|
||||
column: "module_code");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_module_overrides_tenant_id_module_code",
|
||||
table: "tenant_module_overrides",
|
||||
columns: new[] { "tenant_id", "module_code" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "outbox_message");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "plan_module_entitlements");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_auth_policies");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_module_overrides");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "inbox_state");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "outbox_state");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "product_modules");
|
||||
|
||||
migrationBuilder.DropUniqueConstraint(
|
||||
name: "ak_platform_saas_plans_code",
|
||||
table: "platform_saas_plans");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,64 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class EnforceProductModuleCatalog : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO product_modules
|
||||
(id, code, name, status, sort_order, created_at, updated_at)
|
||||
VALUES
|
||||
('10000000-0000-0000-0000-000000000001', 'dashboard', 'Dashboard', 'active', 10, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-000000000002', 'staff', 'Staff', 'active', 20, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-000000000003', 'role', 'Roles', 'active', 30, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-000000000004', 'student', 'Students', 'active', 40, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-000000000005', 'content', 'Content', 'active', 50, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-000000000006', 'settings', 'Settings', 'active', 60, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-000000000007', 'provider', 'Providers', 'active', 70, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-000000000008', 'commerce', 'Commerce', 'active', 80, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-000000000009', 'crm', 'CRM', 'active', 90, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-00000000000a', 'commission', 'Commission', 'active', 100, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
|
||||
('10000000-0000-0000-0000-00000000000b', 'job', 'Background Jobs', 'active', 110, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT (code) DO UPDATE SET
|
||||
name = EXCLUDED.name,
|
||||
status = 'active',
|
||||
sort_order = EXCLUDED.sort_order,
|
||||
updated_at = CURRENT_TIMESTAMP;
|
||||
|
||||
INSERT INTO plan_module_entitlements (id, plan_code, module_code, enabled)
|
||||
SELECT
|
||||
md5('plan-module:' || plan.code || ':' || module.code)::uuid,
|
||||
plan.code,
|
||||
module.code,
|
||||
TRUE
|
||||
FROM platform_saas_plans AS plan
|
||||
CROSS JOIN product_modules AS module
|
||||
WHERE module.code IN
|
||||
('dashboard', 'staff', 'role', 'student', 'content', 'settings',
|
||||
'provider', 'commerce', 'crm', 'commission', 'job')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM plan_module_entitlements AS existing
|
||||
WHERE existing.plan_code = plan.code)
|
||||
ON CONFLICT (plan_code, module_code) DO NOTHING;
|
||||
""");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("""
|
||||
DELETE FROM product_modules
|
||||
WHERE code IN
|
||||
('dashboard', 'staff', 'role', 'student', 'content', 'settings',
|
||||
'provider', 'commerce', 'crm', 'commission', 'job');
|
||||
""");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,4 +15,17 @@ internal static class MigrationBuilderTenantGuardExtensions
|
||||
{
|
||||
migrationBuilder.Sql(PostgreSqlTenantConstraintSql.DropTenantGuards);
|
||||
}
|
||||
|
||||
public static void EnsureSaasCatalogGuards(this MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql(PostgreSqlSaasCatalogConstraintSql.DropOfferingVersionImmutabilityGuards);
|
||||
migrationBuilder.Sql(PostgreSqlSaasCatalogConstraintSql.CreateOfferingVersionImmutabilityGuards);
|
||||
migrationBuilder.Sql(PostgreSqlSaasCatalogConstraintSql.CreateOfferingVersionChildrenImmutabilityGuards);
|
||||
migrationBuilder.Sql(PostgreSqlSaasCatalogConstraintSql.CreateSubscriptionOfferingTypeGuards);
|
||||
}
|
||||
|
||||
public static void DropSaasCatalogGuards(this MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql(PostgreSqlSaasCatalogConstraintSql.DropOfferingVersionImmutabilityGuards);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user