Started refactoring to be compatible with the changed nuget packages and the mooncore changes

This commit is contained in:
2025-07-15 19:21:44 +02:00
parent b53140e633
commit 514f862a9d
71 changed files with 616 additions and 247 deletions

View File

@@ -0,0 +1,10 @@
using MoonCore.PluginFramework;
using Moonlight.ApiServer.Plugins;
namespace MoonlightServers.ApiServer.Runtime;
[PluginLoader]
public partial class DevPluginLoader : IPluginStartup
{
}

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoDefaultLaunchSettingsFile>True</NoDefaultLaunchSettingsFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MoonlightServers.ApiServer\MoonlightServers.ApiServer.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.7" />
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.8"/>
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.7" PrivateAssets="all"/>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,31 @@
using Moonlight.ApiServer.Startup;
using MoonlightServers.ApiServer.Runtime;
var pluginLoader = new DevPluginLoader();
pluginLoader.Initialize();
var cs = new Startup();
await cs.Initialize(args, pluginLoader.Instances);
var builder = WebApplication.CreateBuilder(args);
await cs.AddMoonlight(builder);
var app = builder.Build();
await cs.AddMoonlight(app);
// Handle setup of wasm app hosting in the runtime
// so the Moonlight.ApiServer doesn't need the wasm package
if (cs.Configuration.Frontend.EnableHosting)
{
if (app.Environment.IsDevelopment())
app.UseWebAssemblyDebugging();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
}
await app.RunAsync();

View File

@@ -2,6 +2,8 @@ using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MoonCore.Extended.Abstractions;
using MoonlightServers.ApiServer.Database.Entities;

View File

