From cec8c3af81564e0faecb024f3349d4b82de7e681 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Wed, 16 Apr 2025 01:16:35 +0800 Subject: [PATCH] :card_file_box: Add account relationships --- DysonNetwork.Sphere/Account/Account.cs | 15 +- DysonNetwork.Sphere/Account/Relationship.cs | 18 + DysonNetwork.Sphere/AppDatabase.cs | 24 +- DysonNetwork.Sphere/Auth/Session.cs | 4 +- ...20250415171044_AddRelationship.Designer.cs | 601 ++++++++++++++++++ .../20250415171044_AddRelationship.cs | 55 ++ .../Migrations/AppDatabaseModelSnapshot.cs | 60 ++ DysonNetwork.Sphere/Storage/CloudFile.cs | 2 +- 8 files changed, 764 insertions(+), 15 deletions(-) create mode 100644 DysonNetwork.Sphere/Account/Relationship.cs create mode 100644 DysonNetwork.Sphere/Migrations/20250415171044_AddRelationship.Designer.cs create mode 100644 DysonNetwork.Sphere/Migrations/20250415171044_AddRelationship.cs diff --git a/DysonNetwork.Sphere/Account/Account.cs b/DysonNetwork.Sphere/Account/Account.cs index ffadf74..370aa31 100644 --- a/DysonNetwork.Sphere/Account/Account.cs +++ b/DysonNetwork.Sphere/Account/Account.cs @@ -4,7 +4,7 @@ using NodaTime; namespace DysonNetwork.Sphere.Account; -public class Account : BaseModel +public class Account : ModelBase { public long Id { get; set; } [MaxLength(256)] public string Name { get; set; } = string.Empty; @@ -18,23 +18,26 @@ public class Account : BaseModel [JsonIgnore] public ICollection AuthFactors { get; set; } = new List(); [JsonIgnore] public ICollection Sessions { get; set; } = new List(); [JsonIgnore] public ICollection Challenges { get; set; } = new List(); + + [JsonIgnore] public ICollection OutgoingRelationships { get; set; } = new List(); + [JsonIgnore] public ICollection IncomingRelationships { get; set; } = new List(); } -public class Profile : BaseModel +public class Profile : ModelBase { public long Id { get; set; } [MaxLength(256)] public string? FirstName { get; set; } [MaxLength(256)] public string? MiddleName { get; set; } [MaxLength(256)] public string? LastName { get; set; } [MaxLength(4096)] public string? Bio { get; set; } - + public Storage.CloudFile? Picture { get; set; } public Storage.CloudFile? Background { get; set; } - + [JsonIgnore] public Account Account { get; set; } = null!; } -public class AccountContact : BaseModel +public class AccountContact : ModelBase { public long Id { get; set; } public AccountContactType Type { get; set; } @@ -51,7 +54,7 @@ public enum AccountContactType Address } -public class AccountAuthFactor : BaseModel +public class AccountAuthFactor : ModelBase { public long Id { get; set; } public AccountAuthFactorType Type { get; set; } diff --git a/DysonNetwork.Sphere/Account/Relationship.cs b/DysonNetwork.Sphere/Account/Relationship.cs new file mode 100644 index 0000000..011f871 --- /dev/null +++ b/DysonNetwork.Sphere/Account/Relationship.cs @@ -0,0 +1,18 @@ +namespace DysonNetwork.Sphere.Account; + +public enum RelationshipType +{ + Friend, + Blocked +} + +public class Relationship : ModelBase +{ + public long FromAccountId { get; set; } + public Account FromAccount { get; set; } = null!; + + public long ToAccountId { get; set; } + public Account ToAccount { get; set; } = null!; + + public RelationshipType Type { get; set; } +} \ No newline at end of file diff --git a/DysonNetwork.Sphere/AppDatabase.cs b/DysonNetwork.Sphere/AppDatabase.cs index 493956b..1d59799 100644 --- a/DysonNetwork.Sphere/AppDatabase.cs +++ b/DysonNetwork.Sphere/AppDatabase.cs @@ -7,7 +7,7 @@ using Quartz; namespace DysonNetwork.Sphere; -public abstract class BaseModel +public abstract class ModelBase { public Instant CreatedAt { get; set; } public Instant UpdatedAt { get; set; } @@ -23,6 +23,7 @@ public class AppDatabase( public DbSet AccountProfiles { get; set; } public DbSet AccountContacts { get; set; } public DbSet AccountAuthFactors { get; set; } + public DbSet AccountRelationships { get; set; } public DbSet AuthSessions { get; set; } public DbSet AuthChallenges { get; set; } public DbSet Files { get; set; } @@ -51,10 +52,21 @@ public class AppDatabase( .WithOne(p => p.Account) .HasForeignKey(p => p.Id); + modelBuilder.Entity() + .HasKey(r => new { r.FromAccountId, r.ToAccountId }); + modelBuilder.Entity() + .HasOne(r => r.FromAccount) + .WithMany(a => a.OutgoingRelationships) + .HasForeignKey(r => r.FromAccountId); + modelBuilder.Entity() + .HasOne(r => r.ToAccount) + .WithMany(a => a.IncomingRelationships) + .HasForeignKey(r => r.ToAccountId); + // Automatically apply soft-delete filter to all entities inheriting BaseModel foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { - if (typeof(BaseModel).IsAssignableFrom(entityType.ClrType)) + if (typeof(ModelBase).IsAssignableFrom(entityType.ClrType)) { var method = typeof(AppDatabase) .GetMethod(nameof(SetSoftDeleteFilter), @@ -67,7 +79,7 @@ public class AppDatabase( } private static void SetSoftDeleteFilter(ModelBuilder modelBuilder) - where TEntity : BaseModel + where TEntity : ModelBase { modelBuilder.Entity().HasQueryFilter(e => e.DeletedAt == null); } @@ -76,7 +88,7 @@ public class AppDatabase( { var now = SystemClock.Instance.GetCurrentInstant(); - foreach (var entry in ChangeTracker.Entries()) + foreach (var entry in ChangeTracker.Entries()) { switch (entry.State) { @@ -112,7 +124,7 @@ public class AppDatabaseRecyclingJob(AppDatabase db, ILogger typeof(BaseModel).IsAssignableFrom(t.ClrType) && t.ClrType != typeof(BaseModel)) + .Where(t => typeof(ModelBase).IsAssignableFrom(t.ClrType) && t.ClrType != typeof(ModelBase)) .Select(t => t.ClrType); foreach (var entityType in entityTypes) @@ -120,7 +132,7 @@ public class AppDatabaseRecyclingJob(AppDatabase db, ILogger +using System; +using System.Collections.Generic; +using DysonNetwork.Sphere; +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.Sphere.Migrations +{ + [DbContext(typeof(AppDatabase))] + [Migration("20250415171044_AddRelationship")] + partial class AddRelationship + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("DysonNetwork.Sphere.Account.Account", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("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("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_accounts"); + + b.ToTable("accounts", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Account.AccountAuthFactor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint") + .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("Secret") + .HasColumnType("text") + .HasColumnName("secret"); + + 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.Sphere.Account.AccountContact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint") + .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("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.Sphere.Account.Profile", b => + { + b.Property("Id") + .HasColumnType("bigint") + .HasColumnName("id"); + + b.Property("BackgroundId") + .HasColumnType("text") + .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("FirstName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("first_name"); + + b.Property("LastName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("last_name"); + + b.Property("MiddleName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("middle_name"); + + b.Property("PictureId") + .HasColumnType("text") + .HasColumnName("picture_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_account_profiles"); + + b.HasIndex("BackgroundId") + .HasDatabaseName("ix_account_profiles_background_id"); + + b.HasIndex("PictureId") + .HasDatabaseName("ix_account_profiles_picture_id"); + + b.ToTable("account_profiles", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Account.Relationship", b => + { + b.Property("FromAccountId") + .HasColumnType("bigint") + .HasColumnName("from_account_id"); + + b.Property("ToAccountId") + .HasColumnType("bigint") + .HasColumnName("to_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("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("FromAccountId", "ToAccountId") + .HasName("pk_account_relationships"); + + b.HasIndex("ToAccountId") + .HasDatabaseName("ix_account_relationships_to_account_id"); + + b.ToTable("account_relationships", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Auth.Challenge", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("bigint") + .HasColumnName("account_id"); + + b.Property>("Audiences") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("audiences"); + + b.Property>("BlacklistFactors") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("blacklist_factors"); + + 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") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("device_id"); + + b.Property("ExpiredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expired_at"); + + b.Property("IpAddress") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("ip_address"); + + 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("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.ToTable("auth_challenges", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Auth.Session", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("bigint") + .HasColumnName("account_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.Sphere.Storage.CloudFile", b => + { + b.Property("Id") + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("AccountId") + .HasColumnType("bigint") + .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("Description") + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("description"); + + b.Property>("FileMeta") + .HasColumnType("jsonb") + .HasColumnName("file_meta"); + + b.Property("Hash") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("hash"); + + b.Property("MimeType") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("mime_type"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("name"); + + b.Property("Size") + .HasColumnType("bigint") + .HasColumnName("size"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UploadedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("uploaded_at"); + + b.Property("UploadedTo") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("uploaded_to"); + + b.Property("UsedCount") + .HasColumnType("integer") + .HasColumnName("used_count"); + + b.Property>("UserMeta") + .HasColumnType("jsonb") + .HasColumnName("user_meta"); + + b.HasKey("Id") + .HasName("pk_files"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_files_account_id"); + + b.ToTable("files", (string)null); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Account.AccountAuthFactor", b => + { + b.HasOne("DysonNetwork.Sphere.Account.Account", "Account") + .WithMany("AuthFactors") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_auth_factors_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Account.AccountContact", b => + { + b.HasOne("DysonNetwork.Sphere.Account.Account", "Account") + .WithMany("Contacts") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_contacts_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Account.Profile", b => + { + b.HasOne("DysonNetwork.Sphere.Storage.CloudFile", "Background") + .WithMany() + .HasForeignKey("BackgroundId") + .HasConstraintName("fk_account_profiles_files_background_id"); + + b.HasOne("DysonNetwork.Sphere.Account.Account", "Account") + .WithOne("Profile") + .HasForeignKey("DysonNetwork.Sphere.Account.Profile", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_profiles_accounts_id"); + + b.HasOne("DysonNetwork.Sphere.Storage.CloudFile", "Picture") + .WithMany() + .HasForeignKey("PictureId") + .HasConstraintName("fk_account_profiles_files_picture_id"); + + b.Navigation("Account"); + + b.Navigation("Background"); + + b.Navigation("Picture"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Account.Relationship", b => + { + b.HasOne("DysonNetwork.Sphere.Account.Account", "FromAccount") + .WithMany("OutgoingRelationships") + .HasForeignKey("FromAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_relationships_accounts_from_account_id"); + + b.HasOne("DysonNetwork.Sphere.Account.Account", "ToAccount") + .WithMany("IncomingRelationships") + .HasForeignKey("ToAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_relationships_accounts_to_account_id"); + + b.Navigation("FromAccount"); + + b.Navigation("ToAccount"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Auth.Challenge", b => + { + b.HasOne("DysonNetwork.Sphere.Account.Account", "Account") + .WithMany("Challenges") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_challenges_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Auth.Session", b => + { + b.HasOne("DysonNetwork.Sphere.Account.Account", "Account") + .WithMany("Sessions") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_sessions_accounts_account_id"); + + b.HasOne("DysonNetwork.Sphere.Auth.Challenge", "Challenge") + .WithMany() + .HasForeignKey("ChallengeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_auth_sessions_auth_challenges_challenge_id"); + + b.Navigation("Account"); + + b.Navigation("Challenge"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Storage.CloudFile", b => + { + b.HasOne("DysonNetwork.Sphere.Account.Account", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_files_accounts_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("DysonNetwork.Sphere.Account.Account", b => + { + b.Navigation("AuthFactors"); + + b.Navigation("Challenges"); + + b.Navigation("Contacts"); + + b.Navigation("IncomingRelationships"); + + b.Navigation("OutgoingRelationships"); + + b.Navigation("Profile") + .IsRequired(); + + b.Navigation("Sessions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DysonNetwork.Sphere/Migrations/20250415171044_AddRelationship.cs b/DysonNetwork.Sphere/Migrations/20250415171044_AddRelationship.cs new file mode 100644 index 0000000..8daf184 --- /dev/null +++ b/DysonNetwork.Sphere/Migrations/20250415171044_AddRelationship.cs @@ -0,0 +1,55 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using NodaTime; + +#nullable disable + +namespace DysonNetwork.Sphere.Migrations +{ + /// + public partial class AddRelationship : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "account_relationships", + columns: table => new + { + from_account_id = table.Column(type: "bigint", nullable: false), + to_account_id = table.Column(type: "bigint", nullable: false), + type = table.Column(type: "integer", 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_account_relationships", x => new { x.from_account_id, x.to_account_id }); + table.ForeignKey( + name: "fk_account_relationships_accounts_from_account_id", + column: x => x.from_account_id, + principalTable: "accounts", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_account_relationships_accounts_to_account_id", + column: x => x.to_account_id, + principalTable: "accounts", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "ix_account_relationships_to_account_id", + table: "account_relationships", + column: "to_account_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "account_relationships"); + } + } +} diff --git a/DysonNetwork.Sphere/Migrations/AppDatabaseModelSnapshot.cs b/DysonNetwork.Sphere/Migrations/AppDatabaseModelSnapshot.cs index 664e2f0..38784cd 100644 --- a/DysonNetwork.Sphere/Migrations/AppDatabaseModelSnapshot.cs +++ b/DysonNetwork.Sphere/Migrations/AppDatabaseModelSnapshot.cs @@ -221,6 +221,41 @@ namespace DysonNetwork.Sphere.Migrations b.ToTable("account_profiles", (string)null); }); + modelBuilder.Entity("DysonNetwork.Sphere.Account.Relationship", b => + { + b.Property("FromAccountId") + .HasColumnType("bigint") + .HasColumnName("from_account_id"); + + b.Property("ToAccountId") + .HasColumnType("bigint") + .HasColumnName("to_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("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("FromAccountId", "ToAccountId") + .HasName("pk_account_relationships"); + + b.HasIndex("ToAccountId") + .HasDatabaseName("ix_account_relationships_to_account_id"); + + b.ToTable("account_relationships", (string)null); + }); + modelBuilder.Entity("DysonNetwork.Sphere.Auth.Challenge", b => { b.Property("Id") @@ -474,6 +509,27 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Picture"); }); + modelBuilder.Entity("DysonNetwork.Sphere.Account.Relationship", b => + { + b.HasOne("DysonNetwork.Sphere.Account.Account", "FromAccount") + .WithMany("OutgoingRelationships") + .HasForeignKey("FromAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_relationships_accounts_from_account_id"); + + b.HasOne("DysonNetwork.Sphere.Account.Account", "ToAccount") + .WithMany("IncomingRelationships") + .HasForeignKey("ToAccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_account_relationships_accounts_to_account_id"); + + b.Navigation("FromAccount"); + + b.Navigation("ToAccount"); + }); + modelBuilder.Entity("DysonNetwork.Sphere.Auth.Challenge", b => { b.HasOne("DysonNetwork.Sphere.Account.Account", "Account") @@ -527,6 +583,10 @@ namespace DysonNetwork.Sphere.Migrations b.Navigation("Contacts"); + b.Navigation("IncomingRelationships"); + + b.Navigation("OutgoingRelationships"); + b.Navigation("Profile") .IsRequired(); diff --git a/DysonNetwork.Sphere/Storage/CloudFile.cs b/DysonNetwork.Sphere/Storage/CloudFile.cs index 43a6187..adcefd1 100644 --- a/DysonNetwork.Sphere/Storage/CloudFile.cs +++ b/DysonNetwork.Sphere/Storage/CloudFile.cs @@ -20,7 +20,7 @@ public class RemoteStorageConfig public string? AccessProxy { get; set; } } -public class CloudFile : BaseModel +public class CloudFile : ModelBase { public string Id { get; set; } = Guid.NewGuid().ToString(); [MaxLength(1024)] public string Name { get; set; } = string.Empty;