Chat controller

This commit is contained in:
LittleSheep 2025-05-02 12:07:09 +08:00
parent 8b5ca265b8
commit da6a891b5f
8 changed files with 2696 additions and 74 deletions

View File

@ -176,7 +176,7 @@ public class AppDatabase(
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Chat.ChatMember>()
.HasKey(pm => new { pm.ChatRoom, pm.AccountId });
.HasKey(pm => new { pm.ChatRoomId, pm.AccountId });
modelBuilder.Entity<Chat.ChatMember>()
.HasOne(pm => pm.ChatRoom)
.WithMany(p => p.Members)

View File

@ -1,50 +1,99 @@
using Microsoft.AspNetCore.Mvc;
using DysonNetwork.Sphere.Account;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Sphere.Account;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using DysonNetwork.Sphere.Realm;
using DysonNetwork.Sphere.Storage;
namespace DysonNetwork.Sphere.Chat;
[ApiController]
[Route("/chatrooms")]
[Route("/chat")]
public class ChatRoomController(AppDatabase db, FileService fs) : ControllerBase
{
[HttpGet("{id:long}")]
public async Task<ActionResult<ChatRoom>> GetChatRoom(long id)
{
var chatRoom = await db.ChatRooms
.Where(c => c.Id == id)
.Include(e => e.Picture)
.Include(e => e.Background)
.FirstOrDefaultAsync();
if (chatRoom is null) return NotFound();
return Ok(chatRoom);
}
[HttpGet]
public async Task<ActionResult<List<ChatRoom>>> ListJoinedChatRooms()
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var userId = currentUser.Id;
var members = await db.ChatMembers
.Where(m => m.AccountId == userId)
.Where(m => m.JoinedAt != null)
.Include(e => e.ChatRoom)
.Include(e => e.ChatRoom.Picture)
.Include(e => e.ChatRoom.Background)
.Include(e => e.ChatRoom.Type == ChatRoomType.DirectMessage ? e.ChatRoom.Members : null)
.Select(m => m.ChatRoom)
.ToListAsync();
return members.ToList();
}
public class ChatRoomRequest
{
[Required] [MaxLength(1024)] public string? Name { get; set; }
[MaxLength(4096)] public string? Description { get; set; }
public string? PictureId { get; set; }
public string? BackgroundId { get; set; }
public long? RealmId { get; set; }
}
[HttpPost]
public async Task<ActionResult<ChatRoom>> CreateChatRoom(ChatRoomRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
if (request.Name is null) return BadRequest("You cannot create a chat room without a name.");
CloudFile? picture = null;
if (request.PictureId is not null)
{
picture = await db.Files.FindAsync(request.PictureId);
if (picture is null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
}
CloudFile? background = null;
if (request.BackgroundId is not null)
{
background = await db.Files.FindAsync(request.BackgroundId);
if (background is null) return BadRequest("Invalid background id, unable to find the file on cloud.");
}
var chatRoom = new ChatRoom
{
Name = request.Name,
Description = request.Description ?? string.Empty,
Picture = picture,
Background = background,
CreatedAt = Instant.FromDateTimeUtc(DateTime.UtcNow)
Members = new List<ChatMember>
{
new()
{
Role = ChatMemberRole.Owner,
AccountId = currentUser.Id
}
}
};
if (request.RealmId is not null)
{
var member = await db.RealmMembers
.Where(m => m.AccountId == currentUser.Id)
.Where(m => m.RealmId == request.RealmId)
.FirstOrDefaultAsync();
if (member is null || member.Role < RealmMemberRole.Moderator)
return StatusCode(403, "You need at least be a moderator to create chat linked to the realm.");
chatRoom.RealmId = member.RealmId;
}
if (request.PictureId is not null)
{
chatRoom.Picture = await db.Files.FindAsync(request.PictureId);
if (chatRoom.Picture is null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
}
if (request.BackgroundId is not null)
{
chatRoom.Background = await db.Files.FindAsync(request.BackgroundId);
if (chatRoom.Background is null)
return BadRequest("Invalid background id, unable to find the file on cloud.");
}
db.ChatRooms.Add(chatRoom);
await db.SaveChangesAsync();
@ -56,79 +105,116 @@ public class ChatRoomController(AppDatabase db, FileService fs) : ControllerBase
return Ok(chatRoom);
}
[HttpGet("{id}")]
public async Task<ActionResult<ChatRoom>> GetChatRoom(long id)
{
var chatRoom = await db.ChatRooms.FindAsync(id);
if (chatRoom is null) return NotFound();
return Ok(chatRoom);
}
[HttpGet]
public async Task<ActionResult<List<ChatRoom>>> ListChatRooms()
{
var chatRooms = await db.ChatRooms.ToListAsync();
return chatRooms;
}
public class ChatRoomRequest
{
[Required]
[MaxLength(1024)]
public string? Name { get; set; }
[MaxLength(4096)] public string? Description { get; set; }
public string? PictureId { get; set; }
public string? BackgroundId { get; set; }
}
[HttpPut("{id}")]
[HttpPut("{id:long}")]
public async Task<ActionResult<ChatRoom>> UpdateChatRoom(long id, [FromBody] ChatRoomRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var chatRoom = await db.ChatRooms.FindAsync(id);
var chatRoom = await db.ChatRooms
.Where(e => e.Id == id)
.Include(c => c.Picture)
.Include(c => c.Background)
.FirstOrDefaultAsync();
if (chatRoom is null) return NotFound();
CloudFile? picture = null;
if (chatRoom.RealmId is not null)
{
var realmMember = await db.RealmMembers
.Where(m => m.AccountId == currentUser.Id)
.Where(m => m.RealmId == chatRoom.RealmId)
.FirstOrDefaultAsync();
if (realmMember is null || realmMember.Role < RealmMemberRole.Moderator)
return StatusCode(403, "You need at least be a realm moderator to update the chat.");
}
else
{
var chatMember = await db.ChatMembers
.Where(m => m.AccountId == currentUser.Id)
.Where(m => m.ChatRoomId == chatRoom.Id)
.FirstOrDefaultAsync();
if (chatMember is null || chatMember.Role < ChatMemberRole.Moderator)
return StatusCode(403, "You need at least be a moderator to update the chat.");
}
if (request.RealmId is not null)
{
var member = await db.RealmMembers
.Where(m => m.AccountId == currentUser.Id)
.Where(m => m.RealmId == request.RealmId)
.FirstOrDefaultAsync();
if (member is null || member.Role < RealmMemberRole.Moderator)
return StatusCode(403, "You need at least be a moderator to transfer the chat linked to the realm.");
chatRoom.RealmId = member.RealmId;
}
if (request.PictureId is not null)
{
picture = await db.Files.FindAsync(request.PictureId);
var picture = await db.Files.FindAsync(request.PictureId);
if (picture is null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
await fs.MarkUsageAsync(picture, 1);
if (chatRoom.Picture is not null) await fs.MarkUsageAsync(chatRoom.Picture, -1);
chatRoom.Picture = picture;
}
else if(request.PictureId == "")
{
chatRoom.Picture = null;
}
CloudFile? background = null;
if (request.BackgroundId is not null)
{
background = await db.Files.FindAsync(request.BackgroundId);
var background = await db.Files.FindAsync(request.BackgroundId);
if (background is null) return BadRequest("Invalid background id, unable to find the file on cloud.");
await fs.MarkUsageAsync(background, 1);
if (chatRoom.Background is not null) await fs.MarkUsageAsync(chatRoom.Background, -1);
chatRoom.Background = background;
}
else if(request.BackgroundId == "")
{
chatRoom.Background = null;
}
if (request.Name is not null)
chatRoom.Name = request.Name;
if (request.Description is not null)
chatRoom.Description = request.Description;
db.ChatRooms.Update(chatRoom);
await db.SaveChangesAsync();
return Ok(chatRoom);
}
[HttpDelete("{id}")]
[HttpDelete("{id:long}")]
public async Task<ActionResult> DeleteChatRoom(long id)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var chatRoom = await db.ChatRooms.FindAsync(id);
var chatRoom = await db.ChatRooms
.Where(e => e.Id == id)
.Include(c => c.Picture)
.Include(c => c.Background)
.FirstOrDefaultAsync();
if (chatRoom is null) return NotFound();
if (chatRoom.RealmId is not null)
{
var realmMember = await db.RealmMembers
.Where(m => m.AccountId == currentUser.Id)
.Where(m => m.RealmId == chatRoom.RealmId)
.FirstOrDefaultAsync();
if (realmMember is null || realmMember.Role < RealmMemberRole.Moderator)
return StatusCode(403, "You need at least be a realm moderator to delete the chat.");
}
else
{
var chatMember = await db.ChatMembers
.Where(m => m.AccountId == currentUser.Id)
.Where(m => m.ChatRoomId == chatRoom.Id)
.FirstOrDefaultAsync();
if (chatMember is null || chatMember.Role < ChatMemberRole.Owner)
return StatusCode(403, "You need at least be the owner to delete the chat.");
}
db.ChatRooms.Remove(chatRoom);
await db.SaveChangesAsync();
if (chatRoom.Picture is not null)
await fs.MarkUsageAsync(chatRoom.Picture, -1);
if (chatRoom.Background is not null)
await fs.MarkUsageAsync(chatRoom.Background, -1);
return NoContent();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class RealmAndChat : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Instant>(
name: "created_at",
table: "publisher_members",
type: "timestamp with time zone",
nullable: false,
defaultValue: NodaTime.Instant.FromUnixTimeTicks(0L));
migrationBuilder.AddColumn<Instant>(
name: "deleted_at",
table: "publisher_members",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<Instant>(
name: "updated_at",
table: "publisher_members",
type: "timestamp with time zone",
nullable: false,
defaultValue: NodaTime.Instant.FromUnixTimeTicks(0L));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "created_at",
table: "publisher_members");
migrationBuilder.DropColumn(
name: "deleted_at",
table: "publisher_members");
migrationBuilder.DropColumn(
name: "updated_at",
table: "publisher_members");
}
}
}

View File

@ -645,6 +645,117 @@ namespace DysonNetwork.Sphere.Migrations
b.ToTable("auth_sessions", (string)null);
});
modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatMember", b =>
{
b.Property<long>("ChatRoomId")
.HasColumnType("bigint")
.HasColumnName("chat_room_id");
b.Property<long>("AccountId")
.HasColumnType("bigint")
.HasColumnName("account_id");
b.Property<Instant>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<Instant?>("DeletedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<bool>("IsBot")
.HasColumnType("boolean")
.HasColumnName("is_bot");
b.Property<Instant?>("JoinedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("joined_at");
b.Property<int>("Role")
.HasColumnType("integer")
.HasColumnName("role");
b.Property<Instant>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.HasKey("ChatRoomId", "AccountId")
.HasName("pk_chat_members");
b.HasIndex("AccountId")
.HasDatabaseName("ix_chat_members_account_id");
b.ToTable("chat_members", (string)null);
});
modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatRoom", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("BackgroundId")
.HasColumnType("character varying(128)")
.HasColumnName("background_id");
b.Property<Instant>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<Instant?>("DeletedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(4096)
.HasColumnType("character varying(4096)")
.HasColumnName("description");
b.Property<bool>("IsPublic")
.HasColumnType("boolean")
.HasColumnName("is_public");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(1024)
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<string>("PictureId")
.HasColumnType("character varying(128)")
.HasColumnName("picture_id");
b.Property<long?>("RealmId")
.HasColumnType("bigint")
.HasColumnName("realm_id");
b.Property<int>("Type")
.HasColumnType("integer")
.HasColumnName("type");
b.Property<Instant>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.HasKey("Id")
.HasName("pk_chat_rooms");
b.HasIndex("BackgroundId")
.HasDatabaseName("ix_chat_rooms_background_id");
b.HasIndex("PictureId")
.HasDatabaseName("ix_chat_rooms_picture_id");
b.HasIndex("RealmId")
.HasDatabaseName("ix_chat_rooms_realm_id");
b.ToTable("chat_rooms", (string)null);
});
modelBuilder.Entity("DysonNetwork.Sphere.Permission.PermissionGroup", b =>
{
b.Property<Guid>("Id")
@ -1192,6 +1303,132 @@ namespace DysonNetwork.Sphere.Migrations
b.ToTable("publisher_members", (string)null);
});
modelBuilder.Entity("DysonNetwork.Sphere.Realm.Realm", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<long>("AccountId")
.HasColumnType("bigint")
.HasColumnName("account_id");
b.Property<string>("BackgroundId")
.HasColumnType("character varying(128)")
.HasColumnName("background_id");
b.Property<Instant>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<Instant?>("DeletedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(4096)
.HasColumnType("character varying(4096)")
.HasColumnName("description");
b.Property<bool>("IsCommunity")
.HasColumnType("boolean")
.HasColumnName("is_community");
b.Property<bool>("IsPublic")
.HasColumnType("boolean")
.HasColumnName("is_public");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(1024)
.HasColumnType("character varying(1024)")
.HasColumnName("name");
b.Property<string>("PictureId")
.HasColumnType("character varying(128)")
.HasColumnName("picture_id");
b.Property<string>("Slug")
.IsRequired()
.HasMaxLength(1024)
.HasColumnType("character varying(1024)")
.HasColumnName("slug");
b.Property<Instant>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.Property<string>("VerifiedAs")
.HasMaxLength(4096)
.HasColumnType("character varying(4096)")
.HasColumnName("verified_as");
b.Property<Instant?>("VerifiedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("verified_at");
b.HasKey("Id")
.HasName("pk_realms");
b.HasIndex("AccountId")
.HasDatabaseName("ix_realms_account_id");
b.HasIndex("BackgroundId")
.HasDatabaseName("ix_realms_background_id");
b.HasIndex("PictureId")
.HasDatabaseName("ix_realms_picture_id");
b.HasIndex("Slug")
.IsUnique()
.HasDatabaseName("ix_realms_slug");
b.ToTable("realms", (string)null);
});
modelBuilder.Entity("DysonNetwork.Sphere.Realm.RealmMember", b =>
{
b.Property<long>("RealmId")
.HasColumnType("bigint")
.HasColumnName("realm_id");
b.Property<long>("AccountId")
.HasColumnType("bigint")
.HasColumnName("account_id");
b.Property<Instant>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<Instant?>("DeletedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("deleted_at");
b.Property<Instant?>("JoinedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("joined_at");
b.Property<int>("Role")
.HasColumnType("integer")
.HasColumnName("role");
b.Property<Instant>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("updated_at");
b.HasKey("RealmId", "AccountId")
.HasName("pk_realm_members");
b.HasIndex("AccountId")
.HasDatabaseName("ix_realm_members_account_id");
b.ToTable("realm_members", (string)null);
});
modelBuilder.Entity("DysonNetwork.Sphere.Storage.CloudFile", b =>
{
b.Property<string>("Id")
@ -1492,6 +1729,51 @@ namespace DysonNetwork.Sphere.Migrations
b.Navigation("Challenge");
});
modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatMember", b =>
{
b.HasOne("DysonNetwork.Sphere.Account.Account", "Account")
.WithMany()
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_chat_members_accounts_account_id");
b.HasOne("DysonNetwork.Sphere.Chat.ChatRoom", "ChatRoom")
.WithMany("Members")
.HasForeignKey("ChatRoomId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_chat_members_chat_rooms_chat_room_id");
b.Navigation("Account");
b.Navigation("ChatRoom");
});
modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatRoom", b =>
{
b.HasOne("DysonNetwork.Sphere.Storage.CloudFile", "Background")
.WithMany()
.HasForeignKey("BackgroundId")
.HasConstraintName("fk_chat_rooms_files_background_id");
b.HasOne("DysonNetwork.Sphere.Storage.CloudFile", "Picture")
.WithMany()
.HasForeignKey("PictureId")
.HasConstraintName("fk_chat_rooms_files_picture_id");
b.HasOne("DysonNetwork.Sphere.Realm.Realm", "Realm")
.WithMany("ChatRooms")
.HasForeignKey("RealmId")
.HasConstraintName("fk_chat_rooms_realms_realm_id");
b.Navigation("Background");
b.Navigation("Picture");
b.Navigation("Realm");
});
modelBuilder.Entity("DysonNetwork.Sphere.Permission.PermissionGroupMember", b =>
{
b.HasOne("DysonNetwork.Sphere.Permission.PermissionGroup", "Group")
@ -1627,6 +1909,53 @@ namespace DysonNetwork.Sphere.Migrations
b.Navigation("Publisher");
});
modelBuilder.Entity("DysonNetwork.Sphere.Realm.Realm", b =>
{
b.HasOne("DysonNetwork.Sphere.Account.Account", "Account")
.WithMany()
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_realms_accounts_account_id");
b.HasOne("DysonNetwork.Sphere.Storage.CloudFile", "Background")
.WithMany()
.HasForeignKey("BackgroundId")
.HasConstraintName("fk_realms_files_background_id");
b.HasOne("DysonNetwork.Sphere.Storage.CloudFile", "Picture")
.WithMany()
.HasForeignKey("PictureId")
.HasConstraintName("fk_realms_files_picture_id");
b.Navigation("Account");
b.Navigation("Background");
b.Navigation("Picture");
});
modelBuilder.Entity("DysonNetwork.Sphere.Realm.RealmMember", b =>
{
b.HasOne("DysonNetwork.Sphere.Account.Account", "Account")
.WithMany()
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_realm_members_accounts_account_id");
b.HasOne("DysonNetwork.Sphere.Realm.Realm", "Realm")
.WithMany("Members")
.HasForeignKey("RealmId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_realm_members_realms_realm_id");
b.Navigation("Account");
b.Navigation("Realm");
});
modelBuilder.Entity("DysonNetwork.Sphere.Storage.CloudFile", b =>
{
b.HasOne("DysonNetwork.Sphere.Account.Account", "Account")
@ -1713,6 +2042,11 @@ namespace DysonNetwork.Sphere.Migrations
b.Navigation("Sessions");
});
modelBuilder.Entity("DysonNetwork.Sphere.Chat.ChatRoom", b =>
{
b.Navigation("Members");
});
modelBuilder.Entity("DysonNetwork.Sphere.Permission.PermissionGroup", b =>
{
b.Navigation("Members");
@ -1735,6 +2069,13 @@ namespace DysonNetwork.Sphere.Migrations
b.Navigation("Posts");
});
modelBuilder.Entity("DysonNetwork.Sphere.Realm.Realm", b =>
{
b.Navigation("ChatRooms");
b.Navigation("Members");
});
#pragma warning restore 612, 618
}
}