@@ -6,6 +6,7 @@ using MoonCore.Exceptions;
using MoonCore.Extended.Abstractions;
using MoonCore.Models;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Mappers;
using MoonlightServers.Shared.Http.Requests.Admin.NodeAllocations;
using MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations;
@@ -29,9 +30,9 @@ public class NodeAllocationsController : Controller
[HttpGet("{nodeId:int}/allocations")]
[Authorize(Policy = "permissions:admin.servers.nodes.get")]
public async Task<IPagedData<NodeAllocationDetailResponse>> Get(
public async Task<IPagedData<NodeAllocationResponse>> Get(
[FromRoute] int nodeId,
[FromQuery] int page,
[FromQuery] [Range(0, int.MaxValue)] int page,
[FromQuery] [Range(1, 100)] int pageSize
)
{
@@ -44,14 +45,11 @@ public class NodeAllocationsController : Controller
.Where(x => x.Node.Id == nodeId)
.ToArrayAsync();
var mappedAllocations = allocations.Select(x => new NodeAllocationDetailResponse()
{
Id = x.Id,
IpAddress = x.IpAddress,
Port = x.Port
}).ToArray();
var mappedAllocations = allocations
.Select(AllocationMapper.ToNodeAllocation)
.ToArray();
return new PagedData<NodeAllocationDetailResponse>()
return new PagedData<NodeAllocationResponse>()
{
Items = mappedAllocations,
CurrentPage = page,
@@ -63,7 +61,7 @@ public class NodeAllocationsController : Controller
[HttpGet("{nodeId:int}/allocations/{id:int}")]
[Authorize(Policy = "permissions:admin.servers.nodes.get")]
public async Task<NodeAllocationDetailResponse> GetSingle([FromRoute] int nodeId, [FromRoute] int id)
public async Task<NodeAllocationResponse> GetSingle([FromRoute] int nodeId, [FromRoute] int id)
{
var allocation = await AllocationRepository
.Get()
@@ -73,17 +71,12 @@ public class NodeAllocationsController : Controller
if (allocation == null)
throw new HttpApiException("No allocation with that id found", 404);
return new()
{
Id = allocation.Id,
IpAddress = allocation.IpAddress,
Port = allocation.Port
};
return AllocationMapper.ToNodeAllocation(allocation);
}
[HttpPost("{nodeId:int}/allocations")]
[Authorize(Policy = "permissions:admin.servers.nodes.create")]
public async Task<NodeAllocationDetailResponse> Create(
public async Task<NodeAllocationResponse> Create(
[FromRoute] int nodeId,
[FromBody] CreateNodeAllocationRequest request
)
@@ -95,26 +88,19 @@ public class NodeAllocationsController : Controller
if (node == null)
throw new HttpApiException("No node with that id found", 404);
var allocation = new Allocation
{
IpAddress = request.IpAddress,
Port = request.Port,
Node = node
};
var allocation = AllocationMapper.ToAllocation(request);
var finalVariable = await AllocationRepository.Add(allocation);
var finalAllocation = await AllocationRepository.Add(allocation);
return new()
{
Id = finalVariable.Id,
IpAddress = finalVariable.IpAddress,
Port = finalVariable.Port
};
return AllocationMapper.ToNodeAllocation(finalAllocation);
}
[HttpPatch("{nodeId:int}/allocations/{id:int}")]
public async Task<NodeAllocationDetailResponse> Update([FromRoute] int nodeId, [FromRoute] int id,
[FromBody] UpdateNodeAllocationRequest request)
public async Task<NodeAllocationResponse> Update(
[FromRoute] int nodeId,
[FromRoute] int id,
[FromBody] UpdateNodeAllocationRequest request
)
{
var allocation = await AllocationRepository
.Get()
@@ -124,17 +110,10 @@ public class NodeAllocationsController : Controller
if (allocation == null)
throw new HttpApiException("No allocation with that id found", 404);
allocation.IpAddress = request.IpAddress;
allocation.Port = request.Port;
AllocationMapper.Merge(request, allocation);
await AllocationRepository.Update(allocation);
return new()
{
Id = allocation.Id,
IpAddress = allocation.IpAddress,
Port = allocation.Port
};
return AllocationMapper.ToNodeAllocation(allocation);
}
[HttpDelete("{nodeId:int}/allocations/{id:int}")]
@@ -160,7 +139,7 @@ public class NodeAllocationsController : Controller
if (node == null)
throw new HttpApiException("No node with that id found", 404);
var existingAllocations = AllocationRepository
.Get()
.Where(x => x.Node.Id == nodeId)
@@ -202,8 +181,12 @@ public class NodeAllocationsController : Controller
[HttpGet("{nodeId:int}/allocations/free")]
[Authorize(Policy = "permissions:admin.servers.nodes.get")]
public async Task<IPagedData<NodeAllocationDetailResponse>> GetFree([FromRoute] int nodeId, [FromQuery] int page,
[FromQuery][Range(1, 100)] int pageSize, [FromQuery] int serverId = -1)
public async Task<IPagedData<NodeAllocationResponse>> GetFree(
[FromRoute] int nodeId,
[FromQuery] int page,
[FromQuery] [Range(1, 100)] int pageSize,
[FromQuery] int serverId = -1
)
{
var node = NodeRepository
.Get()
@@ -220,14 +203,11 @@ public class NodeAllocationsController : Controller
var count = await freeAllocationsQuery.CountAsync();
var allocations = await freeAllocationsQuery.ToArrayAsync();
var mappedAllocations = allocations.Select(x => new NodeAllocationDetailResponse()
{
Id = x.Id,
IpAddress = x.IpAddress,
Port = x.Port
}).ToArray();
var mappedAllocations = allocations
.Select(AllocationMapper.ToNodeAllocation)
.ToArray();
return new PagedData<NodeAllocationDetailResponse>()
return new PagedData<NodeAllocationResponse>()
{
Items = mappedAllocations,
CurrentPage = page,

View File

@@ -1,13 +1,14 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MoonCore.Extended.Abstractions;
using MoonCore.Extended.Helpers;
using Microsoft.AspNetCore.Authorization;
using MoonCore.Exceptions;
using MoonCore.Helpers;
using MoonCore.Models;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Mappers;
using MoonlightServers.Shared.Http.Requests.Admin.Nodes;
using MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations;
using MoonlightServers.Shared.Http.Responses.Admin.Nodes;
namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Nodes;
@@ -16,57 +17,102 @@ namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Nodes;
[Route("api/admin/servers/nodes")]
public class NodesController : Controller
{
private readonly CrudHelper<Node, NodeDetailResponse> CrudHelper;
private readonly DatabaseRepository<Node> NodeRepository;
public NodesController(
CrudHelper<Node, NodeDetailResponse> crudHelper,
DatabaseRepository<Node> nodeRepository
)
{
CrudHelper = crudHelper;
NodeRepository = nodeRepository;
}
[HttpGet]
[Authorize(Policy = "permissions:admin.servers.nodes.get")]
public async Task<IPagedData<NodeDetailResponse>> Get([FromQuery] int page, [FromQuery] int pageSize)
public async Task<IPagedData<NodeResponse>> Get(
[FromQuery] [Range(0, int.MaxValue)] int page,
[FromQuery] [Range(1, 100)] int pageSize
)
{
return await CrudHelper.Get(page, pageSize);
var query = NodeRepository
.Get();
var count = await query.CountAsync();
var items = await query
.Skip(page * pageSize)
.Take(pageSize)
.ToArrayAsync();
var mappedItems = items
.Select(NodeMapper.ToAdminNodeResponse)
.ToArray();
return new PagedData<NodeResponse>()
{
Items = mappedItems,
CurrentPage = page,
PageSize = pageSize,
TotalItems = count,
TotalPages = count == 0 ? 0 : count / pageSize
};
}
[HttpGet("{id:int}")]
[Authorize(Policy = "permissions:admin.servers.nodes.get")]
public async Task<NodeDetailResponse> GetSingle([FromRoute] int id)
public async Task<NodeResponse> GetSingle([FromRoute] int id)
{
return await CrudHelper.GetSingle(id);
var node = await NodeRepository
.Get()
.FirstOrDefaultAsync(x => x.Id == id);
if (node == null)
throw new HttpApiException("No node with this id found", 404);
return NodeMapper.ToAdminNodeResponse(node);
}
[HttpPost]
[Authorize(Policy = "permissions:admin.servers.nodes.create")]
public async Task<NodeDetailResponse> Create([FromBody] CreateNodeRequest request)
public async Task<NodeResponse> Create([FromBody] CreateNodeRequest request)
{
var node = Mapper.Map<Node>(request);
var node = NodeMapper.ToNode(request);
node.TokenId = Formatter.GenerateString(6);
node.Token = Formatter.GenerateString(32);
var finalNode = await NodeRepository.Add(node);
return CrudHelper.MapToResult(finalNode);
return NodeMapper.ToAdminNodeResponse(finalNode);
}
[HttpPatch("{id:int}")]
[Authorize(Policy = "permissions:admin.servers.nodes.update")]
public async Task<NodeDetailResponse> Update([FromRoute] int id, [FromBody] UpdateNodeRequest request)
public async Task<NodeResponse> Update([FromRoute] int id, [FromBody] UpdateNodeRequest request)
{
return await CrudHelper.Update(id, request);
var node = await NodeRepository
.Get()
.FirstOrDefaultAsync(x => x.Id == id);
if (node == null)
throw new HttpApiException("No node with this id found", 404);
node = NodeMapper.Merge(request, node);
await NodeRepository.Update(node);
return NodeMapper.ToAdminNodeResponse(node);
}
[HttpDelete("{id:int}")]
[Authorize(Policy = "permissions:admin.servers.nodes.delete")]
public async Task Delete([FromRoute] int id)
{
await CrudHelper.Delete(id);
var node = await NodeRepository
.Get()
.FirstOrDefaultAsync(x => x.Id == id);
if (node == null)
throw new HttpApiException("No node with this id found", 404);
await NodeRepository.Remove(node);
}
}

View File

@@ -1,11 +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.Helpers;
using MoonCore.Models;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Mappers;
using MoonlightServers.Shared.Http.Responses.Admin.ServerVariables;
namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Servers;
@@ -17,32 +18,39 @@ public class ServerVariablesController : Controller
private readonly DatabaseRepository<ServerVariable> VariableRepository;
private readonly DatabaseRepository<Server> ServerRepository;
public ServerVariablesController(DatabaseRepository<ServerVariable> variableRepository, DatabaseRepository<Server> serverRepository)
public ServerVariablesController(DatabaseRepository<ServerVariable> variableRepository,
DatabaseRepository<Server> serverRepository)
{
VariableRepository = variableRepository;
ServerRepository = serverRepository;
}
[HttpGet("{serverId}/variables")]
[Authorize(Policy = "permissions:admin.servers.get")]
public async Task<PagedData<ServerVariableDetailResponse>> Get([FromRoute] int serverId, [FromQuery] int page, [FromQuery] int pageSize)
[Authorize(Policy = "permissions:admin.servers.read")]
public async Task<PagedData<ServerVariableResponse>> Get(
[FromRoute] int serverId,
[FromQuery] [Range(0, int.MaxValue)] int page,
[FromQuery] [Range(1, 100)] int pageSize
)
{
var server = await ServerRepository
var serverExists = await ServerRepository
.Get()
.FirstOrDefaultAsync(x => x.Id == serverId);
.AnyAsync(x => x.Id == serverId);
if (server == null)
if (!serverExists)
throw new HttpApiException("No server with this id found", 404);
var variables = await VariableRepository
.Get()
.Where(x => x.Server.Id == server.Id)
.Where(x => x.Server.Id == serverId)
.Skip(page * pageSize)
.Take(pageSize)
.ToArrayAsync();
var castedVariables = variables
.Select(x => Mapper.Map<ServerVariableDetailResponse>(x))
.Select(ServerVariableMapper.ToAdminResponse)
.ToArray();
return PagedData<ServerVariableDetailResponse>.Create(castedVariables, page, pageSize);
return PagedData<ServerVariableResponse>.Create(castedVariables, page, pageSize);
}
}

View File

@@ -1,6 +1,8 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using MoonCore.Exceptions;
using MoonCore.Extended.Abstractions;
using MoonCore.Extended.Helpers;
@@ -8,6 +10,7 @@ using MoonCore.Helpers;
using MoonCore.Models;
using Moonlight.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Mappers;
using MoonlightServers.ApiServer.Services;
using MoonlightServers.Shared.Http.Requests.Admin.Servers;
using MoonlightServers.Shared.Http.Responses.Admin.Servers;
@@ -18,7 +21,6 @@ namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Servers;
[Route("api/admin/servers")]
public class ServersController : Controller
{
private readonly CrudHelper<Server, ServerDetailResponse> CrudHelper;
private readonly DatabaseRepository<Star> StarRepository;
private readonly DatabaseRepository<Node> NodeRepository;
private readonly DatabaseRepository<Allocation> AllocationRepository;
@@ -29,7 +31,6 @@ public class ServersController : Controller
private readonly ServerService ServerService;
public ServersController(
CrudHelper<Server, ServerDetailResponse> crudHelper,
DatabaseRepository<Star> starRepository,
DatabaseRepository<Node> nodeRepository,
DatabaseRepository<Allocation> allocationRepository,
@@ -40,7 +41,6 @@ public class ServersController : Controller
ServerService serverService
)
{
CrudHelper = crudHelper;
StarRepository = starRepository;
NodeRepository = nodeRepository;
AllocationRepository = allocationRepository;
@@ -49,48 +49,68 @@ public class ServersController : Controller
UserRepository = userRepository;
ServerService = serverService;
Logger = logger;
CrudHelper.QueryModifier = servers => servers
.Include(x => x.Node)
.Include(x => x.Allocations)
.Include(x => x.Variables)
.Include(x => x.Star);
CrudHelper.LateMapper = (server, response) =>
{
response.NodeId = server.Node.Id;
response.StarId = server.Star.Id;
response.AllocationIds = server.Allocations.Select(x => x.Id).ToArray();
return response;
};
}
[HttpGet]
[Authorize(Policy = "permissions:admin.servers.get")]
public async Task<IPagedData<ServerDetailResponse>> Get([FromQuery] int page, [FromQuery] int pageSize)
[Authorize(Policy = "permissions:admin.servers.read")]
public async Task<IPagedData<ServerResponse>> Get(
[FromQuery] [Range(0, int.MaxValue)] int page,
[FromQuery] [Range(1, 100)] int pageSize
)
{
return await CrudHelper.Get(page, pageSize);
var count = await ServerRepository.Get().CountAsync();
var items = await ServerRepository
.Get()
.Include(x => x.Node)
.Include(x => x.Allocations)
.Include(x => x.Variables)
.Include(x => x.Star)
.Skip(page * pageSize)
.Take(pageSize)
.ToArrayAsync();
var mappedItems = items
.Select(ServerMapper.ToAdminServerResponse)
.ToArray();
return new PagedData<ServerResponse>()
{
Items = mappedItems,
CurrentPage = page,
PageSize = pageSize,
TotalItems = count,
TotalPages = count == 0 ? 0 : count / pageSize
};
}
[HttpGet("{id:int}")]
[Authorize(Policy = "permissions:admin.servers.get")]
public async Task<ServerDetailResponse> GetSingle([FromRoute] int id)
[Authorize(Policy = "permissions:admin.servers.read")]
public async Task<ServerResponse> GetSingle([FromRoute] int id)
{
return await CrudHelper.GetSingle(id);
var server = await ServerRepository
.Get()
.Include(x => x.Node)
.Include(x => x.Allocations)
.Include(x => x.Variables)
.Include(x => x.Star)
.FirstOrDefaultAsync(x => x.Id == id);
if (server == null)
throw new HttpApiException("No server with that id found", 404);
return ServerMapper.ToAdminServerResponse(server);
}
[HttpPost]
[Authorize(Policy = "permissions:admin.servers.create")]
public async Task<ServerDetailResponse> Create([FromBody] CreateServerRequest request)
[Authorize(Policy = "permissions:admin.servers.write")]
public async Task<ServerResponse> Create([FromBody] CreateServerRequest request)
{
// Construct model
var server = Mapper.Map<Server>(request);
// Check if owner user exist
if (UserRepository.Get().All(x => x.Id != request.OwnerId))
throw new HttpApiException("No user with this id found", 400);
// Check if the star exists
var star = await StarRepository
.Get()
.Include(x => x.Variables)
@@ -146,6 +166,8 @@ public class ServersController : Controller
);
}
}
var server = ServerMapper.ToServer(request);
// Set allocations
server.Allocations = allocations;
@@ -181,23 +203,33 @@ public class ServersController : Controller
Logger.LogError("Unable to sync server to node the server is assigned to: {e}", e);
// We are deleting the server from the database after the creation has failed
// to ensure we wont have a bugged server in the database which doesnt exist on the node
// to ensure we won't have a bugged server in the database which doesnt exist on the node
await ServerRepository.Remove(finalServer);
throw;
}
return CrudHelper.MapToResult(finalServer);
return ServerMapper.ToAdminServerResponse(finalServer);
}
[HttpPatch("{id:int}")]
public async Task<ServerDetailResponse> Update([FromRoute] int id, [FromBody] UpdateServerRequest request)
[Authorize(Policy = "permissions.admin.servers.write")]
public async Task<ServerResponse> Update([FromRoute] int id, [FromBody] UpdateServerRequest request)
{
//TODO: Handle shrinking virtual disk
var server = await CrudHelper.GetSingleModel(id);
server = Mapper.Map(server, request);
var server = await ServerRepository
.Get()
.Include(x => x.Node)
.Include(x => x.Allocations)
.Include(x => x.Variables)
.Include(x => x.Star)
.FirstOrDefaultAsync(x => x.Id == id);
if (server == null)
throw new HttpApiException("No server with that id found", 404);
server = ServerMapper.Merge(request, server);
var allocations = new List<Allocation>();
@@ -250,14 +282,20 @@ public class ServersController : Controller
// Notify the node about the changes
await ServerService.Sync(server);
return CrudHelper.MapToResult(server);
return ServerMapper.ToAdminServerResponse(server);
}
[HttpDelete("{id:int}")]
public async Task Delete([FromRoute] int id, [FromQuery] bool force = false)
{
var server = await CrudHelper.GetSingleModel(id);
var server = await ServerRepository
.Get()
.Include(x => x.Node)
.FirstOrDefaultAsync(x => x.Id == id);
if (server == null)
throw new HttpApiException("No server with that id found", 404);
try
{
// If the sync fails on the node and we aren't forcing the deletion,
@@ -277,6 +315,6 @@ public class ServersController : Controller
throw;
}
await CrudHelper.Delete(id);
await ServerRepository.Remove(server);
}
}

