diff --git a/MoonlightServers.ApiServer/Http/Controllers/Client/ServerVariablesController.cs b/MoonlightServers.ApiServer/Http/Controllers/Client/ServerVariablesController.cs new file mode 100644 index 0000000..cfd1408 --- /dev/null +++ b/MoonlightServers.ApiServer/Http/Controllers/Client/ServerVariablesController.cs @@ -0,0 +1,135 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using MoonCore.Exceptions; +using MoonCore.Extended.Abstractions; +using Moonlight.ApiServer.Database.Entities; +using MoonlightServers.ApiServer.Database.Entities; +using MoonlightServers.ApiServer.Services; +using MoonlightServers.Shared.Http.Requests.Client.Servers.Variables; +using MoonlightServers.Shared.Http.Responses.Client.Servers.Variables; + +namespace MoonlightServers.ApiServer.Http.Controllers.Client; + +[Authorize] +[ApiController] +[Route("api/client/servers")] +public class ServerVariablesController : Controller +{ + private readonly DatabaseRepository ServerRepository; + private readonly DatabaseRepository UserRepository; + private readonly ServerService ServerService; + + public ServerVariablesController( + DatabaseRepository serverRepository, + DatabaseRepository userRepository, + ServerService serverService + ) + { + ServerRepository = serverRepository; + UserRepository = userRepository; + ServerService = serverService; + } + + [HttpGet("{serverId:int}/variables")] + public async Task Get([FromRoute] int serverId) + { + var server = await GetServerById(serverId); + + return server.Star.Variables.Select(starVariable => + { + var serverVariable = server.Variables.First(x => x.Key == starVariable.Key); + + return new ServerVariableDetailResponse() + { + Key = starVariable.Key, + Value = serverVariable.Value, + Type = starVariable.Type, + Name = starVariable.Name, + Description = starVariable.Description, + Filter = starVariable.Filter + }; + }).ToArray(); + } + + [HttpPut("{serverId:int}/variables")] + public async Task UpdateSingle([FromRoute] int serverId, [FromBody] UpdateServerVariableRequest request) + { + // TODO: Handle filter + + var server = await GetServerById(serverId); + + var serverVariable = server.Variables.FirstOrDefault(x => x.Key == request.Key); + var starVariable = server.Star.Variables.FirstOrDefault(x => x.Key == request.Key); + + if (serverVariable == null || starVariable == null) + throw new HttpApiException($"No variable with the key found: {request.Key}", 400); + + serverVariable.Value = request.Value; + await ServerRepository.Update(server); + + return new ServerVariableDetailResponse() + { + Key = starVariable.Key, + Value = serverVariable.Value, + Type = starVariable.Type, + Name = starVariable.Name, + Description = starVariable.Description, + Filter = starVariable.Filter + }; + } + + [HttpPatch("{serverId:int}/variables")] + public async Task Update([FromRoute] int serverId, [FromBody] UpdateServerVariableRangeRequest request) + { + var server = await GetServerById(serverId); + + foreach (var variable in request.Variables) + { + // TODO: Handle filter + + var serverVariable = server.Variables.FirstOrDefault(x => x.Key == variable.Key); + var starVariable = server.Star.Variables.FirstOrDefault(x => x.Key == variable.Key); + + if (serverVariable == null || starVariable == null) + throw new HttpApiException($"No variable with the key found: {variable.Key}", 400); + + serverVariable.Value = variable.Value; + } + + await ServerRepository.Update(server); + + return request.Variables.Select(requestVariable => + { + var serverVariable = server.Variables.First(x => x.Key == requestVariable.Key); + var starVariable = server.Star.Variables.First(x => x.Key == requestVariable.Key); + + return new ServerVariableDetailResponse() + { + + }; + }).ToArray(); + } + + private async Task GetServerById(int serverId) + { + var server = await ServerRepository + .Get() + .Include(x => x.Variables) + .Include(x => x.Star) + .ThenInclude(x => x.Variables) + .FirstOrDefaultAsync(x => x.Id == serverId); + + if (server == null) + throw new HttpApiException("No server with this id found", 404); + + var userIdClaim = User.Claims.First(x => x.Type == "userId"); + var userId = int.Parse(userIdClaim.Value); + var user = await UserRepository.Get().FirstAsync(x => x.Id == userId); + + if (!ServerService.IsAllowedToAccess(user, server)) + throw new HttpApiException("No server with this id found", 404); + + return server; + } +} \ No newline at end of file diff --git a/MoonlightServers.Frontend/Implementations/DefaultServerTabProvider.cs b/MoonlightServers.Frontend/Implementations/DefaultServerTabProvider.cs index 623d4e2..5f50a1c 100644 --- a/MoonlightServers.Frontend/Implementations/DefaultServerTabProvider.cs +++ b/MoonlightServers.Frontend/Implementations/DefaultServerTabProvider.cs @@ -13,6 +13,7 @@ public class DefaultServerTabProvider : IServerTabProvider [ ServerTab.CreateFromComponent("Console", "console", 0), ServerTab.CreateFromComponent("Files", "files", 1), + ServerTab.CreateFromComponent("Variables", "variables", 2), ServerTab.CreateFromComponent("Settings", "settings", 10), ]; diff --git a/MoonlightServers.Frontend/Services/ServerService.cs b/MoonlightServers.Frontend/Services/ServerService.cs index 1835c95..1e75800 100644 --- a/MoonlightServers.Frontend/Services/ServerService.cs +++ b/MoonlightServers.Frontend/Services/ServerService.cs @@ -1,6 +1,8 @@ using MoonCore.Attributes; using MoonCore.Helpers; using MoonCore.Models; +using MoonlightServers.Shared.Http.Requests.Client.Servers.Variables; +using MoonlightServers.Shared.Http.Responses.Client.Servers.Variables; using MoonlightServers.Shared.Http.Responses.Users.Servers; namespace MoonlightServers.Frontend.Services; @@ -49,7 +51,7 @@ public class ServerService $"api/client/servers/{serverId}/ws" ); } - + public async Task Install(int serverId) { await HttpApiClient.Post( @@ -65,14 +67,14 @@ public class ServerService $"api/client/servers/{serverId}/start" ); } - + public async Task Stop(int serverId) { await HttpApiClient.Post( $"api/client/servers/{serverId}/stop" ); } - + public async Task Kill(int serverId) { await HttpApiClient.Post( @@ -81,4 +83,31 @@ public class ServerService } #endregion + + #region Variables + + public async Task GetVariables(int serverId) + { + return await HttpApiClient.GetJson( + $"api/client/servers/{serverId}/variables" + ); + } + + public async Task UpdateVariables(int serverId, UpdateServerVariableRangeRequest request) + { + await HttpApiClient.Patch( + $"api/client/servers/{serverId}/variables", + request + ); + } + + public async Task UpdateVariable(int serverId, UpdateServerVariableRequest request) + { + await HttpApiClient.Put( + $"api/client/servers/{serverId}/variables", + request + ); + } + + #endregion } \ No newline at end of file diff --git a/MoonlightServers.Frontend/UI/Components/Servers/ServerTabs/VariablesTab.razor b/MoonlightServers.Frontend/UI/Components/Servers/ServerTabs/VariablesTab.razor new file mode 100644 index 0000000..012de6d --- /dev/null +++ b/MoonlightServers.Frontend/UI/Components/Servers/ServerTabs/VariablesTab.razor @@ -0,0 +1,36 @@ +@using MoonCore.Blazor.Tailwind.Components +@using MoonlightServers.Frontend.Services +@using MoonlightServers.Shared.Http.Responses.Client.Servers.Variables + +@inherits BaseServerTab + +@inject ServerService ServerService + + +
+ @foreach (var variable in Variables) + { +
+ +

+ @variable.Description +

+
+ +
+
+ } +
+
+ +@code +{ + private ServerVariableDetailResponse[] Variables; + + private async Task Load(LazyLoader _) + { + Variables = await ServerService.GetVariables(Server.Id); + } +} \ No newline at end of file diff --git a/MoonlightServers.Shared/Http/Requests/Client/Servers/Variables/UpdateServerVariableRangeRequest.cs b/MoonlightServers.Shared/Http/Requests/Client/Servers/Variables/UpdateServerVariableRangeRequest.cs new file mode 100644 index 0000000..30baf8a --- /dev/null +++ b/MoonlightServers.Shared/Http/Requests/Client/Servers/Variables/UpdateServerVariableRangeRequest.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; + +namespace MoonlightServers.Shared.Http.Requests.Client.Servers.Variables; + +public class UpdateServerVariableRangeRequest +{ + [Required(ErrorMessage = "You need to provide variables")] + public UpdateServerVariableRequest[] Variables { get; set; } +} \ No newline at end of file diff --git a/MoonlightServers.Shared/Http/Requests/Client/Servers/Variables/UpdateServerVariableRequest.cs b/MoonlightServers.Shared/Http/Requests/Client/Servers/Variables/UpdateServerVariableRequest.cs new file mode 100644 index 0000000..40202d3 --- /dev/null +++ b/MoonlightServers.Shared/Http/Requests/Client/Servers/Variables/UpdateServerVariableRequest.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations; + +namespace MoonlightServers.Shared.Http.Requests.Client.Servers.Variables; + +public class UpdateServerVariableRequest +{ + [Required(ErrorMessage = "You need to provide a key")] + public string Key { get; set; } + + [Required(ErrorMessage = "You need to provide a value", AllowEmptyStrings = true)] + public string Value { get; set; } +} \ No newline at end of file diff --git a/MoonlightServers.Shared/Http/Responses/Client/Servers/Variables/ServerVariableDetailResponse.cs b/MoonlightServers.Shared/Http/Responses/Client/Servers/Variables/ServerVariableDetailResponse.cs new file mode 100644 index 0000000..ae66b11 --- /dev/null +++ b/MoonlightServers.Shared/Http/Responses/Client/Servers/Variables/ServerVariableDetailResponse.cs @@ -0,0 +1,14 @@ +using MoonlightServers.Shared.Enums; + +namespace MoonlightServers.Shared.Http.Responses.Client.Servers.Variables; + +public class ServerVariableDetailResponse +{ + public string Key { get; set; } + public string Value { get; set; } + + public string Name { get; set; } + public string Description { get; set; } + public StarVariableType Type { get; set; } + public string? Filter { get; set; } +} \ No newline at end of file