Realm member listing apis

This commit is contained in:
LittleSheep 2025-05-04 23:36:47 +08:00
parent 573f984e2c
commit 5844dfb657
4 changed files with 118 additions and 12 deletions

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Sphere.Storage;
using NodaTime;
@ -28,6 +29,11 @@ public class ChatRoom : ModelBase
public long? RealmId { get; set; }
public Realm.Realm? Realm { get; set; }
[NotMapped]
[JsonPropertyName("members")]
public ICollection<ChatMemberTransmissionObject> DirectMembers { get; set; } =
new List<ChatMemberTransmissionObject>();
}
public enum ChatMemberRole
@ -58,4 +64,38 @@ public class ChatMember : ModelBase
public ChatMemberNotify Notify { get; set; } = ChatMemberNotify.All;
public Instant? JoinedAt { get; set; }
public bool IsBot { get; set; } = false;
}
public class ChatMemberTransmissionObject : ModelBase
{
public Guid Id { get; set; }
public long ChatRoomId { get; set; }
public long AccountId { get; set; }
public Account.Account Account { get; set; } = null!;
[MaxLength(1024)] public string? Nick { get; set; }
public ChatMemberRole Role { get; set; } = ChatMemberRole.Member;
public ChatMemberNotify Notify { get; set; } = ChatMemberNotify.All;
public Instant? JoinedAt { get; set; }
public bool IsBot { get; set; } = false;
public static ChatMemberTransmissionObject FromEntity(ChatMember member)
{
return new ChatMemberTransmissionObject
{
Id = member.Id,
ChatRoomId = member.ChatRoomId,
AccountId = member.AccountId,
Account = member.Account,
Nick = member.Nick,
Role = member.Role,
Notify = member.Notify,
JoinedAt = member.JoinedAt,
IsBot = member.IsBot,
CreatedAt = member.CreatedAt,
UpdatedAt = member.UpdatedAt,
DeletedAt = member.DeletedAt
};
}
}

View File

@ -20,6 +20,16 @@ public class ChatRoomController(AppDatabase db, FileService fs, ChatRoomService
.Include(e => e.Realm)
.FirstOrDefaultAsync();
if (chatRoom is null) return NotFound();
if (chatRoom.Type != ChatRoomType.DirectMessage) return Ok(chatRoom);
// Preload members for direct messages
var currentUser = HttpContext.Items["CurrentUser"] as Account.Account;
var directMembers = await db.ChatMembers
.Where(m => (currentUser != null && m.AccountId != currentUser!.Id))
.Include(m => m.Account)
.Include(m => m.Account.Profile)
.ToListAsync();
chatRoom.DirectMembers = directMembers.Select(ChatMemberTransmissionObject.FromEntity).ToList();
return Ok(chatRoom);
}
@ -55,21 +65,22 @@ public class ChatRoomController(AppDatabase db, FileService fs, ChatRoomService
var result = chatRooms.Select(r =>
{
if (r.Type == ChatRoomType.DirectMessage && directMembers.TryGetValue(r.Id, out var otherMember))
r.Members = new List<ChatMember> { otherMember };
r.DirectMembers = new List<ChatMemberTransmissionObject>
{ ChatMemberTransmissionObject.FromEntity(otherMember) };
return r;
}).ToList();
return Ok(result);
}
public class DmCreationRequest
public class DirectMessageRequest
{
[Required] public long RelatedUserId { get; set; }
}
[HttpPost("direct")]
[Authorize]
public async Task<ActionResult<ChatRoom>> CreateDirectMessage([FromBody] DmCreationRequest request)
public async Task<ActionResult<ChatRoom>> CreateDirectMessage([FromBody] DirectMessageRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
return Unauthorized();

View File

@ -41,9 +41,9 @@ public enum RealmMemberRole
public class RealmMember : ModelBase
{
public long RealmId { get; set; }
[JsonIgnore] public Realm Realm { get; set; } = null!;
public Realm Realm { get; set; } = null!;
public long AccountId { get; set; }
[JsonIgnore] public Account.Account Account { get; set; } = null!;
public Account.Account Account { get; set; } = null!;
public RealmMemberRole Role { get; set; } = RealmMemberRole.Normal;
public Instant? JoinedAt { get; set; }

View File

@ -39,8 +39,6 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
return members.ToList();
}
[HttpGet("/")]
[HttpGet("invites")]
[Authorize]
@ -147,27 +145,84 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
return NoContent();
}
[HttpGet("{slug}/members")]
public async Task<ActionResult<List<RealmMember>>> ListMembers(
string slug,
[FromQuery] int offset = 0,
[FromQuery] int take = 20
)
{
var realm = await db.Realms
.Where(r => r.Slug == slug)
.FirstOrDefaultAsync();
if (realm is null) return NotFound();
[HttpDelete("{slug}/members/me")]
if (!realm.IsPublic)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var isMember = await db.RealmMembers
.AnyAsync(m => m.AccountId == currentUser.Id && m.RealmId == realm.Id && m.JoinedAt != null);
if (!isMember) return StatusCode(403, "You must be a member to view this realm's members.");
}
var query = db.RealmMembers
.Where(m => m.RealmId == realm.Id)
.Where(m => m.JoinedAt != null);
var total = await query.CountAsync();
Response.Headers["X-Total"] = total.ToString();
var members = await query
.OrderBy(m => m.CreatedAt)
.Skip(offset)
.Take(take)
.Include(m => m.Account)
.Include(m => m.Account.Profile)
.ToListAsync();
return Ok(members);
}
[HttpGet("{slug}/members/me")]
[Authorize]
public async Task<ActionResult> LeaveRealm(string slug)
public async Task<ActionResult<RealmMember>> GetCurrentIdentity(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var userId = currentUser.Id;
var member = await db.RealmMembers
.Where(m => m.AccountId == userId)
.Where(m => m.Realm.Slug == slug)
.Include(m => m.Account)
.Include(m => m.Account.Profile)
.FirstOrDefaultAsync();
if (member is null) return NotFound();
return Ok(member);
}
[HttpDelete("{slug}/members/me")]
[Authorize]
public async Task<ActionResult> LeaveRealm(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var userId = currentUser.Id;
var member = await db.RealmMembers
.Where(m => m.AccountId == userId)
.Where(m => m.Realm.Slug == slug)
.Where(m => m.JoinedAt != null)
.FirstOrDefaultAsync();
if (member is null) return NotFound();
if (member.Role == RealmMemberRole.Owner)
return StatusCode(403, "Owner cannot leave their own realm.");
db.RealmMembers.Remove(member);
await db.SaveChangesAsync();
return NoContent();
}