View File

@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MoonCore.Exceptions;
@@ -7,6 +8,7 @@ using Microsoft.AspNetCore.Authorization;
using MoonCore.Helpers;
using MoonCore.Models;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Mappers;
using MoonlightServers.Shared.Http.Requests.Admin.StarDockerImages;
using MoonlightServers.Shared.Http.Responses.Admin.StarDockerImages;
@@ -16,45 +18,56 @@ namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Stars;
[Route("api/admin/servers/stars")]
public class StarDockerImagesController : Controller
{
private readonly CrudHelper<StarDockerImage, StarDockerImageDetailResponse> CrudHelper;
private readonly DatabaseRepository<Star> StarRepository;
private readonly DatabaseRepository<StarDockerImage> StarDockerImageRepository;
private Star Star;
public StarDockerImagesController(
CrudHelper<StarDockerImage, StarDockerImageDetailResponse> crudHelper,
DatabaseRepository<Star> starRepository,
DatabaseRepository<StarDockerImage> starDockerImageRepository
)
{
CrudHelper = crudHelper;
StarRepository = starRepository;
StarDockerImageRepository = starDockerImageRepository;
}
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 = dockerImages =>
dockerImages.Where(x => x.Star.Id == star.Id);
}
[HttpGet("{starId:int}/dockerImages")]
[Authorize(Policy = "permissions:admin.servers.stars.get")]
public async Task<IPagedData<StarDockerImageDetailResponse>> Get([FromRoute] int starId, [FromQuery] int page, [FromQuery] int pageSize)
public async Task<IPagedData<StarDockerImageDetailResponse>> 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 = StarDockerImageRepository
.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(DockerImageMapper.ToAdminResponse)
.ToArray();
return new PagedData<StarDockerImageDetailResponse>()
{
Items = mappedItems,
CurrentPage = page,
PageSize = pageSize,
TotalItems = count,
TotalPages = count == 0 ? 0 : count / pageSize
};
}
[HttpGet("{starId:int}/dockerImages/{id:int}")]
@@ -62,16 +75,17 @@ public class StarDockerImagesController : Controller
public async Task<StarDockerImageDetailResponse> GetSingle([FromRoute] int starId, [FromRoute] int id)
{
await ApplyStar(starId);
return await CrudHelper.GetSingle(id);
}
[HttpPost("{starId:int}/dockerImages")]
[Authorize(Policy = "permissions:admin.servers.stars.create")]
public async Task<StarDockerImageDetailResponse> Create([FromRoute] int starId, [FromBody] CreateStarDockerImageRequest request)
public async Task<StarDockerImageDetailResponse> Create([FromRoute] int starId,
[FromBody] CreateStarDockerImageRequest request)
{
await ApplyStar(starId);
var starDockerImage = Mapper.Map<StarDockerImage>(request);
starDockerImage.Star = Star;
@@ -86,7 +100,7 @@ public class StarDockerImagesController : Controller
[FromBody] UpdateStarDockerImageRequest request)
{
await ApplyStar(starId);
return await CrudHelper.Update(id, request);
}
@@ -95,7 +109,7 @@ public class StarDockerImagesController : Controller
public async Task Delete([FromRoute] int starId, [FromRoute] int id)
{
await ApplyStar(starId);
await CrudHelper.Delete(id);
}
}

