From 3ae694a3da5ab57d65a63521e932c55a68938838 Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Thu, 4 Jan 2024 16:03:55 +0100 Subject: [PATCH] Added diagnose file export --- .../App/Extensions/ZipArchiveExtension.cs | 26 +++++++++ Moonlight/App/Services/ConfigService.cs | 23 ++++++++ Moonlight/App/Services/PluginService.cs | 2 + .../App/Services/Sys/MoonlightService.cs | 54 ++++++++++++++++++- Moonlight/Moonlight.csproj | 1 + Moonlight/Program.cs | 14 +++-- .../Navigations/AdminSysNavigation.razor | 8 ++- .../Shared/Components/Partials/Tooltip.razor | 4 +- .../Shared/Views/Admin/Sys/Diagnose.razor | 30 +++++++++++ 9 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 Moonlight/App/Extensions/ZipArchiveExtension.cs create mode 100644 Moonlight/Shared/Views/Admin/Sys/Diagnose.razor diff --git a/Moonlight/App/Extensions/ZipArchiveExtension.cs b/Moonlight/App/Extensions/ZipArchiveExtension.cs new file mode 100644 index 0000000..9937e55 --- /dev/null +++ b/Moonlight/App/Extensions/ZipArchiveExtension.cs @@ -0,0 +1,26 @@ +using System.IO.Compression; +using System.Text; + +namespace Moonlight.App.Extensions; + +public static class ZipArchiveExtension +{ + public static async Task AddFromText(this ZipArchive archive, string entryName, string content) + { + using var memoryStream = new MemoryStream(); + await memoryStream.WriteAsync(Encoding.UTF8.GetBytes(content)); + await memoryStream.FlushAsync(); + + await archive.AddFromStream(entryName, memoryStream); + } + + public static async Task AddFromStream(this ZipArchive archive, string entryName, Stream dataStream) + { + var entry = archive.CreateEntry(entryName, CompressionLevel.Fastest); + await using var stream = entry.Open(); + + dataStream.Position = 0; + await dataStream.CopyToAsync(stream); + await stream.FlushAsync(); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/ConfigService.cs b/Moonlight/App/Services/ConfigService.cs index 322a449..3971940 100644 --- a/Moonlight/App/Services/ConfigService.cs +++ b/Moonlight/App/Services/ConfigService.cs @@ -34,4 +34,27 @@ public class ConfigService { return Data; } + + public string GetDiagnoseJson() + { + var text = File.ReadAllText(Path); + var data = JsonConvert.DeserializeObject(text) ?? new(); + + // Security token + data.Security.Token = ""; + + // Database + if (string.IsNullOrEmpty(data.Database.Password)) + data.Database.Password = "WAS EMPTY"; + else + data.Database.Password = "WAS NOT EMPTY"; + + // Mailserver + if (string.IsNullOrEmpty(data.MailServer.Password)) + data.MailServer.Password = "WAS EMPTY"; + else + data.MailServer.Password = "WAS NOT EMPTY"; + + return JsonConvert.SerializeObject(data, Formatting.Indented); + } } \ No newline at end of file diff --git a/Moonlight/App/Services/PluginService.cs b/Moonlight/App/Services/PluginService.cs index 6179460..6cd608f 100644 --- a/Moonlight/App/Services/PluginService.cs +++ b/Moonlight/App/Services/PluginService.cs @@ -81,6 +81,8 @@ public class PluginService Logger.Info($"Loaded {Plugins.Count} plugin(s)"); } + public Task GetLoadedPlugins() => Task.FromResult(Plugins.ToArray()); + public async Task RunPreInit() { foreach (var plugin in Plugins) diff --git a/Moonlight/App/Services/Sys/MoonlightService.cs b/Moonlight/App/Services/Sys/MoonlightService.cs index a29f4ea..f6fb628 100644 --- a/Moonlight/App/Services/Sys/MoonlightService.cs +++ b/Moonlight/App/Services/Sys/MoonlightService.cs @@ -1,4 +1,5 @@ -using Moonlight.App.Event; +using System.IO.Compression; +using Moonlight.App.Event; using Moonlight.App.Extensions; using Moonlight.App.Helpers; @@ -10,7 +11,8 @@ public class MoonlightService // This service can be used to perform strictly pa private readonly IServiceProvider ServiceProvider; public WebApplication Application { get; set; } // Do NOT modify using a plugin - public MoonlightThemeService Theme { get; set; } + public string LogPath { get; set; } // Do NOT modify using a plugin + public MoonlightThemeService Theme => ServiceProvider.GetRequiredService(); public MoonlightService(ConfigService configService, IServiceProvider serviceProvider) { @@ -28,4 +30,52 @@ public class MoonlightService // This service can be used to perform strictly pa await Application.StopAsync(); } + + public async Task GenerateDiagnoseReport() + { + var scope = ServiceProvider.CreateScope(); + + // Prepare zip file + var memoryStream = new MemoryStream(); + var zip = new ZipArchive(memoryStream, ZipArchiveMode.Create, true); + + // Add current log + // We need to open the file this way because we need to specify the access and share mode directly + // in order to read from a file which is currently written to + var fs = File.Open(LogPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + var sr = new StreamReader(fs); + var log = await sr.ReadToEndAsync(); + sr.Close(); + fs.Close(); + + await zip.AddFromText("log.txt", log); + + // TODO: Add node settings here + + // Add config + var config = ConfigService.GetDiagnoseJson(); + await zip.AddFromText("config.json", config); + + // Make a list of plugins + var pluginService = scope.ServiceProvider.GetRequiredService(); + var plugins = await pluginService.GetLoadedPlugins(); + var pluginList = "Installed plugins:\n"; + + foreach (var plugin in plugins) + { + var assembly = plugin.GetType().Assembly; + pluginList += $"{assembly.FullName} ({assembly.Location})\n"; + } + + await zip.AddFromText("pluginList.txt", pluginList); + + // Add more information here + + // Finalize file + zip.Dispose(); + memoryStream.Close(); + var data = memoryStream.ToArray(); + + return data; + } } \ No newline at end of file diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 00875d8..0e9b7ac 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -43,5 +43,6 @@ + diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index f5c1482..8a45501 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -18,22 +18,29 @@ using Moonlight.App.Services.Users; using Moonlight.App.Services.Utils; using Serilog; +var builder = WebApplication.CreateBuilder(args); + var configService = new ConfigService(); Directory.CreateDirectory(PathBuilder.Dir("storage")); Directory.CreateDirectory(PathBuilder.Dir("storage", "logs")); var logConfig = new LoggerConfiguration(); +var now = DateTime.UtcNow; +var logPath = PathBuilder.File("storage", "logs", $"moonlight-{now.Day}-{now.Month}-{now.Year}---{now.Hour}-{now.Minute}.log"); logConfig = logConfig.Enrich.FromLogContext() - .MinimumLevel.Debug() + .WriteTo.File(logPath, outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}") .WriteTo.Console( outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}"); -Log.Logger = logConfig.CreateLogger(); +if (args.Contains("--debug") || builder.Environment.IsDevelopment()) + logConfig = logConfig.MinimumLevel.Debug(); +else + logConfig = logConfig.MinimumLevel.Information(); -var builder = WebApplication.CreateBuilder(args); +Log.Logger = logConfig.CreateLogger(); // Init plugin system var pluginService = new PluginService(); @@ -126,6 +133,7 @@ app.Services.GetRequiredService(); var moonlightService = app.Services.GetRequiredService(); moonlightService.Application = app; +moonlightService.LogPath = logPath; var serviceService = app.Services.GetRequiredService(); serviceService.Register(ServiceType.Server); diff --git a/Moonlight/Shared/Components/Navigations/AdminSysNavigation.razor b/Moonlight/Shared/Components/Navigations/AdminSysNavigation.razor index a3a730b..9913f81 100644 --- a/Moonlight/Shared/Components/Navigations/AdminSysNavigation.razor +++ b/Moonlight/Shared/Components/Navigations/AdminSysNavigation.razor @@ -16,12 +16,16 @@ Themes + @code { - [Parameter] - public int Index { get; set; } + [Parameter] public int Index { get; set; } } \ No newline at end of file diff --git a/Moonlight/Shared/Components/Partials/Tooltip.razor b/Moonlight/Shared/Components/Partials/Tooltip.razor index 416a37a..f73df5c 100644 --- a/Moonlight/Shared/Components/Partials/Tooltip.razor +++ b/Moonlight/Shared/Components/Partials/Tooltip.razor @@ -1,4 +1,4 @@ -
+
@ChildContent
@@ -6,4 +6,6 @@ { [Parameter] public RenderFragment ChildContent { get; set; } + + [Parameter] public string Color { get; set; } = "primary"; } diff --git a/Moonlight/Shared/Views/Admin/Sys/Diagnose.razor b/Moonlight/Shared/Views/Admin/Sys/Diagnose.razor new file mode 100644 index 0000000..ff5969a --- /dev/null +++ b/Moonlight/Shared/Views/Admin/Sys/Diagnose.razor @@ -0,0 +1,30 @@ +@page "/admin/sys/diagnose" +@using Moonlight.App.Extensions.Attributes +@using Moonlight.App.Models.Enums +@using Moonlight.App.Services.Sys + +@attribute [RequirePermission(Permission.AdminRoot)] + +@inject MoonlightService MoonlightService +@inject FileDownloadService DownloadService + + + + + Dont share this file with random people. + We do our best to clear this file from sensitive information but it can still contain some. + Its safe to share with official moonlight panel developers + + +
+ +
+ +@code +{ + private async Task GenerateDiagnose() + { + var data = await MoonlightService.GenerateDiagnoseReport(); + await DownloadService.DownloadBytes("moonlight-diagnose.zip", data); + } +}