Add maintenance jobs

This commit is contained in:
jvyden 2021-11-24 17:45:34 -05:00
commit 57ba816052
No known key found for this signature in database
GPG key ID: 18BCF2BE0262B278
11 changed files with 134 additions and 19 deletions

View file

@ -7,7 +7,7 @@ using LBPUnion.ProjectLighthouse.Types;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers.ExternalAuth
namespace LBPUnion.ProjectLighthouse.Controllers.Website.ExternalAuth
{
[ApiController]
[Route("/authentication")]

View file

@ -1,23 +1,32 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.CommandLine;
using LBPUnion.ProjectLighthouse.Maintenance;
namespace LBPUnion.ProjectLighthouse.Helpers
{
public static class CommandHelper
public static class MaintenanceHelper
{
public static List<ICommand> Commands { get; }
static CommandHelper()
public static List<IMaintenanceJob> MaintenanceJobs { get; }
private static List<T> getListOfInterfaceObjects<T>() where T : class
{
Commands = Assembly.GetExecutingAssembly()
return Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.GetInterfaces().Contains(typeof(ICommand)) && t.GetConstructor(Type.EmptyTypes) != null)
.Select(t => Activator.CreateInstance(t) as ICommand)
.ToList();
.Where(t => t.GetInterfaces().Contains(typeof(T)) && t.GetConstructor(Type.EmptyTypes) != null)
.Select(t => Activator.CreateInstance(t) as T)
.ToList()!;
}
static MaintenanceHelper()
{
Commands = getListOfInterfaceObjects<ICommand>();
MaintenanceJobs = getListOfInterfaceObjects<IMaintenanceJob>();
}
public static async Task RunCommand(string[] args)
@ -46,5 +55,18 @@ namespace LBPUnion.ProjectLighthouse.Helpers
Console.WriteLine("Command not found.");
}
public static async Task RunMaintenanceJob(string jobName)
{
IMaintenanceJob? job = MaintenanceJobs.FirstOrDefault(j => j.GetType().Name == jobName);
if (job == null) throw new ArgumentNullException();
await RunMaintenanceJob(job);
}
public static async Task RunMaintenanceJob(IMaintenanceJob job)
{
await job.Run();
}
}
}

View file