View File

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

View File

@ -0,0 +1,38 @@
using DysonNetwork.Sphere.Chat;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace DysonNetwork.Sphere.Realm;
[ApiController]
[Route("/realm/{slug}")]
public class RealmChatController(AppDatabase db) : ControllerBase
{
[HttpGet("/chat")]
[Authorize]
public async Task<ActionResult<List<ChatRoom>>> ListRealmChat(string slug)
{
var currentUser = HttpContext.Items["CurrentUser"] as Account.Account;
var realm = await db.Realms
.Where(r => r.Slug == slug)
.FirstOrDefaultAsync();
if (realm is null) return NotFound();
if (!realm.IsPublic)
{
if (currentUser is null) return Unauthorized();
var member = await db.ChatMembers
.Where(m => m.ChatRoomId == realm.Id)
.Where(m => m.AccountId == currentUser.Id)
.FirstOrDefaultAsync();
if (member is null) return BadRequest("You need at least one member to view the realm's chat.");
}
var chatRooms = await db.ChatRooms
.Where(c => c.RealmId == realm.Id)
.ToListAsync();
return Ok(chatRooms);
}
}

View File

@ -13,8 +13,6 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
[HttpGet("{slug}")]
public async Task<ActionResult<Realm>> GetRealm(string slug)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var realm = await db.Realms
.Where(e => e.Slug == slug)
.Include(e => e.Picture)
@ -27,7 +25,7 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
[HttpGet]
[Authorize]
public async Task<ActionResult<List<Realm>>> ListManagedRealms()
public async Task<ActionResult<List<Realm>>> ListJoinedRealms()
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var userId = currentUser.Id;
@ -38,11 +36,14 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
.Include(e => e.Realm)
.Include(e => e.Realm.Picture)
.Include(e => e.Realm.Background)
.Select(m => m.Realm)
.ToListAsync();
return members.Select(m => m.Realm).ToList();
return members.ToList();
}
[HttpGet("/")]
[HttpGet("invites")]
[Authorize]
public async Task<ActionResult<List<RealmMember>>> ListInvites()
@ -179,7 +180,15 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
Description = request.Description!,
AccountId = currentUser.Id,
IsCommunity = request.IsCommunity ?? false,
IsPublic = request.IsPublic ?? false
IsPublic = request.IsPublic ?? false,
Members = new List<RealmMember>
{
new()
{
Role = RealmMemberRole.Owner,
AccountId = currentUser.Id
}
}
};
if (request.PictureId is not null)
@ -242,6 +251,8 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
{
var picture = await db.Files.FindAsync(request.PictureId);
if (picture is null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
await fs.MarkUsageAsync(picture, 1);
if (realm.Picture is not null) await fs.MarkUsageAsync(realm.Picture, -1);
realm.Picture = picture;
}
@ -249,6 +260,8 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
{
var background = await db.Files.FindAsync(request.BackgroundId);
if (background is null) return BadRequest("Invalid background id, unable to find the file on cloud.");
await fs.MarkUsageAsync(background, 1);
if (realm.Background is not null) await fs.MarkUsageAsync(realm.Background, -1);
realm.Background = background;
}
@ -265,6 +278,8 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
var realm = await db.Realms
.Where(r => r.Slug == slug)
.Include(r => r.Picture)
.Include(r => r.Background)
.FirstOrDefaultAsync();
if (realm is null) return NotFound();
@ -276,6 +291,12 @@ public class RealmController(AppDatabase db, RealmService rs, FileService fs) :
db.Realms.Remove(realm);
await db.SaveChangesAsync();
if (realm.Picture is not null)
await fs.MarkUsageAsync(realm.Picture, -1);
if (realm.Background is not null)
await fs.MarkUsageAsync(realm.Background, -1);
return NoContent();
}
}