✨ Realm member listing apis
This commit is contained in:
parent
573f984e2c
commit
5844dfb657
@ -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
|
||||
};
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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; }
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user