View File

@@ -1,6 +1,7 @@
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using MoonCore.Exceptions;
using MoonCore.Helpers;
using MoonlightServers.ApiServer.Services;

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MoonCore.Exceptions;
using MoonCore.Extended.Abstractions;
using MoonCore.Models;

View File

@@ -0,0 +1,14 @@
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.Shared.Http.Requests.Admin.NodeAllocations;
using MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations;
using Riok.Mapperly.Abstractions;
namespace MoonlightServers.ApiServer.Mappers;
[Mapper(AllowNullPropertyAssignment = false)]
public static partial class AllocationMapper
{
public static partial NodeAllocationResponse ToNodeAllocation(Allocation allocation);
public static partial Allocation ToAllocation(CreateNodeAllocationRequest request);
public static partial Allocation Merge(UpdateNodeAllocationRequest request, Allocation allocation);
}

View File

@@ -0,0 +1,15 @@
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;
namespace MoonlightServers.ApiServer.Mappers;
[Mapper(AllowNullPropertyAssignment = false)]
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);
}

View File

@@ -0,0 +1,14 @@
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.Shared.Http.Requests.Admin.Nodes;
using MoonlightServers.Shared.Http.Responses.Admin.Nodes;
using Riok.Mapperly.Abstractions;
namespace MoonlightServers.ApiServer.Mappers;
[Mapper(AllowNullPropertyAssignment = false)]
public static partial class NodeMapper
{
public static partial NodeResponse ToAdminNodeResponse(Node node);
public static partial Node ToNode(CreateNodeRequest request);
public static partial Node Merge(UpdateNodeRequest request, Node node);
}

View File

@@ -0,0 +1,25 @@
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.Shared.Http.Requests.Admin.Servers;
using MoonlightServers.Shared.Http.Responses.Admin.Servers;
using Riok.Mapperly.Abstractions;
namespace MoonlightServers.ApiServer.Mappers;
[Mapper(AllowNullPropertyAssignment = false)]
public static partial class ServerMapper
{
[UserMapping(Default = true)]
public static ServerResponse ToAdminServerResponse(Server server)
{
var response = ToAdminServerResponse_Internal(server);
response.AllocationIds = server.Allocations.Select(x => x.Id).ToArray();
return response;
}
private static partial ServerResponse ToAdminServerResponse_Internal(Server server);
public static partial Server ToServer(CreateServerRequest request);
public static partial Server Merge(UpdateServerRequest request, Server server);
}

View File

@@ -0,0 +1,11 @@
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.Shared.Http.Responses.Admin.ServerVariables;
using Riok.Mapperly.Abstractions;
namespace MoonlightServers.ApiServer.Mappers;
[Mapper(AllowNullPropertyAssignment = false)]
public static partial class ServerVariableMapper
{
public static partial ServerVariableResponse ToAdminResponse(ServerVariable serverVariable);
}

View File

