From d6c37784e1e6462aaf514532f619d4265c26af99 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Tue, 21 Oct 2025 23:45:36 +0800 Subject: [PATCH] :recycle: Move the realm service from sphere to the pass --- .../Identity/BotAccountController.cs | 4 +- .../Identity/BotAccountService.cs | 4 +- DysonNetwork.Pass/AppDatabase.cs | 11 + ...51021153439_AddRealmFromSphere.Designer.cs | 2677 +++++++++++++++++ .../20251021153439_AddRealmFromSphere.cs | 160 + .../Migrations/AppDatabaseModelSnapshot.cs | 318 ++ .../Realm/RealmController.cs | 52 +- .../Realm/RealmService.cs | 33 +- DysonNetwork.Pass/Realm/RealmServiceGrpc.cs | 140 + .../Startup/ApplicationConfiguration.cs | 2 + .../Startup/ServiceCollectionExtensions.cs | 2 + DysonNetwork.Shared/Models/ChatRoom.cs | 2 +- DysonNetwork.Shared/Models/Post.cs | 2 +- DysonNetwork.Shared/Models/Realm.cs | 62 +- DysonNetwork.Shared/Proto/realm.proto | 84 + ...lientHelper.cs => RemoteAccountService.cs} | 2 +- .../Registry/RemoteRealmService.cs | 60 + .../Registry/ServiceInjectionHelper.cs | 24 +- .../Activity/ActivityService.cs | 6 +- DysonNetwork.Sphere/AppDatabase.cs | 22 +- .../Autocompletion/AutocompletionService.cs | 4 +- .../Chat/ChatRoomController.cs | 42 +- DysonNetwork.Sphere/Chat/ChatRoomService.cs | 6 +- .../{Realm => Chat}/RealmChatController.cs | 15 +- ...54500_ChangeRealmReferenceMode.Designer.cs | 2130 +++++++++++++ ...20251021154500_ChangeRealmReferenceMode.cs | 89 + .../Migrations/AppDatabaseModelSnapshot.cs | 732 +++-- DysonNetwork.Sphere/Poll/PollController.cs | 4 +- DysonNetwork.Sphere/Post/PostController.cs | 24 +- DysonNetwork.Sphere/Post/PostService.cs | 2 +- .../Publisher/PublisherService.cs | 6 +- .../Startup/BroadcastEventHandler.cs | 4 - .../Startup/ServiceCollectionExtensions.cs | 5 +- 33 files changed, 6220 insertions(+), 510 deletions(-) create mode 100644 DysonNetwork.Pass/Migrations/20251021153439_AddRealmFromSphere.Designer.cs create mode 100644 DysonNetwork.Pass/Migrations/20251021153439_AddRealmFromSphere.cs rename {DysonNetwork.Sphere => DysonNetwork.Pass}/Realm/RealmController.cs (92%) rename {DysonNetwork.Sphere => DysonNetwork.Pass}/Realm/RealmService.cs (73%) create mode 100644 DysonNetwork.Pass/Realm/RealmServiceGrpc.cs create mode 100644 DysonNetwork.Shared/Proto/realm.proto rename DysonNetwork.Shared/Registry/{AccountClientHelper.cs => RemoteAccountService.cs} (96%) create mode 100644 DysonNetwork.Shared/Registry/RemoteRealmService.cs rename DysonNetwork.Sphere/{Realm => Chat}/RealmChatController.cs (62%) create mode 100644 DysonNetwork.Sphere/Migrations/20251021154500_ChangeRealmReferenceMode.Designer.cs create mode 100644 DysonNetwork.Sphere/Migrations/20251021154500_ChangeRealmReferenceMode.cs diff --git a/DysonNetwork.Develop/Identity/BotAccountController.cs b/DysonNetwork.Develop/Identity/BotAccountController.cs index 01b0d02..f6e9922 100644 --- a/DysonNetwork.Develop/Identity/BotAccountController.cs +++ b/DysonNetwork.Develop/Identity/BotAccountController.cs @@ -19,7 +19,7 @@ public class BotAccountController( DeveloperService ds, DevProjectService projectService, ILogger logger, - AccountClientHelper accounts, + RemoteAccountService remoteAccounts, BotAccountReceiverService.BotAccountReceiverServiceClient accountsReceiver ) : ControllerBase @@ -222,7 +222,7 @@ public class BotAccountController( if (bot is null || bot.ProjectId != projectId) return NotFound("Bot not found"); - var botAccount = await accounts.GetBotAccount(bot.Id); + var botAccount = await remoteAccounts.GetBotAccount(bot.Id); if (request.Name is not null) botAccount.Name = request.Name; if (request.Nick is not null) botAccount.Nick = request.Nick; diff --git a/DysonNetwork.Develop/Identity/BotAccountService.cs b/DysonNetwork.Develop/Identity/BotAccountService.cs index 7087ac7..8a9ed8d 100644 --- a/DysonNetwork.Develop/Identity/BotAccountService.cs +++ b/DysonNetwork.Develop/Identity/BotAccountService.cs @@ -10,7 +10,7 @@ namespace DysonNetwork.Develop.Identity; public class BotAccountService( AppDatabase db, BotAccountReceiverService.BotAccountReceiverServiceClient accountReceiver, - AccountClientHelper accounts + RemoteAccountService remoteAccounts ) { public async Task GetBotByIdAsync(Guid id) @@ -158,7 +158,7 @@ public class BotAccountService( public async Task> LoadBotsAccountAsync(List bots) { var automatedIds = bots.Select(b => b.Id).ToList(); - var data = await accounts.GetBotAccountBatch(automatedIds); + var data = await remoteAccounts.GetBotAccountBatch(automatedIds); foreach (var bot in bots) { diff --git a/DysonNetwork.Pass/AppDatabase.cs b/DysonNetwork.Pass/AppDatabase.cs index faa9126..042941f 100644 --- a/DysonNetwork.Pass/AppDatabase.cs +++ b/DysonNetwork.Pass/AppDatabase.cs @@ -38,6 +38,9 @@ public class AppDatabase( public DbSet AuthChallenges { get; set; } = null!; public DbSet AuthClients { get; set; } = null!; public DbSet ApiKeys { get; set; } = null!; + + public DbSet Realms { get; set; } = null!; + public DbSet RealmMembers { get; set; } = null!; public DbSet Wallets { get; set; } = null!; public DbSet WalletPockets { get; set; } = null!; @@ -127,6 +130,14 @@ public class AppDatabase( .HasOne(r => r.Related) .WithMany(a => a.IncomingRelationships) .HasForeignKey(r => r.RelatedId); + + modelBuilder.Entity() + .HasKey(pm => new { pm.RealmId, pm.AccountId }); + modelBuilder.Entity() + .HasOne(pm => pm.Realm) + .WithMany(p => p.Members) + .HasForeignKey(pm => pm.RealmId) + .OnDelete(DeleteBehavior.Cascade); // Automatically apply soft-delete filter to all entities inheriting BaseModel foreach (var entityType in modelBuilder.Model.GetEntityTypes()) diff --git a/DysonNetwork.Pass/Migrations/20251021153439_AddRealmFromSphere.Designer.cs b/DysonNetwork.Pass/Migrations/20251021153439_AddRealmFromSphere.Designer.cs new file mode 100644 index 0000000..c9e0877 --- /dev/null +++ b/DysonNetwork.Pass/Migrations/20251021153439_AddRealmFromSphere.Designer.cs @@ -0,0 +1,2677 @@ +// +using System; +using System.Collections.Generic; +using System.Text.Json; +using DysonNetwork.Pass; +using DysonNetwork.Shared.GeoIp; +using DysonNetwork.Shared.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NodaTime; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace DysonNetwork.Pass.Migrations +{ + [DbContext(typeof(AppDatabase))] + [Migration("20251021153439_AddRealmFromSphere")] + partial class AddRealmFromSphere + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAbuseReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("reason"); + + b.Property("Resolution") + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("resolution"); + + b.Property("ResolvedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("resolved_at"); + + b.Property("ResourceIdentifier") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("resource_identifier"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_abuse_reports"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_abuse_reports_account_id"); + + b.ToTable("abuse_reports", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ActivatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("activated_at"); + + b.Property("AutomatedId") + .HasColumnType("uuid") + .HasColumnName("automated_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsSuperuser") + .HasColumnType("boolean") + .HasColumnName("is_superuser"); + + b.Property("Language") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("language"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("name"); + + b.Property("Nick") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("nick"); + + b.Property("Region") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("region"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_accounts"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_accounts_name"); + + b.ToTable("accounts", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountAuthFactor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property>("Config") + .HasColumnType("jsonb") + .HasColumnName("config"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("EnabledAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("enabled_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Secret") + .HasMaxLength(8196) + .HasColumnType("character varying(8196)") + .HasColumnName("secret"); + + b.Property("Trustworthy") + .HasColumnType("integer") + .HasColumnName("trustworthy"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_auth_factors"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_auth_factors_account_id"); + + b.ToTable("account_auth_factors", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountBadge", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("ActivatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("activated_at"); + + b.Property("Caption") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("caption"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Label") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("label"); + + b.Property>("Meta") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_badges"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_badges_account_id"); + + b.ToTable("badges", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccessToken") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("access_token"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("LastUsedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_used_at"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("ProvidedIdentifier") + .IsRequired() + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("provided_identifier"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("provider"); + + b.Property("RefreshToken") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("refresh_token"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_connections"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_connections_account_id"); + + b.ToTable("account_connections", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountContact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("content"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsPrimary") + .HasColumnType("boolean") + .HasColumnName("is_primary"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("VerifiedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("verified_at"); + + b.HasKey("Id") + .HasName("pk_account_contacts"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_contacts_account_id"); + + b.ToTable("account_contacts", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("ActiveBadge") + .HasColumnType("jsonb") + .HasColumnName("active_badge"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("Bio") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("bio"); + + b.Property("Birthday") + .HasColumnType("timestamp with time zone") + .HasColumnName("birthday"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Experience") + .HasColumnType("integer") + .HasColumnName("experience"); + + b.Property("FirstName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("first_name"); + + b.Property("Gender") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("gender"); + + b.Property("LastName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("last_name"); + + b.Property("LastSeenAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_at"); + + b.Property>("Links") + .HasColumnType("jsonb") + .HasColumnName("links"); + + b.Property("Location") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("location"); + + b.Property("MiddleName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("middle_name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("Pronouns") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("pronouns"); + + b.Property("SocialCredits") + .HasColumnType("double precision") + .HasColumnName("social_credits"); + + b.Property("TimeZone") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("time_zone"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UsernameColor") + .HasColumnType("jsonb") + .HasColumnName("username_color"); + + b.Property("Verification") + .HasColumnType("jsonb") + .HasColumnName("verification"); + + b.HasKey("Id") + .HasName("pk_account_profiles"); + + b.HasIndex("AccountId") + .IsUnique() + .HasDatabaseName("ix_account_profiles_account_id"); + + b.ToTable("account_profiles", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property>("BlockedPermissions") + .HasColumnType("jsonb") + .HasColumnName("blocked_permissions"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("reason"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_punishments"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_punishments_account_id"); + + b.ToTable("punishments", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountRelationship", b => + { + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("RelatedId") + .HasColumnType("uuid") + .HasColumnName("related_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Status") + .HasColumnType("smallint") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("AccountId", "RelatedId") + .HasName("pk_account_relationships"); + + b.HasIndex("RelatedId") + .HasDatabaseName("ix_account_relationships_related_id"); + + b.ToTable("account_relationships", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("AppIdentifier") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("app_identifier"); + + b.Property("Attitude") + .HasColumnType("integer") + .HasColumnName("attitude"); + + b.Property("ClearedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("cleared_at"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsAutomated") + .HasColumnType("boolean") + .HasColumnName("is_automated"); + + b.Property("IsInvisible") + .HasColumnType("boolean") + .HasColumnName("is_invisible"); + + b.Property("IsNotDisturb") + .HasColumnType("boolean") + .HasColumnName("is_not_disturb"); + + b.Property("Label") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("label"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_statuses"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_statuses_account_id"); + + b.ToTable("account_statuses", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnActionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Action") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("action"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IpAddress") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ip_address"); + + b.Property("Location") + .HasColumnType("jsonb") + .HasColumnName("location"); + + b.Property>("Meta") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("session_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserAgent") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("user_agent"); + + b.HasKey("Id") + .HasName("pk_action_logs"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_action_logs_account_id"); + + b.ToTable("action_logs", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnApiKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("label"); + + b.Property("SessionId") + .HasColumnType("uuid") + .HasColumnName("session_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_api_keys"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_api_keys_account_id"); + + b.HasIndex("SessionId") + .HasDatabaseName("ix_api_keys_session_id"); + + b.ToTable("api_keys", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthChallenge", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property>("Audiences") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("audiences"); + + b.Property>("BlacklistFactors") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("blacklist_factors"); + + b.Property("ClientId") + .HasColumnType("uuid") + .HasColumnName("client_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("FailedAttempts") + .HasColumnType("integer") + .HasColumnName("failed_attempts"); + + b.Property("IpAddress") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ip_address"); + + b.Property("Location") + .HasColumnType("jsonb") + .HasColumnName("location"); + + b.Property("Nonce") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("nonce"); + + b.Property>("Scopes") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("scopes"); + + b.Property("StepRemain") + .HasColumnType("integer") + .HasColumnName("step_remain"); + + b.Property("StepTotal") + .HasColumnType("integer") + .HasColumnName("step_total"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserAgent") + .HasMaxLength(512) + .HasColumnType("character varying(512)") + .HasColumnName("user_agent"); + + b.HasKey("Id") + .HasName("pk_auth_challenges"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_auth_challenges_account_id"); + + b.HasIndex("ClientId") + .HasDatabaseName("ix_auth_challenges_client_id"); + + b.ToTable("auth_challenges", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthClient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeviceId") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("device_id"); + + b.Property("DeviceLabel") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("device_label"); + + b.Property("DeviceName") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("device_name"); + + b.Property("Platform") + .HasColumnType("integer") + .HasColumnName("platform"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_auth_clients"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_auth_clients_account_id"); + + b.ToTable("auth_clients", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthSession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("AppId") + .HasColumnType("uuid") + .HasColumnName("app_id"); + + b.Property("ChallengeId") + .HasColumnType("uuid") + .HasColumnName("challenge_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("LastGrantedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_granted_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_auth_sessions"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_auth_sessions_account_id"); + + b.HasIndex("ChallengeId") + .HasDatabaseName("ix_auth_sessions_challenge_id"); + + b.ToTable("auth_sessions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMember", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BreakUntil") + .HasColumnType("timestamp with time zone") + .HasColumnName("break_until"); + + b.Property("ChatRoomId") + .HasColumnType("uuid") + .HasColumnName("chat_room_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsBot") + .HasColumnType("boolean") + .HasColumnName("is_bot"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joined_at"); + + b.Property("LastReadAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_at"); + + b.Property("LeaveAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("leave_at"); + + b.Property("Nick") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("nick"); + + b.Property("Notify") + .HasColumnType("integer") + .HasColumnName("notify"); + + b.Property("Role") + .HasColumnType("integer") + .HasColumnName("role"); + + b.Property("TimeoutCause") + .HasColumnType("jsonb") + .HasColumnName("timeout_cause"); + + b.Property("TimeoutUntil") + .HasColumnType("timestamp with time zone") + .HasColumnName("timeout_until"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_sn_chat_member"); + + b.HasIndex("ChatRoomId") + .HasDatabaseName("ix_sn_chat_member_chat_room_id"); + + b.ToTable("sn_chat_member", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("IsCommunity") + .HasColumnType("boolean") + .HasColumnName("is_community"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Name") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("SnRealmId") + .HasColumnType("uuid") + .HasColumnName("sn_realm_id"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_sn_chat_room"); + + b.HasIndex("SnRealmId") + .HasDatabaseName("ix_sn_chat_room_sn_realm_id"); + + b.ToTable("sn_chat_room", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnCheckInResult", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BackdatedFrom") + .HasColumnType("timestamp with time zone") + .HasColumnName("backdated_from"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("RewardExperience") + .HasColumnType("integer") + .HasColumnName("reward_experience"); + + b.Property("RewardPoints") + .HasColumnType("numeric") + .HasColumnName("reward_points"); + + b.Property>("Tips") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("tips"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_check_in_results"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_account_check_in_results_account_id"); + + b.ToTable("account_check_in_results", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnExperienceRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BonusMultiplier") + .HasColumnType("double precision") + .HasColumnName("bonus_multiplier"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Delta") + .HasColumnType("bigint") + .HasColumnName("delta"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("reason"); + + b.Property("ReasonType") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("reason_type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_experience_records"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_experience_records_account_id"); + + b.ToTable("experience_records", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnMagicSpell", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("AffectedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("affected_at"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property>("Meta") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("Spell") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("spell"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_magic_spells"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_magic_spells_account_id"); + + b.HasIndex("Spell") + .IsUnique() + .HasDatabaseName("ix_magic_spells_spell"); + + b.ToTable("magic_spells", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("key"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_permission_groups"); + + b.ToTable("permission_groups", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroupMember", b => + { + b.Property("GroupId") + .HasColumnType("uuid") + .HasColumnName("group_id"); + + b.Property("Actor") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("actor"); + + b.Property("AffectedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("affected_at"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("GroupId", "Actor") + .HasName("pk_permission_group_members"); + + b.ToTable("permission_group_members", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionNode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Actor") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("actor"); + + b.Property("AffectedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("affected_at"); + + b.Property("Area") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("area"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("GroupId") + .HasColumnType("uuid") + .HasColumnName("group_id"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("key"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Value") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("value"); + + b.HasKey("Id") + .HasName("pk_permission_nodes"); + + b.HasIndex("GroupId") + .HasDatabaseName("ix_permission_nodes_group_id"); + + b.HasIndex("Key", "Area", "Actor") + .HasDatabaseName("ix_permission_nodes_key_area_actor"); + + b.ToTable("permission_nodes", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("IsCommunity") + .HasColumnType("boolean") + .HasColumnName("is_community"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("slug"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Verification") + .HasColumnType("jsonb") + .HasColumnName("verification"); + + b.HasKey("Id") + .HasName("pk_realms"); + + b.HasIndex("Slug") + .IsUnique() + .HasDatabaseName("ix_realms_slug"); + + b.ToTable("realms", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joined_at"); + + b.Property("LeaveAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("leave_at"); + + b.Property("Role") + .HasColumnType("integer") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("RealmId", "AccountId") + .HasName("pk_realm_members"); + + b.ToTable("realm_members", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSocialCreditRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Delta") + .HasColumnType("double precision") + .HasColumnName("delta"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("reason"); + + b.Property("ReasonType") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("reason_type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_social_credit_records"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_social_credit_records_account_id"); + + b.ToTable("social_credit_records", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWallet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallets"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_wallets_account_id"); + + b.ToTable("wallets", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletCoupon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AffectedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("affected_at"); + + b.Property("Code") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("code"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DiscountAmount") + .HasColumnType("numeric") + .HasColumnName("discount_amount"); + + b.Property("DiscountRate") + .HasColumnType("double precision") + .HasColumnName("discount_rate"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Identifier") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("identifier"); + + b.Property("MaxUsage") + .HasColumnType("integer") + .HasColumnName("max_usage"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_coupons"); + + b.ToTable("wallet_coupons", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFund", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatorAccountId") + .HasColumnType("uuid") + .HasColumnName("creator_account_id"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("currency"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Message") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("SplitType") + .HasColumnType("integer") + .HasColumnName("split_type"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("TotalAmount") + .HasColumnType("numeric") + .HasColumnName("total_amount"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_funds"); + + b.HasIndex("CreatorAccountId") + .HasDatabaseName("ix_wallet_funds_creator_account_id"); + + b.ToTable("wallet_funds", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFundRecipient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("FundId") + .HasColumnType("uuid") + .HasColumnName("fund_id"); + + b.Property("IsReceived") + .HasColumnType("boolean") + .HasColumnName("is_received"); + + b.Property("ReceivedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("received_at"); + + b.Property("RecipientAccountId") + .HasColumnType("uuid") + .HasColumnName("recipient_account_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_fund_recipients"); + + b.HasIndex("FundId") + .HasDatabaseName("ix_wallet_fund_recipients_fund_id"); + + b.HasIndex("RecipientAccountId") + .HasDatabaseName("ix_wallet_fund_recipients_recipient_account_id"); + + b.ToTable("wallet_fund_recipients", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletGift", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("BasePrice") + .HasColumnType("numeric") + .HasColumnName("base_price"); + + b.Property("CouponId") + .HasColumnType("uuid") + .HasColumnName("coupon_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("FinalPrice") + .HasColumnType("numeric") + .HasColumnName("final_price"); + + b.Property("GiftCode") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("gift_code"); + + b.Property("GifterId") + .HasColumnType("uuid") + .HasColumnName("gifter_id"); + + b.Property("IsOpenGift") + .HasColumnType("boolean") + .HasColumnName("is_open_gift"); + + b.Property("Message") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)") + .HasColumnName("message"); + + b.Property("PaymentDetails") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payment_details"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("payment_method"); + + b.Property("RecipientId") + .HasColumnType("uuid") + .HasColumnName("recipient_id"); + + b.Property("RedeemedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("redeemed_at"); + + b.Property("RedeemerId") + .HasColumnType("uuid") + .HasColumnName("redeemer_id"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("SubscriptionId") + .HasColumnType("uuid") + .HasColumnName("subscription_id"); + + b.Property("SubscriptionIdentifier") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("subscription_identifier"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_gifts"); + + b.HasIndex("CouponId") + .HasDatabaseName("ix_wallet_gifts_coupon_id"); + + b.HasIndex("GiftCode") + .HasDatabaseName("ix_wallet_gifts_gift_code"); + + b.HasIndex("GifterId") + .HasDatabaseName("ix_wallet_gifts_gifter_id"); + + b.HasIndex("RecipientId") + .HasDatabaseName("ix_wallet_gifts_recipient_id"); + + b.HasIndex("RedeemerId") + .HasDatabaseName("ix_wallet_gifts_redeemer_id"); + + b.HasIndex("SubscriptionId") + .IsUnique() + .HasDatabaseName("ix_wallet_gifts_subscription_id"); + + b.ToTable("wallet_gifts", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("AppIdentifier") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("app_identifier"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("currency"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("PayeeWalletId") + .HasColumnType("uuid") + .HasColumnName("payee_wallet_id"); + + b.Property("ProductIdentifier") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("product_identifier"); + + b.Property("Remarks") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("remarks"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("TransactionId") + .HasColumnType("uuid") + .HasColumnName("transaction_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_payment_orders"); + + b.HasIndex("PayeeWalletId") + .HasDatabaseName("ix_payment_orders_payee_wallet_id"); + + b.HasIndex("TransactionId") + .HasDatabaseName("ix_payment_orders_transaction_id"); + + b.ToTable("payment_orders", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletPocket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("currency"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("WalletId") + .HasColumnType("uuid") + .HasColumnName("wallet_id"); + + b.HasKey("Id") + .HasName("pk_wallet_pockets"); + + b.HasIndex("WalletId") + .HasDatabaseName("ix_wallet_pockets_wallet_id"); + + b.ToTable("wallet_pockets", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BasePrice") + .HasColumnType("numeric") + .HasColumnName("base_price"); + + b.Property("BegunAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("begun_at"); + + b.Property("CouponId") + .HasColumnType("uuid") + .HasColumnName("coupon_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("EndedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("ended_at"); + + b.Property("Identifier") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("identifier"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("is_active"); + + b.Property("IsFreeTrial") + .HasColumnType("boolean") + .HasColumnName("is_free_trial"); + + b.Property("PaymentDetails") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payment_details"); + + b.Property("PaymentMethod") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("payment_method"); + + b.Property("RenewalAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("renewal_at"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_wallet_subscriptions"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_wallet_subscriptions_account_id"); + + b.HasIndex("CouponId") + .HasDatabaseName("ix_wallet_subscriptions_coupon_id"); + + b.HasIndex("Identifier") + .HasDatabaseName("ix_wallet_subscriptions_identifier"); + + b.HasIndex("Status") + .HasDatabaseName("ix_wallet_subscriptions_status"); + + b.HasIndex("AccountId", "Identifier") + .HasDatabaseName("ix_wallet_subscriptions_account_id_identifier"); + + b.HasIndex("AccountId", "IsActive") + .HasDatabaseName("ix_wallet_subscriptions_account_id_is_active"); + + b.ToTable("wallet_subscriptions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("currency"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("PayeeWalletId") + .HasColumnType("uuid") + .HasColumnName("payee_wallet_id"); + + b.Property("PayerWalletId") + .HasColumnType("uuid") + .HasColumnName("payer_wallet_id"); + + b.Property("Remarks") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("remarks"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_payment_transactions"); + + b.HasIndex("PayeeWalletId") + .HasDatabaseName("ix_payment_transactions_payee_wallet_id"); + + b.HasIndex("PayerWalletId") + .HasDatabaseName("ix_payment_transactions_payer_wallet_id"); + + b.ToTable("payment_transactions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAbuseReport", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_abuse_reports_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountAuthFactor", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("AuthFactors") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_auth_factors_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountBadge", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Badges") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_badges_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountConnection", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Connections") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_connections_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountContact", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Contacts") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_contacts_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountProfile", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithOne("Profile") + .HasForeignKey("DysonNetwork.Shared.Models.SnAccountProfile", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_profiles_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountPunishment", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_punishments_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountRelationship", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("OutgoingRelationships") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_relationships_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Related") + .WithMany("IncomingRelationships") + .HasForeignKey("RelatedId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_relationships_accounts_related_id"); + + b.Navigation("Account"); + + b.Navigation("Related"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccountStatus", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_statuses_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnActionLog", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_action_logs_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnApiKey", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_keys_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAuthSession", "Session") + .WithMany() + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_api_keys_auth_sessions_session_id"); + + b.Navigation("Account"); + + b.Navigation("Session"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthChallenge", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Challenges") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_challenges_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAuthClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .HasConstraintName("fk_auth_challenges_auth_clients_client_id"); + + b.Navigation("Account"); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthClient", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_clients_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAuthSession", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany("Sessions") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_sessions_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAuthChallenge", "Challenge") + .WithMany() + .HasForeignKey("ChallengeId") + .HasConstraintName("fk_auth_sessions_auth_challenges_challenge_id"); + + b.Navigation("Account"); + + b.Navigation("Challenge"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnChatRoom", "ChatRoom") + .WithMany("Members") + .HasForeignKey("ChatRoomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_sn_chat_member_sn_chat_room_chat_room_id"); + + b.Navigation("ChatRoom"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", null) + .WithMany("ChatRooms") + .HasForeignKey("SnRealmId") + .HasConstraintName("fk_sn_chat_room_realms_sn_realm_id"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnCheckInResult", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_check_in_results_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnExperienceRecord", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_experience_records_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnMagicSpell", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .HasConstraintName("fk_magic_spells_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroupMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPermissionGroup", "Group") + .WithMany("Members") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_permission_group_members_permission_groups_group_id"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionNode", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPermissionGroup", "Group") + .WithMany("Nodes") + .HasForeignKey("GroupId") + .HasConstraintName("fk_permission_nodes_permission_groups_group_id"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", "Realm") + .WithMany("Members") + .HasForeignKey("RealmId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_realm_members_realms_realm_id"); + + b.Navigation("Realm"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSocialCreditRecord", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_social_credit_records_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWallet", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallets_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFund", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "CreatorAccount") + .WithMany() + .HasForeignKey("CreatorAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_funds_accounts_creator_account_id"); + + b.Navigation("CreatorAccount"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFundRecipient", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWalletFund", "Fund") + .WithMany("Recipients") + .HasForeignKey("FundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_fund_recipients_wallet_funds_fund_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "RecipientAccount") + .WithMany() + .HasForeignKey("RecipientAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_fund_recipients_accounts_recipient_account_id"); + + b.Navigation("Fund"); + + b.Navigation("RecipientAccount"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletGift", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWalletCoupon", "Coupon") + .WithMany() + .HasForeignKey("CouponId") + .HasConstraintName("fk_wallet_gifts_wallet_coupons_coupon_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Gifter") + .WithMany() + .HasForeignKey("GifterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_gifts_accounts_gifter_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Recipient") + .WithMany() + .HasForeignKey("RecipientId") + .HasConstraintName("fk_wallet_gifts_accounts_recipient_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Redeemer") + .WithMany() + .HasForeignKey("RedeemerId") + .HasConstraintName("fk_wallet_gifts_accounts_redeemer_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnWalletSubscription", "Subscription") + .WithOne("Gift") + .HasForeignKey("DysonNetwork.Shared.Models.SnWalletGift", "SubscriptionId") + .HasConstraintName("fk_wallet_gifts_wallet_subscriptions_subscription_id"); + + b.Navigation("Coupon"); + + b.Navigation("Gifter"); + + b.Navigation("Recipient"); + + b.Navigation("Redeemer"); + + b.Navigation("Subscription"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletOrder", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWallet", "PayeeWallet") + .WithMany() + .HasForeignKey("PayeeWalletId") + .HasConstraintName("fk_payment_orders_wallets_payee_wallet_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnWalletTransaction", "Transaction") + .WithMany() + .HasForeignKey("TransactionId") + .HasConstraintName("fk_payment_orders_payment_transactions_transaction_id"); + + b.Navigation("PayeeWallet"); + + b.Navigation("Transaction"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletPocket", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWallet", "Wallet") + .WithMany("Pockets") + .HasForeignKey("WalletId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_pockets_wallets_wallet_id"); + + b.Navigation("Wallet"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletSubscription", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_wallet_subscriptions_accounts_account_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnWalletCoupon", "Coupon") + .WithMany() + .HasForeignKey("CouponId") + .HasConstraintName("fk_wallet_subscriptions_wallet_coupons_coupon_id"); + + b.Navigation("Account"); + + b.Navigation("Coupon"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletTransaction", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnWallet", "PayeeWallet") + .WithMany() + .HasForeignKey("PayeeWalletId") + .HasConstraintName("fk_payment_transactions_wallets_payee_wallet_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnWallet", "PayerWallet") + .WithMany() + .HasForeignKey("PayerWalletId") + .HasConstraintName("fk_payment_transactions_wallets_payer_wallet_id"); + + b.Navigation("PayeeWallet"); + + b.Navigation("PayerWallet"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnAccount", b => + { + b.Navigation("AuthFactors"); + + b.Navigation("Badges"); + + b.Navigation("Challenges"); + + b.Navigation("Connections"); + + b.Navigation("Contacts"); + + b.Navigation("IncomingRelationships"); + + b.Navigation("OutgoingRelationships"); + + b.Navigation("Profile") + .IsRequired(); + + b.Navigation("Sessions"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroup", b => + { + b.Navigation("Members"); + + b.Navigation("Nodes"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => + { + b.Navigation("ChatRooms"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWallet", b => + { + b.Navigation("Pockets"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletFund", b => + { + b.Navigation("Recipients"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWalletSubscription", b => + { + b.Navigation("Gift"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DysonNetwork.Pass/Migrations/20251021153439_AddRealmFromSphere.cs b/DysonNetwork.Pass/Migrations/20251021153439_AddRealmFromSphere.cs new file mode 100644 index 0000000..2fa7220 --- /dev/null +++ b/DysonNetwork.Pass/Migrations/20251021153439_AddRealmFromSphere.cs @@ -0,0 +1,160 @@ +using System; +using DysonNetwork.Shared.Models; +using Microsoft.EntityFrameworkCore.Migrations; +using NodaTime; + +#nullable disable + +namespace DysonNetwork.Pass.Migrations +{ + /// + public partial class AddRealmFromSphere : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "realms", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + slug = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), + name = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: false), + description = table.Column(type: "character varying(4096)", maxLength: 4096, nullable: false), + is_community = table.Column(type: "boolean", nullable: false), + is_public = table.Column(type: "boolean", nullable: false), + picture_id = table.Column(type: "character varying(32)", maxLength: 32, nullable: true), + background_id = table.Column(type: "character varying(32)", maxLength: 32, nullable: true), + picture = table.Column(type: "jsonb", nullable: true), + background = table.Column(type: "jsonb", nullable: true), + verification = table.Column(type: "jsonb", nullable: true), + account_id = table.Column(type: "uuid", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: false), + deleted_at = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_realms", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "realm_members", + columns: table => new + { + realm_id = table.Column(type: "uuid", nullable: false), + account_id = table.Column(type: "uuid", nullable: false), + role = table.Column(type: "integer", nullable: false), + joined_at = table.Column(type: "timestamp with time zone", nullable: true), + leave_at = table.Column(type: "timestamp with time zone", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: false), + deleted_at = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_realm_members", x => new { x.realm_id, x.account_id }); + table.ForeignKey( + name: "fk_realm_members_realms_realm_id", + column: x => x.realm_id, + principalTable: "realms", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "sn_chat_room", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + name = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + description = table.Column(type: "character varying(4096)", maxLength: 4096, nullable: true), + type = table.Column(type: "integer", nullable: false), + is_community = table.Column(type: "boolean", nullable: false), + is_public = table.Column(type: "boolean", nullable: false), + picture_id = table.Column(type: "character varying(32)", maxLength: 32, nullable: true), + background_id = table.Column(type: "character varying(32)", maxLength: 32, nullable: true), + picture = table.Column(type: "jsonb", nullable: true), + background = table.Column(type: "jsonb", nullable: true), + realm_id = table.Column(type: "uuid", nullable: true), + sn_realm_id = table.Column(type: "uuid", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: false), + deleted_at = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_sn_chat_room", x => x.id); + table.ForeignKey( + name: "fk_sn_chat_room_realms_sn_realm_id", + column: x => x.sn_realm_id, + principalTable: "realms", + principalColumn: "id"); + }); + + migrationBuilder.CreateTable( + name: "sn_chat_member", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + chat_room_id = table.Column(type: "uuid", nullable: false), + account_id = table.Column(type: "uuid", nullable: false), + nick = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + role = table.Column(type: "integer", nullable: false), + notify = table.Column(type: "integer", nullable: false), + last_read_at = table.Column(type: "timestamp with time zone", nullable: true), + joined_at = table.Column(type: "timestamp with time zone", nullable: true), + leave_at = table.Column(type: "timestamp with time zone", nullable: true), + is_bot = table.Column(type: "boolean", nullable: false), + break_until = table.Column(type: "timestamp with time zone", nullable: true), + timeout_until = table.Column(type: "timestamp with time zone", nullable: true), + timeout_cause = table.Column(type: "jsonb", nullable: true), + created_at = table.Column(type: "timestamp with time zone", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: false), + deleted_at = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_sn_chat_member", x => x.id); + table.ForeignKey( + name: "fk_sn_chat_member_sn_chat_room_chat_room_id", + column: x => x.chat_room_id, + principalTable: "sn_chat_room", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "ix_realms_slug", + table: "realms", + column: "slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "ix_sn_chat_member_chat_room_id", + table: "sn_chat_member", + column: "chat_room_id"); + + migrationBuilder.CreateIndex( + name: "ix_sn_chat_room_sn_realm_id", + table: "sn_chat_room", + column: "sn_realm_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "realm_members"); + + migrationBuilder.DropTable( + name: "sn_chat_member"); + + migrationBuilder.DropTable( + name: "sn_chat_room"); + + migrationBuilder.DropTable( + name: "realms"); + } + } +} diff --git a/DysonNetwork.Pass/Migrations/AppDatabaseModelSnapshot.cs b/DysonNetwork.Pass/Migrations/AppDatabaseModelSnapshot.cs index 099d5ea..6cceb78 100644 --- a/DysonNetwork.Pass/Migrations/AppDatabaseModelSnapshot.cs +++ b/DysonNetwork.Pass/Migrations/AppDatabaseModelSnapshot.cs @@ -954,6 +954,159 @@ namespace DysonNetwork.Pass.Migrations b.ToTable("auth_sessions", (string)null); }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMember", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BreakUntil") + .HasColumnType("timestamp with time zone") + .HasColumnName("break_until"); + + b.Property("ChatRoomId") + .HasColumnType("uuid") + .HasColumnName("chat_room_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsBot") + .HasColumnType("boolean") + .HasColumnName("is_bot"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joined_at"); + + b.Property("LastReadAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_at"); + + b.Property("LeaveAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("leave_at"); + + b.Property("Nick") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("nick"); + + b.Property("Notify") + .HasColumnType("integer") + .HasColumnName("notify"); + + b.Property("Role") + .HasColumnType("integer") + .HasColumnName("role"); + + b.Property("TimeoutCause") + .HasColumnType("jsonb") + .HasColumnName("timeout_cause"); + + b.Property("TimeoutUntil") + .HasColumnType("timestamp with time zone") + .HasColumnName("timeout_until"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_sn_chat_member"); + + b.HasIndex("ChatRoomId") + .HasDatabaseName("ix_sn_chat_member_chat_room_id"); + + b.ToTable("sn_chat_member", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("IsCommunity") + .HasColumnType("boolean") + .HasColumnName("is_community"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Name") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("SnRealmId") + .HasColumnType("uuid") + .HasColumnName("sn_realm_id"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_sn_chat_room"); + + b.HasIndex("SnRealmId") + .HasDatabaseName("ix_sn_chat_room_sn_realm_id"); + + b.ToTable("sn_chat_room", (string)null); + }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnCheckInResult", b => { b.Property("Id") @@ -1252,6 +1405,127 @@ namespace DysonNetwork.Pass.Migrations b.ToTable("permission_nodes", (string)null); }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("IsCommunity") + .HasColumnType("boolean") + .HasColumnName("is_community"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("slug"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Verification") + .HasColumnType("jsonb") + .HasColumnName("verification"); + + b.HasKey("Id") + .HasName("pk_realms"); + + b.HasIndex("Slug") + .IsUnique() + .HasDatabaseName("ix_realms_slug"); + + b.ToTable("realms", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joined_at"); + + b.Property("LeaveAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("leave_at"); + + b.Property("Role") + .HasColumnType("integer") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("RealmId", "AccountId") + .HasName("pk_realm_members"); + + b.ToTable("realm_members", (string)null); + }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSocialCreditRecord", b => { b.Property("Id") @@ -2089,6 +2363,26 @@ namespace DysonNetwork.Pass.Migrations b.Navigation("Challenge"); }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnChatRoom", "ChatRoom") + .WithMany("Members") + .HasForeignKey("ChatRoomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_sn_chat_member_sn_chat_room_chat_room_id"); + + b.Navigation("ChatRoom"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", null) + .WithMany("ChatRooms") + .HasForeignKey("SnRealmId") + .HasConstraintName("fk_sn_chat_room_realms_sn_realm_id"); + }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnCheckInResult", b => { b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") @@ -2145,6 +2439,18 @@ namespace DysonNetwork.Pass.Migrations b.Navigation("Group"); }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", "Realm") + .WithMany("Members") + .HasForeignKey("RealmId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_realm_members_realms_realm_id"); + + b.Navigation("Realm"); + }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSocialCreditRecord", b => { b.HasOne("DysonNetwork.Shared.Models.SnAccount", "Account") @@ -2329,6 +2635,11 @@ namespace DysonNetwork.Pass.Migrations b.Navigation("Sessions"); }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.Navigation("Members"); + }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPermissionGroup", b => { b.Navigation("Members"); @@ -2336,6 +2647,13 @@ namespace DysonNetwork.Pass.Migrations b.Navigation("Nodes"); }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => + { + b.Navigation("ChatRooms"); + + b.Navigation("Members"); + }); + modelBuilder.Entity("DysonNetwork.Shared.Models.SnWallet", b => { b.Navigation("Pockets"); diff --git a/DysonNetwork.Sphere/Realm/RealmController.cs b/DysonNetwork.Pass/Realm/RealmController.cs similarity index 92% rename from DysonNetwork.Sphere/Realm/RealmController.cs rename to DysonNetwork.Pass/Realm/RealmController.cs index 6e37b5e..b1df29a 100644 --- a/DysonNetwork.Sphere/Realm/RealmController.cs +++ b/DysonNetwork.Pass/Realm/RealmController.cs @@ -1,14 +1,14 @@ using System.ComponentModel.DataAnnotations; +using DysonNetwork.Shared.Models; using DysonNetwork.Shared.Proto; using DysonNetwork.Shared.Registry; +using Google.Protobuf.WellKnownTypes; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using NodaTime; -using Google.Protobuf.WellKnownTypes; -using DysonNetwork.Shared.Models; -namespace DysonNetwork.Sphere.Realm; +namespace DysonNetwork.Pass.Realm; [ApiController] [Route("/api/realms")] @@ -19,7 +19,7 @@ public class RealmController( FileReferenceService.FileReferenceServiceClient fileRefs, ActionLogService.ActionLogServiceClient als, AccountService.AccountServiceClient accounts, - AccountClientHelper accountsHelper + RemoteAccountService remoteAccountsHelper ) : Controller { [HttpGet("{slug}")] @@ -37,7 +37,7 @@ public class RealmController( [Authorize] public async Task>> ListJoinedRealms() { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var accountId = Guid.Parse(currentUser.Id); var members = await db.RealmMembers @@ -54,7 +54,7 @@ public class RealmController( [Authorize] public async Task>> ListInvites() { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var accountId = Guid.Parse(currentUser.Id); var members = await db.RealmMembers @@ -77,7 +77,7 @@ public class RealmController( public async Task> InviteMember(string slug, [FromBody] RealmMemberRequest request) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var accountId = Guid.Parse(currentUser.Id); var relatedUser = @@ -168,7 +168,7 @@ public class RealmController( [Authorize] public async Task> AcceptMemberInvite(string slug) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var accountId = Guid.Parse(currentUser.Id); var member = await db.RealmMembers @@ -202,7 +202,7 @@ public class RealmController( [Authorize] public async Task DeclineMemberInvite(string slug) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var accountId = Guid.Parse(currentUser.Id); var member = await db.RealmMembers @@ -248,7 +248,7 @@ public class RealmController( if (!realm.IsPublic) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); if (!await rs.IsMemberWithRole(realm.Id, Guid.Parse(currentUser.Id), RealmMemberRole.Normal)) return StatusCode(403, "You must be a member to view this realm's members."); } @@ -263,7 +263,7 @@ public class RealmController( .OrderBy(m => m.JoinedAt) .ToListAsync(); - var memberStatuses = await accountsHelper.GetAccountStatusBatch( + var memberStatuses = await remoteAccountsHelper.GetAccountStatusBatch( members.Select(m => m.AccountId).ToList() ); @@ -306,7 +306,7 @@ public class RealmController( [Authorize] public async Task> GetCurrentIdentity(string slug) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var accountId = Guid.Parse(currentUser.Id); var member = await db.RealmMembers @@ -323,7 +323,7 @@ public class RealmController( [Authorize] public async Task LeaveRealm(string slug) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var accountId = Guid.Parse(currentUser.Id); var member = await db.RealmMembers @@ -371,7 +371,7 @@ public class RealmController( [Authorize] public async Task> CreateRealm(RealmRequest request) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); if (string.IsNullOrWhiteSpace(request.Name)) return BadRequest("You cannot create a realm without a name."); if (string.IsNullOrWhiteSpace(request.Slug)) return BadRequest("You cannot create a realm without a slug."); @@ -459,7 +459,7 @@ public class RealmController( [Authorize] public async Task> Update(string slug, [FromBody] RealmRequest request) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var realm = await db.Realms .Where(r => r.Slug == slug) @@ -568,7 +568,7 @@ public class RealmController( [Authorize] public async Task> JoinRealm(string slug) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var realm = await db.Realms .Where(r => r.Slug == slug) @@ -641,7 +641,7 @@ public class RealmController( [Authorize] public async Task RemoveMember(string slug, Guid memberId) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var realm = await db.Realms .Where(r => r.Slug == slug) @@ -681,7 +681,7 @@ public class RealmController( public async Task> UpdateMemberRole(string slug, Guid memberId, [FromBody] int newRole) { if (newRole >= RealmMemberRole.Owner) return BadRequest("Unable to set realm member to owner or greater role."); - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var realm = await db.Realms .Where(r => r.Slug == slug) @@ -723,7 +723,7 @@ public class RealmController( [Authorize] public async Task Delete(string slug) { - if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized(); + if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized(); var transaction = await db.Database.BeginTransactionAsync(); @@ -737,11 +737,6 @@ public class RealmController( try { - var chats = await db.ChatRooms - .Where(c => c.RealmId == realm.Id) - .Select(c => c.Id) - .ToListAsync(); - db.Realms.Remove(realm); await db.SaveChangesAsync(); @@ -749,15 +744,6 @@ public class RealmController( await db.RealmMembers .Where(m => m.RealmId == realm.Id) .ExecuteUpdateAsync(m => m.SetProperty(m => m.DeletedAt, now)); - await db.ChatRooms - .Where(c => c.RealmId == realm.Id) - .ExecuteUpdateAsync(c => c.SetProperty(c => c.DeletedAt, now)); - await db.ChatMessages - .Where(m => chats.Contains(m.ChatRoomId)) - .ExecuteUpdateAsync(m => m.SetProperty(m => m.DeletedAt, now)); - await db.ChatMembers - .Where(m => chats.Contains(m.ChatRoomId)) - .ExecuteUpdateAsync(m => m.SetProperty(m => m.DeletedAt, now)); await db.SaveChangesAsync(); await transaction.CommitAsync(); } diff --git a/DysonNetwork.Sphere/Realm/RealmService.cs b/DysonNetwork.Pass/Realm/RealmService.cs similarity index 73% rename from DysonNetwork.Sphere/Realm/RealmService.cs rename to DysonNetwork.Pass/Realm/RealmService.cs index 495fa16..73f8340 100644 --- a/DysonNetwork.Sphere/Realm/RealmService.cs +++ b/DysonNetwork.Pass/Realm/RealmService.cs @@ -1,20 +1,18 @@ +using DysonNetwork.Pass.Localization; using DysonNetwork.Shared; using DysonNetwork.Shared.Cache; using DysonNetwork.Shared.Models; using DysonNetwork.Shared.Proto; using DysonNetwork.Shared.Registry; -using DysonNetwork.Sphere.Localization; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Localization; -namespace DysonNetwork.Sphere.Realm; +namespace DysonNetwork.Pass.Realm; public class RealmService( AppDatabase db, RingService.RingServiceClient pusher, - AccountService.AccountServiceClient accounts, IStringLocalizer localizer, - AccountClientHelper accountsHelper, ICacheService cache ) { @@ -42,13 +40,18 @@ public class RealmService( public async Task SendInviteNotify(SnRealmMember member) { - var account = await accounts.GetAccountAsync(new GetAccountRequest { Id = member.AccountId.ToString() }); - CultureService.SetCultureInfo(account); + var account = await db.Accounts + .Include(a => a.Profile) + .FirstOrDefaultAsync(a => a.Id == member.AccountId); + + if (account == null) throw new InvalidOperationException("Account not found"); + + CultureService.SetCultureInfo(account.Language); await pusher.SendPushNotificationToUserAsync( new SendPushNotificationToUserRequest { - UserId = account.Id, + UserId = account.Id.ToString(), Notification = new PushNotification { Topic = "invites.realms", @@ -75,20 +78,26 @@ public class RealmService( public async Task LoadMemberAccount(SnRealmMember member) { - var account = await accountsHelper.GetAccount(member.AccountId); - member.Account = SnAccount.FromProtoValue(account); + var account = await db.Accounts + .Include(a => a.Profile) + .FirstOrDefaultAsync(a => a.Id == member.AccountId); + if (account != null) + member.Account = account; return member; } public async Task> LoadMemberAccounts(ICollection members) { var accountIds = members.Select(m => m.AccountId).ToList(); - var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a); + var accountsDict = await db.Accounts + .Include(a => a.Profile) + .Where(a => accountIds.Contains(a.Id)) + .ToDictionaryAsync(a => a.Id, a => a); return members.Select(m => { - if (accounts.TryGetValue(m.AccountId, out var account)) - m.Account = SnAccount.FromProtoValue(account); + if (accountsDict.TryGetValue(m.AccountId, out var account)) + m.Account = account; return m; }).ToList(); } diff --git a/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs b/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs new file mode 100644 index 0000000..2880a14 --- /dev/null +++ b/DysonNetwork.Pass/Realm/RealmServiceGrpc.cs @@ -0,0 +1,140 @@ +using DysonNetwork.Shared.Proto; +using Google.Protobuf.WellKnownTypes; +using Grpc.Core; +using Microsoft.EntityFrameworkCore; +using DysonNetwork.Pass.Localization; +using DysonNetwork.Shared; +using DysonNetwork.Shared.Cache; +using Microsoft.Extensions.Localization; + +namespace DysonNetwork.Pass.Realm; + +public class RealmServiceGrpc( + AppDatabase db, + RingService.RingServiceClient pusher, + IStringLocalizer localizer, + ICacheService cache +) + : Shared.Proto.RealmService.RealmServiceBase +{ + private const string CacheKeyPrefix = "account:realms:"; + + public override async Task GetRealm(GetRealmRequest request, ServerCallContext context) + { + var realm = request.QueryCase switch + { + GetRealmRequest.QueryOneofCase.Id when !string.IsNullOrWhiteSpace(request.Id) => await db.Realms.FindAsync( + Guid.Parse(request.Id)), + GetRealmRequest.QueryOneofCase.Slug when !string.IsNullOrWhiteSpace(request.Slug) => await db.Realms + .FirstOrDefaultAsync(r => r.Slug == request.Slug), + _ => throw new RpcException(new Status(StatusCode.InvalidArgument, "Must provide either id or slug")) + }; + + return realm == null + ? throw new RpcException(new Status(StatusCode.NotFound, "Realm not found")) + : realm.ToProtoValue(); + } + + public override async Task GetUserRealms(GetUserRealmsRequest request, + ServerCallContext context) + { + var accountId = Guid.Parse(request.AccountId); + var cacheKey = $"{CacheKeyPrefix}{accountId}"; + var (found, cachedRealms) = await cache.GetAsyncWithStatus>(cacheKey); + if (found && cachedRealms != null) + return new GetUserRealmsResponse { RealmIds = { cachedRealms.Select(g => g.ToString()) } }; + + var realms = await db.RealmMembers + .Include(m => m.Realm) + .Where(m => m.AccountId == accountId) + .Where(m => m.JoinedAt != null && m.LeaveAt == null) + .Select(m => m.Realm!.Id) + .ToListAsync(); + + // Cache the result for 5 minutes + await cache.SetAsync(cacheKey, realms, TimeSpan.FromMinutes(5)); + + return new GetUserRealmsResponse { RealmIds = { realms.Select(g => g.ToString()) } }; + } + + public override async Task SendInviteNotify(SendInviteNotifyRequest request, ServerCallContext context) + { + var member = request.Member; + var account = await db.Accounts + .AsNoTracking() + .Include(a => a.Profile) + .FirstOrDefaultAsync(a => a.Id == Guid.Parse(member.AccountId)); + + if (account == null) throw new RpcException(new Status(StatusCode.NotFound, "Account not found")); + + CultureService.SetCultureInfo(account.Language); + + await pusher.SendPushNotificationToUserAsync( + new SendPushNotificationToUserRequest + { + UserId = account.Id.ToString(), + Notification = new PushNotification + { + Topic = "invites.realms", + Title = localizer["RealmInviteTitle"], + Body = localizer["RealmInviteBody", member.Realm?.Name ?? "Unknown Realm"], + ActionUri = "/realms", + IsSavable = true + } + } + ); + + return new Empty(); + } + + public override async Task IsMemberWithRole(IsMemberWithRoleRequest request, ServerCallContext context) + { + if (request.RequiredRoles.Count == 0) + return new BoolValue { Value = false }; + + var maxRequiredRole = request.RequiredRoles.Max(); + var member = await db.RealmMembers + .Where(m => m.RealmId == Guid.Parse(request.RealmId) && m.AccountId == Guid.Parse(request.AccountId) && + m.JoinedAt != null && m.LeaveAt == null) + .FirstOrDefaultAsync(); + return new BoolValue { Value = member?.Role >= maxRequiredRole }; + } + + public override async Task LoadMemberAccount(LoadMemberAccountRequest request, + ServerCallContext context) + { + var member = request.Member; + var account = await db.Accounts + .AsNoTracking() + .Include(a => a.Profile) + .FirstOrDefaultAsync(a => a.Id == Guid.Parse(member.AccountId)); + + var response = new RealmMember(member) { Account = account?.ToProtoValue() }; + return response; + } + + public override async Task LoadMemberAccounts(LoadMemberAccountsRequest request, + ServerCallContext context) + { + var accountIds = request.Members.Select(m => Guid.Parse(m.AccountId)).ToList(); + var accounts = await db.Accounts + .AsNoTracking() + .Include(a => a.Profile) + .Where(a => accountIds.Contains(a.Id)) + .ToDictionaryAsync(a => a.Id, a => a.ToProtoValue()); + + var response = new LoadMemberAccountsResponse(); + foreach (var member in request.Members) + { + var updatedMember = new RealmMember(member); + if (accounts.TryGetValue(Guid.Parse(member.AccountId), out var account)) + { + updatedMember.Account = account; + } + + response.Members.Add(updatedMember); + } + + return response; + } +} diff --git a/DysonNetwork.Pass/Startup/ApplicationConfiguration.cs b/DysonNetwork.Pass/Startup/ApplicationConfiguration.cs index 668e1f7..b29cac0 100644 --- a/DysonNetwork.Pass/Startup/ApplicationConfiguration.cs +++ b/DysonNetwork.Pass/Startup/ApplicationConfiguration.cs @@ -3,6 +3,7 @@ using DysonNetwork.Pass.Auth; using DysonNetwork.Pass.Credit; using DysonNetwork.Pass.Leveling; using DysonNetwork.Pass.Permission; +using DysonNetwork.Pass.Realm; using DysonNetwork.Pass.Wallet; using DysonNetwork.Shared.Http; using Prometheus; @@ -42,6 +43,7 @@ public static class ApplicationConfiguration app.MapGrpcService(); app.MapGrpcService(); app.MapGrpcService(); + app.MapGrpcService(); return app; } diff --git a/DysonNetwork.Pass/Startup/ServiceCollectionExtensions.cs b/DysonNetwork.Pass/Startup/ServiceCollectionExtensions.cs index 7872daa..b26029e 100644 --- a/DysonNetwork.Pass/Startup/ServiceCollectionExtensions.cs +++ b/DysonNetwork.Pass/Startup/ServiceCollectionExtensions.cs @@ -17,6 +17,7 @@ using DysonNetwork.Pass.Credit; using DysonNetwork.Pass.Handlers; using DysonNetwork.Pass.Leveling; using DysonNetwork.Pass.Mailer; +using DysonNetwork.Pass.Realm; using DysonNetwork.Pass.Safety; using DysonNetwork.Pass.Wallet.PaymentHandlers; using DysonNetwork.Shared.Cache; @@ -152,6 +153,7 @@ public static class ServiceCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.Configure(configuration.GetSection("OidcProvider")); services.AddScoped(); diff --git a/DysonNetwork.Shared/Models/ChatRoom.cs b/DysonNetwork.Shared/Models/ChatRoom.cs index 40a9a57..85188cb 100644 --- a/DysonNetwork.Shared/Models/ChatRoom.cs +++ b/DysonNetwork.Shared/Models/ChatRoom.cs @@ -30,7 +30,7 @@ public class SnChatRoom : ModelBase, IIdentifiedResource [JsonIgnore] public ICollection Members { get; set; } = new List(); public Guid? RealmId { get; set; } - public SnRealm? Realm { get; set; } + [NotMapped] public SnRealm? Realm { get; set; } [NotMapped] [JsonPropertyName("members")] diff --git a/DysonNetwork.Shared/Models/Post.cs b/DysonNetwork.Shared/Models/Post.cs index fa3f13d..10b0d1e 100644 --- a/DysonNetwork.Shared/Models/Post.cs +++ b/DysonNetwork.Shared/Models/Post.cs @@ -64,7 +64,7 @@ public class SnPost : ModelBase, IIdentifiedResource, IActivity public SnPost? ForwardedPost { get; set; } public Guid? RealmId { get; set; } - public SnRealm? Realm { get; set; } + [NotMapped] public SnRealm? Realm { get; set; } [Column(TypeName = "jsonb")] public List Attachments { get; set; } = []; diff --git a/DysonNetwork.Shared/Models/Realm.cs b/DysonNetwork.Shared/Models/Realm.cs index 59e968e..049f16e 100644 --- a/DysonNetwork.Shared/Models/Realm.cs +++ b/DysonNetwork.Shared/Models/Realm.cs @@ -1,8 +1,10 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; +using DysonNetwork.Shared.Proto; using Microsoft.EntityFrameworkCore; using NodaTime; +using NodaTime.Serialization.Protobuf; namespace DysonNetwork.Shared.Models; @@ -31,6 +33,28 @@ public class SnRealm : ModelBase, IIdentifiedResource public Guid AccountId { get; set; } public string ResourceIdentifier => $"realm:{Id}"; + + public Realm ToProtoValue() + { + return new Realm + { + Id = Id.ToString(), + Name = Name + }; + } + + public static SnRealm FromProtoValue(Realm proto) + { + return new SnRealm + { + Id = Guid.Parse(proto.Id), + Name = proto.Name, + Slug = "", // Required but not in proto + Description = "", + IsCommunity = false, + IsPublic = false + }; + } } public abstract class RealmMemberRole @@ -51,4 +75,40 @@ public class SnRealmMember : ModelBase public int Role { get; set; } = RealmMemberRole.Normal; public Instant? JoinedAt { get; set; } public Instant? LeaveAt { get; set; } -} \ No newline at end of file + + public Proto.RealmMember ToProtoValue() + { + var proto = new Proto.RealmMember + { + AccountId = AccountId.ToString(), + RealmId = RealmId.ToString(), + Role = Role, + JoinedAt = JoinedAt?.ToTimestamp(), + LeaveAt = LeaveAt?.ToTimestamp(), + Realm = Realm.ToProtoValue() + }; + if (Account != null) + { + proto.Account = Account.ToProtoValue(); + } + return proto; + } + + public static SnRealmMember FromProtoValue(RealmMember proto) + { + var member = new SnRealmMember + { + AccountId = Guid.Parse(proto.AccountId), + RealmId = Guid.Parse(proto.RealmId), + Role = proto.Role, + JoinedAt = proto.JoinedAt?.ToInstant(), + LeaveAt = proto.LeaveAt?.ToInstant(), + Realm = proto.Realm != null ? SnRealm.FromProtoValue(proto.Realm) : new SnRealm() // Provide default or handle null + }; + if (proto.Account != null) + { + member.Account = SnAccount.FromProtoValue(proto.Account); + } + return member; + } +} diff --git a/DysonNetwork.Shared/Proto/realm.proto b/DysonNetwork.Shared/Proto/realm.proto new file mode 100644 index 0000000..2418873 --- /dev/null +++ b/DysonNetwork.Shared/Proto/realm.proto @@ -0,0 +1,84 @@ +syntax = "proto3"; + +package proto; + +option csharp_namespace = "DysonNetwork.Shared.Proto"; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/empty.proto"; + +import 'account.proto'; + +// Message Definitions + +message Realm { + string id = 1; + string name = 2; +} + +message RealmMember { + string account_id = 1; + string realm_id = 2; + int32 role = 3; + optional google.protobuf.Timestamp joined_at = 4; + optional google.protobuf.Timestamp leave_at = 5; + optional Account account = 6; + optional Realm realm = 7; +} + +// Service Definitions + +service RealmService { + // Get realm by id or slug + rpc GetRealm(GetRealmRequest) returns (Realm) {} + // Get realms for a user + rpc GetUserRealms(GetUserRealmsRequest) returns (GetUserRealmsResponse) {} + // Send invitation notification + rpc SendInviteNotify(SendInviteNotifyRequest) returns (google.protobuf.Empty) {} + // Check if member has required role + rpc IsMemberWithRole(IsMemberWithRoleRequest) returns (google.protobuf.BoolValue) {} + // Load account for a member + rpc LoadMemberAccount(LoadMemberAccountRequest) returns (RealmMember) {} + // Load accounts for members + rpc LoadMemberAccounts(LoadMemberAccountsRequest) returns (LoadMemberAccountsResponse) {} +} + +// Request/Response Messages + +message GetRealmRequest { + oneof query { + string id = 1; + string slug = 2; + } +} + +message GetUserRealmsRequest { + string account_id = 1; +} + +message GetUserRealmsResponse { + repeated string realm_ids = 1; +} + +message SendInviteNotifyRequest { + RealmMember member = 1; +} + +message IsMemberWithRoleRequest { + string realm_id = 1; + string account_id = 2; + repeated int32 required_roles = 3; +} + +message LoadMemberAccountRequest { + RealmMember member = 1; +} + +message LoadMemberAccountsRequest { + repeated RealmMember members = 1; +} + +message LoadMemberAccountsResponse { + repeated RealmMember members = 1; +} diff --git a/DysonNetwork.Shared/Registry/AccountClientHelper.cs b/DysonNetwork.Shared/Registry/RemoteAccountService.cs similarity index 96% rename from DysonNetwork.Shared/Registry/AccountClientHelper.cs rename to DysonNetwork.Shared/Registry/RemoteAccountService.cs index 7c3899b..9c8e811 100644 --- a/DysonNetwork.Shared/Registry/AccountClientHelper.cs +++ b/DysonNetwork.Shared/Registry/RemoteAccountService.cs @@ -3,7 +3,7 @@ using DysonNetwork.Shared.Proto; namespace DysonNetwork.Shared.Registry; -public class AccountClientHelper(AccountService.AccountServiceClient accounts) +public class RemoteAccountService(AccountService.AccountServiceClient accounts) { public async Task GetAccount(Guid id) { diff --git a/DysonNetwork.Shared/Registry/RemoteRealmService.cs b/DysonNetwork.Shared/Registry/RemoteRealmService.cs new file mode 100644 index 0000000..15ca7b1 --- /dev/null +++ b/DysonNetwork.Shared/Registry/RemoteRealmService.cs @@ -0,0 +1,60 @@ +using DysonNetwork.Shared.Models; +using DysonNetwork.Shared.Proto; + +namespace DysonNetwork.Shared.Registry; + +public class RemoteRealmService(RealmService.RealmServiceClient realms) +{ + public async Task GetRealm(string id) + { + var request = new GetRealmRequest { Id = id }; + var response = await realms.GetRealmAsync(request); + return SnRealm.FromProtoValue(response); + } + + public async Task GetRealmBySlug(string slug) + { + var request = new GetRealmRequest { Slug = slug }; + var response = await realms.GetRealmAsync(request); + return SnRealm.FromProtoValue(response); + } + + public async Task> GetUserRealms(Guid accountId) + { + var request = new GetUserRealmsRequest { AccountId = accountId.ToString() }; + var response = await realms.GetUserRealmsAsync(request); + return response.RealmIds.Select(Guid.Parse).ToList(); + } + + public async Task SendInviteNotify(SnRealmMember member) + { + var protoMember = member.ToProtoValue(); + var request = new SendInviteNotifyRequest { Member = protoMember }; + await realms.SendInviteNotifyAsync(request); + } + + public async Task IsMemberWithRole(Guid realmId, Guid accountId, List requiredRoles) + { + var request = new IsMemberWithRoleRequest { RealmId = realmId.ToString(), AccountId = accountId.ToString() }; + request.RequiredRoles.AddRange(requiredRoles); + var response = await realms.IsMemberWithRoleAsync(request); + return response.Value; + } + + public async Task LoadMemberAccount(SnRealmMember member) + { + var protoMember = member.ToProtoValue(); + var request = new LoadMemberAccountRequest { Member = protoMember }; + var response = await realms.LoadMemberAccountAsync(request); + return SnRealmMember.FromProtoValue(response); + } + + public async Task> LoadMemberAccounts(List members) + { + var protoMembers = members.Select(m => m.ToProtoValue()).ToList(); + var request = new LoadMemberAccountsRequest(); + request.Members.AddRange(protoMembers); + var response = await realms.LoadMemberAccountsAsync(request); + return response.Members.Select(SnRealmMember.FromProtoValue).ToList(); + } +} diff --git a/DysonNetwork.Shared/Registry/ServiceInjectionHelper.cs b/DysonNetwork.Shared/Registry/ServiceInjectionHelper.cs index bd7441a..6b13a8c 100644 --- a/DysonNetwork.Shared/Registry/ServiceInjectionHelper.cs +++ b/DysonNetwork.Shared/Registry/ServiceInjectionHelper.cs @@ -36,11 +36,11 @@ public static class ServiceInjectionHelper public static IServiceCollection AddAccountService(this IServiceCollection services) { services - .AddGrpcClient(o => o.Address = new Uri("https://_grpc.pass") ) + .AddGrpcClient(o => o.Address = new Uri("https://_grpc.pass")) .ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler() { ServerCertificateCustomValidationCallback = (_, _, _, _) => true } ); - services.AddSingleton(); + services.AddSingleton(); services .AddGrpcClient(o => @@ -59,10 +59,17 @@ public static class ServiceInjectionHelper .ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler() { ServerCertificateCustomValidationCallback = (_, _, _, _) => true } ); + + services + .AddGrpcClient(o => o.Address = new Uri("https://_grpc.pass")) + .ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler() + { ServerCertificateCustomValidationCallback = (_, _, _, _) => true } + ); + services.AddSingleton(); return services; } - + public static IServiceCollection AddDriveService(this IServiceCollection services) { services.AddGrpcClient(o => o.Address = new Uri("https://_grpc.drive")) @@ -70,7 +77,8 @@ public static class ServiceInjectionHelper { ServerCertificateCustomValidationCallback = (_, _, _, _) => true } ); - services.AddGrpcClient(o => o.Address = new Uri("https://_grpc.drive")) + services.AddGrpcClient(o => + o.Address = new Uri("https://_grpc.drive")) .ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler() { ServerCertificateCustomValidationCallback = (_, _, _, _) => true } ); @@ -80,7 +88,8 @@ public static class ServiceInjectionHelper public static IServiceCollection AddPublisherService(this IServiceCollection services) { - services.AddGrpcClient(o => o.Address = new Uri("https://_grpc.sphere")) + services + .AddGrpcClient(o => o.Address = new Uri("https://_grpc.sphere")) .ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler() { ServerCertificateCustomValidationCallback = (_, _, _, _) => true } ); @@ -90,11 +99,12 @@ public static class ServiceInjectionHelper public static IServiceCollection AddDevelopService(this IServiceCollection services) { - services.AddGrpcClient(o => o.Address = new Uri("https://_grpc.develop")) + services.AddGrpcClient(o => + o.Address = new Uri("https://_grpc.develop")) .ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler() { ServerCertificateCustomValidationCallback = (_, _, _, _) => true } ); return services; } -} \ No newline at end of file +} diff --git a/DysonNetwork.Sphere/Activity/ActivityService.cs b/DysonNetwork.Sphere/Activity/ActivityService.cs index 0e90a16..4f4fa80 100644 --- a/DysonNetwork.Sphere/Activity/ActivityService.cs +++ b/DysonNetwork.Sphere/Activity/ActivityService.cs @@ -1,8 +1,8 @@ using DysonNetwork.Shared.Models; using DysonNetwork.Shared.Proto; +using DysonNetwork.Shared.Registry; using DysonNetwork.Sphere.Discovery; using DysonNetwork.Sphere.Post; -using DysonNetwork.Sphere.Realm; using DysonNetwork.Sphere.WebReader; using Microsoft.EntityFrameworkCore; using NodaTime; @@ -13,7 +13,7 @@ public class ActivityService( AppDatabase db, Publisher.PublisherService pub, PostService ps, - RealmService rs, + RemoteRealmService rs, DiscoveryService ds, AccountService.AccountServiceClient accounts ) @@ -345,4 +345,4 @@ public class ActivityService( var postCount = posts.Count; return score + postCount; } -} \ No newline at end of file +} diff --git a/DysonNetwork.Sphere/AppDatabase.cs b/DysonNetwork.Sphere/AppDatabase.cs index 8710cae..e09f936 100644 --- a/DysonNetwork.Sphere/AppDatabase.cs +++ b/DysonNetwork.Sphere/AppDatabase.cs @@ -1,6 +1,7 @@ using System.Linq.Expressions; using System.Reflection; using DysonNetwork.Shared.Models; +using DysonNetwork.Sphere.WebReader; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Query; @@ -24,6 +25,10 @@ public class AppDatabase( public DbSet PublisherSubscriptions { get; set; } = null!; public DbSet PublisherFeatures { get; set; } = null!; + // TODO Remove the realms table after the data migration is done + public DbSet Realms { get; set; } = null!; + public DbSet RealmMembers { get; set; } = null!; + public DbSet Posts { get; set; } = null!; public DbSet PostReactions { get; set; } = null!; public DbSet PostAwards { get; set; } = null!; @@ -33,26 +38,23 @@ public class AppDatabase( public DbSet PostFeaturedRecords { get; set; } = null!; public DbSet PostCategorySubscriptions { get; set; } = null!; - public DbSet Polls { get; set; } = null!; + public DbSet Polls { get; set; } = null!; public DbSet PollQuestions { get; set; } = null!; public DbSet PollAnswers { get; set; } = null!; - public DbSet Realms { get; set; } = null!; - public DbSet RealmMembers { get; set; } = null!; - public DbSet ChatRooms { get; set; } = null!; public DbSet ChatMembers { get; set; } = null!; public DbSet ChatMessages { get; set; } = null!; public DbSet ChatRealtimeCall { get; set; } = null!; public DbSet ChatReactions { get; set; } = null!; - public DbSet Stickers { get; set; } = null!; + public DbSet Stickers { get; set; } = null!; public DbSet StickerPacks { get; set; } = null!; public DbSet StickerPackOwnerships { get; set; } = null!; - public DbSet WebArticles { get; set; } = null!; - public DbSet WebFeeds { get; set; } = null!; - public DbSet WebFeedSubscriptions { get; set; } = null!; + public DbSet WebArticles { get; set; } = null!; + public DbSet WebFeeds { get; set; } = null!; + public DbSet WebFeedSubscriptions { get; set; } = null!; protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { @@ -150,10 +152,10 @@ public class AppDatabase( .HasForeignKey(m => m.SenderId) .OnDelete(DeleteBehavior.Cascade); - modelBuilder.Entity() + modelBuilder.Entity() .HasIndex(f => f.Url) .IsUnique(); - modelBuilder.Entity() + modelBuilder.Entity() .HasIndex(a => a.Url) .IsUnique(); diff --git a/DysonNetwork.Sphere/Autocompletion/AutocompletionService.cs b/DysonNetwork.Sphere/Autocompletion/AutocompletionService.cs index 1da9380..0f9cdda 100644 --- a/DysonNetwork.Sphere/Autocompletion/AutocompletionService.cs +++ b/DysonNetwork.Sphere/Autocompletion/AutocompletionService.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore; namespace DysonNetwork.Sphere.Autocompletion; -public class AutocompletionService(AppDatabase db, AccountClientHelper accountsHelper) +public class AutocompletionService(AppDatabase db, RemoteAccountService remoteAccountsHelper) { public async Task> GetAutocompletion(string content, Guid? chatId = null, Guid? realmId = null, int limit = 10) { @@ -47,7 +47,7 @@ public class AutocompletionService(AppDatabase db, AccountClientHelper accountsH switch (type) { case "u": - var allAccounts = await accountsHelper.SearchAccounts(query); + var allAccounts = await remoteAccountsHelper.SearchAccounts(query); var filteredAccounts = allAccounts; if (chatId.HasValue) diff --git a/DysonNetwork.Sphere/Chat/ChatRoomController.cs b/DysonNetwork.Sphere/Chat/ChatRoomController.cs index ca97691..0e689e8 100644 --- a/DysonNetwork.Sphere/Chat/ChatRoomController.cs +++ b/DysonNetwork.Sphere/Chat/ChatRoomController.cs @@ -6,7 +6,7 @@ using DysonNetwork.Shared.Auth; using DysonNetwork.Shared.Proto; using DysonNetwork.Shared.Registry; using DysonNetwork.Sphere.Localization; -using DysonNetwork.Sphere.Realm; + using Grpc.Core; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Localization; @@ -20,14 +20,14 @@ namespace DysonNetwork.Sphere.Chat; public class ChatRoomController( AppDatabase db, ChatRoomService crs, - RealmService rs, + RemoteRealmService rs, IStringLocalizer localizer, AccountService.AccountServiceClient accounts, FileService.FileServiceClient files, FileReferenceService.FileReferenceServiceClient fileRefs, ActionLogService.ActionLogServiceClient als, RingService.RingServiceClient pusher, - AccountClientHelper accountsHelper + RemoteAccountService remoteAccountsHelper ) : ControllerBase { [HttpGet("{id:guid}")] @@ -203,7 +203,7 @@ public class ChatRoomController( if (request.RealmId is not null) { if (!await rs.IsMemberWithRole(request.RealmId.Value, Guid.Parse(currentUser.Id), - RealmMemberRole.Moderator)) + [RealmMemberRole.Moderator])) return StatusCode(403, "You need at least be a moderator to create chat linked to the realm."); chatRoom.RealmId = request.RealmId; } @@ -301,7 +301,7 @@ public class ChatRoomController( if (chatRoom.RealmId is not null) { if (!await rs.IsMemberWithRole(chatRoom.RealmId.Value, Guid.Parse(currentUser.Id), - RealmMemberRole.Moderator)) + [RealmMemberRole.Moderator])) return StatusCode(403, "You need at least be a realm moderator to update the chat."); } else if (!await crs.IsMemberWithRole(chatRoom.Id, Guid.Parse(currentUser.Id), ChatMemberRole.Moderator)) @@ -309,13 +309,9 @@ public class ChatRoomController( if (request.RealmId is not null) { - var member = await db.RealmMembers - .Where(m => m.AccountId == Guid.Parse(currentUser.Id)) - .Where(m => m.RealmId == request.RealmId) - .FirstOrDefaultAsync(); - if (member is null || member.Role < RealmMemberRole.Moderator) + if (!await rs.IsMemberWithRole(request.RealmId.Value, Guid.Parse(currentUser.Id), [RealmMemberRole.Moderator])) return StatusCode(403, "You need at least be a moderator to transfer the chat linked to the realm."); - chatRoom.RealmId = member.RealmId; + chatRoom.RealmId = request.RealmId; } if (request.PictureId is not null) @@ -415,7 +411,7 @@ public class ChatRoomController( if (chatRoom.RealmId is not null) { if (!await rs.IsMemberWithRole(chatRoom.RealmId.Value, Guid.Parse(currentUser.Id), - RealmMemberRole.Moderator)) + [RealmMemberRole.Moderator])) return StatusCode(403, "You need at least be a realm moderator to delete the chat."); } else if (!await crs.IsMemberWithRole(chatRoom.Id, Guid.Parse(currentUser.Id), ChatMemberRole.Owner)) @@ -507,7 +503,7 @@ public class ChatRoomController( .Select(m => m.AccountId) .ToListAsync(); - var memberStatuses = await accountsHelper.GetAccountStatusBatch(members); + var memberStatuses = await remoteAccountsHelper.GetAccountStatusBatch(members); var onlineCount = memberStatuses.Count(s => s.Value.IsOnline); @@ -546,7 +542,7 @@ public class ChatRoomController( .OrderBy(m => m.JoinedAt) .ToListAsync(); - var memberStatuses = await accountsHelper.GetAccountStatusBatch( + var memberStatuses = await remoteAccountsHelper.GetAccountStatusBatch( members.Select(m => m.AccountId).ToList() ); @@ -623,11 +619,7 @@ public class ChatRoomController( // Handle realm-owned chat rooms if (chatRoom.RealmId is not null) { - var realmMember = await db.RealmMembers - .Where(m => m.AccountId == accountId) - .Where(m => m.RealmId == chatRoom.RealmId) - .FirstOrDefaultAsync(); - if (realmMember is null || realmMember.Role < RealmMemberRole.Moderator) + if (!await rs.IsMemberWithRole(chatRoom.RealmId.Value, accountId, [RealmMemberRole.Moderator])) return StatusCode(403, "You need at least be a realm moderator to invite members to this chat."); } else @@ -832,11 +824,7 @@ public class ChatRoomController( // Check if the chat room is owned by a realm if (chatRoom.RealmId is not null) { - var realmMember = await db.RealmMembers - .Where(m => m.AccountId == Guid.Parse(currentUser.Id)) - .Where(m => m.RealmId == chatRoom.RealmId) - .FirstOrDefaultAsync(); - if (realmMember is null || realmMember.Role < RealmMemberRole.Moderator) + if (!await rs.IsMemberWithRole(chatRoom.RealmId.Value, Guid.Parse(currentUser.Id), [RealmMemberRole.Moderator])) return StatusCode(403, "You need at least be a realm moderator to change member roles."); } else @@ -898,13 +886,13 @@ public class ChatRoomController( // Check if the chat room is owned by a realm if (chatRoom.RealmId is not null) { - if (!await rs.IsMemberWithRole(chatRoom.RealmId.Value, Guid.Parse(currentUser.Id), - RealmMemberRole.Moderator)) + if (!await rs.IsMemberWithRole(chatRoom.RealmId.Value, Guid.Parse(currentUser.Id), + [RealmMemberRole.Moderator])) return StatusCode(403, "You need at least be a realm moderator to remove members."); } else { - if (!await crs.IsMemberWithRole(chatRoom.Id, Guid.Parse(currentUser.Id), ChatMemberRole.Moderator)) + if (!await crs.IsMemberWithRole(chatRoom.Id, Guid.Parse(currentUser.Id), [ChatMemberRole.Moderator])) return StatusCode(403, "You need at least be a moderator to remove members."); } diff --git a/DysonNetwork.Sphere/Chat/ChatRoomService.cs b/DysonNetwork.Sphere/Chat/ChatRoomService.cs index 3cf1824..3df03c9 100644 --- a/DysonNetwork.Sphere/Chat/ChatRoomService.cs +++ b/DysonNetwork.Sphere/Chat/ChatRoomService.cs @@ -9,7 +9,7 @@ namespace DysonNetwork.Sphere.Chat; public class ChatRoomService( AppDatabase db, ICacheService cache, - AccountClientHelper accountsHelper + RemoteAccountService remoteAccountsHelper ) { private const string ChatRoomGroupPrefix = "chatroom:"; @@ -147,7 +147,7 @@ public class ChatRoomService( public async Task LoadMemberAccount(SnChatMember member) { - var account = await accountsHelper.GetAccount(member.AccountId); + var account = await remoteAccountsHelper.GetAccount(member.AccountId); member.Account = SnAccount.FromProtoValue(account); return member; } @@ -155,7 +155,7 @@ public class ChatRoomService( public async Task> LoadMemberAccounts(ICollection members) { var accountIds = members.Select(m => m.AccountId).ToList(); - var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a); + var accounts = (await remoteAccountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a); return [ diff --git a/DysonNetwork.Sphere/Realm/RealmChatController.cs b/DysonNetwork.Sphere/Chat/RealmChatController.cs similarity index 62% rename from DysonNetwork.Sphere/Realm/RealmChatController.cs rename to DysonNetwork.Sphere/Chat/RealmChatController.cs index 5f15ad1..2077d36 100644 --- a/DysonNetwork.Sphere/Realm/RealmChatController.cs +++ b/DysonNetwork.Sphere/Chat/RealmChatController.cs @@ -1,30 +1,27 @@ using DysonNetwork.Shared.Models; -using DysonNetwork.Shared.Proto; +using DysonNetwork.Shared.Registry; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace DysonNetwork.Sphere.Realm; +namespace DysonNetwork.Sphere.Chat; [ApiController] [Route("/api/realms/{slug}")] -public class RealmChatController(AppDatabase db, RealmService rs) : ControllerBase +public class RealmChatController(AppDatabase db, RemoteRealmService rs) : ControllerBase { [HttpGet("chat")] [Authorize] public async Task>> ListRealmChat(string slug) { - var currentUser = HttpContext.Items["CurrentUser"] as Account; + var currentUser = HttpContext.Items["CurrentUser"] as Shared.Proto.Account; var accountId = currentUser is null ? Guid.Empty : Guid.Parse(currentUser.Id); - var realm = await db.Realms - .Where(r => r.Slug == slug) - .FirstOrDefaultAsync(); - if (realm is null) return NotFound(); + var realm = await rs.GetRealmBySlug(slug); if (!realm.IsPublic) { if (currentUser is null) return Unauthorized(); - if (!await rs.IsMemberWithRole(realm.Id, accountId, RealmMemberRole.Normal)) + if (!await rs.IsMemberWithRole(realm.Id, accountId, [RealmMemberRole.Normal])) return StatusCode(403, "You need at least one member to view the realm's chat."); } diff --git a/DysonNetwork.Sphere/Migrations/20251021154500_ChangeRealmReferenceMode.Designer.cs b/DysonNetwork.Sphere/Migrations/20251021154500_ChangeRealmReferenceMode.Designer.cs new file mode 100644 index 0000000..6af23d1 --- /dev/null +++ b/DysonNetwork.Sphere/Migrations/20251021154500_ChangeRealmReferenceMode.Designer.cs @@ -0,0 +1,2130 @@ +// +using System; +using System.Collections.Generic; +using System.Text.Json; +using DysonNetwork.Shared.Models; +using DysonNetwork.Sphere; +using DysonNetwork.Sphere.WebReader; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NodaTime; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using NpgsqlTypes; + +#nullable disable + +namespace DysonNetwork.Sphere.Migrations +{ + [DbContext(typeof(AppDatabase))] + [Migration("20251021154500_ChangeRealmReferenceMode")] + partial class ChangeRealmReferenceMode + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMember", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("BreakUntil") + .HasColumnType("timestamp with time zone") + .HasColumnName("break_until"); + + b.Property("ChatRoomId") + .HasColumnType("uuid") + .HasColumnName("chat_room_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("IsBot") + .HasColumnType("boolean") + .HasColumnName("is_bot"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joined_at"); + + b.Property("LastReadAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_at"); + + b.Property("LeaveAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("leave_at"); + + b.Property("Nick") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("nick"); + + b.Property("Notify") + .HasColumnType("integer") + .HasColumnName("notify"); + + b.Property("Role") + .HasColumnType("integer") + .HasColumnName("role"); + + b.Property("TimeoutCause") + .HasColumnType("jsonb") + .HasColumnName("timeout_cause"); + + b.Property("TimeoutUntil") + .HasColumnType("timestamp with time zone") + .HasColumnName("timeout_until"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_chat_members"); + + b.HasAlternateKey("ChatRoomId", "AccountId") + .HasName("ak_chat_members_chat_room_id_account_id"); + + b.ToTable("chat_members", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property>("Attachments") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("attachments"); + + b.Property("ChatRoomId") + .HasColumnType("uuid") + .HasColumnName("chat_room_id"); + + b.Property("Content") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("content"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("edited_at"); + + b.Property("ForwardedMessageId") + .HasColumnType("uuid") + .HasColumnName("forwarded_message_id"); + + b.Property>("MembersMentioned") + .HasColumnType("jsonb") + .HasColumnName("members_mentioned"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("Nonce") + .IsRequired() + .HasMaxLength(36) + .HasColumnType("character varying(36)") + .HasColumnName("nonce"); + + b.Property("RepliedMessageId") + .HasColumnType("uuid") + .HasColumnName("replied_message_id"); + + b.Property("SenderId") + .HasColumnType("uuid") + .HasColumnName("sender_id"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_chat_messages"); + + b.HasIndex("ChatRoomId") + .HasDatabaseName("ix_chat_messages_chat_room_id"); + + b.HasIndex("ForwardedMessageId") + .HasDatabaseName("ix_chat_messages_forwarded_message_id"); + + b.HasIndex("RepliedMessageId") + .HasDatabaseName("ix_chat_messages_replied_message_id"); + + b.HasIndex("SenderId") + .HasDatabaseName("ix_chat_messages_sender_id"); + + b.ToTable("chat_messages", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessageReaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Attitude") + .HasColumnType("integer") + .HasColumnName("attitude"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("MessageId") + .HasColumnType("uuid") + .HasColumnName("message_id"); + + b.Property("SenderId") + .HasColumnType("uuid") + .HasColumnName("sender_id"); + + b.Property("Symbol") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("symbol"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_chat_reactions"); + + b.HasIndex("MessageId") + .HasDatabaseName("ix_chat_reactions_message_id"); + + b.HasIndex("SenderId") + .HasDatabaseName("ix_chat_reactions_sender_id"); + + b.ToTable("chat_reactions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("IsCommunity") + .HasColumnType("boolean") + .HasColumnName("is_community"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Name") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("SnRealmId") + .HasColumnType("uuid") + .HasColumnName("sn_realm_id"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_chat_rooms"); + + b.HasIndex("SnRealmId") + .HasDatabaseName("ix_chat_rooms_sn_realm_id"); + + b.ToTable("chat_rooms", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPoll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("EndedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("ended_at"); + + b.Property("IsAnonymous") + .HasColumnType("boolean") + .HasColumnName("is_anonymous"); + + b.Property("PublisherId") + .HasColumnType("uuid") + .HasColumnName("publisher_id"); + + b.Property("Title") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("title"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_polls"); + + b.HasIndex("PublisherId") + .HasDatabaseName("ix_polls_publisher_id"); + + b.ToTable("polls", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property>("Answer") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("answer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("PollId") + .HasColumnType("uuid") + .HasColumnName("poll_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_poll_answers"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_poll_answers_poll_id"); + + b.ToTable("poll_answers", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPollQuestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("IsRequired") + .HasColumnType("boolean") + .HasColumnName("is_required"); + + b.Property>("Options") + .HasColumnType("jsonb") + .HasColumnName("options"); + + b.Property("Order") + .HasColumnType("integer") + .HasColumnName("order"); + + b.Property("PollId") + .HasColumnType("uuid") + .HasColumnName("poll_id"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("title"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_poll_questions"); + + b.HasIndex("PollId") + .HasDatabaseName("ix_poll_questions_poll_id"); + + b.ToTable("poll_questions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPost", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property>("Attachments") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("attachments"); + + b.Property("AwardedScore") + .HasColumnType("numeric") + .HasColumnName("awarded_score"); + + b.Property("Content") + .HasColumnType("text") + .HasColumnName("content"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("Downvotes") + .HasColumnType("integer") + .HasColumnName("downvotes"); + + b.Property("EditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("edited_at"); + + b.Property("EmbedView") + .HasColumnType("jsonb") + .HasColumnName("embed_view"); + + b.Property("ForwardedGone") + .HasColumnType("boolean") + .HasColumnName("forwarded_gone"); + + b.Property("ForwardedPostId") + .HasColumnType("uuid") + .HasColumnName("forwarded_post_id"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("PinMode") + .HasColumnType("integer") + .HasColumnName("pin_mode"); + + b.Property("PublishedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("published_at"); + + b.Property("PublisherId") + .HasColumnType("uuid") + .HasColumnName("publisher_id"); + + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("RepliedGone") + .HasColumnType("boolean") + .HasColumnName("replied_gone"); + + b.Property("RepliedPostId") + .HasColumnType("uuid") + .HasColumnName("replied_post_id"); + + b.Property("SearchVector") + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("tsvector") + .HasColumnName("search_vector") + .HasAnnotation("Npgsql:TsVectorConfig", "simple") + .HasAnnotation("Npgsql:TsVectorProperties", new[] { "Title", "Description", "Content" }); + + b.Property>("SensitiveMarks") + .HasColumnType("jsonb") + .HasColumnName("sensitive_marks"); + + b.Property("Slug") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("slug"); + + b.Property("Title") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("title"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Upvotes") + .HasColumnType("integer") + .HasColumnName("upvotes"); + + b.Property("ViewsTotal") + .HasColumnType("integer") + .HasColumnName("views_total"); + + b.Property("ViewsUnique") + .HasColumnType("integer") + .HasColumnName("views_unique"); + + b.Property("Visibility") + .HasColumnType("integer") + .HasColumnName("visibility"); + + b.HasKey("Id") + .HasName("pk_posts"); + + b.HasIndex("ForwardedPostId") + .HasDatabaseName("ix_posts_forwarded_post_id"); + + b.HasIndex("PublisherId") + .HasDatabaseName("ix_posts_publisher_id"); + + b.HasIndex("RepliedPostId") + .HasDatabaseName("ix_posts_replied_post_id"); + + b.HasIndex("SearchVector") + .HasDatabaseName("ix_posts_search_vector"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("SearchVector"), "GIN"); + + b.ToTable("posts", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostAward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.Property("Attitude") + .HasColumnType("integer") + .HasColumnName("attitude"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Message") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PostId") + .HasColumnType("uuid") + .HasColumnName("post_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_post_awards"); + + b.HasIndex("PostId") + .HasDatabaseName("ix_post_awards_post_id"); + + b.ToTable("post_awards", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("name"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("slug"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_post_categories"); + + b.ToTable("post_categories", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCategorySubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CategoryId") + .HasColumnType("uuid") + .HasColumnName("category_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("TagId") + .HasColumnType("uuid") + .HasColumnName("tag_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_post_category_subscriptions"); + + b.HasIndex("CategoryId") + .HasDatabaseName("ix_post_category_subscriptions_category_id"); + + b.HasIndex("TagId") + .HasDatabaseName("ix_post_category_subscriptions_tag_id"); + + b.ToTable("post_category_subscriptions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("name"); + + b.Property("PublisherId") + .HasColumnType("uuid") + .HasColumnName("publisher_id"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("slug"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_post_collections"); + + b.HasIndex("PublisherId") + .HasDatabaseName("ix_post_collections_publisher_id"); + + b.ToTable("post_collections", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostFeaturedRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("FeaturedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("featured_at"); + + b.Property("PostId") + .HasColumnType("uuid") + .HasColumnName("post_id"); + + b.Property("SocialCredits") + .HasColumnType("integer") + .HasColumnName("social_credits"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_post_featured_records"); + + b.HasIndex("PostId") + .HasDatabaseName("ix_post_featured_records_post_id"); + + b.ToTable("post_featured_records", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostReaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Attitude") + .HasColumnType("integer") + .HasColumnName("attitude"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("PostId") + .HasColumnType("uuid") + .HasColumnName("post_id"); + + b.Property("Symbol") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("symbol"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_post_reactions"); + + b.HasIndex("PostId") + .HasDatabaseName("ix_post_reactions_post_id"); + + b.ToTable("post_reactions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("name"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("slug"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_post_tags"); + + b.ToTable("post_tags", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisher", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + + b.Property("Bio") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("bio"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("name"); + + b.Property("Nick") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("nick"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Verification") + .HasColumnType("jsonb") + .HasColumnName("verification"); + + b.HasKey("Id") + .HasName("pk_publishers"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_publishers_name"); + + b.HasIndex("RealmId") + .HasDatabaseName("ix_publishers_realm_id"); + + b.ToTable("publishers", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherFeature", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("Flag") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("flag"); + + b.Property("PublisherId") + .HasColumnType("uuid") + .HasColumnName("publisher_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_publisher_features"); + + b.HasIndex("PublisherId") + .HasDatabaseName("ix_publisher_features_publisher_id"); + + b.ToTable("publisher_features", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherMember", b => + { + b.Property("PublisherId") + .HasColumnType("uuid") + .HasColumnName("publisher_id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joined_at"); + + b.Property("Role") + .HasColumnType("integer") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("PublisherId", "AccountId") + .HasName("pk_publisher_members"); + + b.ToTable("publisher_members", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("PublisherId") + .HasColumnType("uuid") + .HasColumnName("publisher_id"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.Property("Tier") + .HasColumnType("integer") + .HasColumnName("tier"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_publisher_subscriptions"); + + b.HasIndex("PublisherId") + .HasDatabaseName("ix_publisher_subscriptions_publisher_id"); + + b.ToTable("publisher_subscriptions", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("IsCommunity") + .HasColumnType("boolean") + .HasColumnName("is_community"); + + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("slug"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Verification") + .HasColumnType("jsonb") + .HasColumnName("verification"); + + b.HasKey("Id") + .HasName("pk_realms"); + + b.HasIndex("Slug") + .IsUnique() + .HasDatabaseName("ix_realms_slug"); + + b.ToTable("realms", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.Property("RealmId") + .HasColumnType("uuid") + .HasColumnName("realm_id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("joined_at"); + + b.Property("LeaveAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("leave_at"); + + b.Property("Role") + .HasColumnType("integer") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("RealmId", "AccountId") + .HasName("pk_realm_members"); + + b.ToTable("realm_members", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealtimeCall", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("EndedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("ended_at"); + + b.Property("ProviderName") + .HasColumnType("text") + .HasColumnName("provider_name"); + + b.Property("RoomId") + .HasColumnType("uuid") + .HasColumnName("room_id"); + + b.Property("SenderId") + .HasColumnType("uuid") + .HasColumnName("sender_id"); + + b.Property("SessionId") + .HasColumnType("text") + .HasColumnName("session_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UpstreamConfigJson") + .HasColumnType("jsonb") + .HasColumnName("upstream"); + + b.HasKey("Id") + .HasName("pk_chat_realtime_call"); + + b.HasIndex("RoomId") + .HasDatabaseName("ix_chat_realtime_call_room_id"); + + b.HasIndex("SenderId") + .HasDatabaseName("ix_chat_realtime_call_sender_id"); + + b.ToTable("chat_realtime_call", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSticker", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Image") + .HasColumnType("jsonb") + .HasColumnName("image"); + + b.Property("ImageId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("image_id"); + + b.Property("PackId") + .HasColumnType("uuid") + .HasColumnName("pack_id"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("slug"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_stickers"); + + b.HasIndex("PackId") + .HasDatabaseName("ix_stickers_pack_id"); + + b.HasIndex("Slug") + .HasDatabaseName("ix_stickers_slug"); + + b.ToTable("stickers", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Prefix") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("prefix"); + + b.Property("PublisherId") + .HasColumnType("uuid") + .HasColumnName("publisher_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_sticker_packs"); + + b.HasIndex("Prefix") + .IsUnique() + .HasDatabaseName("ix_sticker_packs_prefix"); + + b.HasIndex("PublisherId") + .HasDatabaseName("ix_sticker_packs_publisher_id"); + + b.ToTable("sticker_packs", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPackOwnership", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("PackId") + .HasColumnType("uuid") + .HasColumnName("pack_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_sticker_pack_ownerships"); + + b.HasIndex("PackId") + .HasDatabaseName("ix_sticker_pack_ownerships_pack_id"); + + b.ToTable("sticker_pack_ownerships", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.WebReader.WebArticle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Author") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("author"); + + b.Property("Content") + .HasColumnType("text") + .HasColumnName("content"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("FeedId") + .HasColumnType("uuid") + .HasColumnName("feed_id"); + + b.Property>("Meta") + .HasColumnType("jsonb") + .HasColumnName("meta"); + + b.Property("Preview") + .HasColumnType("jsonb") + .HasColumnName("preview"); + + b.Property("PublishedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("published_at"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("title"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_web_articles"); + + b.HasIndex("FeedId") + .HasDatabaseName("ix_web_articles_feed_id"); + + b.HasIndex("Url") + .IsUnique() + .HasDatabaseName("ix_web_articles_url"); + + b.ToTable("web_articles", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.WebReader.WebFeed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Config") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("config"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Description") + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("description"); + + b.Property("Preview") + .HasColumnType("jsonb") + .HasColumnName("preview"); + + b.Property("PublisherId") + .HasColumnType("uuid") + .HasColumnName("publisher_id"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("title"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(8192) + .HasColumnType("character varying(8192)") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_web_feeds"); + + b.HasIndex("PublisherId") + .HasDatabaseName("ix_web_feeds_publisher_id"); + + b.HasIndex("Url") + .IsUnique() + .HasDatabaseName("ix_web_feeds_url"); + + b.ToTable("web_feeds", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.WebReader.WebFeedSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("uuid") + .HasColumnName("account_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("FeedId") + .HasColumnType("uuid") + .HasColumnName("feed_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_web_feed_subscriptions"); + + b.HasIndex("FeedId") + .HasDatabaseName("ix_web_feed_subscriptions_feed_id"); + + b.ToTable("web_feed_subscriptions", (string)null); + }); + + modelBuilder.Entity("SnPostSnPostCategory", b => + { + b.Property("CategoriesId") + .HasColumnType("uuid") + .HasColumnName("categories_id"); + + b.Property("PostsId") + .HasColumnType("uuid") + .HasColumnName("posts_id"); + + b.HasKey("CategoriesId", "PostsId") + .HasName("pk_post_category_links"); + + b.HasIndex("PostsId") + .HasDatabaseName("ix_post_category_links_posts_id"); + + b.ToTable("post_category_links", (string)null); + }); + + modelBuilder.Entity("SnPostSnPostCollection", b => + { + b.Property("CollectionsId") + .HasColumnType("uuid") + .HasColumnName("collections_id"); + + b.Property("PostsId") + .HasColumnType("uuid") + .HasColumnName("posts_id"); + + b.HasKey("CollectionsId", "PostsId") + .HasName("pk_post_collection_links"); + + b.HasIndex("PostsId") + .HasDatabaseName("ix_post_collection_links_posts_id"); + + b.ToTable("post_collection_links", (string)null); + }); + + modelBuilder.Entity("SnPostSnPostTag", b => + { + b.Property("PostsId") + .HasColumnType("uuid") + .HasColumnName("posts_id"); + + b.Property("TagsId") + .HasColumnType("uuid") + .HasColumnName("tags_id"); + + b.HasKey("PostsId", "TagsId") + .HasName("pk_post_tag_links"); + + b.HasIndex("TagsId") + .HasDatabaseName("ix_post_tag_links_tags_id"); + + b.ToTable("post_tag_links", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnChatRoom", "ChatRoom") + .WithMany("Members") + .HasForeignKey("ChatRoomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chat_members_chat_rooms_chat_room_id"); + + b.Navigation("ChatRoom"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessage", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnChatRoom", "ChatRoom") + .WithMany() + .HasForeignKey("ChatRoomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chat_messages_chat_rooms_chat_room_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnChatMessage", "ForwardedMessage") + .WithMany() + .HasForeignKey("ForwardedMessageId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_chat_messages_chat_messages_forwarded_message_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnChatMessage", "RepliedMessage") + .WithMany() + .HasForeignKey("RepliedMessageId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_chat_messages_chat_messages_replied_message_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnChatMember", "Sender") + .WithMany() + .HasForeignKey("SenderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chat_messages_chat_members_sender_id"); + + b.Navigation("ChatRoom"); + + b.Navigation("ForwardedMessage"); + + b.Navigation("RepliedMessage"); + + b.Navigation("Sender"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessageReaction", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnChatMessage", "Message") + .WithMany("Reactions") + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chat_reactions_chat_messages_message_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnChatMember", "Sender") + .WithMany() + .HasForeignKey("SenderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chat_reactions_chat_members_sender_id"); + + b.Navigation("Message"); + + b.Navigation("Sender"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", null) + .WithMany("ChatRooms") + .HasForeignKey("SnRealmId") + .HasConstraintName("fk_chat_rooms_realms_sn_realm_id"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPoll", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Polls") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_polls_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPollAnswer", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPoll", "Poll") + .WithMany() + .HasForeignKey("PollId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_poll_answers_polls_poll_id"); + + b.Navigation("Poll"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPollQuestion", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPoll", "Poll") + .WithMany("Questions") + .HasForeignKey("PollId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_poll_questions_polls_poll_id"); + + b.Navigation("Poll"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPost", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", "ForwardedPost") + .WithMany() + .HasForeignKey("ForwardedPostId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_posts_posts_forwarded_post_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Posts") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_posts_publishers_publisher_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPost", "RepliedPost") + .WithMany() + .HasForeignKey("RepliedPostId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_posts_posts_replied_post_id"); + + b.Navigation("ForwardedPost"); + + b.Navigation("Publisher"); + + b.Navigation("RepliedPost"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostAward", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", "Post") + .WithMany("Awards") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_awards_posts_post_id"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCategorySubscription", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPostCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .HasConstraintName("fk_post_category_subscriptions_post_categories_category_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPostTag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .HasConstraintName("fk_post_category_subscriptions_post_tags_tag_id"); + + b.Navigation("Category"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCollection", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Collections") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_collections_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostFeaturedRecord", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_featured_records_posts_post_id"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostReaction", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", "Post") + .WithMany("Reactions") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_reactions_posts_post_id"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisher", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", "Realm") + .WithMany() + .HasForeignKey("RealmId") + .HasConstraintName("fk_publishers_realms_realm_id"); + + b.Navigation("Realm"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherFeature", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Features") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_publisher_features_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Members") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_publisher_members_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherSubscription", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Subscriptions") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_publisher_subscriptions_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", "Realm") + .WithMany("Members") + .HasForeignKey("RealmId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_realm_members_realms_realm_id"); + + b.Navigation("Realm"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealtimeCall", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnChatRoom", "Room") + .WithMany() + .HasForeignKey("RoomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chat_realtime_call_chat_rooms_room_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnChatMember", "Sender") + .WithMany() + .HasForeignKey("SenderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_chat_realtime_call_chat_members_sender_id"); + + b.Navigation("Room"); + + b.Navigation("Sender"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSticker", b => + { + b.HasOne("DysonNetwork.Shared.Models.StickerPack", "Pack") + .WithMany("Stickers") + .HasForeignKey("PackId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_stickers_sticker_packs_pack_id"); + + b.Navigation("Pack"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPack", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany() + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_sticker_packs_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPackOwnership", b => + { + b.HasOne("DysonNetwork.Shared.Models.StickerPack", "Pack") + .WithMany("Ownerships") + .HasForeignKey("PackId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_sticker_pack_ownerships_sticker_packs_pack_id"); + + b.Navigation("Pack"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.WebReader.WebArticle", b => + { + b.HasOne("DysonNetwork.Sphere.WebReader.WebFeed", "Feed") + .WithMany("Articles") + .HasForeignKey("FeedId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_web_articles_web_feeds_feed_id"); + + b.Navigation("Feed"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.WebReader.WebFeed", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany() + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_web_feeds_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.WebReader.WebFeedSubscription", b => + { + b.HasOne("DysonNetwork.Sphere.WebReader.WebFeed", "Feed") + .WithMany() + .HasForeignKey("FeedId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_web_feed_subscriptions_web_feeds_feed_id"); + + b.Navigation("Feed"); + }); + + modelBuilder.Entity("SnPostSnPostCategory", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPostCategory", null) + .WithMany() + .HasForeignKey("CategoriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_category_links_post_categories_categories_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPost", null) + .WithMany() + .HasForeignKey("PostsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_category_links_posts_posts_id"); + }); + + modelBuilder.Entity("SnPostSnPostCollection", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPostCollection", null) + .WithMany() + .HasForeignKey("CollectionsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_collection_links_post_collections_collections_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPost", null) + .WithMany() + .HasForeignKey("PostsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_collection_links_posts_posts_id"); + }); + + modelBuilder.Entity("SnPostSnPostTag", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", null) + .WithMany() + .HasForeignKey("PostsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_tag_links_posts_posts_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPostTag", null) + .WithMany() + .HasForeignKey("TagsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_tag_links_post_tags_tags_id"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessage", b => + { + b.Navigation("Reactions"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPoll", b => + { + b.Navigation("Questions"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPost", b => + { + b.Navigation("Awards"); + + b.Navigation("Reactions"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisher", b => + { + b.Navigation("Collections"); + + b.Navigation("Features"); + + b.Navigation("Members"); + + b.Navigation("Polls"); + + b.Navigation("Posts"); + + b.Navigation("Subscriptions"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => + { + b.Navigation("ChatRooms"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPack", b => + { + b.Navigation("Ownerships"); + + b.Navigation("Stickers"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.WebReader.WebFeed", b => + { + b.Navigation("Articles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DysonNetwork.Sphere/Migrations/20251021154500_ChangeRealmReferenceMode.cs b/DysonNetwork.Sphere/Migrations/20251021154500_ChangeRealmReferenceMode.cs new file mode 100644 index 0000000..148d0b9 --- /dev/null +++ b/DysonNetwork.Sphere/Migrations/20251021154500_ChangeRealmReferenceMode.cs @@ -0,0 +1,89 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DysonNetwork.Sphere.Migrations +{ + /// + public partial class ChangeRealmReferenceMode : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "fk_chat_rooms_realms_realm_id", + table: "chat_rooms"); + + migrationBuilder.DropForeignKey( + name: "fk_posts_realms_realm_id", + table: "posts"); + + migrationBuilder.DropIndex( + name: "ix_posts_realm_id", + table: "posts"); + + migrationBuilder.DropIndex( + name: "ix_chat_rooms_realm_id", + table: "chat_rooms"); + + migrationBuilder.AddColumn( + name: "sn_realm_id", + table: "chat_rooms", + type: "uuid", + nullable: true); + + migrationBuilder.CreateIndex( + name: "ix_chat_rooms_sn_realm_id", + table: "chat_rooms", + column: "sn_realm_id"); + + migrationBuilder.AddForeignKey( + name: "fk_chat_rooms_realms_sn_realm_id", + table: "chat_rooms", + column: "sn_realm_id", + principalTable: "realms", + principalColumn: "id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "fk_chat_rooms_realms_sn_realm_id", + table: "chat_rooms"); + + migrationBuilder.DropIndex( + name: "ix_chat_rooms_sn_realm_id", + table: "chat_rooms"); + + migrationBuilder.DropColumn( + name: "sn_realm_id", + table: "chat_rooms"); + + migrationBuilder.CreateIndex( + name: "ix_posts_realm_id", + table: "posts", + column: "realm_id"); + + migrationBuilder.CreateIndex( + name: "ix_chat_rooms_realm_id", + table: "chat_rooms", + column: "realm_id"); + + migrationBuilder.AddForeignKey( + name: "fk_chat_rooms_realms_realm_id", + table: "chat_rooms", + column: "realm_id", + principalTable: "realms", + principalColumn: "id"); + + migrationBuilder.AddForeignKey( + name: "fk_posts_realms_realm_id", + table: "posts", + column: "realm_id", + principalTable: "realms", + principalColumn: "id"); + } + } +} diff --git a/DysonNetwork.Sphere/Migrations/AppDatabaseModelSnapshot.cs b/DysonNetwork.Sphere/Migrations/AppDatabaseModelSnapshot.cs index a5d3a1a..06286eb 100644 --- a/DysonNetwork.Sphere/Migrations/AppDatabaseModelSnapshot.cs +++ b/DysonNetwork.Sphere/Migrations/AppDatabaseModelSnapshot.cs @@ -28,7 +28,7 @@ namespace DysonNetwork.Sphere.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatMember", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMember", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -105,79 +105,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("chat_members", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatRoom", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("id"); - - b.Property("Background") - .HasColumnType("jsonb") - .HasColumnName("background"); - - b.Property("BackgroundId") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasColumnName("background_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("deleted_at"); - - b.Property("Description") - .HasMaxLength(4096) - .HasColumnType("character varying(4096)") - .HasColumnName("description"); - - b.Property("IsCommunity") - .HasColumnType("boolean") - .HasColumnName("is_community"); - - b.Property("IsPublic") - .HasColumnType("boolean") - .HasColumnName("is_public"); - - b.Property("Name") - .HasMaxLength(1024) - .HasColumnType("character varying(1024)") - .HasColumnName("name"); - - b.Property("Picture") - .HasColumnType("jsonb") - .HasColumnName("picture"); - - b.Property("PictureId") - .HasMaxLength(32) - .HasColumnType("character varying(32)") - .HasColumnName("picture_id"); - - b.Property("RealmId") - .HasColumnType("uuid") - .HasColumnName("realm_id"); - - b.Property("Type") - .HasColumnType("integer") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_chat_rooms"); - - b.HasIndex("RealmId") - .HasDatabaseName("ix_chat_rooms_realm_id"); - - b.ToTable("chat_rooms", (string)null); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Chat.Message", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessage", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -264,7 +192,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("chat_messages", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.MessageReaction", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessageReaction", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -313,13 +241,22 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("chat_reactions", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.RealtimeCall", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid") .HasColumnName("id"); + b.Property("Background") + .HasColumnType("jsonb") + .HasColumnName("background"); + + b.Property("BackgroundId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("background_id"); + b.Property("CreatedAt") .HasColumnType("timestamp with time zone") .HasColumnName("created_at"); @@ -328,47 +265,59 @@ namespace DysonNetwork.Sphere.Migrations .HasColumnType("timestamp with time zone") .HasColumnName("deleted_at"); - b.Property("EndedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("ended_at"); + b.Property("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); - b.Property("ProviderName") - .HasColumnType("text") - .HasColumnName("provider_name"); + b.Property("IsCommunity") + .HasColumnType("boolean") + .HasColumnName("is_community"); - b.Property("RoomId") + b.Property("IsPublic") + .HasColumnType("boolean") + .HasColumnName("is_public"); + + b.Property("Name") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Picture") + .HasColumnType("jsonb") + .HasColumnName("picture"); + + b.Property("PictureId") + .HasMaxLength(32) + .HasColumnType("character varying(32)") + .HasColumnName("picture_id"); + + b.Property("RealmId") .HasColumnType("uuid") - .HasColumnName("room_id"); + .HasColumnName("realm_id"); - b.Property("SenderId") + b.Property("SnRealmId") .HasColumnType("uuid") - .HasColumnName("sender_id"); + .HasColumnName("sn_realm_id"); - b.Property("SessionId") - .HasColumnType("text") - .HasColumnName("session_id"); + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); b.Property("UpdatedAt") .HasColumnType("timestamp with time zone") .HasColumnName("updated_at"); - b.Property("UpstreamConfigJson") - .HasColumnType("jsonb") - .HasColumnName("upstream"); - b.HasKey("Id") - .HasName("pk_chat_realtime_call"); + .HasName("pk_chat_rooms"); - b.HasIndex("RoomId") - .HasDatabaseName("ix_chat_realtime_call_room_id"); + b.HasIndex("SnRealmId") + .HasDatabaseName("ix_chat_rooms_sn_realm_id"); - b.HasIndex("SenderId") - .HasDatabaseName("ix_chat_realtime_call_sender_id"); - - b.ToTable("chat_realtime_call", (string)null); + b.ToTable("chat_rooms", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Poll.Poll", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPoll", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -418,7 +367,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("polls", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Poll.PollAnswer", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPollAnswer", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -459,7 +408,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("poll_answers", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Poll.PollQuestion", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPollQuestion", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -518,7 +467,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("poll_questions", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.Post", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPost", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -654,9 +603,6 @@ namespace DysonNetwork.Sphere.Migrations b.HasIndex("PublisherId") .HasDatabaseName("ix_posts_publisher_id"); - b.HasIndex("RealmId") - .HasDatabaseName("ix_posts_realm_id"); - b.HasIndex("RepliedPostId") .HasDatabaseName("ix_posts_replied_post_id"); @@ -668,7 +614,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("posts", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostAward", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostAward", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -717,7 +663,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_awards", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostCategory", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCategory", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -753,7 +699,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_categories", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostCategorySubscription", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCategorySubscription", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -796,7 +742,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_category_subscriptions", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostCollection", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCollection", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -844,7 +790,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_collections", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostFeaturedRecord", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostFeaturedRecord", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -884,7 +830,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_featured_records", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostReaction", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostReaction", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -930,7 +876,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_reactions", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostTag", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostTag", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -966,7 +912,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_tags", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.Publisher", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisher", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -1049,7 +995,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("publishers", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.PublisherFeature", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherFeature", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -1091,7 +1037,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("publisher_features", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.PublisherMember", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherMember", b => { b.Property("PublisherId") .HasColumnType("uuid") @@ -1127,7 +1073,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("publisher_members", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.PublisherSubscription", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherSubscription", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -1171,7 +1117,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("publisher_subscriptions", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Realm.Realm", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -1252,7 +1198,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("realms", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Realm.RealmMember", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => { b.Property("RealmId") .HasColumnType("uuid") @@ -1292,7 +1238,62 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("realm_members", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Sticker.Sticker", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealtimeCall", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("EndedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("ended_at"); + + b.Property("ProviderName") + .HasColumnType("text") + .HasColumnName("provider_name"); + + b.Property("RoomId") + .HasColumnType("uuid") + .HasColumnName("room_id"); + + b.Property("SenderId") + .HasColumnType("uuid") + .HasColumnName("sender_id"); + + b.Property("SessionId") + .HasColumnType("text") + .HasColumnName("session_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UpstreamConfigJson") + .HasColumnType("jsonb") + .HasColumnName("upstream"); + + b.HasKey("Id") + .HasName("pk_chat_realtime_call"); + + b.HasIndex("RoomId") + .HasDatabaseName("ix_chat_realtime_call_room_id"); + + b.HasIndex("SenderId") + .HasDatabaseName("ix_chat_realtime_call_sender_id"); + + b.ToTable("chat_realtime_call", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSticker", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -1342,7 +1343,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("stickers", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Sticker.StickerPack", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPack", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -1396,7 +1397,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("sticker_packs", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Sticker.StickerPackOwnership", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPackOwnership", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -1599,7 +1600,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("web_feed_subscriptions", (string)null); }); - modelBuilder.Entity("PostPostCategory", b => + modelBuilder.Entity("SnPostSnPostCategory", b => { b.Property("CategoriesId") .HasColumnType("uuid") @@ -1618,7 +1619,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_category_links", (string)null); }); - modelBuilder.Entity("PostPostCollection", b => + modelBuilder.Entity("SnPostSnPostCollection", b => { b.Property("CollectionsId") .HasColumnType("uuid") @@ -1637,7 +1638,7 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_collection_links", (string)null); }); - modelBuilder.Entity("PostPostTag", b => + modelBuilder.Entity("SnPostSnPostTag", b => { b.Property("PostsId") .HasColumnType("uuid") @@ -1656,9 +1657,9 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("post_tag_links", (string)null); }); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatMember", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMember", b => { - b.HasOne("DysonNetwork.Sphere.Chat.ChatRoom", "ChatRoom") + b.HasOne("DysonNetwork.Shared.Models.SnChatRoom", "ChatRoom") .WithMany("Members") .HasForeignKey("ChatRoomId") .OnDelete(DeleteBehavior.Cascade) @@ -1668,38 +1669,28 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("ChatRoom"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatRoom", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessage", b => { - b.HasOne("DysonNetwork.Sphere.Realm.Realm", "Realm") - .WithMany("ChatRooms") - .HasForeignKey("RealmId") - .HasConstraintName("fk_chat_rooms_realms_realm_id"); - - b.Navigation("Realm"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Chat.Message", b => - { - b.HasOne("DysonNetwork.Sphere.Chat.ChatRoom", "ChatRoom") + b.HasOne("DysonNetwork.Shared.Models.SnChatRoom", "ChatRoom") .WithMany() .HasForeignKey("ChatRoomId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() .HasConstraintName("fk_chat_messages_chat_rooms_chat_room_id"); - b.HasOne("DysonNetwork.Sphere.Chat.Message", "ForwardedMessage") + b.HasOne("DysonNetwork.Shared.Models.SnChatMessage", "ForwardedMessage") .WithMany() .HasForeignKey("ForwardedMessageId") .OnDelete(DeleteBehavior.Restrict) .HasConstraintName("fk_chat_messages_chat_messages_forwarded_message_id"); - b.HasOne("DysonNetwork.Sphere.Chat.Message", "RepliedMessage") + b.HasOne("DysonNetwork.Shared.Models.SnChatMessage", "RepliedMessage") .WithMany() .HasForeignKey("RepliedMessageId") .OnDelete(DeleteBehavior.Restrict) .HasConstraintName("fk_chat_messages_chat_messages_replied_message_id"); - b.HasOne("DysonNetwork.Sphere.Chat.ChatMember", "Sender") + b.HasOne("DysonNetwork.Shared.Models.SnChatMember", "Sender") .WithMany() .HasForeignKey("SenderId") .OnDelete(DeleteBehavior.Cascade) @@ -1715,16 +1706,16 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Sender"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.MessageReaction", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessageReaction", b => { - b.HasOne("DysonNetwork.Sphere.Chat.Message", "Message") + b.HasOne("DysonNetwork.Shared.Models.SnChatMessage", "Message") .WithMany("Reactions") .HasForeignKey("MessageId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() .HasConstraintName("fk_chat_reactions_chat_messages_message_id"); - b.HasOne("DysonNetwork.Sphere.Chat.ChatMember", "Sender") + b.HasOne("DysonNetwork.Shared.Models.SnChatMember", "Sender") .WithMany() .HasForeignKey("SenderId") .OnDelete(DeleteBehavior.Cascade) @@ -1736,16 +1727,211 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Sender"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.RealtimeCall", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => { - b.HasOne("DysonNetwork.Sphere.Chat.ChatRoom", "Room") + b.HasOne("DysonNetwork.Shared.Models.SnRealm", null) + .WithMany("ChatRooms") + .HasForeignKey("SnRealmId") + .HasConstraintName("fk_chat_rooms_realms_sn_realm_id"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPoll", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Polls") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_polls_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPollAnswer", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPoll", "Poll") + .WithMany() + .HasForeignKey("PollId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_poll_answers_polls_poll_id"); + + b.Navigation("Poll"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPollQuestion", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPoll", "Poll") + .WithMany("Questions") + .HasForeignKey("PollId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_poll_questions_polls_poll_id"); + + b.Navigation("Poll"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPost", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", "ForwardedPost") + .WithMany() + .HasForeignKey("ForwardedPostId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_posts_posts_forwarded_post_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Posts") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_posts_publishers_publisher_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPost", "RepliedPost") + .WithMany() + .HasForeignKey("RepliedPostId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_posts_posts_replied_post_id"); + + b.Navigation("ForwardedPost"); + + b.Navigation("Publisher"); + + b.Navigation("RepliedPost"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostAward", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", "Post") + .WithMany("Awards") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_awards_posts_post_id"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCategorySubscription", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPostCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .HasConstraintName("fk_post_category_subscriptions_post_categories_category_id"); + + b.HasOne("DysonNetwork.Shared.Models.SnPostTag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .HasConstraintName("fk_post_category_subscriptions_post_tags_tag_id"); + + b.Navigation("Category"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostCollection", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Collections") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_collections_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostFeaturedRecord", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_featured_records_posts_post_id"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPostReaction", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPost", "Post") + .WithMany("Reactions") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_post_reactions_posts_post_id"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisher", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", "Realm") + .WithMany() + .HasForeignKey("RealmId") + .HasConstraintName("fk_publishers_realms_realm_id"); + + b.Navigation("Realm"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherFeature", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Features") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_publisher_features_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Members") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_publisher_members_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisherSubscription", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") + .WithMany("Subscriptions") + .HasForeignKey("PublisherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_publisher_subscriptions_publishers_publisher_id"); + + b.Navigation("Publisher"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealmMember", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnRealm", "Realm") + .WithMany("Members") + .HasForeignKey("RealmId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_realm_members_realms_realm_id"); + + b.Navigation("Realm"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealtimeCall", b => + { + b.HasOne("DysonNetwork.Shared.Models.SnChatRoom", "Room") .WithMany() .HasForeignKey("RoomId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() .HasConstraintName("fk_chat_realtime_call_chat_rooms_room_id"); - b.HasOne("DysonNetwork.Sphere.Chat.ChatMember", "Sender") + b.HasOne("DysonNetwork.Shared.Models.SnChatMember", "Sender") .WithMany() .HasForeignKey("SenderId") .OnDelete(DeleteBehavior.Cascade) @@ -1757,203 +1943,9 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Sender"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Poll.Poll", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnSticker", b => { - b.HasOne("DysonNetwork.Sphere.Publisher.Publisher", "Publisher") - .WithMany("Polls") - .HasForeignKey("PublisherId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_polls_publishers_publisher_id"); - - b.Navigation("Publisher"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Poll.PollAnswer", b => - { - b.HasOne("DysonNetwork.Sphere.Poll.Poll", "Poll") - .WithMany() - .HasForeignKey("PollId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_poll_answers_polls_poll_id"); - - b.Navigation("Poll"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Poll.PollQuestion", b => - { - b.HasOne("DysonNetwork.Sphere.Poll.Poll", "Poll") - .WithMany("Questions") - .HasForeignKey("PollId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_poll_questions_polls_poll_id"); - - b.Navigation("Poll"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Post.Post", b => - { - b.HasOne("DysonNetwork.Sphere.Post.Post", "ForwardedPost") - .WithMany() - .HasForeignKey("ForwardedPostId") - .OnDelete(DeleteBehavior.Restrict) - .HasConstraintName("fk_posts_posts_forwarded_post_id"); - - b.HasOne("DysonNetwork.Sphere.Publisher.Publisher", "Publisher") - .WithMany("Posts") - .HasForeignKey("PublisherId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_posts_publishers_publisher_id"); - - b.HasOne("DysonNetwork.Sphere.Realm.Realm", "Realm") - .WithMany() - .HasForeignKey("RealmId") - .HasConstraintName("fk_posts_realms_realm_id"); - - b.HasOne("DysonNetwork.Sphere.Post.Post", "RepliedPost") - .WithMany() - .HasForeignKey("RepliedPostId") - .OnDelete(DeleteBehavior.Restrict) - .HasConstraintName("fk_posts_posts_replied_post_id"); - - b.Navigation("ForwardedPost"); - - b.Navigation("Publisher"); - - b.Navigation("Realm"); - - b.Navigation("RepliedPost"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostAward", b => - { - b.HasOne("DysonNetwork.Sphere.Post.Post", "Post") - .WithMany("Awards") - .HasForeignKey("PostId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_post_awards_posts_post_id"); - - b.Navigation("Post"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostCategorySubscription", b => - { - b.HasOne("DysonNetwork.Sphere.Post.PostCategory", "Category") - .WithMany() - .HasForeignKey("CategoryId") - .HasConstraintName("fk_post_category_subscriptions_post_categories_category_id"); - - b.HasOne("DysonNetwork.Sphere.Post.PostTag", "Tag") - .WithMany() - .HasForeignKey("TagId") - .HasConstraintName("fk_post_category_subscriptions_post_tags_tag_id"); - - b.Navigation("Category"); - - b.Navigation("Tag"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostCollection", b => - { - b.HasOne("DysonNetwork.Sphere.Publisher.Publisher", "Publisher") - .WithMany("Collections") - .HasForeignKey("PublisherId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_post_collections_publishers_publisher_id"); - - b.Navigation("Publisher"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostFeaturedRecord", b => - { - b.HasOne("DysonNetwork.Sphere.Post.Post", "Post") - .WithMany() - .HasForeignKey("PostId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_post_featured_records_posts_post_id"); - - b.Navigation("Post"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Post.PostReaction", b => - { - b.HasOne("DysonNetwork.Sphere.Post.Post", "Post") - .WithMany("Reactions") - .HasForeignKey("PostId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_post_reactions_posts_post_id"); - - b.Navigation("Post"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.Publisher", b => - { - b.HasOne("DysonNetwork.Sphere.Realm.Realm", "Realm") - .WithMany() - .HasForeignKey("RealmId") - .HasConstraintName("fk_publishers_realms_realm_id"); - - b.Navigation("Realm"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.PublisherFeature", b => - { - b.HasOne("DysonNetwork.Sphere.Publisher.Publisher", "Publisher") - .WithMany("Features") - .HasForeignKey("PublisherId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_publisher_features_publishers_publisher_id"); - - b.Navigation("Publisher"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.PublisherMember", b => - { - b.HasOne("DysonNetwork.Sphere.Publisher.Publisher", "Publisher") - .WithMany("Members") - .HasForeignKey("PublisherId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_publisher_members_publishers_publisher_id"); - - b.Navigation("Publisher"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.PublisherSubscription", b => - { - b.HasOne("DysonNetwork.Sphere.Publisher.Publisher", "Publisher") - .WithMany("Subscriptions") - .HasForeignKey("PublisherId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_publisher_subscriptions_publishers_publisher_id"); - - b.Navigation("Publisher"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Realm.RealmMember", b => - { - b.HasOne("DysonNetwork.Sphere.Realm.Realm", "Realm") - .WithMany("Members") - .HasForeignKey("RealmId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_realm_members_realms_realm_id"); - - b.Navigation("Realm"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Sticker.Sticker", b => - { - b.HasOne("DysonNetwork.Sphere.Sticker.StickerPack", "Pack") + b.HasOne("DysonNetwork.Shared.Models.StickerPack", "Pack") .WithMany("Stickers") .HasForeignKey("PackId") .OnDelete(DeleteBehavior.Cascade) @@ -1963,9 +1955,9 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Pack"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Sticker.StickerPack", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPack", b => { - b.HasOne("DysonNetwork.Sphere.Publisher.Publisher", "Publisher") + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") .WithMany() .HasForeignKey("PublisherId") .OnDelete(DeleteBehavior.Cascade) @@ -1975,9 +1967,9 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Publisher"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Sticker.StickerPackOwnership", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPackOwnership", b => { - b.HasOne("DysonNetwork.Sphere.Sticker.StickerPack", "Pack") + b.HasOne("DysonNetwork.Shared.Models.StickerPack", "Pack") .WithMany("Ownerships") .HasForeignKey("PackId") .OnDelete(DeleteBehavior.Cascade) @@ -2001,7 +1993,7 @@ namespace DysonNetwork.Sphere.Migrations modelBuilder.Entity("DysonNetwork.Sphere.WebReader.WebFeed", b => { - b.HasOne("DysonNetwork.Sphere.Publisher.Publisher", "Publisher") + b.HasOne("DysonNetwork.Shared.Models.SnPublisher", "Publisher") .WithMany() .HasForeignKey("PublisherId") .OnDelete(DeleteBehavior.Cascade) @@ -2023,16 +2015,16 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Feed"); }); - modelBuilder.Entity("PostPostCategory", b => + modelBuilder.Entity("SnPostSnPostCategory", b => { - b.HasOne("DysonNetwork.Sphere.Post.PostCategory", null) + b.HasOne("DysonNetwork.Shared.Models.SnPostCategory", null) .WithMany() .HasForeignKey("CategoriesId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() .HasConstraintName("fk_post_category_links_post_categories_categories_id"); - b.HasOne("DysonNetwork.Sphere.Post.Post", null) + b.HasOne("DysonNetwork.Shared.Models.SnPost", null) .WithMany() .HasForeignKey("PostsId") .OnDelete(DeleteBehavior.Cascade) @@ -2040,16 +2032,16 @@ namespace DysonNetwork.Sphere.Migrations .HasConstraintName("fk_post_category_links_posts_posts_id"); }); - modelBuilder.Entity("PostPostCollection", b => + modelBuilder.Entity("SnPostSnPostCollection", b => { - b.HasOne("DysonNetwork.Sphere.Post.PostCollection", null) + b.HasOne("DysonNetwork.Shared.Models.SnPostCollection", null) .WithMany() .HasForeignKey("CollectionsId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() .HasConstraintName("fk_post_collection_links_post_collections_collections_id"); - b.HasOne("DysonNetwork.Sphere.Post.Post", null) + b.HasOne("DysonNetwork.Shared.Models.SnPost", null) .WithMany() .HasForeignKey("PostsId") .OnDelete(DeleteBehavior.Cascade) @@ -2057,16 +2049,16 @@ namespace DysonNetwork.Sphere.Migrations .HasConstraintName("fk_post_collection_links_posts_posts_id"); }); - modelBuilder.Entity("PostPostTag", b => + modelBuilder.Entity("SnPostSnPostTag", b => { - b.HasOne("DysonNetwork.Sphere.Post.Post", null) + b.HasOne("DysonNetwork.Shared.Models.SnPost", null) .WithMany() .HasForeignKey("PostsId") .OnDelete(DeleteBehavior.Cascade) .IsRequired() .HasConstraintName("fk_post_tag_links_posts_posts_id"); - b.HasOne("DysonNetwork.Sphere.Post.PostTag", null) + b.HasOne("DysonNetwork.Shared.Models.SnPostTag", null) .WithMany() .HasForeignKey("TagsId") .OnDelete(DeleteBehavior.Cascade) @@ -2074,29 +2066,29 @@ namespace DysonNetwork.Sphere.Migrations .HasConstraintName("fk_post_tag_links_post_tags_tags_id"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatRoom", b => - { - b.Navigation("Members"); - }); - - modelBuilder.Entity("DysonNetwork.Sphere.Chat.Message", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatMessage", b => { b.Navigation("Reactions"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Poll.Poll", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnChatRoom", b => + { + b.Navigation("Members"); + }); + + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPoll", b => { b.Navigation("Questions"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Post.Post", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPost", b => { b.Navigation("Awards"); b.Navigation("Reactions"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Publisher.Publisher", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnPublisher", b => { b.Navigation("Collections"); @@ -2111,14 +2103,14 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Subscriptions"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Realm.Realm", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.SnRealm", b => { b.Navigation("ChatRooms"); b.Navigation("Members"); }); - modelBuilder.Entity("DysonNetwork.Sphere.Sticker.StickerPack", b => + modelBuilder.Entity("DysonNetwork.Shared.Models.StickerPack", b => { b.Navigation("Ownerships"); diff --git a/DysonNetwork.Sphere/Poll/PollController.cs b/DysonNetwork.Sphere/Poll/PollController.cs index df488b0..211c3e9 100644 --- a/DysonNetwork.Sphere/Poll/PollController.cs +++ b/DysonNetwork.Sphere/Poll/PollController.cs @@ -16,7 +16,7 @@ public class PollController( AppDatabase db, PollService polls, Publisher.PublisherService pub, - AccountClientHelper accountsHelper + RemoteAccountService remoteAccountsHelper ) : ControllerBase { [HttpGet("{id:guid}")] @@ -110,7 +110,7 @@ public class PollController( if (!poll.IsAnonymous) { var answeredAccountsId = answers.Select(x => x.AccountId).Distinct().ToList(); - var answeredAccounts = await accountsHelper.GetAccountBatch(answeredAccountsId); + var answeredAccounts = await remoteAccountsHelper.GetAccountBatch(answeredAccountsId); // Populate Account field for each answer foreach (var answer in answers) diff --git a/DysonNetwork.Sphere/Post/PostController.cs b/DysonNetwork.Sphere/Post/PostController.cs index e71fcf4..8787ac8 100644 --- a/DysonNetwork.Sphere/Post/PostController.cs +++ b/DysonNetwork.Sphere/Post/PostController.cs @@ -6,7 +6,7 @@ using DysonNetwork.Shared.Models; using DysonNetwork.Shared.Proto; using DysonNetwork.Shared.Registry; using DysonNetwork.Sphere.Poll; -using DysonNetwork.Sphere.Realm; + using DysonNetwork.Sphere.WebReader; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -24,12 +24,12 @@ public class PostController( AppDatabase db, PostService ps, PublisherService pub, - AccountClientHelper accountsHelper, + RemoteAccountService remoteAccountsHelper, AccountService.AccountServiceClient accounts, ActionLogService.ActionLogServiceClient als, PaymentService.PaymentServiceClient payments, PollService polls, - RealmService rs + RemoteRealmService rs ) : ControllerBase { @@ -108,7 +108,7 @@ public class PostController( var userRealms = currentUser is null ? [] : await rs.GetUserRealms(accountId); var publisher = pubName == null ? null : await db.Publishers.FirstOrDefaultAsync(p => p.Name == pubName); - var realm = realmName == null ? null : await db.Realms.FirstOrDefaultAsync(r => r.Slug == realmName); + var realm = realmName == null ? null : (realmName != null ? await rs.GetRealmBySlug(realmName) : null); var query = db.Posts .Include(e => e.Categories) @@ -274,7 +274,7 @@ public class PostController( .Skip(offset) .ToListAsync(); - var accountsProto = await accountsHelper.GetAccountBatch(reactions.Select(r => r.AccountId).ToList()); + var accountsProto = await remoteAccountsHelper.GetAccountBatch(reactions.Select(r => r.AccountId).ToList()); var accounts = accountsProto.ToDictionary(a => Guid.Parse(a.Id), a => SnAccount.FromProtoValue(a)); foreach (var reaction in reactions) @@ -480,9 +480,8 @@ public class PostController( if (request.RealmId is not null) { - var realm = await db.Realms.FindAsync(request.RealmId.Value); - if (realm is null) return BadRequest("Realm was not found."); - if (!await rs.IsMemberWithRole(realm.Id, accountId, RealmMemberRole.Normal)) + var realm = await rs.GetRealm(request.RealmId.Value.ToString()); + if (!await rs.IsMemberWithRole(realm.Id, accountId, new List { RealmMemberRole.Normal })) return StatusCode(403, "You are not a member of this realm."); post.RealmId = realm.Id; } @@ -708,7 +707,7 @@ public class PostController( if (request.Mode == PostPinMode.RealmPage && post.RealmId != null) { - if (!await rs.IsMemberWithRole(post.RealmId.Value, accountId, RealmMemberRole.Moderator)) + if (!await rs.IsMemberWithRole(post.RealmId.Value, accountId, new List { RealmMemberRole.Moderator })) return StatusCode(403, "You are not a moderator of this realm"); } @@ -756,7 +755,7 @@ public class PostController( if (post is { PinMode: PostPinMode.RealmPage, RealmId: not null }) { - if (!await rs.IsMemberWithRole(post.RealmId.Value, accountId, RealmMemberRole.Moderator)) + if (!await rs.IsMemberWithRole(post.RealmId.Value, accountId, new List { RealmMemberRole.Moderator })) return StatusCode(403, "You are not a moderator of this realm"); } @@ -865,9 +864,8 @@ public class PostController( // The realm is the same as well as the poll if (request.RealmId is not null) { - var realm = await db.Realms.FindAsync(request.RealmId.Value); - if (realm is null) return BadRequest("Realm was not found."); - if (!await rs.IsMemberWithRole(realm.Id, accountId, RealmMemberRole.Normal)) + var realm = await rs.GetRealm(request.RealmId.Value.ToString()); + if (!await rs.IsMemberWithRole(realm.Id, accountId, new List { RealmMemberRole.Normal })) return StatusCode(403, "You are not a member of this realm."); post.RealmId = realm.Id; } diff --git a/DysonNetwork.Sphere/Post/PostService.cs b/DysonNetwork.Sphere/Post/PostService.cs index 4f30e3b..558888a 100644 --- a/DysonNetwork.Sphere/Post/PostService.cs +++ b/DysonNetwork.Sphere/Post/PostService.cs @@ -938,7 +938,7 @@ public partial class PostService( var pub = scope.ServiceProvider.GetRequiredService(); var nty = scope.ServiceProvider.GetRequiredService(); var accounts = scope.ServiceProvider.GetRequiredService(); - var accountsHelper = scope.ServiceProvider.GetRequiredService(); + var accountsHelper = scope.ServiceProvider.GetRequiredService(); try { var sender = await accountsHelper.GetAccount(accountId); diff --git a/DysonNetwork.Sphere/Publisher/PublisherService.cs b/DysonNetwork.Sphere/Publisher/PublisherService.cs index 8152ba3..6feaa9a 100644 --- a/DysonNetwork.Sphere/Publisher/PublisherService.cs +++ b/DysonNetwork.Sphere/Publisher/PublisherService.cs @@ -11,7 +11,7 @@ public class PublisherService( AppDatabase db, FileReferenceService.FileReferenceServiceClient fileRefs, ICacheService cache, - AccountClientHelper accountsHelper + RemoteAccountService remoteAccountsHelper ) { public async Task GetPublisherByName(string name) @@ -420,7 +420,7 @@ public class PublisherService( public async Task LoadMemberAccount(SnPublisherMember member) { - var account = await accountsHelper.GetAccount(member.AccountId); + var account = await remoteAccountsHelper.GetAccount(member.AccountId); member.Account = SnAccount.FromProtoValue(account); return member; } @@ -428,7 +428,7 @@ public class PublisherService( public async Task> LoadMemberAccounts(ICollection members) { var accountIds = members.Select(m => m.AccountId).ToList(); - var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a); + var accounts = (await remoteAccountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a); return [.. members.Select(m => { diff --git a/DysonNetwork.Sphere/Startup/BroadcastEventHandler.cs b/DysonNetwork.Sphere/Startup/BroadcastEventHandler.cs index 644f470..94a222a 100644 --- a/DysonNetwork.Sphere/Startup/BroadcastEventHandler.cs +++ b/DysonNetwork.Sphere/Startup/BroadcastEventHandler.cs @@ -134,10 +134,6 @@ public class BroadcastEventHandler( .Where(m => m.AccountId == evt.AccountId) .ExecuteDeleteAsync(cancellationToken: stoppingToken); - await db.RealmMembers - .Where(m => m.AccountId == evt.AccountId) - .ExecuteDeleteAsync(cancellationToken: stoppingToken); - await using var transaction = await db.Database.BeginTransactionAsync(cancellationToken: stoppingToken); try { diff --git a/DysonNetwork.Sphere/Startup/ServiceCollectionExtensions.cs b/DysonNetwork.Sphere/Startup/ServiceCollectionExtensions.cs index 6836381..cf0ea47 100644 --- a/DysonNetwork.Sphere/Startup/ServiceCollectionExtensions.cs +++ b/DysonNetwork.Sphere/Startup/ServiceCollectionExtensions.cs @@ -5,7 +5,6 @@ using DysonNetwork.Sphere.Chat.Realtime; using DysonNetwork.Sphere.Localization; using DysonNetwork.Sphere.Post; using DysonNetwork.Sphere.Publisher; -using DysonNetwork.Sphere.Realm; using DysonNetwork.Sphere.Sticker; using Microsoft.AspNetCore.RateLimiting; using NodaTime; @@ -110,7 +109,6 @@ public static class ServiceCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -119,7 +117,8 @@ public static class ServiceCollectionExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.AddScoped(); var translationProvider = configuration["Translation:Provider"]?.ToLower();