Initial commit

This commit is contained in:
2026-04-23 21:38:24 -04:00
commit 63e12a9636
1762 changed files with 1672620 additions and 0 deletions
@@ -0,0 +1,134 @@
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;
}