🗃️ Realm database modeling

This commit is contained in:
LittleSheep 2025-05-02 00:08:21 +08:00
parent 24f1a3a9e9
commit 30db6ad9f1
6 changed files with 67 additions and 16 deletions

View File

@ -20,11 +20,11 @@ public class AppDatabase(
IConfiguration configuration
) : DbContext(options)
{
public DbSet<PermissionNode> PermissionNodes { get; set; } = null!;
public DbSet<PermissionGroup> PermissionGroups { get; set; } = null!;
public DbSet<PermissionGroupMember> PermissionGroupMembers { get; set; } = null!;
public DbSet<PermissionNode> PermissionNodes { get; set; }
public DbSet<PermissionGroup> PermissionGroups { get; set; }
public DbSet<PermissionGroupMember> PermissionGroupMembers { get; set; }
public DbSet<Account.MagicSpell> MagicSpells { get; set; } = null!;
public DbSet<Account.MagicSpell> MagicSpells { get; set; }
public DbSet<Account.Account> Accounts { get; set; }
public DbSet<Account.Profile> AccountProfiles { get; set; }
public DbSet<Account.AccountContact> AccountContacts { get; set; }
@ -48,6 +48,9 @@ public class AppDatabase(
public DbSet<Post.PostCategory> PostCategories { get; set; }
public DbSet<Post.PostCollection> PostCollections { get; set; }
public DbSet<Realm.Realm> Realms { get; set; }
public DbSet<Realm.RealmMember> RealmMembers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var dataSourceBuilder = new NpgsqlDataSourceBuilder(configuration.GetConnectionString("App"));
@ -154,19 +157,30 @@ public class AppDatabase(
.HasMany(p => p.Collections)
.WithMany(c => c.Posts)
.UsingEntity(j => j.ToTable("post_collection_links"));
modelBuilder.Entity<Realm.RealmMember>()
.HasKey(pm => new { pm.RealmId, pm.AccountId });
modelBuilder.Entity<Realm.RealmMember>()
.HasOne(pm => pm.Realm)
.WithMany(p => p.Members)
.HasForeignKey(pm => pm.RealmId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Post.PublisherMember>()
.HasOne(pm => pm.Account)
.WithMany()
.HasForeignKey(pm => pm.AccountId)
.OnDelete(DeleteBehavior.Cascade);
// Automatically apply soft-delete filter to all entities inheriting BaseModel
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
if (typeof(ModelBase).IsAssignableFrom(entityType.ClrType))
{
var method = typeof(AppDatabase)
.GetMethod(nameof(SetSoftDeleteFilter),
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)!
.MakeGenericMethod(entityType.ClrType);
if (!typeof(ModelBase).IsAssignableFrom(entityType.ClrType)) continue;
var method = typeof(AppDatabase)
.GetMethod(nameof(SetSoftDeleteFilter),
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)!
.MakeGenericMethod(entityType.ClrType);
method.Invoke(null, [modelBuilder]);
}
method.Invoke(null, [modelBuilder]);
}
}

View File

@ -23,7 +23,7 @@ public class PermissionService(AppDatabase db)
.ToListAsync();
var permission = await db.PermissionNodes
.Where(n => n.GroupId == null || groupsId.Contains(n.GroupId.Value))
.Where(n => n.Key == key && (n.GroupId != null || n.Actor == actor) && n.Area == area)
.Where(n => (n.Key == key || n.Key == "*") && (n.GroupId != null || n.Actor == actor) && n.Area == area)
.Where(n => n.ExpiredAt == null || n.ExpiredAt < now)
.Where(n => n.AffectedAt == null || n.AffectedAt >= now)
.FirstOrDefaultAsync();

View File

@ -41,7 +41,7 @@ public enum PublisherMemberRole
Viewer = 25
}
public class PublisherMember : ModelBase
public class PublisherMember
{
public long PublisherId { get; set; }
[JsonIgnore] public Publisher Publisher { get; set; } = null!;

View File

@ -1,6 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using DysonNetwork.Sphere.Storage;
using NodaTime;
namespace DysonNetwork.Sphere.Realm;
@ -12,7 +13,27 @@ public class Realm : ModelBase
public CloudFile? Picture { get; set; }
public CloudFile? Background { get; set; }
[JsonIgnore] public ICollection<RealmMember> Members { get; set; } = new List<RealmMember>();
public long? AccountId { get; set; }
[JsonIgnore] public Account.Account? Account { get; set; }
public long AccountId { get; set; }
[JsonIgnore] public Account.Account Account { get; set; }
}
public enum RealmMemberRole
{
Owner = 100,
Moderator = 50,
Normal = 0
}
public class RealmMember : ModelBase
{
public long RealmId { get; set; }
[JsonIgnore] public Realm Realm { get; set; } = null!;
public long AccountId { get; set; }
[JsonIgnore] public Account.Account Account { get; set; } = null!;
public RealmMemberRole Role { get; set; }
public Instant? JoinedAt { get; set; }
}

View File

@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Mvc;
namespace DysonNetwork.Sphere.Realm;
[ApiController]
[Route("/realms")]
public class RealmController : ControllerBase
{
}

View File

@ -0,0 +1,6 @@
namespace DysonNetwork.Sphere.Realm;
public class RealmService(AppDatabase db)
{
}