135 lines
5.4 KiB
C#
135 lines
5.4 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using PowderCoating.Shared.Constants;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using PowderCoating.Core.Entities;
|
|
using PowderCoating.Infrastructure.Data;
|
|
using System.Reflection;
|
|
|
|
namespace PowderCoating.Web.Controllers;
|
|
|
|
/// <summary>
|
|
/// SuperAdmin-only system health and runtime information page.
|
|
/// Aggregates application version, database connectivity, migration state,
|
|
/// seed history, user counts, and host environment details into a single view
|
|
/// to give platform operators a quick operational snapshot without needing
|
|
/// server or database console access.
|
|
/// </summary>
|
|
[Authorize(Policy = AppConstants.Policies.SuperAdminOnly)]
|
|
public class SystemInfoController : Controller
|
|
{
|
|
private readonly ApplicationDbContext _dbContext;
|
|
private readonly UserManager<ApplicationUser> _userManager;
|
|
private readonly IWebHostEnvironment _env;
|
|
|
|
public SystemInfoController(
|
|
ApplicationDbContext dbContext,
|
|
UserManager<ApplicationUser> userManager,
|
|
IWebHostEnvironment env)
|
|
{
|
|
_dbContext = dbContext;
|
|
_userManager = userManager;
|
|
_env = env;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gathers and renders runtime system information into a
|
|
/// <see cref="SystemInfoViewModel"/>.
|
|
/// <para>
|
|
/// Key design decisions:
|
|
/// <list type="bullet">
|
|
/// <item>The informational version string (from
|
|
/// <see cref="AssemblyInformationalVersionAttribute"/>) is preferred over the
|
|
/// numeric version because it can include Git commit hashes or pre-release labels
|
|
/// set during CI builds.</item>
|
|
/// <item>Database connectivity is tested via <c>CanConnectAsync()</c> rather than
|
|
/// a raw query to keep the check lightweight and independent of schema state.</item>
|
|
/// <item>Applied migrations are listed (not pending) so the view can report the
|
|
/// last applied migration without needing write access to the migration history.</item>
|
|
/// <item><c>SeedData.LastSeedRun</c> is a static field updated by the seed service
|
|
/// each time seeding completes; it shows <c>null</c> if no seed has run since
|
|
/// the last application restart.</item>
|
|
/// <item>Server time is reported in both local and UTC to help operators diagnose
|
|
/// timezone-related scheduling issues.</item>
|
|
/// </list>
|
|
/// </para>
|
|
/// </summary>
|
|
public async Task<IActionResult> Index()
|
|
{
|
|
// App version from assembly
|
|
var assembly = Assembly.GetEntryAssembly();
|
|
var version = assembly?.GetName().Version?.ToString() ?? "Unknown";
|
|
var infoVersion = assembly?
|
|
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
|
|
?.InformationalVersion ?? version;
|
|
|
|
// Database connectivity
|
|
bool dbConnected;
|
|
string dbStatus;
|
|
string? lastMigration = null;
|
|
int migrationCount = 0;
|
|
try
|
|
{
|
|
dbConnected = await _dbContext.Database.CanConnectAsync();
|
|
dbStatus = dbConnected ? "Connected" : "Unreachable";
|
|
if (dbConnected)
|
|
{
|
|
var applied = await _dbContext.Database.GetAppliedMigrationsAsync();
|
|
var migrations = applied.ToList();
|
|
migrationCount = migrations.Count;
|
|
lastMigration = migrations.LastOrDefault();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
dbConnected = false;
|
|
dbStatus = $"Error: {ex.Message}";
|
|
}
|
|
|
|
// User counts
|
|
var totalUsers = await _userManager.Users.CountAsync();
|
|
var activeUsers = await _userManager.Users.CountAsync(u => u.IsActive);
|
|
|
|
var vm = new SystemInfoViewModel
|
|
{
|
|
AppVersion = infoVersion,
|
|
DatabaseConnected = dbConnected,
|
|
DatabaseStatus = dbStatus,
|
|
LastAppliedMigration = lastMigration,
|
|
MigrationCount = migrationCount,
|
|
LastSeedRun = SeedData.LastSeedRun,
|
|
ServerTime = DateTime.Now,
|
|
ServerTimeUtc = DateTime.UtcNow,
|
|
ServerTimeZone = TimeZoneInfo.Local.DisplayName,
|
|
ActiveUserCount = activeUsers,
|
|
TotalUserCount = totalUsers,
|
|
EnvironmentName = _env.EnvironmentName,
|
|
MachineName = Environment.MachineName,
|
|
OsDescription = System.Runtime.InteropServices.RuntimeInformation.OSDescription,
|
|
RuntimeVersion = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription
|
|
};
|
|
|
|
return View(vm);
|
|
}
|
|
}
|
|
|
|
public class SystemInfoViewModel
|
|
{
|
|
public string AppVersion { get; set; } = string.Empty;
|
|
public bool DatabaseConnected { get; set; }
|
|
public string DatabaseStatus { get; set; } = string.Empty;
|
|
public string? LastAppliedMigration { get; set; }
|
|
public int MigrationCount { get; set; }
|
|
public DateTime? LastSeedRun { get; set; }
|
|
public DateTime ServerTime { get; set; }
|
|
public DateTime ServerTimeUtc { get; set; }
|
|
public string ServerTimeZone { get; set; } = string.Empty;
|
|
public int ActiveUserCount { get; set; }
|
|
public int TotalUserCount { get; set; }
|
|
public string EnvironmentName { get; set; } = string.Empty;
|
|
public string MachineName { get; set; } = string.Empty;
|
|
public string OsDescription { get; set; } = string.Empty;
|
|
public string RuntimeVersion { get; set; } = string.Empty;
|
|
}
|