diff --git a/Moonlight/App/Helpers/Files/ContextAction.cs b/Moonlight/App/Helpers/Files/ContextAction.cs new file mode 100644 index 0000000..704c425 --- /dev/null +++ b/Moonlight/App/Helpers/Files/ContextAction.cs @@ -0,0 +1,8 @@ +namespace Moonlight.App.Helpers.Files; + +public class ContextAction +{ + public string Id { get; set; } = ""; + public string Name { get; set; } = ""; + public Action Action { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/Files/FileAccess.cs b/Moonlight/App/Helpers/Files/FileAccess.cs new file mode 100644 index 0000000..a900c46 --- /dev/null +++ b/Moonlight/App/Helpers/Files/FileAccess.cs @@ -0,0 +1,24 @@ +namespace Moonlight.App.Helpers.Files; + +public abstract class FileAccess : ICloneable +{ + public string CurrentPath { get; set; } = "/"; + + public abstract Task Ls(); + public abstract Task Cd(string dir); + public abstract Task Up(); + public abstract Task SetDir(string dir); + public abstract Task Read(FileData fileData); + public abstract Task Write(FileData fileData, string content); + public abstract Task Upload(string name, Stream stream, Action? progressUpdated = null); + public abstract Task MkDir(string name); + public abstract Task Pwd(); + public abstract Task DownloadUrl(FileData fileData); + public abstract Task DownloadStream(FileData fileData); + public abstract Task Delete(FileData fileData); + public abstract Task Move(FileData fileData, string newPath); + public abstract Task Compress(params FileData[] files); + public abstract Task Decompress(FileData fileData); + public abstract Task GetLaunchUrl(); + public abstract object Clone(); +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/Files/FileData.cs b/Moonlight/App/Helpers/Files/FileData.cs new file mode 100644 index 0000000..f0bb75f --- /dev/null +++ b/Moonlight/App/Helpers/Files/FileData.cs @@ -0,0 +1,8 @@ +namespace Moonlight.App.Helpers.Files; + +public class FileData +{ + public string Name { get; set; } = ""; + public long Size { get; set; } + public bool IsFile { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/Files/WingsFileAccess.cs b/Moonlight/App/Helpers/Files/WingsFileAccess.cs new file mode 100644 index 0000000..b1c2296 --- /dev/null +++ b/Moonlight/App/Helpers/Files/WingsFileAccess.cs @@ -0,0 +1,232 @@ +using System.Web; +using Moonlight.App.Database.Entities; +using Moonlight.App.Models.Wings.Requests; +using Moonlight.App.Models.Wings.Resources; +using Moonlight.App.Services; +using RestSharp; + +namespace Moonlight.App.Helpers.Files; + +public class WingsFileAccess : FileAccess +{ + private readonly WingsApiHelper WingsApiHelper; + private readonly WingsJwtHelper WingsJwtHelper; + private readonly ConfigService ConfigService; + private readonly Server Server; + private readonly User User; + + public WingsFileAccess( + WingsApiHelper wingsApiHelper, + WingsJwtHelper wingsJwtHelper, + Server server, + ConfigService configService, + User user) + { + WingsApiHelper = wingsApiHelper; + WingsJwtHelper = wingsJwtHelper; + Server = server; + ConfigService = configService; + User = user; + + if (server.Node == null) + { + throw new ArgumentException("The wings file access server model needs to include the node data"); + } + } + + public override async Task Ls() + { + var res = await WingsApiHelper.Get( + Server.Node, + $"api/servers/{Server.Uuid}/files/list-directory?directory={CurrentPath}" + ); + + var x = new List(); + + foreach (var response in res) + { + x.Add(new() + { + Name = response.Name, + Size = response.File ? response.Size : 0, + IsFile = response.File, + }); + } + + return x.ToArray(); + } + + public override Task Cd(string dir) + { + var x = Path.Combine(CurrentPath, dir).Replace("\\", "/") + "/"; + x = x.Replace("//", "/"); + CurrentPath = x; + + return Task.CompletedTask; + } + + public override Task Up() + { + CurrentPath = Path.GetFullPath(Path.Combine(CurrentPath, "..")).Replace("\\", "/").Replace("C:", ""); + return Task.CompletedTask; + } + + public override Task SetDir(string dir) + { + CurrentPath = dir; + return Task.CompletedTask; + } + + public override async Task Read(FileData fileData) + { + return await WingsApiHelper.GetRaw(Server.Node, + $"api/servers/{Server.Uuid}/files/contents?file={CurrentPath}{fileData.Name}"); + } + + public override async Task Write(FileData fileData, string content) + { + await WingsApiHelper.PostRaw(Server.Node, + $"api/servers/{Server.Uuid}/files/write?file={CurrentPath}{fileData.Name}", content); + } + + public override async Task Upload(string name, Stream dataStream, Action? progressUpdated = null) + { + var token = WingsJwtHelper.Generate( + Server.Node.Token, + claims => { claims.Add("server_uuid", Server.Uuid.ToString()); } + ); + + var client = new RestClient(); + var request = new RestRequest(); + + if (Server.Node.Ssl) + request.Resource = + $"https://{Server.Node.Fqdn}:{Server.Node.HttpPort}/upload/file?token={token}&directory={CurrentPath}"; + else + request.Resource = + $"http://{Server.Node.Fqdn}:{Server.Node.HttpPort}/upload/file?token={token}&directory={CurrentPath}"; + + request.AddParameter("name", "files"); + request.AddParameter("filename", name); + request.AddHeader("Content-Type", "multipart/form-data"); + request.AddHeader("Origin", ConfigService.GetSection("Moonlight").GetValue("AppUrl")); + request.AddFile("files", () => + { + return new StreamProgressHelper(dataStream) + { + Progress = i => { progressUpdated?.Invoke(i); } + }; + }, name); + + await client.ExecutePostAsync(request); + + client.Dispose(); + dataStream.Close(); + } + + public override async Task MkDir(string name) + { + await WingsApiHelper.Post(Server.Node, $"api/servers/{Server.Uuid}/files/create-directory", + new CreateDirectory() + { + Name = name, + Path = CurrentPath + } + ); + } + + public override Task Pwd() + { + return Task.FromResult(CurrentPath); + } + + public override Task DownloadUrl(FileData fileData) + { + var token = WingsJwtHelper.Generate(Server.Node.Token, claims => + { + claims.Add("server_uuid", Server.Uuid.ToString()); + claims.Add("file_path", CurrentPath + "/" + fileData.Name); + }); + + if (Server.Node.Ssl) + { + return Task.FromResult( + $"https://{Server.Node.Fqdn}:{Server.Node.HttpPort}/download/file?token={token}" + ); + } + else + { + return Task.FromResult( + $"http://{Server.Node.Fqdn}:{Server.Node.HttpPort}/download/file?token={token}" + ); + } + } + + public override Task DownloadStream(FileData fileData) + { + throw new NotImplementedException(); + } + + public override async Task Delete(FileData fileData) + { + await WingsApiHelper.Post(Server.Node, $"api/servers/{Server.Uuid}/files/delete", new DeleteFiles() + { + Root = CurrentPath, + Files = new() + { + fileData.Name + } + }); + } + + public override async Task Move(FileData fileData, string newPath) + { + var req = new RenameFiles() + { + Root = "/", + Files = new[] + { + new RenameFilesData() + { + From = (CurrentPath + fileData.Name), + To = newPath + } + } + }; + + await WingsApiHelper.Put(Server.Node, $"api/servers/{Server.Uuid}/files/rename", req); + } + + public override async Task Compress(params FileData[] files) + { + var req = new CompressFiles() + { + Root = CurrentPath, + Files = files.Select(x => x.Name).ToArray() + }; + + await WingsApiHelper.Post(Server.Node, $"api/servers/{Server.Uuid}/files/compress", req); + } + + public override async Task Decompress(FileData fileData) + { + var req = new DecompressFile() + { + Root = CurrentPath, + File = fileData.Name + }; + + await WingsApiHelper.Post(Server.Node, $"api/servers/{Server.Uuid}/files/decompress", req); + } + + public override Task GetLaunchUrl() + { + return Task.FromResult( + $"sftp://{User.Id}.{StringHelper.IntToStringWithLeadingZeros(Server.Id, 8)}@{Server.Node.Fqdn}:{Server.Node.SftpPort}"); + } + + public override object Clone() + { + return new WingsFileAccess(WingsApiHelper, WingsJwtHelper, Server, ConfigService, User); + } +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/PaperApiHelper.cs b/Moonlight/App/Helpers/PaperApiHelper.cs index 232b4a8..c8e1a3f 100644 --- a/Moonlight/App/Helpers/PaperApiHelper.cs +++ b/Moonlight/App/Helpers/PaperApiHelper.cs @@ -24,11 +24,11 @@ public class PaperApiHelper else requrl = ApiUrl + "/" + url; - RestRequest request = new(requrl); + RestRequest request = new(requrl, Method.Get); request.AddHeader("Content-Type", "application/json"); - var response = await client.GetAsync(request); + var response = await client.ExecuteAsync(request); if (!response.IsSuccessful) { diff --git a/Moonlight/App/Helpers/WingsApiHelper.cs b/Moonlight/App/Helpers/WingsApiHelper.cs index 23900b4..9611d64 100644 --- a/Moonlight/App/Helpers/WingsApiHelper.cs +++ b/Moonlight/App/Helpers/WingsApiHelper.cs @@ -14,24 +14,13 @@ public class WingsApiHelper Client = new(); } - private string GetApiUrl(Node node) - { - if(node.Ssl) - return $"https://{node.Fqdn}:{node.HttpPort}/"; - else - return $"http://{node.Fqdn}:{node.HttpPort}/"; - //return $"https://{node.Fqdn}:{node.HttpPort}/"; - } - public async Task Get(Node node, string resource) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Get; - var response = await Client.GetAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -53,13 +42,11 @@ public class WingsApiHelper public async Task GetRaw(Node node, string resource) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Get; - var response = await Client.GetAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -81,18 +68,16 @@ public class WingsApiHelper public async Task Post(Node node, string resource, object? body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Post; request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody ); - var response = await Client.PostAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -114,16 +99,14 @@ public class WingsApiHelper public async Task Post(Node node, string resource, object? body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Post; - if(body != null) + if(body != null) request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); - var response = await Client.PostAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -143,15 +126,13 @@ public class WingsApiHelper public async Task PostRaw(Node node, string resource, object body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Post; request.AddParameter("text/plain", body, ParameterType.RequestBody); - var response = await Client.PostAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -171,16 +152,14 @@ public class WingsApiHelper public async Task Delete(Node node, string resource, object? body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Delete; - if(body != null) + if(body != null) request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); - var response = await Client.DeleteAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -200,15 +179,13 @@ public class WingsApiHelper public async Task Put(Node node, string resource, object? body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Put; request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); - var response = await Client.PutAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -225,4 +202,20 @@ public class WingsApiHelper } } } + + private RestRequest CreateRequest(Node node, string resource) + { + var url = (node.Ssl ? "https" : "http") + $"://{node.Fqdn}:{node.HttpPort}/" + resource; + + var request = new RestRequest(url) + { + Timeout = 60 * 15 + }; + + request.AddHeader("Content-Type", "application/json"); + request.AddHeader("Accept", "application/json"); + request.AddHeader("Authorization", "Bearer " + node.Token); + + return request; + } } \ No newline at end of file diff --git a/Moonlight/App/Models/Files/Accesses/WingsFileAccess.cs b/Moonlight/App/Models/Files/Accesses/WingsFileAccess.cs index 6d181e2..1d64ab8 100644 --- a/Moonlight/App/Models/Files/Accesses/WingsFileAccess.cs +++ b/Moonlight/App/Models/Files/Accesses/WingsFileAccess.cs @@ -39,7 +39,7 @@ public class WingsFileAccess : IFileAccess public async Task GetDirectoryContent() { - var res = await WingsApiHelper.Get(Node, + var res = await WingsApiHelper.Get(Node, $"api/servers/{Server.Uuid}/files/list-directory?directory={Path}"); var x = new List(); @@ -130,7 +130,7 @@ public class WingsFileAccess : IFileAccess public async Task CreateDirectory(string name) { await WingsApiHelper.Post(Node, $"api/servers/{Server.Uuid}/files/create-directory", - new CreateDirectoryRequest() + new CreateDirectory() { Name = name, Path = Path @@ -171,7 +171,7 @@ public class WingsFileAccess : IFileAccess public async Task Delete(FileManagerObject managerObject) { - await WingsApiHelper.Post(Node, $"api/servers/{Server.Uuid}/files/delete", new DeleteFilesRequest() + await WingsApiHelper.Post(Node, $"api/servers/{Server.Uuid}/files/delete", new DeleteFiles() { Root = Path, Files = new() @@ -183,7 +183,7 @@ public class WingsFileAccess : IFileAccess public async Task Move(FileManagerObject managerObject, string newPath) { - await WingsApiHelper.Put(Node, $"api/servers/{Server.Uuid}/files/rename", new RenameFilesRequest() + await WingsApiHelper.Put(Node, $"api/servers/{Server.Uuid}/files/rename", new RenameFiles() { Root = "/", Files = new[] diff --git a/Moonlight/App/Models/Files/FileContextAction.cs b/Moonlight/App/Models/Files/FileContextAction.cs new file mode 100644 index 0000000..7570013 --- /dev/null +++ b/Moonlight/App/Models/Files/FileContextAction.cs @@ -0,0 +1,8 @@ +namespace Moonlight.App.Models.Files; + +public class FileContextAction +{ + public string Id { get; set; } + public string Name { get; set; } + public Action Action { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Wings/Requests/CompressFiles.cs b/Moonlight/App/Models/Wings/Requests/CompressFiles.cs new file mode 100644 index 0000000..2c86667 --- /dev/null +++ b/Moonlight/App/Models/Wings/Requests/CompressFiles.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Moonlight.App.Models.Wings.Requests; + +public class CompressFiles +{ + [JsonProperty("root")] + public string Root { get; set; } + + [JsonProperty("files")] + public string[] Files { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Wings/Requests/CreateBackupRequest.cs b/Moonlight/App/Models/Wings/Requests/CreateBackup.cs similarity index 89% rename from Moonlight/App/Models/Wings/Requests/CreateBackupRequest.cs rename to Moonlight/App/Models/Wings/Requests/CreateBackup.cs index a0ce5b4..779abf1 100644 --- a/Moonlight/App/Models/Wings/Requests/CreateBackupRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/CreateBackup.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class CreateBackupRequest +public class CreateBackup { [JsonProperty("adapter")] public string Adapter { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/CreateDirectoryRequest.cs b/Moonlight/App/Models/Wings/Requests/CreateDirectory.cs similarity index 85% rename from Moonlight/App/Models/Wings/Requests/CreateDirectoryRequest.cs rename to Moonlight/App/Models/Wings/Requests/CreateDirectory.cs index 62c95e3..1dc6617 100644 --- a/Moonlight/App/Models/Wings/Requests/CreateDirectoryRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/CreateDirectory.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class CreateDirectoryRequest +public class CreateDirectory { [JsonProperty("name")] public string Name { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/CreateServerRequest.cs b/Moonlight/App/Models/Wings/Requests/CreateServer.cs similarity index 87% rename from Moonlight/App/Models/Wings/Requests/CreateServerRequest.cs rename to Moonlight/App/Models/Wings/Requests/CreateServer.cs index 3288d88..7e939a4 100644 --- a/Moonlight/App/Models/Wings/Requests/CreateServerRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/CreateServer.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class CreateServerRequest +public class CreateServer { [JsonProperty("uuid")] public Guid Uuid { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/DecompressFile.cs b/Moonlight/App/Models/Wings/Requests/DecompressFile.cs new file mode 100644 index 0000000..5fb7073 --- /dev/null +++ b/Moonlight/App/Models/Wings/Requests/DecompressFile.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Moonlight.App.Models.Wings.Requests; + +public class DecompressFile +{ + [JsonProperty("root")] + public string Root { get; set; } + + [JsonProperty("file")] + public string File { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Wings/Requests/DeleteFilesRequest.cs b/Moonlight/App/Models/Wings/Requests/DeleteFiles.cs similarity index 86% rename from Moonlight/App/Models/Wings/Requests/DeleteFilesRequest.cs rename to Moonlight/App/Models/Wings/Requests/DeleteFiles.cs index c64487f..9988ff0 100644 --- a/Moonlight/App/Models/Wings/Requests/DeleteFilesRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/DeleteFiles.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class DeleteFilesRequest +public class DeleteFiles { [JsonProperty("root")] public string Root { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/RenameFilesRequest.cs b/Moonlight/App/Models/Wings/Requests/RenameFiles.cs similarity index 91% rename from Moonlight/App/Models/Wings/Requests/RenameFilesRequest.cs rename to Moonlight/App/Models/Wings/Requests/RenameFiles.cs index 8355cff..f565a32 100644 --- a/Moonlight/App/Models/Wings/Requests/RenameFilesRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/RenameFiles.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class RenameFilesRequest +public class RenameFiles { [JsonProperty("root")] public string Root { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/RestoreBackupRequest.cs b/Moonlight/App/Models/Wings/Requests/RestoreBackup.cs similarity index 90% rename from Moonlight/App/Models/Wings/Requests/RestoreBackupRequest.cs rename to Moonlight/App/Models/Wings/Requests/RestoreBackup.cs index 0dfa9cb..fcd7b8a 100644 --- a/Moonlight/App/Models/Wings/Requests/RestoreBackupRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/RestoreBackup.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class RestoreBackupRequest +public class RestoreBackup { [JsonProperty("adapter")] public string Adapter { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/ServerPowerRequest.cs b/Moonlight/App/Models/Wings/Requests/ServerPower.cs similarity index 81% rename from Moonlight/App/Models/Wings/Requests/ServerPowerRequest.cs rename to Moonlight/App/Models/Wings/Requests/ServerPower.cs index 597d9e5..e877fb7 100644 --- a/Moonlight/App/Models/Wings/Requests/ServerPowerRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/ServerPower.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class ServerPowerRequest +public class ServerPower { [JsonProperty("action")] public string Action { get; set; } diff --git a/Moonlight/App/Models/Wings/Resources/ListDirectoryRequest.cs b/Moonlight/App/Models/Wings/Resources/ListDirectory.cs similarity index 94% rename from Moonlight/App/Models/Wings/Resources/ListDirectoryRequest.cs rename to Moonlight/App/Models/Wings/Resources/ListDirectory.cs index 0a67bfa..d99e15d 100644 --- a/Moonlight/App/Models/Wings/Resources/ListDirectoryRequest.cs +++ b/Moonlight/App/Models/Wings/Resources/ListDirectory.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Resources; -public class ListDirectoryRequest +public class ListDirectory { [JsonProperty("name")] public string Name { get; set; } diff --git a/Moonlight/App/Models/Wings/Resources/ServerDetailsResponse.cs b/Moonlight/App/Models/Wings/Resources/ServerDetails.cs similarity index 78% rename from Moonlight/App/Models/Wings/Resources/ServerDetailsResponse.cs rename to Moonlight/App/Models/Wings/Resources/ServerDetails.cs index bc89a29..b14ac56 100644 --- a/Moonlight/App/Models/Wings/Resources/ServerDetailsResponse.cs +++ b/Moonlight/App/Models/Wings/Resources/ServerDetails.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Resources; -public class ServerDetailsResponse +public class ServerDetails { [JsonProperty("state")] public string State { get; set; } @@ -11,9 +11,9 @@ public class ServerDetailsResponse public bool IsSuspended { get; set; } [JsonProperty("utilization")] - public ServerDetailsResponseUtilization Utilization { get; set; } + public ServerDetailsUtilization Utilization { get; set; } - public class ServerDetailsResponseUtilization + public class ServerDetailsUtilization { [JsonProperty("memory_bytes")] public long MemoryBytes { get; set; } @@ -25,7 +25,7 @@ public class ServerDetailsResponse public double CpuAbsolute { get; set; } [JsonProperty("network")] - public ServerDetailsResponseNetwork Network { get; set; } + public ServerDetailsNetwork Network { get; set; } [JsonProperty("uptime")] public long Uptime { get; set; } @@ -37,7 +37,7 @@ public class ServerDetailsResponse public long DiskBytes { get; set; } } - public class ServerDetailsResponseNetwork + public class ServerDetailsNetwork { [JsonProperty("rx_bytes")] public long RxBytes { get; set; } diff --git a/Moonlight/App/Services/Interop/ModalService.cs b/Moonlight/App/Services/Interop/ModalService.cs new file mode 100644 index 0000000..881fb2e --- /dev/null +++ b/Moonlight/App/Services/Interop/ModalService.cs @@ -0,0 +1,23 @@ +using Microsoft.JSInterop; + +namespace Moonlight.App.Services.Interop; + +public class ModalService +{ + private readonly IJSRuntime JsRuntime; + + public ModalService(IJSRuntime jsRuntime) + { + JsRuntime = jsRuntime; + } + + public async Task Show(string name) + { + await JsRuntime.InvokeVoidAsync("moonlight.modals.show", name); + } + + public async Task Hide(string name) + { + await JsRuntime.InvokeVoidAsync("moonlight.modals.hide", name); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/Interop/ToastService.cs b/Moonlight/App/Services/Interop/ToastService.cs index 3eff8a1..5e1839d 100644 --- a/Moonlight/App/Services/Interop/ToastService.cs +++ b/Moonlight/App/Services/Interop/ToastService.cs @@ -30,4 +30,19 @@ public class ToastService { await JsRuntime.InvokeVoidAsync("showSuccessToast", message); } + + public async Task CreateProcessToast(string id, string text) + { + await JsRuntime.InvokeVoidAsync("createToast", id, text); + } + + public async Task UpdateProcessToast(string id, string text) + { + await JsRuntime.InvokeVoidAsync("modifyToast", id, text); + } + + public async Task RemoveProcessToast(string id) + { + await JsRuntime.InvokeVoidAsync("removeToast", id); + } } \ No newline at end of file diff --git a/Moonlight/App/Services/ServerService.cs b/Moonlight/App/Services/ServerService.cs index 0542a09..2f69fd7 100644 --- a/Moonlight/App/Services/ServerService.cs +++ b/Moonlight/App/Services/ServerService.cs @@ -75,11 +75,11 @@ public class ServerService return s; } - public async Task GetDetails(Server s) + public async Task GetDetails(Server s) { Server server = EnsureNodeData(s); - return await WingsApiHelper.Get( + return await WingsApiHelper.Get( server.Node, $"api/servers/{server.Uuid}" ); @@ -91,7 +91,7 @@ public class ServerService var rawSignal = signal.ToString().ToLower(); - await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/power", new ServerPowerRequest() + await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/power", new ServerPower() { Action = rawSignal }); @@ -118,7 +118,7 @@ public class ServerService serverData.Backups.Add(backup); ServerRepository.Update(serverData); - await WingsApiHelper.Post(serverData.Node, $"api/servers/{serverData.Uuid}/backup", new CreateBackupRequest() + await WingsApiHelper.Post(serverData.Node, $"api/servers/{serverData.Uuid}/backup", new CreateBackup() { Adapter = "wings", Uuid = backup.Uuid, @@ -158,7 +158,7 @@ public class ServerService Server server = EnsureNodeData(s); await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/backup/{serverBackup.Uuid}/restore", - new RestoreBackupRequest() + new RestoreBackup() { Adapter = "wings" }); @@ -299,7 +299,7 @@ public class ServerService try { - await WingsApiHelper.Post(node, $"api/servers", new CreateServerRequest() + await WingsApiHelper.Post(node, $"api/servers", new CreateServer() { Uuid = newServerData.Uuid, StartOnCompletion = false diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 07c3a9f..9609e64 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -68,7 +68,6 @@ - diff --git a/Moonlight/Pages/_Layout.cshtml b/Moonlight/Pages/_Layout.cshtml index cbfcf6e..b82364f 100644 --- a/Moonlight/Pages/_Layout.cshtml +++ b/Moonlight/Pages/_Layout.cshtml @@ -101,6 +101,7 @@ + @@ -112,5 +113,6 @@ + \ No newline at end of file diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index 8dc9429..c1519c1 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -93,6 +93,7 @@ namespace Moonlight builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor b/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor index 0a2888c..9af01b0 100644 --- a/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor +++ b/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor @@ -3,27 +3,30 @@ @using Moonlight.Shared.Components.Partials @inject SmartTranslateService TranslationService +@inject IJSRuntime JsRuntime -
- -
- -@if (!HideControls) -{ -