Added diagnose frontend and backend implementation

This commit is contained in:
2025-12-27 23:32:36 +01:00
parent be3cdb8235
commit e1c0645428
11 changed files with 380 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
using Microsoft.AspNetCore.Mvc;
using Moonlight.Api.Mappers;
using Moonlight.Api.Services;
using Moonlight.Shared.Http.Responses.Admin;
namespace Moonlight.Api.Http.Controllers.Admin;
[ApiController]
[Route("api/admin/system/diagnose")]
public class DiagnoseController : Controller
{
private readonly DiagnoseService DiagnoseService;
public DiagnoseController(DiagnoseService diagnoseService)
{
DiagnoseService = diagnoseService;
}
[HttpGet]
public async Task<ActionResult<DiagnoseResultResponse[]>> GetAsync()
{
var results = await DiagnoseService.DiagnoseAsync();
return results
.OrderBy(x => x.Level)
.MapToResult()
.ToArray();
}
}

View File

@@ -0,0 +1,33 @@
using Moonlight.Api.Interfaces;
using Moonlight.Api.Models;
using Moonlight.Api.Services;
namespace Moonlight.Api.Implementations;
public sealed class UpdateDiagnoseProvider : IDiagnoseProvider
{
private readonly ApplicationService ApplicationService;
public UpdateDiagnoseProvider(ApplicationService applicationService)
{
ApplicationService = applicationService;
}
public Task<DiagnoseResult[]> DiagnoseAsync()
{
if (ApplicationService.IsUpToDate)
return Task.FromResult<DiagnoseResult[]>([]);
return Task.FromResult<DiagnoseResult[]>([
new DiagnoseResult(
DiagnoseLevel.Warning,
"Instance is not up-to-date",
["Moonlight", "Update Check"],
"Update your moonlight instance to receive bug fixes, new features and security patches. Update button can be found in the overview",
null,
"/admin",
null
)
]);
}
}

View File

@@ -0,0 +1,8 @@
using Moonlight.Api.Models;
namespace Moonlight.Api.Interfaces;
public interface IDiagnoseProvider
{
public Task<DiagnoseResult[]> DiagnoseAsync();
}

View File

@@ -0,0 +1,14 @@
using System.Diagnostics.CodeAnalysis;
using Moonlight.Api.Models;
using Moonlight.Shared.Http.Responses.Admin;
using Riok.Mapperly.Abstractions;
namespace Moonlight.Api.Mappers;
[Mapper]
[SuppressMessage("Mapper", "RMG020:No members are mapped in an object mapping")]
[SuppressMessage("Mapper", "RMG012:No members are mapped in an object mapping")]
public static partial class DiagnoseResultMapper
{
public static partial IEnumerable<DiagnoseResultResponse> MapToResult(this IEnumerable<DiagnoseResult> results);
}

View File

@@ -0,0 +1,10 @@
namespace Moonlight.Api.Models;
public record DiagnoseResult(DiagnoseLevel Level, string Title, string[] Tags, string? Message, string? StackStrace, string? SolutionUrl, string? ReportUrl);
public enum DiagnoseLevel
{
Error = 0,
Warning = 1,
Healthy = 2
}

View File

@@ -0,0 +1,38 @@
using Microsoft.Extensions.Logging;
using Moonlight.Api.Interfaces;
using Moonlight.Api.Models;
namespace Moonlight.Api.Services;
public class DiagnoseService
{
private readonly IEnumerable<IDiagnoseProvider> Providers;
private readonly ILogger<DiagnoseService> Logger;
public DiagnoseService(IEnumerable<IDiagnoseProvider> providers, ILogger<DiagnoseService> logger)
{
Providers = providers;
Logger = logger;
}
public async Task<DiagnoseResult[]> DiagnoseAsync()
{
var results = new List<DiagnoseResult>();
foreach (var provider in Providers)
{
try
{
results.AddRange(
await provider.DiagnoseAsync()
);
}
catch (Exception e)
{
Logger.LogError(e, "An unhandled error occured while processing provider");
}
}
return results.ToArray();
}
}

View File

@@ -4,6 +4,8 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using Moonlight.Shared.Http;
using Moonlight.Api.Helpers;
using Moonlight.Api.Implementations;
using Moonlight.Api.Interfaces;
using Moonlight.Api.Services;
namespace Moonlight.Api.Startup;
@@ -23,6 +25,10 @@ public partial class Startup
builder.Services.AddSingleton<ApplicationService>();
builder.Services.AddHostedService(sp => sp.GetRequiredService<ApplicationService>());
builder.Services.AddSingleton<DiagnoseService>();
builder.Services.AddSingleton<IDiagnoseProvider, UpdateDiagnoseProvider>();
}
private static void UseBase(WebApplication application)