♻️ Centralized data models (wip)

This commit is contained in:
2025-09-27 14:09:28 +08:00
parent 51b6f7309e
commit e70d8371f8
206 changed files with 1352 additions and 2128 deletions

View File

@@ -1,56 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Data;
using DysonNetwork.Sphere.Chat;
using Microsoft.EntityFrameworkCore;
using NodaTime;
namespace DysonNetwork.Sphere.Realm;
[Index(nameof(Slug), IsUnique = true)]
public class Realm : ModelBase, IIdentifiedResource
{
public Guid Id { get; set; }
[MaxLength(1024)] public string Slug { get; set; } = string.Empty;
[MaxLength(1024)] public string Name { get; set; } = string.Empty;
[MaxLength(4096)] public string Description { get; set; } = string.Empty;
public bool IsCommunity { get; set; }
public bool IsPublic { get; set; }
// Outdated fields, for backward compability
[MaxLength(32)] public string? PictureId { get; set; }
[MaxLength(32)] public string? BackgroundId { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Picture { get; set; }
[Column(TypeName = "jsonb")] public CloudFileReferenceObject? Background { get; set; }
[Column(TypeName = "jsonb")] public VerificationMark? Verification { get; set; }
[JsonIgnore] public ICollection<RealmMember> Members { get; set; } = new List<RealmMember>();
[JsonIgnore] public ICollection<ChatRoom> ChatRooms { get; set; } = new List<ChatRoom>();
public Guid AccountId { get; set; }
public string ResourceIdentifier => $"realm:{Id}";
}
public abstract class RealmMemberRole
{
public const int Owner = 100;
public const int Moderator = 50;
public const int Normal = 0;
}
public class RealmMember : ModelBase
{
public Guid RealmId { get; set; }
public Realm Realm { get; set; } = null!;
public Guid AccountId { get; set; }
[NotMapped] public AccountReference? Account { get; set; }
[NotMapped] public AccountStatusReference? Status { get; set; }
public int Role { get; set; } = RealmMemberRole.Normal;
public Instant? JoinedAt { get; set; }
public Instant? LeaveAt { get; set; }
}

View File

@@ -1,5 +1,5 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Chat;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@@ -12,7 +12,7 @@ public class RealmChatController(AppDatabase db, RealmService rs) : ControllerBa
{
[HttpGet("chat")]
[Authorize]
public async Task<ActionResult<List<ChatRoom>>> ListRealmChat(string slug)
public async Task<ActionResult<List<SnChatRoom>>> ListRealmChat(string slug)
{
var currentUser = HttpContext.Items["CurrentUser"] as Account;
var accountId = currentUser is null ? Guid.Empty : Guid.Parse(currentUser.Id);

View File

@@ -1,5 +1,4 @@
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using Microsoft.AspNetCore.Authorization;
@@ -7,6 +6,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using Google.Protobuf.WellKnownTypes;
using DysonNetwork.Shared.Models;
namespace DysonNetwork.Sphere.Realm;
@@ -53,7 +53,7 @@ public class RealmController(
[HttpGet("invites")]
[Authorize]
public async Task<ActionResult<List<RealmMember>>> ListInvites()
public async Task<ActionResult<List<SnRealmMember>>> ListInvites()
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -75,7 +75,7 @@ public class RealmController(
[HttpPost("invites/{slug}")]
[Authorize]
public async Task<ActionResult<RealmMember>> InviteMember(string slug,
public async Task<ActionResult<SnRealmMember>> InviteMember(string slug,
[FromBody] RealmMemberRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -110,7 +110,7 @@ public class RealmController(
if (hasExistingMember)
return BadRequest("This user has been joined the realm or leave cannot be invited again.");
var member = new RealmMember
var member = new SnRealmMember
{
AccountId = Guid.Parse(relatedUser.Id),
RealmId = realm.Id,
@@ -211,7 +211,7 @@ public class RealmController(
[HttpGet("{slug}/members")]
public async Task<ActionResult<List<RealmMember>>> ListMembers(
public async Task<ActionResult<List<SnRealmMember>>> ListMembers(
string slug,
[FromQuery] int offset = 0,
[FromQuery] int take = 20,
@@ -281,7 +281,7 @@ public class RealmController(
[HttpGet("{slug}/members/me")]
[Authorize]
public async Task<ActionResult<RealmMember>> GetCurrentIdentity(string slug)
public async Task<ActionResult<SnRealmMember>> GetCurrentIdentity(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
@@ -362,7 +362,7 @@ public class RealmController(
AccountId = Guid.Parse(currentUser.Id),
IsCommunity = request.IsCommunity ?? false,
IsPublic = request.IsPublic ?? false,
Members = new List<RealmMember>
Members = new List<SnRealmMember>
{
new()
{
@@ -377,14 +377,14 @@ public class RealmController(
{
var pictureResult = await files.GetFileAsync(new GetFileRequest { Id = request.PictureId });
if (pictureResult is null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
realm.Picture = CloudFileReferenceObject.FromProtoValue(pictureResult);
realm.Picture = SnCloudFileReferenceObject.FromProtoValue(pictureResult);
}
if (request.BackgroundId is not null)
{
var backgroundResult = await files.GetFileAsync(new GetFileRequest { Id = request.BackgroundId });
if (backgroundResult is null) return BadRequest("Invalid background id, unable to find the file on cloud.");
realm.Background = CloudFileReferenceObject.FromProtoValue(backgroundResult);
realm.Background = SnCloudFileReferenceObject.FromProtoValue(backgroundResult);
}
db.Realms.Add(realm);
@@ -479,7 +479,7 @@ public class RealmController(
});
}
realm.Picture = CloudFileReferenceObject.FromProtoValue(pictureResult);
realm.Picture = SnCloudFileReferenceObject.FromProtoValue(pictureResult);
// Create a new reference
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
@@ -504,7 +504,7 @@ public class RealmController(
});
}
realm.Background = CloudFileReferenceObject.FromProtoValue(backgroundResult);
realm.Background = SnCloudFileReferenceObject.FromProtoValue(backgroundResult);
// Create a new reference
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
@@ -542,7 +542,7 @@ public class RealmController(
[HttpPost("{slug}/members/me")]
[Authorize]
public async Task<ActionResult<RealmMember>> JoinRealm(string slug)
public async Task<ActionResult<SnRealmMember>> JoinRealm(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
@@ -560,7 +560,7 @@ public class RealmController(
if (existingMember is not null)
return BadRequest("You are already a member of this realm.");
var member = new RealmMember
var member = new SnRealmMember
{
AccountId = Guid.Parse(currentUser.Id),
RealmId = realm.Id,
@@ -629,7 +629,7 @@ public class RealmController(
[HttpPatch("{slug}/members/{memberId:guid}/role")]
[Authorize]
public async Task<ActionResult<RealmMember>> UpdateMemberRole(string slug, Guid memberId, [FromBody] int newRole)
public async Task<ActionResult<SnRealmMember>> 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();

View File

@@ -1,6 +1,7 @@
using DysonNetwork.Shared;
using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Shared.Registry;
using DysonNetwork.Sphere.Localization;
@@ -39,7 +40,7 @@ public class RealmService(
return realms;
}
public async Task SendInviteNotify(RealmMember member)
public async Task SendInviteNotify(SnRealmMember member)
{
var account = await accounts.GetAccountAsync(new GetAccountRequest { Id = member.AccountId.ToString() });
CultureService.SetCultureInfo(account);
@@ -71,14 +72,14 @@ public class RealmService(
return member?.Role >= maxRequiredRole;
}
public async Task<RealmMember> LoadMemberAccount(RealmMember member)
public async Task<SnRealmMember> LoadMemberAccount(SnRealmMember member)
{
var account = await accountsHelper.GetAccount(member.AccountId);
member.Account = AccountReference.FromProtoValue(account);
member.Account = SnAccount.FromProtoValue(account);
return member;
}
public async Task<List<RealmMember>> LoadMemberAccounts(ICollection<RealmMember> members)
public async Task<List<SnRealmMember>> LoadMemberAccounts(ICollection<SnRealmMember> members)
{
var accountIds = members.Select(m => m.AccountId).ToList();
var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a);
@@ -86,7 +87,7 @@ public class RealmService(
return members.Select(m =>
{
if (accounts.TryGetValue(m.AccountId, out var account))
m.Account = AccountReference.FromProtoValue(account);
m.Account = SnAccount.FromProtoValue(account);
return m;
}).ToList();
}