using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using MoonCore.Attributes; using MoonCore.Exceptions; using MoonCore.Extended.Abstractions; using MoonCore.Extensions; using MoonCore.Models; using Moonlight.ApiServer.Database.Entities; using MoonlightServers.ApiServer.Database.Entities; using MoonlightServers.ApiServer.Extensions; using MoonlightServers.ApiServer.Services; using MoonlightServers.Shared.Http.Responses.User.Allocations; using MoonlightServers.Shared.Http.Responses.Users.Servers; namespace MoonlightServers.ApiServer.Http.Controllers.Users; [ApiController] [Route("api/servers")] public class ServersController : Controller { private readonly DatabaseRepository ServerRepository; private readonly NodeService NodeService; public ServersController(DatabaseRepository serverRepository, NodeService nodeService) { ServerRepository = serverRepository; NodeService = nodeService; } [HttpGet("list")] [RequirePermission("meta.authenticated")] public async Task> List([FromQuery] int page, [FromQuery] int pageSize) { var user = User.AsIdentity(); var query = ServerRepository .Get() .Include(x => x.Allocations) .Include(x => x.Star) .Include(x => x.Node) .Where(x => x.OwnerId == user.Id); var count = await query.CountAsync(); var items = await query.Skip(page * pageSize).Take(pageSize).ToArrayAsync(); var mappedItems = items.Select(x => new ServerDetailResponse() { Id = x.Id, Name = x.Name, NodeName = x.Node.Name, StarName = x.Star.Name, Allocations = x.Allocations.Select(y => new AllocationDetailResponse() { Id = y.Id, Port = y.Port, IpAddress = y.IpAddress }).ToArray() }).ToArray(); return new PagedData() { Items = mappedItems, CurrentPage = page, PageSize = pageSize, TotalItems = count, TotalPages = count == 0 ? 0 : count / pageSize }; } [HttpGet("{serverId:int}/status")] [RequirePermission("meta.authenticated")] public async Task GetStatus([FromRoute] int serverId) { var server = await GetServerWithPermCheck(serverId); var apiClient = await NodeService.CreateApiClient(server.Node); try { var data = await apiClient.GetJson( $"api/servers/{server.Id}/status" ); return new ServerStatusResponse() { PowerState = data.State.ToServerPowerState() }; } catch (HttpRequestException e) { throw new HttpApiException("Unable to access the node the server is running on", 502); } } private async Task GetServerWithPermCheck(int serverId) { var user = User.AsIdentity(); var server = await ServerRepository .Get() .Include(x => x.Node) .FirstOrDefaultAsync(x => x.Id == serverId); if (server == null) throw new HttpApiException("No server with this id found", 404); if (server.OwnerId == user.Id) // The current user is the owner return server; if (User.HasPermission("admin.servers.get")) // The current user is an admin return server; throw new HttpApiException("No server with this id found", 404); } }