forked from gongxuegit/tiku-backend.net
feat: harden SaaS authentication and authorization
This commit is contained in:
@@ -13,7 +13,7 @@ using Tiku.Infrastructure.Persistence;
|
||||
namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(TikuDbContext))]
|
||||
[Migration("20260728014412_InitialSchema")]
|
||||
[Migration("20260728031410_InitialSchema")]
|
||||
partial class InitialSchema
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -28,6 +28,110 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "ltree");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("FriendlyName")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("friendly_name");
|
||||
|
||||
b.Property<string>("Xml")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("xml");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_data_protection_keys");
|
||||
|
||||
b.ToTable("data_protection_keys", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("claim_type");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("claim_value");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_user_claims");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_user_claims_user_id");
|
||||
|
||||
b.ToTable("user_claims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("login_provider");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("provider_key");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("provider_display_name");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey")
|
||||
.HasName("pk_user_logins");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_user_logins_user_id");
|
||||
|
||||
b.ToTable("user_logins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("login_provider");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("value");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name")
|
||||
.HasName("pk_user_tokens");
|
||||
|
||||
b.ToTable("user_tokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Catalog.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -7918,11 +8022,21 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnName("id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("access_failed_count");
|
||||
|
||||
b.Property<string>("AvatarUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)")
|
||||
.HasColumnName("avatar_url");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("concurrency_stamp");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
@@ -7934,6 +8048,14 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("citext")
|
||||
.HasColumnName("email");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("email_confirmed");
|
||||
|
||||
b.Property<bool>("ForcePasswordChange")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("force_password_change");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastSeenAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("last_seen_at");
|
||||
@@ -7943,25 +8065,48 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("legacy_id");
|
||||
|
||||
b.Property<string>("LegacyPasswordHash")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("legacy_password_hash");
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("lockout_enabled");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("lockout_end");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<bool>("PasswordMigrationRequired")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("password_migration_required");
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(320)
|
||||
.HasColumnType("character varying(320)")
|
||||
.HasColumnName("normalized_email");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("normalized_user_name");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnType("character varying(1024)")
|
||||
.HasColumnName("password_hash");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("phone");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("phone_number");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("phone_number_confirmed");
|
||||
|
||||
b.Property<string>("PrimaryRole")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
@@ -7978,36 +8123,50 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("score");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("security_stamp");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("status");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("two_factor_enabled");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("updated_at")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<string>("Username")
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("username");
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_users");
|
||||
|
||||
b.HasIndex("Email")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_email");
|
||||
|
||||
b.HasIndex("LegacyId")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_legacy_id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("email_index");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("user_name_index");
|
||||
|
||||
b.HasIndex("Phone")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_phone");
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_username");
|
||||
|
||||
b.ToTable("users", (string)null);
|
||||
});
|
||||
|
||||
@@ -8052,12 +8211,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("character varying(255)")
|
||||
.HasColumnName("provider_subject");
|
||||
|
||||
b.Property<JsonElement>("SecretPayload")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("secret_payload")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("UnionId")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)")
|
||||
@@ -12651,6 +12804,95 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("question_versions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthChallenge", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.Property<DateTimeOffset?>("ConsumedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("consumed_at");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("created_at")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("expires_at");
|
||||
|
||||
b.Property<string>("IpAddress")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("ip_address");
|
||||
|
||||
b.Property<string>("Provider")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)")
|
||||
.HasColumnName("provider");
|
||||
|
||||
b.Property<string>("Purpose")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("purpose");
|
||||
|
||||
b.Property<string>("Realm")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("realm");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("security_stamp");
|
||||
|
||||
b.Property<Guid?>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("tenant_id");
|
||||
|
||||
b.Property<string>("TokenHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("token_hash");
|
||||
|
||||
b.Property<string>("UserAgent")
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnType("character varying(1024)")
|
||||
.HasColumnName("user_agent");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_auth_challenges");
|
||||
|
||||
b.HasIndex("TenantId")
|
||||
.HasDatabaseName("ix_auth_challenges_tenant_id");
|
||||
|
||||
b.HasIndex("TokenHash")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_auth_challenges_token_hash");
|
||||
|
||||
b.HasIndex("UserId", "Purpose", "ExpiresAt")
|
||||
.HasDatabaseName("ix_auth_challenges_user_id_purpose_expires_at");
|
||||
|
||||
b.ToTable("auth_challenges", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("ck_auth_challenges_realm_tenant", "(realm = 'tenant' and tenant_id is not null) or (realm = 'platform' and tenant_id is null)");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthLoginEvent", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -12755,20 +12997,53 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnName("metadata")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<bool>("MfaSatisfied")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("mfa_satisfied");
|
||||
|
||||
b.Property<Guid?>("ParentSessionId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("parent_session_id");
|
||||
|
||||
b.Property<string>("Provider")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)")
|
||||
.HasColumnName("provider");
|
||||
|
||||
b.Property<string>("Realm")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("realm");
|
||||
|
||||
b.Property<Guid?>("ReplacedBySessionId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("replaced_by_session_id");
|
||||
|
||||
b.Property<DateTimeOffset?>("RevokedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("revoked_at");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
b.Property<string>("RevokedReason")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("revoked_reason");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("security_stamp");
|
||||
|
||||
b.Property<Guid?>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("tenant_id");
|
||||
|
||||
b.Property<Guid>("TokenFamilyId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("token_family_id");
|
||||
|
||||
b.Property<string>("TokenHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
@@ -12793,8 +13068,8 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_auth_sessions");
|
||||
|
||||
b.HasAlternateKey("TenantId", "Id")
|
||||
.HasName("ak_auth_sessions_tenant_id_id");
|
||||
b.HasIndex("TenantId")
|
||||
.HasDatabaseName("ix_auth_sessions_tenant_id");
|
||||
|
||||
b.HasIndex("TokenHash")
|
||||
.IsUnique()
|
||||
@@ -12804,11 +13079,17 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_auth_sessions_user_id");
|
||||
|
||||
b.HasIndex("TenantId", "UserId", "ExpiresAt")
|
||||
.HasDatabaseName("ix_auth_sessions_tenant_id_user_id_expires_at")
|
||||
b.HasIndex("TokenFamilyId", "RevokedAt")
|
||||
.HasDatabaseName("ix_auth_sessions_token_family_id_revoked_at");
|
||||
|
||||
b.HasIndex("Realm", "TenantId", "UserId", "ExpiresAt")
|
||||
.HasDatabaseName("ix_auth_sessions_realm_tenant_id_user_id_expires_at")
|
||||
.HasFilter("revoked_at is null");
|
||||
|
||||
b.ToTable("auth_sessions", (string)null);
|
||||
b.ToTable("auth_sessions", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("ck_auth_sessions_realm_tenant", "(realm = 'tenant' and tenant_id is not null) or (realm = 'platform' and tenant_id is null)");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.SmsSendRateLimit", b =>
|
||||
@@ -12934,9 +13215,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_sms_verification_codes");
|
||||
|
||||
b.HasAlternateKey("TenantId", "Id")
|
||||
.HasName("ak_sms_verification_codes_tenant_id_id");
|
||||
|
||||
b.HasIndex("TenantId", "Phone", "Purpose")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_sms_verification_codes_tenant_id_phone_purpose")
|
||||
@@ -13626,22 +13904,12 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("character varying(50)")
|
||||
.HasColumnName("legacy_role");
|
||||
|
||||
b.Property<JsonElement>("Permissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("role");
|
||||
|
||||
b.Property<Guid?>("RoleTemplateId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("role_template_id");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
@@ -13671,9 +13939,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_tenant_memberships_user_id");
|
||||
|
||||
b.HasIndex("TenantId", "RoleTemplateId")
|
||||
.HasDatabaseName("ix_tenant_memberships_tenant_id_role_template_id");
|
||||
|
||||
b.HasIndex("TenantId", "UserId", "Role")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_tenant_memberships_tenant_id_user_id_role");
|
||||
@@ -13681,126 +13946,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("tenant_memberships", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.TenantRoleTemplate", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.Property<string>("BaseRole")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("base_role");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("code");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("created_at")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("created_by");
|
||||
|
||||
b.Property<JsonElement>("DataScope")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("data_scope")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("description");
|
||||
|
||||
b.Property<JsonElement>("FieldPermissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("field_permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<bool>("IsSystem")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("is_system");
|
||||
|
||||
b.Property<JsonElement>("MenuPermissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("menu_permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<JsonElement>("ModulePermissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("module_permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<JsonElement>("Permissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("sort_order");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("status");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("tenant_id");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("updated_at")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("updated_by");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_tenant_role_templates");
|
||||
|
||||
b.HasAlternateKey("TenantId", "Id")
|
||||
.HasName("ak_tenant_role_templates_tenant_id_id");
|
||||
|
||||
b.HasIndex("CreatedBy")
|
||||
.HasDatabaseName("ix_tenant_role_templates_created_by");
|
||||
|
||||
b.HasIndex("UpdatedBy")
|
||||
.HasDatabaseName("ix_tenant_role_templates_updated_by");
|
||||
|
||||
b.HasIndex("TenantId", "Code")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_tenant_role_templates_tenant_id_code");
|
||||
|
||||
b.HasIndex("TenantId", "Status", "SortOrder")
|
||||
.HasDatabaseName("ix_tenant_role_templates_tenant_id_status_sort_order");
|
||||
|
||||
b.ToTable("tenant_role_templates", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.TenantSecret", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -14156,6 +14301,36 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("tenant_student_notes", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_user_claims_users_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_user_logins_users_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_user_tokens_users_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Catalog.Category", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Tenancy.Tenant", null)
|
||||
@@ -17207,12 +17382,28 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasConstraintName("fk_question_versions_questions_tenant_id_question_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthLoginEvent", b =>
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthChallenge", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Tenancy.Tenant", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.HasConstraintName("fk_auth_challenges_tenants_tenant_id");
|
||||
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_auth_challenges_users_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthLoginEvent", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Tenancy.Tenant", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_auth_login_events_tenants_tenant_id");
|
||||
|
||||
@@ -17229,7 +17420,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_auth_sessions_tenants_tenant_id");
|
||||
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
@@ -17378,35 +17568,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_tenant_memberships_users_user_id");
|
||||
|
||||
b.HasOne("Tiku.Domain.Tenancy.TenantRoleTemplate", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId", "RoleTemplateId")
|
||||
.HasPrincipalKey("TenantId", "Id")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.HasConstraintName("fk_tenant_memberships_tenant_role_templates_tenant_id_role_tem~");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.TenantRoleTemplate", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CreatedBy")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("fk_tenant_role_templates_users_created_by");
|
||||
|
||||
b.HasOne("Tiku.Domain.Tenancy.Tenant", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_tenant_role_templates_tenants_tenant_id");
|
||||
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UpdatedBy")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("fk_tenant_role_templates_users_updated_by");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.TenantSecret", b =>
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Tiku.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
@@ -38,6 +38,20 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
table.UniqueConstraint("ak_backend_permissions_code", x => x.code);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "data_protection_keys",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
friendly_name = table.Column<string>(type: "text", nullable: true),
|
||||
xml = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_data_protection_keys", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "platform_backend_roles",
|
||||
columns: table => new
|
||||
@@ -137,19 +151,31 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
legacy_id = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
username = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
email = table.Column<string>(type: "citext", maxLength: 320, nullable: true),
|
||||
phone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
name = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
avatar_url = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
primary_role = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
score = table.Column<int>(type: "integer", nullable: false),
|
||||
last_seen_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
legacy_password_hash = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
|
||||
password_migration_required = table.Column<bool>(type: "boolean", nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
force_password_change = table.Column<bool>(type: "boolean", nullable: false),
|
||||
raw_profile = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
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()")
|
||||
updated_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
user_name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
normalized_user_name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
email = table.Column<string>(type: "citext", maxLength: 320, nullable: true),
|
||||
normalized_email = table.Column<string>(type: "character varying(320)", maxLength: 320, nullable: true),
|
||||
email_confirmed = table.Column<bool>(type: "boolean", nullable: false),
|
||||
password_hash = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true),
|
||||
security_stamp = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
concurrency_stamp = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
phone_number = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
phone_number_confirmed = table.Column<bool>(type: "boolean", nullable: false),
|
||||
two_factor_enabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||
lockout_end = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
lockout_enabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||
access_failed_count = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@@ -265,6 +291,27 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_claims",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
claim_type = table.Column<string>(type: "text", nullable: true),
|
||||
claim_value = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_user_claims", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_user_claims_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_identities",
|
||||
columns: table => new
|
||||
@@ -277,7 +324,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
open_id = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
|
||||
phone = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
email = table.Column<string>(type: "citext", maxLength: 320, nullable: true),
|
||||
secret_payload = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
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()")
|
||||
},
|
||||
@@ -292,6 +338,46 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_logins",
|
||||
columns: table => new
|
||||
{
|
||||
login_provider = table.Column<string>(type: "text", nullable: false),
|
||||
provider_key = table.Column<string>(type: "text", nullable: false),
|
||||
provider_display_name = table.Column<string>(type: "text", nullable: true),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_user_logins", x => new { x.login_provider, x.provider_key });
|
||||
table.ForeignKey(
|
||||
name: "fk_user_logins_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "user_tokens",
|
||||
columns: table => new
|
||||
{
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
login_provider = table.Column<string>(type: "text", nullable: false),
|
||||
name = table.Column<string>(type: "text", nullable: false),
|
||||
value = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_user_tokens", x => new { x.user_id, x.login_provider, x.name });
|
||||
table.ForeignKey(
|
||||
name: "fk_user_tokens_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "platform_backend_role_menus",
|
||||
columns: table => new
|
||||
@@ -403,6 +489,42 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "auth_challenges",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
realm = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
purpose = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
token_hash = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||
security_stamp = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
expires_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
consumed_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
ip_address = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
user_agent = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true),
|
||||
created_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_auth_challenges", x => x.id);
|
||||
table.CheckConstraint("ck_auth_challenges_realm_tenant", "(realm = 'tenant' and tenant_id is not null) or (realm = 'platform' and tenant_id is null)");
|
||||
table.ForeignKey(
|
||||
name: "fk_auth_challenges_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_auth_challenges_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "auth_login_events",
|
||||
columns: table => new
|
||||
@@ -428,7 +550,7 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_auth_login_events_users_user_id",
|
||||
column: x => x.user_id,
|
||||
@@ -442,22 +564,29 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
realm = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
tenant_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
token_family_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
parent_session_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
replaced_by_session_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
token_hash = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
|
||||
security_stamp = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
|
||||
mfa_satisfied = table.Column<bool>(type: "boolean", nullable: false),
|
||||
provider = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||
expires_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
revoked_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
revoked_reason = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
||||
ip_address = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true),
|
||||
user_agent = table.Column<string>(type: "character varying(1000)", maxLength: 1000, 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_auth_sessions", x => x.id);
|
||||
table.UniqueConstraint("ak_auth_sessions_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_auth_sessions_realm_tenant", "(realm = 'tenant' and tenant_id is not null) or (realm = 'platform' and tenant_id is null)");
|
||||
table.ForeignKey(
|
||||
name: "fk_auth_sessions_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
@@ -1186,7 +1315,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_sms_verification_codes", x => x.id);
|
||||
table.UniqueConstraint("ak_sms_verification_codes_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.CheckConstraint("ck_sms_verification_codes_attempts", "attempts >= 0");
|
||||
table.ForeignKey(
|
||||
name: "fk_sms_verification_codes_tenants_tenant_id",
|
||||
@@ -1498,50 +1626,34 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_role_templates",
|
||||
name: "tenant_memberships",
|
||||
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: "text", nullable: true),
|
||||
base_role = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
role = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
menu_permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
module_permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
field_permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
data_scope = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
is_system = table.Column<bool>(type: "boolean", nullable: false),
|
||||
sort_order = table.Column<int>(type: "integer", nullable: false),
|
||||
created_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
updated_by = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
legacy_role = table.Column<string>(type: "character varying(50)", maxLength: 50, 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_role_templates", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_role_templates_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.PrimaryKey("pk_tenant_memberships", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_memberships_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_role_templates_tenants_tenant_id",
|
||||
name: "fk_tenant_memberships_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_role_templates_users_created_by",
|
||||
column: x => x.created_by,
|
||||
name: "fk_tenant_memberships_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_role_templates_users_updated_by",
|
||||
column: x => x.updated_by,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
@@ -2885,45 +2997,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "tenant_memberships",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "uuid", nullable: false, defaultValueSql: "gen_random_uuid()"),
|
||||
user_id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
role_template_id = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
role = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
status = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
|
||||
permissions = table.Column<JsonElement>(type: "jsonb", nullable: false, defaultValueSql: "'{}'::jsonb"),
|
||||
legacy_role = table.Column<string>(type: "character varying(50)", maxLength: 50, 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_memberships", x => x.id);
|
||||
table.UniqueConstraint("ak_tenant_memberships_tenant_id_id", x => new { x.tenant_id, x.id });
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_memberships_tenant_role_templates_tenant_id_role_tem~",
|
||||
columns: x => new { x.tenant_id, x.role_template_id },
|
||||
principalTable: "tenant_role_templates",
|
||||
principalColumns: new[] { "tenant_id", "id" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_memberships_tenants_tenant_id",
|
||||
column: x => x.tenant_id,
|
||||
principalTable: "tenants",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "fk_tenant_memberships_users_user_id",
|
||||
column: x => x.user_id,
|
||||
principalTable: "users",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "content_nodes",
|
||||
columns: table => new
|
||||
@@ -6392,6 +6465,22 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
table: "audit_logs",
|
||||
columns: new[] { "tenant_id", "target_type", "target_id", "created_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_challenges_tenant_id",
|
||||
table: "auth_challenges",
|
||||
column: "tenant_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_challenges_token_hash",
|
||||
table: "auth_challenges",
|
||||
column: "token_hash",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_challenges_user_id_purpose_expires_at",
|
||||
table: "auth_challenges",
|
||||
columns: new[] { "user_id", "purpose", "expires_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_login_events_tenant_id_user_id_created_at",
|
||||
table: "auth_login_events",
|
||||
@@ -6403,11 +6492,21 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_sessions_tenant_id_user_id_expires_at",
|
||||
name: "ix_auth_sessions_realm_tenant_id_user_id_expires_at",
|
||||
table: "auth_sessions",
|
||||
columns: new[] { "tenant_id", "user_id", "expires_at" },
|
||||
columns: new[] { "realm", "tenant_id", "user_id", "expires_at" },
|
||||
filter: "revoked_at is null");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_sessions_tenant_id",
|
||||
table: "auth_sessions",
|
||||
column: "tenant_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_sessions_token_family_id_revoked_at",
|
||||
table: "auth_sessions",
|
||||
columns: new[] { "token_family_id", "revoked_at" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_auth_sessions_token_hash",
|
||||
table: "auth_sessions",
|
||||
@@ -8609,11 +8708,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
table: "tenant_invoices",
|
||||
columns: new[] { "tenant_id", "status", "due_date" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_memberships_tenant_id_role_template_id",
|
||||
table: "tenant_memberships",
|
||||
columns: new[] { "tenant_id", "role_template_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_memberships_tenant_id_user_id_role",
|
||||
table: "tenant_memberships",
|
||||
@@ -8656,27 +8750,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
table: "tenant_question_references",
|
||||
columns: new[] { "question_owner_tenant_id", "question_id" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_role_templates_created_by",
|
||||
table: "tenant_role_templates",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_role_templates_tenant_id_code",
|
||||
table: "tenant_role_templates",
|
||||
columns: new[] { "tenant_id", "code" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_role_templates_tenant_id_status_sort_order",
|
||||
table: "tenant_role_templates",
|
||||
columns: new[] { "tenant_id", "status", "sort_order" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_role_templates_updated_by",
|
||||
table: "tenant_role_templates",
|
||||
column: "updated_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_tenant_secrets_tenant_id_purpose_provider_secret_key",
|
||||
table: "tenant_secrets",
|
||||
@@ -8850,6 +8923,11 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
table: "user_badges",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_claims_user_id",
|
||||
table: "user_claims",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_identities_provider_provider_subject",
|
||||
table: "user_identities",
|
||||
@@ -8861,6 +8939,11 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
table: "user_identities",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_logins_user_id",
|
||||
table: "user_logins",
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_user_notifications_created_by",
|
||||
table: "user_notifications",
|
||||
@@ -8942,10 +9025,9 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
column: "user_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_users_email",
|
||||
name: "email_index",
|
||||
table: "users",
|
||||
column: "email",
|
||||
unique: true);
|
||||
column: "normalized_email");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_users_legacy_id",
|
||||
@@ -8960,9 +9042,9 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_users_username",
|
||||
name: "user_name_index",
|
||||
table: "users",
|
||||
column: "username",
|
||||
column: "normalized_user_name",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
@@ -9347,6 +9429,9 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "app_assets");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "auth_challenges");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "auth_login_events");
|
||||
|
||||
@@ -9395,6 +9480,9 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "dashboard_daily_stats");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "data_protection_keys");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "entitlements");
|
||||
|
||||
@@ -9578,15 +9666,24 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_badges");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_claims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_identities");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_logins");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_notifications");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_score_events");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_tokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "user_word_favorites");
|
||||
|
||||
@@ -9662,9 +9759,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_backend_roles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_role_templates");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "tenant_classes");
|
||||
|
||||
@@ -25,6 +25,110 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "ltree");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("FriendlyName")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("friendly_name");
|
||||
|
||||
b.Property<string>("Xml")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("xml");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_data_protection_keys");
|
||||
|
||||
b.ToTable("data_protection_keys", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("claim_type");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("claim_value");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_user_claims");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_user_claims_user_id");
|
||||
|
||||
b.ToTable("user_claims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("login_provider");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("provider_key");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("provider_display_name");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey")
|
||||
.HasName("pk_user_logins");
|
||||
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_user_logins_user_id");
|
||||
|
||||
b.ToTable("user_logins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("login_provider");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("value");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name")
|
||||
.HasName("pk_user_tokens");
|
||||
|
||||
b.ToTable("user_tokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Catalog.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -7915,11 +8019,21 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnName("id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("access_failed_count");
|
||||
|
||||
b.Property<string>("AvatarUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)")
|
||||
.HasColumnName("avatar_url");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("concurrency_stamp");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
@@ -7931,6 +8045,14 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("citext")
|
||||
.HasColumnName("email");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("email_confirmed");
|
||||
|
||||
b.Property<bool>("ForcePasswordChange")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("force_password_change");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastSeenAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("last_seen_at");
|
||||
@@ -7940,25 +8062,48 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("legacy_id");
|
||||
|
||||
b.Property<string>("LegacyPasswordHash")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("legacy_password_hash");
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("lockout_enabled");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("lockout_end");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<bool>("PasswordMigrationRequired")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("password_migration_required");
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(320)
|
||||
.HasColumnType("character varying(320)")
|
||||
.HasColumnName("normalized_email");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("normalized_user_name");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnType("character varying(1024)")
|
||||
.HasColumnName("password_hash");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("phone");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("phone_number");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("phone_number_confirmed");
|
||||
|
||||
b.Property<string>("PrimaryRole")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
@@ -7975,36 +8120,50 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("score");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("security_stamp");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("status");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("two_factor_enabled");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("updated_at")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<string>("Username")
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("username");
|
||||
.HasColumnName("user_name");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_users");
|
||||
|
||||
b.HasIndex("Email")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_email");
|
||||
|
||||
b.HasIndex("LegacyId")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_legacy_id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("email_index");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("user_name_index");
|
||||
|
||||
b.HasIndex("Phone")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_phone");
|
||||
|
||||
b.HasIndex("Username")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_username");
|
||||
|
||||
b.ToTable("users", (string)null);
|
||||
});
|
||||
|
||||
@@ -8049,12 +8208,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("character varying(255)")
|
||||
.HasColumnName("provider_subject");
|
||||
|
||||
b.Property<JsonElement>("SecretPayload")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("secret_payload")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("UnionId")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)")
|
||||
@@ -12648,6 +12801,95 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("question_versions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthChallenge", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.Property<DateTimeOffset?>("ConsumedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("consumed_at");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("created_at")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("expires_at");
|
||||
|
||||
b.Property<string>("IpAddress")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("ip_address");
|
||||
|
||||
b.Property<string>("Provider")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)")
|
||||
.HasColumnName("provider");
|
||||
|
||||
b.Property<string>("Purpose")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("purpose");
|
||||
|
||||
b.Property<string>("Realm")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("realm");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("security_stamp");
|
||||
|
||||
b.Property<Guid?>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("tenant_id");
|
||||
|
||||
b.Property<string>("TokenHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)")
|
||||
.HasColumnName("token_hash");
|
||||
|
||||
b.Property<string>("UserAgent")
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnType("character varying(1024)")
|
||||
.HasColumnName("user_agent");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("user_id");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_auth_challenges");
|
||||
|
||||
b.HasIndex("TenantId")
|
||||
.HasDatabaseName("ix_auth_challenges_tenant_id");
|
||||
|
||||
b.HasIndex("TokenHash")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_auth_challenges_token_hash");
|
||||
|
||||
b.HasIndex("UserId", "Purpose", "ExpiresAt")
|
||||
.HasDatabaseName("ix_auth_challenges_user_id_purpose_expires_at");
|
||||
|
||||
b.ToTable("auth_challenges", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("ck_auth_challenges_realm_tenant", "(realm = 'tenant' and tenant_id is not null) or (realm = 'platform' and tenant_id is null)");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthLoginEvent", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -12752,20 +12994,53 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnName("metadata")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<bool>("MfaSatisfied")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("mfa_satisfied");
|
||||
|
||||
b.Property<Guid?>("ParentSessionId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("parent_session_id");
|
||||
|
||||
b.Property<string>("Provider")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)")
|
||||
.HasColumnName("provider");
|
||||
|
||||
b.Property<string>("Realm")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("realm");
|
||||
|
||||
b.Property<Guid?>("ReplacedBySessionId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("replaced_by_session_id");
|
||||
|
||||
b.Property<DateTimeOffset?>("RevokedAt")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("revoked_at");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
b.Property<string>("RevokedReason")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("revoked_reason");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("security_stamp");
|
||||
|
||||
b.Property<Guid?>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("tenant_id");
|
||||
|
||||
b.Property<Guid>("TokenFamilyId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("token_family_id");
|
||||
|
||||
b.Property<string>("TokenHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(256)
|
||||
@@ -12790,8 +13065,8 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_auth_sessions");
|
||||
|
||||
b.HasAlternateKey("TenantId", "Id")
|
||||
.HasName("ak_auth_sessions_tenant_id_id");
|
||||
b.HasIndex("TenantId")
|
||||
.HasDatabaseName("ix_auth_sessions_tenant_id");
|
||||
|
||||
b.HasIndex("TokenHash")
|
||||
.IsUnique()
|
||||
@@ -12801,11 +13076,17 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_auth_sessions_user_id");
|
||||
|
||||
b.HasIndex("TenantId", "UserId", "ExpiresAt")
|
||||
.HasDatabaseName("ix_auth_sessions_tenant_id_user_id_expires_at")
|
||||
b.HasIndex("TokenFamilyId", "RevokedAt")
|
||||
.HasDatabaseName("ix_auth_sessions_token_family_id_revoked_at");
|
||||
|
||||
b.HasIndex("Realm", "TenantId", "UserId", "ExpiresAt")
|
||||
.HasDatabaseName("ix_auth_sessions_realm_tenant_id_user_id_expires_at")
|
||||
.HasFilter("revoked_at is null");
|
||||
|
||||
b.ToTable("auth_sessions", (string)null);
|
||||
b.ToTable("auth_sessions", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("ck_auth_sessions_realm_tenant", "(realm = 'tenant' and tenant_id is not null) or (realm = 'platform' and tenant_id is null)");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.SmsSendRateLimit", b =>
|
||||
@@ -12931,9 +13212,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_sms_verification_codes");
|
||||
|
||||
b.HasAlternateKey("TenantId", "Id")
|
||||
.HasName("ak_sms_verification_codes_tenant_id_id");
|
||||
|
||||
b.HasIndex("TenantId", "Phone", "Purpose")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_sms_verification_codes_tenant_id_phone_purpose")
|
||||
@@ -13623,22 +13901,12 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasColumnType("character varying(50)")
|
||||
.HasColumnName("legacy_role");
|
||||
|
||||
b.Property<JsonElement>("Permissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("role");
|
||||
|
||||
b.Property<Guid?>("RoleTemplateId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("role_template_id");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
@@ -13668,9 +13936,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.HasIndex("UserId")
|
||||
.HasDatabaseName("ix_tenant_memberships_user_id");
|
||||
|
||||
b.HasIndex("TenantId", "RoleTemplateId")
|
||||
.HasDatabaseName("ix_tenant_memberships_tenant_id_role_template_id");
|
||||
|
||||
b.HasIndex("TenantId", "UserId", "Role")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_tenant_memberships_tenant_id_user_id_role");
|
||||
@@ -13678,126 +13943,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("tenant_memberships", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.TenantRoleTemplate", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.Property<string>("BaseRole")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("base_role");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("code");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("created_at")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid?>("CreatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("created_by");
|
||||
|
||||
b.Property<JsonElement>("DataScope")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("data_scope")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("description");
|
||||
|
||||
b.Property<JsonElement>("FieldPermissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("field_permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<bool>("IsSystem")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("is_system");
|
||||
|
||||
b.Property<JsonElement>("MenuPermissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("menu_permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<JsonElement>("ModulePermissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("module_permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)")
|
||||
.HasColumnName("name");
|
||||
|
||||
b.Property<JsonElement>("Permissions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("permissions")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("sort_order");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("status");
|
||||
|
||||
b.Property<Guid>("TenantId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("tenant_id");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("updated_at")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid?>("UpdatedBy")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("updated_by");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_tenant_role_templates");
|
||||
|
||||
b.HasAlternateKey("TenantId", "Id")
|
||||
.HasName("ak_tenant_role_templates_tenant_id_id");
|
||||
|
||||
b.HasIndex("CreatedBy")
|
||||
.HasDatabaseName("ix_tenant_role_templates_created_by");
|
||||
|
||||
b.HasIndex("UpdatedBy")
|
||||
.HasDatabaseName("ix_tenant_role_templates_updated_by");
|
||||
|
||||
b.HasIndex("TenantId", "Code")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_tenant_role_templates_tenant_id_code");
|
||||
|
||||
b.HasIndex("TenantId", "Status", "SortOrder")
|
||||
.HasDatabaseName("ix_tenant_role_templates_tenant_id_status_sort_order");
|
||||
|
||||
b.ToTable("tenant_role_templates", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.TenantSecret", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -14153,6 +14298,36 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
b.ToTable("tenant_student_notes", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_user_claims_users_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_user_logins_users_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_user_tokens_users_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Catalog.Category", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Tenancy.Tenant", null)
|
||||
@@ -17204,12 +17379,28 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.HasConstraintName("fk_question_versions_questions_tenant_id_question_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthLoginEvent", b =>
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthChallenge", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Tenancy.Tenant", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.HasConstraintName("fk_auth_challenges_tenants_tenant_id");
|
||||
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_auth_challenges_users_user_id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.AuthLoginEvent", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Tenancy.Tenant", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_auth_login_events_tenants_tenant_id");
|
||||
|
||||
@@ -17226,7 +17417,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_auth_sessions_tenants_tenant_id");
|
||||
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
@@ -17375,35 +17565,6 @@ namespace Tiku.Infrastructure.Persistence.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_tenant_memberships_users_user_id");
|
||||
|
||||
b.HasOne("Tiku.Domain.Tenancy.TenantRoleTemplate", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId", "RoleTemplateId")
|
||||
.HasPrincipalKey("TenantId", "Id")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.HasConstraintName("fk_tenant_memberships_tenant_role_templates_tenant_id_role_tem~");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.TenantRoleTemplate", b =>
|
||||
{
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CreatedBy")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("fk_tenant_role_templates_users_created_by");
|
||||
|
||||
b.HasOne("Tiku.Domain.Tenancy.Tenant", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TenantId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired()
|
||||
.HasConstraintName("fk_tenant_role_templates_tenants_tenant_id");
|
||||
|
||||
b.HasOne("Tiku.Domain.Identity.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UpdatedBy")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.HasConstraintName("fk_tenant_role_templates_users_updated_by");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Tiku.Domain.Tenancy.TenantSecret", b =>
|
||||
|
||||
Reference in New Issue
Block a user