@@ -0,0 +1,14 @@
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.Shared.Http.Requests.Admin.StarVariables;
using MoonlightServers.Shared.Http.Responses.Admin.StarVariables;
using Riok.Mapperly.Abstractions;
namespace MoonlightServers.ApiServer.Mappers;
[Mapper(AllowNullPropertyAssignment = false)]
public static partial class StarVariableMapper
{
public static partial StarVariableDetailResponse ToAdminResponse(StarVariable variable);
public static partial StarVariable ToStarVariable(CreateStarVariableRequest request);
public static partial StarVariable Merge(UpdateStarVariableRequest request, StarVariable variable);
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
@@ -16,13 +16,13 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Moonlight.ApiServer" Version="2.1.0"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.5"/>
<PackageReference Include="Moonlight.ApiServer" Version="2.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7"/>
<PackageReference Include="Riok.Mapperly" Version="4.3.0-next.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MoonlightServers.DaemonShared\MoonlightServers.DaemonShared.csproj"/>
<ProjectReference Include="..\MoonlightServers.Frontend\MoonlightServers.Frontend.csproj"/>
<ProjectReference Include="..\MoonlightServers.Shared\MoonlightServers.Shared.csproj"/>
</ItemGroup>

View File

@@ -1,18 +0,0 @@
using System.Text.Json;
using Moonlight.ApiServer;
using Moonlight.ApiServer.Models;
using MoonlightServers.ApiServer.Startup;
// Development Server Startup
// This file is a small helper for development instances for moonlight.
// It calls the moonlight startup with the current project loaded as a plugin.
// This allows you to develop and debug projects without any hassle
// !!! DO NOT HARDCORE ANY SECRETS HERE !!!
var startup = new Startup();
await startup.Run(args, [
new PluginStartup()
]);

View File

@@ -1,3 +1,5 @@
using Microsoft.Extensions.Hosting;
namespace MoonlightServers.ApiServer.Services;
public class NodeBootService : IHostedLifecycleService

View File

@@ -1,5 +1,6 @@
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MoonCore.Attributes;
using MoonCore.Exceptions;
using MoonCore.Extended.Abstractions;

View File

@@ -1,3 +1,7 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MoonCore.Extensions;
using Moonlight.ApiServer.Configuration;
using Moonlight.ApiServer.Models;

View File

@@ -0,0 +1,10 @@
using MoonCore.PluginFramework;
using Moonlight.Client.Plugins;
namespace MoonlightServers.Frontend.Runtime;
[PluginLoader]
public partial class DevPluginLoader : IPluginStartup
{
}

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.8" />
<PackageReference Include="MoonCore.PluginFramework.Generator" Version="1.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.7" PrivateAssets="all"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MoonlightServers.Frontend\MoonlightServers.Frontend.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Moonlight.Client.Startup;
using MoonlightServers.Frontend.Runtime;
var pluginLoader = new DevPluginLoader();
pluginLoader.Initialize();
var startup = new Startup();
await startup.Initialize(pluginLoader.Instances);
var wasmHostBuilder = WebAssemblyHostBuilder.CreateDefault(args);
await startup.AddMoonlight(wasmHostBuilder);
var wasmApp = wasmHostBuilder.Build();
await startup.AddMoonlight(wasmApp);
await wasmApp.RunAsync();

View File

@@ -1,3 +1,5 @@
using System.IO.Enumeration;
using MoonCore.Blazor.FlyonUi.Helpers;
using MoonCore.Blazor.Tailwind.Fm;
using MoonCore.Blazor.Tailwind.Fm.Models;
using MoonCore.Blazor.Tailwind.Services;

View File

@@ -16,10 +16,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.5"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.5" PrivateAssets="all"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.7"/>
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.5" />
<PackageReference Include="Moonlight.Client" Version="2.1.0"/>
<PackageReference Include="Moonlight.Client" Version="2.1.3"/>
<PackageReference Include="XtermBlazor" Version="2.1.2" />
</ItemGroup>

View File

@@ -1,4 +1,5 @@
using Moonlight.Client;
using Moonlight.Client.Startup;
using MoonlightServers.Frontend.Startup;
// Development Client Startup

View File

@@ -1,8 +1,9 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonCore.Blazor.Tailwind.Components
@using MoonlightServers.Shared.Http.Requests.Admin.NodeAllocations
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Add a new allocation</h1>

View File

@@ -1,8 +1,9 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonCore.Blazor.Tailwind.Components
@using MoonlightServers.Shared.Http.Requests.Admin.NodeAllocations
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Add a range of new allocations</h1>

View File

@@ -1,10 +1,11 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Helpers
@using MoonlightServers.Shared.Http.Requests.Admin.NodeAllocations
@using MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Update allocation</h1>
@@ -30,7 +31,7 @@
@code
{
[Parameter] public Func<UpdateNodeAllocationRequest, Task> OnSubmit { get; set; }
[Parameter] public NodeAllocationDetailResponse Allocation { get; set; }
[Parameter] public NodeAllocationResponse Allocation { get; set; }
private UpdateNodeAllocationRequest Form;
private HandleForm HandleForm;

View File

@@ -1,3 +1,7 @@
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.DataTables
@using MoonCore.Blazor.FlyonUi.Modals
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonlightServers.Shared.Http.Responses.Admin.Nodes
@using MoonCore.Blazor.Tailwind.Dt
@@ -31,13 +35,13 @@
</div>
</div>
<div class="col-span-1 md:col-span-2 -mb-3">
<DataTable @ref="Table" TItem="NodeAllocationDetailResponse">
<DataTable @ref="Table" TItem="NodeAllocationResponse">
<Configuration>
<Pagination TItem="NodeAllocationDetailResponse" ItemSource="LoadData" />
<Pagination TItem="NodeAllocationResponse" ItemSource="LoadData" />
<DataTableColumn TItem="NodeAllocationDetailResponse" Field="@(x => x.IpAddress)" Name="IP Address"/>
<DataTableColumn TItem="NodeAllocationDetailResponse" Field="@(x => x.Port)" Name="Port"/>
<DataTableColumn TItem="NodeAllocationDetailResponse">
<DataTableColumn TItem="NodeAllocationResponse" Field="@(x => x.IpAddress)" Name="IP Address"/>
<DataTableColumn TItem="NodeAllocationResponse" Field="@(x => x.Port)" Name="Port"/>
<DataTableColumn TItem="NodeAllocationResponse">
<ColumnTemplate>
<div class="flex justify-end items-center">
<a @onclick="() => UpdateAllocation(context)" @onclick:preventDefault href="#"
@@ -58,13 +62,13 @@
@code
{
[Parameter] public NodeDetailResponse Node { get; set; }
[Parameter] public NodeResponse Node { get; set; }
private DataTable<NodeAllocationDetailResponse> Table;
private DataTable<NodeAllocationResponse> Table;
private async Task<IPagedData<NodeAllocationDetailResponse>> LoadData(PaginationOptions options)
private async Task<IPagedData<NodeAllocationResponse>> LoadData(PaginationOptions options)
{
return await ApiClient.GetJson<PagedData<NodeAllocationDetailResponse>>(
return await ApiClient.GetJson<PagedData<NodeAllocationResponse>>(
$"api/admin/servers/nodes/{Node.Id}/allocations?page={options.Page}&pageSize={options.PerPage}"
);
}
@@ -98,7 +102,7 @@
await ModalService.Launch<CreateAllocationModal>(parameters => { parameters.Add("OnSubmit", onSubmit); });
}
private async Task UpdateAllocation(NodeAllocationDetailResponse allocation)
private async Task UpdateAllocation(NodeAllocationResponse allocation)
{
Func<UpdateNodeAllocationRequest, Task> onSubmit = async request =>
{
@@ -115,7 +119,7 @@
});
}
private async Task DeleteAllocation(NodeAllocationDetailResponse allocation)
private async Task DeleteAllocation(NodeAllocationResponse allocation)
{
await AlertService.ConfirmDanger(
"Delete allocation",

View File

@@ -1,3 +1,5 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers
@@ -170,7 +172,7 @@
@code
{
[Parameter] public NodeDetailResponse Node { get; set; }
[Parameter] public NodeResponse Node { get; set; }
private StatisticsResponse Statistics;
private DockerStatisticsResponse DockerStatistics;

View File

@@ -25,14 +25,14 @@
{
[Parameter] public CreateServerRequest Request { get; set; }
private async Task<NodeAllocationDetailResponse[]> Loader()
private async Task<NodeAllocationResponse[]> Loader()
{
// Handle unselected node
if (Request.NodeId <= 0)
return [];
var items = await PagedData<NodeAllocationDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<NodeAllocationDetailResponse>>(
var items = await PagedData<NodeAllocationResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<NodeAllocationResponse>>(
$"api/admin/servers/nodes/{Request.NodeId}/allocations/free?page={page}&pageSize={pageSize}"
)
);

View File

@@ -102,10 +102,10 @@
return items;
}
private async Task<NodeDetailResponse[]> LoadNodes()
private async Task<NodeResponse[]> LoadNodes()
{
var items = await PagedData<NodeDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<NodeDetailResponse>>(
var items = await PagedData<NodeResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<NodeResponse>>(
$"api/admin/servers/nodes?page={page}&pageSize={pageSize}"
)
);

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonCore.Helpers
@using MoonCore.Blazor.Tailwind.Components

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Components
@using MoonlightServers.Shared.Enums
@using MoonlightServers.Shared.Http.Requests.Client.Servers.Shares

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Helpers
@using MoonlightServers.Frontend.Services
@using MoonCore.Blazor.Tailwind.Fm
@using MoonCore.Blazor.Tailwind.Services

View File

@@ -1,3 +1,5 @@
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Helpers
@using MoonCore.Blazor.Tailwind.Components

View File

@@ -1,3 +1,7 @@
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Modals
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Modals

View File

@@ -1,3 +1,5 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonlightServers.Frontend.Services

View File

@@ -25,12 +25,12 @@
@code
{
[Parameter] public UpdateServerRequest Request { get; set; }
[Parameter] public ServerDetailResponse Server { get; set; }
[Parameter] public ServerResponse Server { get; set; }
private async Task<NodeAllocationDetailResponse[]> Loader()
private async Task<NodeAllocationResponse[]> Loader()
{
var items = await PagedData<NodeAllocationDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<NodeAllocationDetailResponse>>(
var items = await PagedData<NodeAllocationResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<NodeAllocationResponse>>(
$"api/admin/servers/nodes/{Server.NodeId}/allocations/free?page={page}&pageSize={pageSize}&serverId={Server.Id}"
)
);

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonCore.Helpers
@using MoonCore.Blazor.Tailwind.Components
@@ -43,10 +44,10 @@
@code
{
[Parameter] public UpdateServerRequest Request { get; set; }
[Parameter] public ServerDetailResponse Server { get; set; }
[Parameter] public ServerResponse Server { get; set; }
private StarVariableDetailResponse[] StarVariables;
private ServerVariableDetailResponse[] Variables;
private ServerVariableResponse[] Variables;
private async Task Load(LazyLoader _)
{
@@ -56,14 +57,14 @@
)
);
Variables = await PagedData<ServerVariableDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<ServerVariableDetailResponse>>(
Variables = await PagedData<ServerVariableResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<ServerVariableResponse>>(
$"api/admin/servers/{Server.Id}/variables?page={page}&pageSize={pageSize}"
)
);
}
private async Task UpdateValue(ServerVariableDetailResponse serverVariable, ChangeEventArgs args)
private async Task UpdateValue(ServerVariableResponse serverVariable, ChangeEventArgs args)
{
var value = args.Value?.ToString() ?? "";

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Components
@using MoonlightServers.Shared.Enums
@using MoonlightServers.Shared.Http.Requests.Client.Servers.Shares

View File

@@ -1,10 +1,11 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonlightServers.Frontend.UI.Components.Forms
@using MoonCore.Blazor.Tailwind.Components
@using MoonlightServers.Shared.Http.Requests.Admin.StarDockerImages
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Add a new variable</h1>

View File

@@ -1,9 +1,10 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonCore.Blazor.Tailwind.Components
@using MoonlightServers.Shared.Models
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Add a new parse configuration</h1>

View File

@@ -1,10 +1,11 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonlightServers.Shared.Http.Requests.Admin.StarVariables
@using MoonlightServers.Frontend.UI.Components.Forms
@using MoonCore.Blazor.Tailwind.Components
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Add a new variable</h1>

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Frontend.UI.Components.Forms
@using MoonCore.Blazor.Tailwind.Components
@@ -5,7 +6,7 @@
@using MoonlightServers.Shared.Http.Requests.Admin.StarDockerImages
@using MoonlightServers.Shared.Http.Responses.Admin.StarDockerImages
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Update variable</h1>

View File

@@ -1,10 +1,11 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Helpers
@using MoonlightServers.Shared.Models
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Update parse configuration</h1>

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonlightServers.Shared.Http.Requests.Admin.StarVariables
@@ -6,7 +7,7 @@
@using MoonCore.Helpers
@using MoonlightServers.Shared.Http.Responses.Admin.StarVariables
@inherits BaseModal
@inherits MoonCore.Blazor.FlyonUi.Modals.Components.BaseModal
<h1 class="mb-5 font-semibold text-xl">Update variable</h1>

View File

@@ -1,3 +1,7 @@
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Modals
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Modals

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Ace
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
@using MoonCore.Blazor.Tailwind.Ace

View File

@@ -1,3 +1,4 @@
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Helpers
@using MoonCore.Models

View File

@@ -1,4 +1,7 @@
@using System.Text.Json
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.Modals
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Blazor.Tailwind.Modals
@using MoonCore.Blazor.Tailwind.Toasts

View File

@@ -1,3 +1,7 @@
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Modals
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Modals

View File

@@ -1,5 +1,7 @@
@page "/admin/servers/all/create"
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers

View File

@@ -1,5 +1,8 @@
@page "/admin/servers/all"
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.DataTables
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Helpers
@using MoonCore.Models
@@ -28,13 +31,13 @@
</PageHeader>
</div>
<DataTable @ref="Table" TItem="ServerDetailResponse">
<DataTable @ref="Table" TItem="ServerResponse">
<Configuration>
<Pagination TItem="ServerDetailResponse" ItemSource="LoadData" />
<Pagination TItem="ServerResponse" ItemSource="LoadData" />
<DataTableColumn TItem="ServerDetailResponse" Field="@(x => x.Id)" Name="Id"/>
<DataTableColumn TItem="ServerDetailResponse" Field="@(x => x.Name)" Name="Name"/>
<DataTableColumn TItem="ServerDetailResponse" Field="@(x => x.NodeId)" Name="Node">
<DataTableColumn TItem="ServerResponse" Field="@(x => x.Id)" Name="Id"/>
<DataTableColumn TItem="ServerResponse" Field="@(x => x.Name)" Name="Name"/>
<DataTableColumn TItem="ServerResponse" Field="@(x => x.NodeId)" Name="Node">
<ColumnTemplate>
@{
var node = Nodes.FirstOrDefault(x => x.Id == context.NodeId);
@@ -45,7 +48,7 @@
</span>
</ColumnTemplate>
</DataTableColumn>
<DataTableColumn TItem="ServerDetailResponse" Field="@(x => x.StarId)" Name="Star">
<DataTableColumn TItem="ServerResponse" Field="@(x => x.StarId)" Name="Star">
<ColumnTemplate>
@{
var star = Stars.FirstOrDefault(x => x.Id == context.StarId);
@@ -56,7 +59,7 @@
</span>
</ColumnTemplate>
</DataTableColumn>
<DataTableColumn TItem="ServerDetailResponse">
<DataTableColumn TItem="ServerResponse">
<ColumnTemplate>
<div class="flex justify-end">
<a href="/admin/servers/all/update/@(context.Id)" class="text-primary mr-2 sm:mr-3">
@@ -75,21 +78,21 @@
@code
{
private DataTable<ServerDetailResponse> Table;
private DataTable<ServerResponse> Table;
private List<StarDetailResponse> Stars = new();
private List<NodeDetailResponse> Nodes = new();
private List<NodeResponse> Nodes = new();
private async Task<IPagedData<ServerDetailResponse>> LoadData(PaginationOptions options)
private async Task<IPagedData<ServerResponse>> LoadData(PaginationOptions options)
{
// Clear potential previous data
var data = await ApiClient.GetJson<PagedData<ServerDetailResponse>>($"api/admin/servers?page={options.Page}&pageSize={options.PerPage}");
var data = await ApiClient.GetJson<PagedData<ServerResponse>>($"api/admin/servers?page={options.Page}&pageSize={options.PerPage}");
foreach (var item in data.Items)
{
if (Nodes.All(x => x.Id != item.NodeId))
{
var node = await ApiClient.GetJson<NodeDetailResponse>($"api/admin/servers/nodes/{item.NodeId}");
var node = await ApiClient.GetJson<NodeResponse>($"api/admin/servers/nodes/{item.NodeId}");
Nodes.Add(node);
}
@@ -103,14 +106,14 @@
return data;
}
private async Task Delete(ServerDetailResponse detailResponse)
private async Task Delete(ServerResponse response)
{
await AlertService.ConfirmDanger(
"Server deletion",
$"Do you really want to delete the server '{detailResponse.Name}'",
$"Do you really want to delete the server '{response.Name}'",
async () =>
{
await ApiClient.Delete($"api/admin/servers/{detailResponse.Id}");
await ApiClient.Delete($"api/admin/servers/{response.Id}");
await ToastService.Success("Successfully deleted server");
await Table.Refresh();

View File

@@ -1,5 +1,7 @@
@page "/admin/servers/all/update/{Id:int}"
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers
@@ -51,11 +53,11 @@
private HandleForm Form;
private UpdateServerRequest Request;
private ServerDetailResponse Server;
private ServerResponse Server;
private async Task Load(LazyLoader _)
{
Server = await ApiClient.GetJson<ServerDetailResponse>($"api/admin/servers/{Id}");
Server = await ApiClient.GetJson<ServerResponse>($"api/admin/servers/{Id}");
Request = Mapper.Map<UpdateServerRequest>(Server);
}

View File

@@ -1,5 +1,7 @@
@page "/admin/servers/nodes/create"
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers

View File

@@ -1,5 +1,8 @@
@page "/admin/servers/nodes"
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.DataTables
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Helpers
@using MoonCore.Models
@@ -31,20 +34,20 @@
</PageHeader>
</div>
<DataTable TItem="NodeDetailResponse">
<DataTable TItem="NodeResponse">
<Configuration>
<Pagination TItem="NodeDetailResponse" ItemSource="LoadData"/>
<Pagination TItem="NodeResponse" ItemSource="LoadData"/>
<DataTableColumn TItem="NodeDetailResponse" Field="@(x => x.Id)" Name="Id"/>
<DataTableColumn TItem="NodeDetailResponse" Field="@(x => x.Name)" Name="Name">
<DataTableColumn TItem="NodeResponse" Field="@(x => x.Id)" Name="Id"/>
<DataTableColumn TItem="NodeResponse" Field="@(x => x.Name)" Name="Name">
<ColumnTemplate>
<a class="text-primary" href="/admin/servers/nodes/update/@(context.Id)">
@context.Name
</a>
</ColumnTemplate>
</DataTableColumn>
<DataTableColumn TItem="NodeDetailResponse" Field="@(x => x.Fqdn)" Name="Fqdn"/>
<DataTableColumn TItem="NodeDetailResponse" Field="@(x => x.Fqdn)" Name="Status">
<DataTableColumn TItem="NodeResponse" Field="@(x => x.Fqdn)" Name="Fqdn"/>
<DataTableColumn TItem="NodeResponse" Field="@(x => x.Fqdn)" Name="Status">
<ColumnTemplate>
@{
var isFetched = StatusResponses.TryGetValue(context.Id, out var data);
@@ -92,7 +95,7 @@
}
</ColumnTemplate>
</DataTableColumn>
<DataTableColumn TItem="NodeDetailResponse"
<DataTableColumn TItem="NodeResponse"
Name="Utilization"
HeaderCss="p-2 font-semibold text-left hidden xl:table-cell"
ColumnCss="p-2 text-left font-normal hidden xl:table-cell">
@@ -138,7 +141,7 @@
}
</ColumnTemplate>
</DataTableColumn>
<DataTableColumn TItem="NodeDetailResponse">
<DataTableColumn TItem="NodeResponse">
<ColumnTemplate>
<div class="flex justify-end">
<a href="/admin/servers/nodes/update/@(context.Id)" class="text-primary mr-2 sm:mr-3">
@@ -157,17 +160,17 @@
@code
{
private DataTable<NodeDetailResponse> Table;
private DataTable<NodeResponse> Table;
private Dictionary<int, NodeSystemStatusResponse?> StatusResponses = new();
private Dictionary<int, StatisticsResponse?> Statistics = new();
private async Task<IPagedData<NodeDetailResponse>> LoadData(PaginationOptions options)
private async Task<IPagedData<NodeResponse>> LoadData(PaginationOptions options)
{
Statistics.Clear();
StatusResponses.Clear();
var result = await ApiClient.GetJson<PagedData<NodeDetailResponse>>(
var result = await ApiClient.GetJson<PagedData<NodeResponse>>(
$"api/admin/servers/nodes?page={options.Page}&pageSize={options.PerPage}"
);
@@ -214,14 +217,14 @@
return result;
}
private async Task Delete(NodeDetailResponse detailResponse)
private async Task Delete(NodeResponse response)
{
await AlertService.ConfirmDanger(
"Node deletion",
$"Do you really want to delete the node '{detailResponse.Name}'",
$"Do you really want to delete the node '{response.Name}'",
async () =>
{
await ApiClient.Delete($"api/admin/servers/nodes/{detailResponse.Id}");
await ApiClient.Delete($"api/admin/servers/nodes/{response.Id}");
await ToastService.Success("Successfully deleted node");
await Table.Refresh();

View File

@@ -1,5 +1,7 @@
@page "/admin/servers/nodes/update/{Id:int}"
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers
@@ -56,11 +58,11 @@
private HandleForm Form;
private UpdateNodeRequest Request;
private NodeDetailResponse Node;
private NodeResponse Node;
private async Task Load(LazyLoader _)
{
Node = await ApiClient.GetJson<NodeDetailResponse>($"api/admin/servers/nodes/{Id}");
Node = await ApiClient.GetJson<NodeResponse>($"api/admin/servers/nodes/{Id}");
Request = Mapper.Map<UpdateNodeRequest>(Node);
}

View File

@@ -1,6 +1,8 @@
@page "/admin/servers/stars/create"
@using Microsoft.AspNetCore.Components.Authorization
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers

View File

@@ -1,5 +1,9 @@
@page "/admin/servers/stars"
@using MoonCore.Blazor.FlyonUi.Alerts
@using MoonCore.Blazor.FlyonUi.DataTables
@using MoonCore.Blazor.FlyonUi.Helpers
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Helpers
@using MoonCore.Models

View File

@@ -1,5 +1,7 @@
@page "/admin/servers/stars/update/{Id:int}"
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.FlyonUi.Toasts
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers

View File

@@ -1,5 +1,6 @@
@page "/servers"
@using MoonCore.Blazor.FlyonUi.Components
@using MoonlightServers.Frontend.UI.Components.Servers
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Models

View File

@@ -2,6 +2,7 @@
@page "/servers/{ServerId:int}/{TabPath:alpha}"
@using Microsoft.AspNetCore.SignalR.Client
@using MoonCore.Blazor.FlyonUi.Components
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Exceptions
@using MoonCore.Helpers

View File

@@ -1,6 +1,6 @@
namespace MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations;
public class NodeAllocationDetailResponse
public class NodeAllocationResponse
{
public int Id { get; set; }

View File

@@ -1,6 +1,6 @@
namespace MoonlightServers.Shared.Http.Responses.Admin.Nodes;
public class NodeDetailResponse
public class NodeResponse
{
public int Id { get; set; }

View File

@@ -1,6 +1,6 @@
namespace MoonlightServers.Shared.Http.Responses.Admin.ServerVariables;
public class ServerVariableDetailResponse
public class ServerVariableResponse
{
public int Id { get; set; }
public string Key { get; set; }

View File

@@ -1,9 +1,6 @@
using MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations;
using MoonlightServers.Shared.Http.Responses.Admin.ServerVariables;
namespace MoonlightServers.Shared.Http.Responses.Admin.Servers;
public class ServerDetailResponse
public class ServerResponse
{
public int Id { get; set; }

View File

@@ -15,6 +15,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
plugin.json = plugin.json
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Runtime", "Runtime", "{7836BC34-096D-440C-9DF9-81116EACAABA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoonlightServers.ApiServer.Runtime", "MoonlightServers.ApiServer.Runtime\MoonlightServers.ApiServer.Runtime.csproj", "{9F4370FA-C38D-4E84-892F-12ED5DD40FC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoonlightServers.Frontend.Runtime", "MoonlightServers.Frontend.Runtime\MoonlightServers.Frontend.Runtime.csproj", "{97BDDD86-6FE1-42E0-BF16-152DFABC8287}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -41,5 +47,17 @@ Global
{15EBCC5D-2440-4B5B-A046-F8327E0C1CB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{15EBCC5D-2440-4B5B-A046-F8327E0C1CB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15EBCC5D-2440-4B5B-A046-F8327E0C1CB8}.Release|Any CPU.Build.0 = Release|Any CPU
{9F4370FA-C38D-4E84-892F-12ED5DD40FC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F4370FA-C38D-4E84-892F-12ED5DD40FC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F4370FA-C38D-4E84-892F-12ED5DD40FC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F4370FA-C38D-4E84-892F-12ED5DD40FC6}.Release|Any CPU.Build.0 = Release|Any CPU
{97BDDD86-6FE1-42E0-BF16-152DFABC8287}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{97BDDD86-6FE1-42E0-BF16-152DFABC8287}.Debug|Any CPU.Build.0 = Debug|Any CPU
{97BDDD86-6FE1-42E0-BF16-152DFABC8287}.Release|Any CPU.ActiveCfg = Release|Any CPU
{97BDDD86-6FE1-42E0-BF16-152DFABC8287}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{9F4370FA-C38D-4E84-892F-12ED5DD40FC6} = {7836BC34-096D-440C-9DF9-81116EACAABA}
{97BDDD86-6FE1-42E0-BF16-152DFABC8287} = {7836BC34-096D-440C-9DF9-81116EACAABA}
EndGlobalSection
EndGlobal