diff --git a/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarDockerImagesController.cs b/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarDockerImagesController.cs index c12c072..805a386 100644 --- a/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarDockerImagesController.cs +++ b/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarDockerImagesController.cs @@ -15,22 +15,22 @@ using MoonlightServers.Shared.Http.Responses.Admin.StarDockerImages; namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Stars; [ApiController] -[Route("api/admin/servers/stars")] +[Route("api/admin/servers/stars/{starId:int}/dockerImages")] public class StarDockerImagesController : Controller { private readonly DatabaseRepository StarRepository; - private readonly DatabaseRepository StarDockerImageRepository; + private readonly DatabaseRepository DockerImageRepository; public StarDockerImagesController( DatabaseRepository starRepository, - DatabaseRepository starDockerImageRepository + DatabaseRepository dockerImageRepository ) { StarRepository = starRepository; - StarDockerImageRepository = starDockerImageRepository; + DockerImageRepository = dockerImageRepository; } - [HttpGet("{starId:int}/dockerImages")] + [HttpGet] [Authorize(Policy = "permissions:admin.servers.stars.get")] public async Task> Get( [FromRoute] int starId, @@ -41,16 +41,16 @@ public class StarDockerImagesController : Controller var starExists = StarRepository .Get() .Any(x => x.Id == starId); - - if(starExists) + + if (!starExists) throw new HttpApiException("No star with this id found", 404); - var query = StarDockerImageRepository + var query = DockerImageRepository .Get() .Where(x => x.Star.Id == starId); var count = await query.CountAsync(); - + var items = await query .Skip(page * pageSize) .Take(pageSize) @@ -70,46 +70,95 @@ public class StarDockerImagesController : Controller }; } - [HttpGet("{starId:int}/dockerImages/{id:int}")] - [Authorize(Policy = "permissions:admin.servers.stars.get")] + [HttpGet("{id:int}")] + [Authorize(Policy = "permissions:admin.servers.stars.read")] public async Task GetSingle([FromRoute] int starId, [FromRoute] int id) { - await ApplyStar(starId); + var starExists = StarRepository + .Get() + .Any(x => x.Id == starId); - return await CrudHelper.GetSingle(id); + if (!starExists) + throw new HttpApiException("No star with this id found", 404); + + var dockerImage = await DockerImageRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id && x.Star.Id == starId); + + if (dockerImage == null) + throw new HttpApiException("No star docker image with this id found", 404); + + return DockerImageMapper.ToAdminResponse(dockerImage); } - [HttpPost("{starId:int}/dockerImages")] - [Authorize(Policy = "permissions:admin.servers.stars.create")] - public async Task Create([FromRoute] int starId, - [FromBody] CreateStarDockerImageRequest request) + [HttpPost("")] + [Authorize(Policy = "permissions:admin.servers.stars.write")] + public async Task Create( + [FromRoute] int starId, + [FromBody] CreateStarDockerImageRequest request + ) { - await ApplyStar(starId); + var star = await StarRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == starId); - var starDockerImage = Mapper.Map(request); - starDockerImage.Star = Star; + if (star == null) + throw new HttpApiException("No star with this id found", 404); - var finalVariable = await StarDockerImageRepository.Add(starDockerImage); + var dockerImage = DockerImageMapper.ToDockerImage(request); + dockerImage.Star = star; - return CrudHelper.MapToResult(finalVariable); + var finalDockerImage = await DockerImageRepository.Add(dockerImage); + + return DockerImageMapper.ToAdminResponse(finalDockerImage); } - [HttpPatch("{starId:int}/dockerImages/{id:int}")] - [Authorize(Policy = "permissions:admin.servers.stars.update")] - public async Task Update([FromRoute] int starId, [FromRoute] int id, - [FromBody] UpdateStarDockerImageRequest request) + [HttpPatch("{id:int}")] + [Authorize(Policy = "permissions:admin.servers.stars.write")] + public async Task Update( + [FromRoute] int starId, + [FromRoute] int id, + [FromBody] UpdateStarDockerImageRequest request + ) { - await ApplyStar(starId); + var starExists = StarRepository + .Get() + .Any(x => x.Id == starId); - return await CrudHelper.Update(id, request); + if (!starExists) + throw new HttpApiException("No star with this id found", 404); + + var dockerImage = await DockerImageRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id && x.Star.Id == starId); + + if (dockerImage == null) + throw new HttpApiException("No star docker image with this id found", 404); + + dockerImage = DockerImageMapper.Merge(request, dockerImage); + await DockerImageRepository.Update(dockerImage); + + return DockerImageMapper.ToAdminResponse(dockerImage); } - [HttpDelete("{starId:int}/dockerImages/{id:int}")] - [Authorize(Policy = "permissions:admin.servers.stars.delete")] + [HttpDelete("{id:int}")] + [Authorize(Policy = "permissions:admin.servers.stars.write")] public async Task Delete([FromRoute] int starId, [FromRoute] int id) { - await ApplyStar(starId); + var starExists = StarRepository + .Get() + .Any(x => x.Id == starId); - await CrudHelper.Delete(id); + if (!starExists) + throw new HttpApiException("No star with this id found", 404); + + var dockerImage = await DockerImageRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id && x.Star.Id == starId); + + if (dockerImage == null) + throw new HttpApiException("No star docker image with this id found", 404); + + await DockerImageRepository.Remove(dockerImage); } } \ No newline at end of file diff --git a/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarImportExportController.cs b/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarImportExportController.cs index cd57b9e..37f7cb4 100644 --- a/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarImportExportController.cs +++ b/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarImportExportController.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using MoonCore.Exceptions; using MoonCore.Helpers; +using MoonlightServers.ApiServer.Mappers; using MoonlightServers.ApiServer.Services; using MoonlightServers.Shared.Http.Responses.Admin.Stars; @@ -48,6 +49,6 @@ public class StarImportExportController : Controller var star = await ImportExportService.Import(content); - return Mapper.Map(star); + return StarMapper.ToAdminResponse(star); } } \ No newline at end of file diff --git a/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarVariablesController.cs b/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarVariablesController.cs index 43c3460..517fe8a 100644 --- a/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarVariablesController.cs +++ b/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarVariablesController.cs @@ -1,12 +1,12 @@ +using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Authorization; using MoonCore.Exceptions; using MoonCore.Extended.Abstractions; -using MoonCore.Extended.Helpers; -using MoonCore.Helpers; using MoonCore.Models; using MoonlightServers.ApiServer.Database.Entities; +using MoonlightServers.ApiServer.Mappers; using MoonlightServers.Shared.Http.Requests.Admin.StarVariables; using MoonlightServers.Shared.Http.Responses.Admin.StarVariables; @@ -16,91 +16,147 @@ namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Stars; [Route("api/admin/servers/stars")] public class StarVariablesController : Controller { - private readonly CrudHelper CrudHelper; private readonly DatabaseRepository StarRepository; - private readonly DatabaseRepository StarVariableRepository; - - private Star Star; + private readonly DatabaseRepository VariableRepository; public StarVariablesController( - CrudHelper crudHelper, DatabaseRepository starRepository, - DatabaseRepository starVariableRepository) + DatabaseRepository variableRepository) { - CrudHelper = crudHelper; StarRepository = starRepository; - StarVariableRepository = starVariableRepository; - } - - private async Task ApplyStar(int id) - { - var star = await StarRepository - .Get() - .FirstOrDefaultAsync(x => x.Id == id); - - if (star == null) - throw new HttpApiException("A star with this id could not be found", 404); - - Star = star; - - CrudHelper.QueryModifier = variables => - variables.Where(x => x.Star.Id == star.Id); + VariableRepository = variableRepository; } [HttpGet("{starId:int}/variables")] [Authorize(Policy = "permissions:admin.servers.stars.get")] - public async Task> Get([FromRoute] int starId, [FromQuery] int page, [FromQuery] int pageSize) + public async Task> Get( + [FromRoute] int starId, + [FromQuery] [Range(0, int.MaxValue)] int page, + [FromQuery] [Range(1, 100)] int pageSize + ) { - await ApplyStar(starId); + var starExists = StarRepository + .Get() + .Any(x => x.Id == starId); - return await CrudHelper.Get(page, pageSize); + if (!starExists) + throw new HttpApiException("No star with this id found", 404); + + var query = VariableRepository + .Get() + .Where(x => x.Star.Id == starId); + + var count = await query.CountAsync(); + + var items = await query + .Skip(page * pageSize) + .Take(pageSize) + .ToArrayAsync(); + + var mappedItems = items + .Select(StarVariableMapper.ToAdminResponse) + .ToArray(); + + return new PagedData() + { + Items = mappedItems, + CurrentPage = page, + PageSize = pageSize, + TotalItems = count, + TotalPages = count == 0 ? 0 : count / pageSize + }; } [HttpGet("{starId:int}/variables/{id:int}")] [Authorize(Policy = "permissions:admin.servers.stars.get")] - public async Task GetSingle([FromRoute] int starId, [FromRoute] int id) + public async Task GetSingle( + [FromRoute] int starId, + [FromRoute] int id + ) { - await ApplyStar(starId); - - return await CrudHelper.GetSingle(id); + var starExists = StarRepository + .Get() + .Any(x => x.Id == starId); + + if (!starExists) + throw new HttpApiException("No star with this id found", 404); + + var starVariable = await VariableRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id && x.Star.Id == starId); + + if (starVariable == null) + throw new HttpApiException("No variable with this id found", 404); + + return StarVariableMapper.ToAdminResponse(starVariable); } [HttpPost("{starId:int}/variables")] [Authorize(Policy = "permissions:admin.servers.stars.create")] - public async Task Create([FromRoute] int starId, [FromBody] CreateStarVariableRequest request) + public async Task Create([FromRoute] int starId, + [FromBody] CreateStarVariableRequest request) { - await ApplyStar(starId); - - var starVariable = Mapper.Map(request); - starVariable.Star = Star; + var star = StarRepository + .Get() + .FirstOrDefault(x => x.Id == starId); - var finalVariable = await StarVariableRepository.Add(starVariable); + if (star == null) + throw new HttpApiException("No star with this id found", 404); - return CrudHelper.MapToResult(finalVariable); + var starVariable = StarVariableMapper.ToStarVariable(request); + starVariable.Star = star; + + await VariableRepository.Add(starVariable); + + return StarVariableMapper.ToAdminResponse(starVariable); } [HttpPatch("{starId:int}/variables/{id:int}")] [Authorize(Policy = "permissions:admin.servers.stars.update")] - public async Task Update([FromRoute] int starId, [FromRoute] int id, - [FromBody] UpdateStarVariableRequest request) + public async Task Update( + [FromRoute] int starId, + [FromRoute] int id, + [FromBody] UpdateStarVariableRequest request + ) { - await ApplyStar(starId); - - var variable = await CrudHelper.GetSingleModel(id); + var starExists = StarRepository + .Get() + .Any(x => x.Id == starId); - variable = Mapper.Map(variable, request); + if (!starExists) + throw new HttpApiException("No star with this id found", 404); + + var starVariable = await VariableRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id && x.Star.Id == starId); + + if (starVariable == null) + throw new HttpApiException("No variable with this id found", 404); - await StarVariableRepository.Update(variable); + starVariable = StarVariableMapper.Merge(request, starVariable); + await VariableRepository.Update(starVariable); - return CrudHelper.MapToResult(variable); + return StarVariableMapper.ToAdminResponse(starVariable); } [HttpDelete("{starId:int}/variables/{id:int}")] [Authorize(Policy = "permissions:admin.servers.stars.delete")] public async Task Delete([FromRoute] int starId, [FromRoute] int id) { - await ApplyStar(starId); + var starExists = StarRepository + .Get() + .Any(x => x.Id == starId); + + if (!starExists) + throw new HttpApiException("No star with this id found", 404); + + var starVariable = await VariableRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id && x.Star.Id == starId); + + if (starVariable == null) + throw new HttpApiException("No variable with this id found", 404); - await CrudHelper.Delete(id); + await VariableRepository.Remove(starVariable); } } \ No newline at end of file diff --git a/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarsController.cs b/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarsController.cs index 2c55b02..e45c057 100644 --- a/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarsController.cs +++ b/MoonlightServers.ApiServer/Http/Controllers/Admin/Stars/StarsController.cs @@ -1,15 +1,14 @@ +using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Authorization; +using MoonCore.Exceptions; using MoonCore.Extended.Abstractions; -using MoonCore.Extended.Helpers; -using MoonCore.Helpers; using MoonCore.Models; using MoonlightServers.ApiServer.Database.Entities; +using MoonlightServers.ApiServer.Mappers; using MoonlightServers.Shared.Http.Requests.Admin.Stars; -using MoonlightServers.Shared.Http.Responses.Admin.StarDockerImages; using MoonlightServers.Shared.Http.Responses.Admin.Stars; -using MoonlightServers.Shared.Http.Responses.Admin.StarVariables; namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Stars; @@ -17,35 +16,62 @@ namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Stars; [Route("api/admin/servers/stars")] public class StarsController : Controller { - private readonly CrudHelper CrudHelper; private readonly DatabaseRepository StarRepository; - public StarsController(CrudHelper crudHelper, DatabaseRepository starRepository) + public StarsController(DatabaseRepository starRepository) { - CrudHelper = crudHelper; StarRepository = starRepository; } [HttpGet] - [Authorize(Policy = "permissions:admin.servers.stars.get")] - public async Task> Get([FromQuery] int page, [FromQuery] int pageSize) + [Authorize(Policy = "permissions:admin.servers.stars.read")] + public async Task> Get( + [FromQuery] [Range(0, int.MaxValue)] int page, + [FromQuery] [Range(1, 100)] int pageSize + ) { - return await CrudHelper.Get(page, pageSize); + var count = await StarRepository.Get().CountAsync(); + + var items = await StarRepository + .Get() + .Skip(page * pageSize) + .Take(pageSize) + .ToArrayAsync(); + + var mappedItems = items + .Select(StarMapper.ToAdminResponse) + .ToArray(); + + return new PagedData() + { + CurrentPage = page, + Items = mappedItems, + PageSize = pageSize, + TotalItems = count, + TotalPages = count == 0 ? 0 : count / pageSize + }; } [HttpGet("{id:int}")] - [Authorize(Policy = "permissions:admin.servers.stars.get")] + [Authorize(Policy = "permissions:admin.servers.stars.read")] public async Task GetSingle([FromRoute] int id) { - return await CrudHelper.GetSingle(id); + var star = await StarRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id); + + if (star == null) + throw new HttpApiException("No star with that id found", 404); + + return StarMapper.ToAdminResponse(star); } [HttpPost] [Authorize(Policy = "permissions:admin.servers.stars.create")] public async Task Create([FromBody] CreateStarRequest request) { - var star = Mapper.Map(request); - + var star = StarMapper.ToStar(request); + // Default values star.DonateUrl = null; star.UpdateUrl = null; @@ -63,20 +89,40 @@ public class StarsController : Controller var finalStar = await StarRepository.Add(star); - return CrudHelper.MapToResult(finalStar); + return StarMapper.ToAdminResponse(finalStar); } [HttpPatch("{id:int}")] [Authorize(Policy = "permissions:admin.servers.stars.update")] - public async Task Update([FromRoute] int id, [FromBody] UpdateStarRequest request) + public async Task Update( + [FromRoute] int id, + [FromBody] UpdateStarRequest request + ) { - return await CrudHelper.Update(id, request); + var star = await StarRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id); + + if (star == null) + throw new HttpApiException("No star with that id found", 404); + + star = StarMapper.Merge(request, star); + await StarRepository.Update(star); + + return StarMapper.ToAdminResponse(star); } [HttpDelete("{id:int}")] [Authorize(Policy = "permissions:admin.servers.stars.delete")] public async Task Delete([FromRoute] int id) { - await CrudHelper.Delete(id); + var star = await StarRepository + .Get() + .FirstOrDefaultAsync(x => x.Id == id); + + if (star == null) + throw new HttpApiException("No star with that id found", 404); + + await StarRepository.Remove(star); } } \ No newline at end of file diff --git a/MoonlightServers.ApiServer/Mappers/DockerImageMapper.cs b/MoonlightServers.ApiServer/Mappers/DockerImageMapper.cs index d4f7b1a..8eaad00 100644 --- a/MoonlightServers.ApiServer/Mappers/DockerImageMapper.cs +++ b/MoonlightServers.ApiServer/Mappers/DockerImageMapper.cs @@ -1,6 +1,5 @@ using MoonlightServers.ApiServer.Database.Entities; using MoonlightServers.Shared.Http.Requests.Admin.StarDockerImages; -using MoonlightServers.Shared.Http.Requests.Admin.StarVariables; using MoonlightServers.Shared.Http.Responses.Admin.StarDockerImages; using Riok.Mapperly.Abstractions; @@ -11,5 +10,5 @@ public static partial class DockerImageMapper { public static partial StarDockerImageDetailResponse ToAdminResponse(StarDockerImage dockerImage); public static partial StarDockerImage ToDockerImage(CreateStarDockerImageRequest request); - public static partial StarDockerImage Merge(UpdateStarVariableRequest request, StarDockerImage variable); + public static partial StarDockerImage Merge(UpdateStarDockerImageRequest request, StarDockerImage variable); } \ No newline at end of file diff --git a/MoonlightServers.ApiServer/Mappers/StarMapper.cs b/MoonlightServers.ApiServer/Mappers/StarMapper.cs new file mode 100644 index 0000000..92d1009 --- /dev/null +++ b/MoonlightServers.ApiServer/Mappers/StarMapper.cs @@ -0,0 +1,15 @@ +using MoonlightServers.ApiServer.Database.Entities; +using MoonlightServers.Shared.Http.Requests.Admin.StarDockerImages; +using MoonlightServers.Shared.Http.Requests.Admin.Stars; +using MoonlightServers.Shared.Http.Responses.Admin.Stars; +using Riok.Mapperly.Abstractions; + +namespace MoonlightServers.ApiServer.Mappers; + +[Mapper(AllowNullPropertyAssignment = false)] +public static partial class StarMapper +{ + public static partial StarDetailResponse ToAdminResponse(Star star); + public static partial Star ToStar(CreateStarRequest request); + public static partial Star Merge(UpdateStarRequest request, Star star); +} \ No newline at end of file diff --git a/MoonlightServers.ApiServer/Services/ServerService.cs b/MoonlightServers.ApiServer/Services/ServerService.cs index c0cbb80..a59482b 100644 --- a/MoonlightServers.ApiServer/Services/ServerService.cs +++ b/MoonlightServers.ApiServer/Services/ServerService.cs @@ -149,12 +149,8 @@ public class ServerService { if (server.OwnerId == user.Id) return true; - - var permissions = JsonSerializer.Deserialize( - user.PermissionsJson - ) ?? []; - - return PermissionHelper.HasPermission(permissions, "admin.servers.get"); + + return PermissionHelper.HasPermission(user.Permissions, "admin.servers.get"); } private async Task GetApiClient(Server server) diff --git a/MoonlightServers.ApiServer/Startup/PluginStartup.cs b/MoonlightServers.ApiServer/Startup/PluginStartup.cs index 4e3ae67..e6de9d4 100644 --- a/MoonlightServers.ApiServer/Startup/PluginStartup.cs +++ b/MoonlightServers.ApiServer/Startup/PluginStartup.cs @@ -13,7 +13,6 @@ using MoonlightServers.ApiServer.Interfaces; namespace MoonlightServers.ApiServer.Startup; -[PluginStartup] public class PluginStartup : IPluginStartup { public Task BuildApplication(IServiceProvider serviceProvider, IHostApplicationBuilder builder) @@ -30,7 +29,7 @@ public class PluginStartup : IPluginStartup var configuration = serviceProvider.GetRequiredService(); - if (configuration.Client.Enable) + if (configuration.Frontend.EnableHosting) { builder.Services.AddSingleton(new FrontendConfigurationOption() {