Added node server sync and delete sync. Cleaned up codebase and extracted calls to apis to services
This commit is contained in:
@@ -14,27 +14,6 @@ namespace MoonlightServers.ApiServer.Services;
|
||||
[Singleton]
|
||||
public class NodeService
|
||||
{
|
||||
public async Task<HttpApiClient> CreateApiClient(Node node)
|
||||
{
|
||||
var url = "";
|
||||
|
||||
if (node.UseSsl)
|
||||
url += "https://";
|
||||
else
|
||||
url += "http://";
|
||||
|
||||
url += $"{node.Fqdn}:{node.HttpPort}/";
|
||||
|
||||
var httpClient = new HttpClient()
|
||||
{
|
||||
BaseAddress = new Uri(url)
|
||||
};
|
||||
|
||||
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {node.Token}");
|
||||
|
||||
return new HttpApiClient(httpClient);
|
||||
}
|
||||
|
||||
public string CreateAccessToken(Node node, Action<Dictionary<string, object>> parameters, TimeSpan duration)
|
||||
{
|
||||
var claims = new Dictionary<string, object>();
|
||||
@@ -63,7 +42,7 @@ public class NodeService
|
||||
|
||||
public async Task<SystemStatusResponse> GetSystemStatus(Node node)
|
||||
{
|
||||
using var apiClient = await CreateApiClient(node);
|
||||
using var apiClient = CreateApiClient(node);
|
||||
return await apiClient.GetJson<SystemStatusResponse>("api/system/status");
|
||||
}
|
||||
|
||||
@@ -71,21 +50,66 @@ public class NodeService
|
||||
|
||||
public async Task<StatisticsApplicationResponse> GetApplicationStatistics(Node node)
|
||||
{
|
||||
using var apiClient = await CreateApiClient(node);
|
||||
using var apiClient = CreateApiClient(node);
|
||||
return await apiClient.GetJson<StatisticsApplicationResponse>("api/statistics/application");
|
||||
}
|
||||
|
||||
public async Task<StatisticsHostResponse> GetHostStatistics(Node node)
|
||||
{
|
||||
using var apiClient = await CreateApiClient(node);
|
||||
using var apiClient = CreateApiClient(node);
|
||||
return await apiClient.GetJson<StatisticsHostResponse>("api/statistics/host");
|
||||
}
|
||||
|
||||
public async Task<StatisticsDockerResponse> GetDockerStatistics(Node node)
|
||||
{
|
||||
using var apiClient = await CreateApiClient(node);
|
||||
using var apiClient = CreateApiClient(node);
|
||||
return await apiClient.GetJson<StatisticsDockerResponse>("api/statistics/docker");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
private string GenerateJwt(Node node)
|
||||
{
|
||||
var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
|
||||
|
||||
var securityTokenDescriptor = new SecurityTokenDescriptor()
|
||||
{
|
||||
//Expires = DateTime.UtcNow.AddYears(1),
|
||||
Expires = DateTime.UtcNow.AddMinutes(1),
|
||||
NotBefore = DateTime.UtcNow.AddSeconds(-1),
|
||||
IssuedAt = DateTime.UtcNow,
|
||||
SigningCredentials = new SigningCredentials(
|
||||
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
|
||||
node.Token
|
||||
)),
|
||||
SecurityAlgorithms.HmacSha256
|
||||
)
|
||||
};
|
||||
|
||||
var securityToken = jwtSecurityTokenHandler.CreateJwtSecurityToken(securityTokenDescriptor);
|
||||
|
||||
return jwtSecurityTokenHandler.WriteToken(securityToken);
|
||||
}
|
||||
|
||||
public HttpApiClient CreateApiClient(Node node)
|
||||
{
|
||||
var url = "";
|
||||
|
||||
url += node.UseSsl ? "https://" : "http://";
|
||||
url += $"{node.Fqdn}:{node.HttpPort}/";
|
||||
|
||||
var httpClient = new HttpClient()
|
||||
{
|
||||
BaseAddress = new Uri(url)
|
||||
};
|
||||
|
||||
var jwt = GenerateJwt(node);
|
||||
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {jwt}");
|
||||
|
||||
return new HttpApiClient(httpClient);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
165
MoonlightServers.ApiServer/Services/ServerService.cs
Normal file
165
MoonlightServers.ApiServer/Services/ServerService.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MoonCore.Attributes;
|
||||
using MoonCore.Exceptions;
|
||||
using MoonCore.Extended.Abstractions;
|
||||
using MoonCore.Helpers;
|
||||
using Moonlight.ApiServer.Database.Entities;
|
||||
using MoonlightServers.ApiServer.Database.Entities;
|
||||
using MoonlightServers.DaemonShared.DaemonSide.Http.Responses.Servers;
|
||||
|
||||
namespace MoonlightServers.ApiServer.Services;
|
||||
|
||||
[Scoped]
|
||||
public class ServerService
|
||||
{
|
||||
private readonly NodeService NodeService;
|
||||
private readonly DatabaseRepository<Server> ServerRepository;
|
||||
|
||||
public ServerService(NodeService nodeService, DatabaseRepository<Server> serverRepository)
|
||||
{
|
||||
NodeService = nodeService;
|
||||
ServerRepository = serverRepository;
|
||||
}
|
||||
|
||||
#region Power Actions
|
||||
|
||||
public async Task Start(Server server)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var apiClient = await GetApiClient(server);
|
||||
await apiClient.Post($"api/servers/{server.Id}/start");
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
throw new HttpApiException("Unable to access the node the server is running on", 502);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Stop(Server server)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var apiClient = await GetApiClient(server);
|
||||
await apiClient.Post($"api/servers/{server.Id}/stop");
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
throw new HttpApiException("Unable to access the node the server is running on", 502);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Kill(Server server)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var apiClient = await GetApiClient(server);
|
||||
await apiClient.Post($"api/servers/{server.Id}/kill");
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
throw new HttpApiException("Unable to access the node the server is running on", 502);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public async Task Install(Server server)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var apiClient = await GetApiClient(server);
|
||||
await apiClient.Post($"api/servers/{server.Id}/install");
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
throw new HttpApiException("Unable to access the node the server is running on", 502);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Sync(Server server)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var apiClient = await GetApiClient(server);
|
||||
await apiClient.Post($"api/servers/{server.Id}/sync");
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
throw new HttpApiException("Unable to access the node the server is running on", 502);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SyncDelete(Server server)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var apiClient = await GetApiClient(server);
|
||||
await apiClient.Delete($"api/servers/{server.Id}");
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
throw new HttpApiException("Unable to access the node the server is running on", 502);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ServerStatusResponse> GetStatus(Server server)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var apiClient = await GetApiClient(server);
|
||||
return await apiClient.GetJson<ServerStatusResponse>($"api/servers/{server.Id}/status");
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
throw new HttpApiException("Unable to access the node the server is running on", 502);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ServerLogsResponse> GetLogs(Server server)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var apiClient = await GetApiClient(server);
|
||||
return await apiClient.GetJson<ServerLogsResponse>($"api/servers/{server.Id}/logs");
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
throw new HttpApiException("Unable to access the node the server is running on", 502);
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
public bool IsAllowedToAccess(User user, Server server)
|
||||
{
|
||||
if (server.OwnerId == user.Id)
|
||||
return true;
|
||||
|
||||
var permissions = JsonSerializer.Deserialize<string[]>(
|
||||
user.PermissionsJson
|
||||
) ?? [];
|
||||
|
||||
return PermissionHelper.HasPermission(permissions, "admin.servers.get");
|
||||
}
|
||||
|
||||
private async Task<HttpApiClient> GetApiClient(Server server)
|
||||
{
|
||||
var serverWithNode = server;
|
||||
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||
// It can be null when its not included when loading via ef !!!
|
||||
if (server.Node == null)
|
||||
{
|
||||
serverWithNode = await ServerRepository
|
||||
.Get()
|
||||
.Include(x => x.Node)
|
||||
.FirstAsync(x => x.Id == server.Id);
|
||||
}
|
||||
|
||||
return NodeService.CreateApiClient(serverWithNode.Node);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user