diff --git a/.idx/dev.nix b/.idx/dev.nix new file mode 100644 index 0000000..58ca764 --- /dev/null +++ b/.idx/dev.nix @@ -0,0 +1,58 @@ +# To learn more about how to use Nix to configure your environment +# see: https://firebase.google.com/docs/studio/customize-workspace +{ pkgs, ... }: { + # Which nixpkgs channel to use. + channel = "stable-24.05"; # or "unstable" + + # Use https://search.nixos.org/packages to find packages + packages = [ + pkgs.icu # The deps of dotnet somehow + pkgs.dotnetCorePackages.sdk_9_0_1xx + # pkgs.go + # pkgs.python311 + # pkgs.python311Packages.pip + # pkgs.nodejs_20 + # pkgs.nodePackages.nodemon + ]; + + # Sets environment variables in the workspace + env = {}; + idx = { + # Search for the extensions you want on https://open-vsx.org/ and use "publisher.id" + extensions = [ + "k--kato.intellij-idea-keybindings" + # "vscodevim.vim" + ]; + + # Enable previews + previews = { + enable = true; + previews = { + # web = { + # # Example: run "npm run dev" with PORT set to IDX's defined port for previews, + # # and show it in IDX's web preview panel + # command = ["npm" "run" "dev"]; + # manager = "web"; + # env = { + # # Environment variables to set for your server + # PORT = "$PORT"; + # }; + # }; + }; + }; + + # Workspace lifecycle hooks + workspace = { + # Runs when a workspace is first created + onCreate = { + # Example: install JS dependencies from NPM + # npm-install = "npm install"; + }; + # Runs when the workspace is (re)started + onStart = { + # Example: start a background task to watch and re-build backend code + # watch-backend = "npm run watch-backend"; + }; + }; + }; +} diff --git a/DysonNetwork.Sphere/AppDatabase.cs b/DysonNetwork.Sphere/AppDatabase.cs index 6079f64..2d6788b 100644 --- a/DysonNetwork.Sphere/AppDatabase.cs +++ b/DysonNetwork.Sphere/AppDatabase.cs @@ -79,7 +79,8 @@ public class AppDatabase( { PermissionService.NewPermissionNode("group:default", "global", "posts.create", true), PermissionService.NewPermissionNode("group:default", "global", "publishers.create", true), - PermissionService.NewPermissionNode("group:default", "global", "files.create", true) + PermissionService.NewPermissionNode("group:default", "global", "files.create", true), + PermissionService.NewPermissionNode("group:default", "global", "chatrooms.create", true) } }); await context.SaveChangesAsync(cancellationToken); diff --git a/DysonNetwork.Sphere/Chat/ChatController.cs b/DysonNetwork.Sphere/Chat/ChatController.cs index 0be8635..e69de29 100644 --- a/DysonNetwork.Sphere/Chat/ChatController.cs +++ b/DysonNetwork.Sphere/Chat/ChatController.cs @@ -1,15 +0,0 @@ -using DysonNetwork.Sphere.Account; -using DysonNetwork.Sphere.Realm; -using DysonNetwork.Sphere.Chat; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; -using System.Threading.Tasks; - -namespace DysonNetwork.Sphere.Chat; - -[ApiController] -[Route("/chat")] -public class ChatController(AppDatabase db) : ControllerBase -{ -} \ No newline at end of file diff --git a/DysonNetwork.Sphere/Chat/ChatRoomController.cs b/DysonNetwork.Sphere/Chat/ChatRoomController.cs new file mode 100644 index 0000000..6170c64 --- /dev/null +++ b/DysonNetwork.Sphere/Chat/ChatRoomController.cs @@ -0,0 +1,134 @@ +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.Storage; + +namespace DysonNetwork.Sphere.Chat; + +[ApiController] +[Route("/chatrooms")] +public class ChatRoomController(AppDatabase db, FileService fs) : ControllerBase +{ + [HttpPost] + public async Task> 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) + }; + + db.ChatRooms.Add(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 Ok(chatRoom); + } + + [HttpGet("{id}")] + public async Task> GetChatRoom(long id) + { + var chatRoom = await db.ChatRooms.FindAsync(id); + if (chatRoom is null) return NotFound(); + return Ok(chatRoom); + } + + [HttpGet] + public async Task>> 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}")] + public async Task> UpdateChatRoom(long id, [FromBody] ChatRoomRequest request) + { + if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); + + var chatRoom = await db.ChatRooms.FindAsync(id); + if (chatRoom is null) return NotFound(); + + 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."); + 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); + if (background is null) return BadRequest("Invalid background id, unable to find the file on cloud."); + } + else if(request.BackgroundId == "") + { + chatRoom.Background = null; + } + if (request.Name is not null) + chatRoom.Name = request.Name; + + db.ChatRooms.Update(chatRoom); + await db.SaveChangesAsync(); + return Ok(chatRoom); + } + + [HttpDelete("{id}")] + public async Task DeleteChatRoom(long id) + { + if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); + + var chatRoom = await db.ChatRooms.FindAsync(id); + if (chatRoom is null) return NotFound(); + + db.ChatRooms.Remove(chatRoom); + await db.SaveChangesAsync(); + return NoContent(); + } +} \ No newline at end of file diff --git a/DysonNetwork.Sphere/Chat/ChatRoomService.cs b/DysonNetwork.Sphere/Chat/ChatRoomService.cs new file mode 100644 index 0000000..04fd4f1 --- /dev/null +++ b/DysonNetwork.Sphere/Chat/ChatRoomService.cs @@ -0,0 +1,5 @@ +namespace DysonNetwork.Sphere.Chat; + +public class ChatRoomService() +{ +} \ No newline at end of file