@ -1,11 +1,13 @@
#nullable enable
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.CommandLine
namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
{
[UsedImplicitly]
public class MakeUserAdminCommand : ICommand
{
private readonly Database database = new();

View file

@ -1,12 +1,14 @@
#nullable enable
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.CommandLine
namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
{
[UsedImplicitly]
public class ResetPasswordCommand : ICommand
{
private readonly Database database = new();

View file

@ -1,6 +1,6 @@
using System.Threading.Tasks;
namespace LBPUnion.ProjectLighthouse.CommandLine
namespace LBPUnion.ProjectLighthouse.Maintenance
{
public interface ICommand
{

View file

@ -0,0 +1,13 @@
using System.Threading.Tasks;
namespace LBPUnion.ProjectLighthouse.Maintenance
{
public interface IMaintenanceJob
{
public Task Run();
public string Name();
public string Description();
}
}

View file

@ -0,0 +1,41 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Types;
namespace LBPUnion.ProjectLighthouse.Maintenance.MaintenanceJobs
{
public class CleanupBrokenPhotosMaintenanceJob : IMaintenanceJob
{
private readonly Database database = new();
public string Name() => "Cleanup Broken Photos";
public string Description() => "Deletes all photos that have missing assets.";
[SuppressMessage("ReSharper", "LoopCanBePartlyConvertedToQuery")]
public async Task Run()
{
foreach (Photo photo in this.database.Photos)
{
bool hashNullOrEmpty = string.IsNullOrEmpty
(photo.LargeHash) ||
string.IsNullOrEmpty(photo.MediumHash) ||
string.IsNullOrEmpty(photo.SmallHash) ||
string.IsNullOrEmpty(photo.PlanHash);
bool allHashesDontExist = FileHelper.ResourcesNotUploaded(photo.LargeHash, photo.MediumHash, photo.SmallHash, photo.PlanHash).Length != 0;
if (hashNullOrEmpty || allHashesDontExist)
{
Console.WriteLine
(
$"Removing photo (id: {photo.PhotoId}): {nameof(hashNullOrEmpty)}: {hashNullOrEmpty}, {nameof(allHashesDontExist)}: {allHashesDontExist}"
);
this.database.Photos.Remove(photo);
}
}
await this.database.SaveChangesAsync();
}
}
}

View file

@ -1,5 +1,6 @@
@page "/admin"
@using LBPUnion.ProjectLighthouse.CommandLine
@using LBPUnion.ProjectLighthouse.Helpers
@using LBPUnion.ProjectLighthouse.Maintenance
@model LBPUnion.ProjectLighthouse.Pages.AdminPanelPage
@{
@ -8,11 +9,12 @@
<h1>Admin Panel</h1>
<h2>Commands</h2>
<div class="ui grid">
@foreach (ICommand command in Model!.Commands)
@foreach (ICommand command in MaintenanceHelper.Commands)
{
<div class="four wide column">
<div class="ui black segment">
<div class="ui blue segment">
<h3>@command.Name()</h3>
<form>
<div class="ui input" style="width: 100%;">
@ -27,4 +29,27 @@
</div>
</div>
}
</div>
<h2>Maintenance Jobs</h2>
<p>
<b>Warning: Interrupting Lighthouse during maintenance may leave the database in an unclean state.</b>
</p>
<div class="ui grid">
@foreach (IMaintenanceJob job in MaintenanceHelper.MaintenanceJobs)
{
<div class="four wide column">
<div class="ui red segment">
<h3>@job.Name()</h3>
<p>@job.Description()</p>
<form>
<input type="text" name="maintenanceJob" style="display: none;" value="@job.GetType().Name">
<button type="submit" class="ui green button" style="width: 100%;">
<i class="play icon"></i>
Execute
</button>
</form>
</div>
</div>
}
</div>

View file

@ -1,8 +1,8 @@
#nullable enable
using System.Collections.Generic;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.CommandLine;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Maintenance;
using LBPUnion.ProjectLighthouse.Pages.Layouts;
using LBPUnion.ProjectLighthouse.Types;
using Microsoft.AspNetCore.Mvc;
@ -14,9 +14,9 @@ namespace LBPUnion.ProjectLighthouse.Pages
public AdminPanelPage(Database database) : base(database)
{}
public List<ICommand> Commands = CommandHelper.Commands;
public List<ICommand> Commands = MaintenanceHelper.Commands;
public async Task<IActionResult> OnGet([FromQuery] string? args, [FromQuery] string? command)
public async Task<IActionResult> OnGet([FromQuery] string? args, [FromQuery] string? command, [FromQuery] string? maintenanceJob)
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
@ -27,7 +27,13 @@ namespace LBPUnion.ProjectLighthouse.Pages
args ??= "";
args = command + " " + args;
string[] split = args.Split(" ");
await CommandHelper.RunCommand(split);
await MaintenanceHelper.RunCommand(split);
return this.Redirect("~/admin");
}
if (!string.IsNullOrEmpty(maintenanceJob))
{
await MaintenanceHelper.RunMaintenanceJob(maintenanceJob);
return this.Redirect("~/admin");
}

View file

@ -65,7 +65,7 @@ namespace LBPUnion.ProjectLighthouse
if (args.Length != 0)
{
CommandHelper.RunCommand(args).Wait();
MaintenanceHelper.RunCommand(args).Wait();
return;
}

View file

@ -33,6 +33,10 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="CommandLine"/>
</ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="git describe --long --always --dirty --exclude=\* --abbrev=8 &gt; &quot;$(ProjectDir)/gitVersion.txt&quot;"/>
<Exec Command="git branch --show-current &gt; &quot;$(ProjectDir)/gitBranch.txt&quot;"/>