Add ability for cases to perform actions

This commit is contained in:
jvyden 2022-08-05 20:32:35 -04:00
parent bfaef6ba4c
commit 4718970f6b
No known key found for this signature in database
GPG key ID: 18BCF2BE0262B278
10 changed files with 169 additions and 41 deletions

View file

@ -28,22 +28,7 @@ public class ModerationCaseController : ControllerBase
@case.DismissedAt = DateTime.Now;
@case.DismisserId = user.UserId;
await this.database.SaveChangesAsync();
return this.Ok();
}
[HttpGet("undoDismiss")]
public async Task<IActionResult> UndoDismissCase([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null || !user.IsModerator) return this.StatusCode(403, "");
ModerationCase? @case = await this.database.Cases.FirstOrDefaultAsync(c => c.CaseId == id);
if (@case == null) return this.NotFound();
@case.DismissedAt = null;
@case.DismisserId = null;
@case.Processed = false;
await this.database.SaveChangesAsync();

View file

@ -35,7 +35,7 @@ public class CasePage : BaseLayout
.Include(c => c.Dismisser)
.OrderByDescending(c => c.CaseId)
.ToListAsync();
this.CaseCount = await this.Database.Cases.CountAsync(c => c.Description.Contains(this.SearchValue));
this.CaseCount = await this.Database.Cases.CountAsync(c => c.Reason.Contains(this.SearchValue));
this.PageNumber = pageNumber;
this.PageAmount = Math.Max(1, (int)Math.Ceiling((double)this.CaseCount / ServerStatics.PageSize));

View file

@ -23,7 +23,7 @@ public class NewCasePage : BaseLayout
ModerationCase @case = new()
{
Type = (CaseType)type,
Description = description,
Reason = description,
ExpiresAt = expires,
CreatedAt = DateTime.Now,
CreatorId = 1,

View file

@ -49,14 +49,24 @@
<p><strong>Affected user:</strong> <a href="/user/@user.UserId">@user.Username</a></p>
}
@if (!string.IsNullOrWhiteSpace(Model.Description))
<h3>Reason</h3>
@if (!string.IsNullOrWhiteSpace(Model.Reason))
{
<h3>Description</h3>
<pre>@Model.Description</pre>
<pre>@Model.Reason</pre>
}
else
{
<b>No description was provided.</b>
<pre><b>No reason was provided.</b></pre>
}
<h3>Moderator Notes</h3>
@if (!string.IsNullOrWhiteSpace(Model.ModeratorNotes))
{
<pre>@Model.ModeratorNotes</pre>
}
else
{
<pre><b>No notes were provided.</b></pre>
}
@if (!Model.Dismissed)
@ -66,11 +76,4 @@
<span>Dismiss</span>
</a>
}
else
{
<a class="ui yellow small button" href="/moderation/case/@Model.CaseId/undoDismiss">
<i class="undo icon"></i>
<span>Undo dismission</span> @* TODO: fix english here lol wtf is this *@
</a>
}
</div>

View file

@ -13,7 +13,6 @@ public enum CaseType
LevelLock = 4,
LevelCommentsDisabled = 5,
LevelDetailsEdited = 6,
}
public static class CaseTypeExtensions
@ -36,7 +35,6 @@ public static class CaseTypeExtensions
{
CaseType.LevelLock => true,
CaseType.LevelCommentsDisabled => true,
CaseType.LevelDetailsEdited => true,
_ => false,
};
}

View file

@ -0,0 +1,80 @@
#nullable enable
using System;
using System.Linq;
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Levels;
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Administration.Maintenance.RepeatingTasks;
public class PerformCaseActionsTask : IRepeatingTask
{
public string Name => "Perform actions on moderation cases";
public TimeSpan RepeatInterval => TimeSpan.FromSeconds(10);
public DateTime LastRan { get; set; }
public async Task Run(Database database)
{
foreach (ModerationCase @case in await database.Cases.Where(c => !c.Processed).ToListAsync())
{
User? user = null;
Slot? slot = null;
if (@case.Type.AffectsUser())
{
user = await @case.GetUserAsync(database);
}
else if(@case.Type.AffectsLevel())
{
slot = await @case.GetSlotAsync(database);
}
if (@case.Expired || @case.Dismissed)
{
switch (@case.Type)
{
case CaseType.UserBan:
case CaseType.UserRestriction:
case CaseType.UserSilence:
{
user!.PermissionLevel = PermissionLevel.Default;
break;
};
case CaseType.UserCommentsDisabled: break;
case CaseType.LevelLock: break;
case CaseType.LevelCommentsDisabled: break;
default: throw new ArgumentOutOfRangeException();
}
}
else
{
switch (@case.Type)
{
case CaseType.UserSilence:
{
user!.PermissionLevel = PermissionLevel.Silenced;
break;
}
case CaseType.UserRestriction:
{
user!.PermissionLevel = PermissionLevel.Restricted;
break;
}
case CaseType.UserBan:
{
user!.PermissionLevel = PermissionLevel.Banned;
break;
}
case CaseType.UserCommentsDisabled: break;
case CaseType.LevelLock: break;
case CaseType.LevelCommentsDisabled: break;
default: throw new ArgumentOutOfRangeException();
}
}
@case.Processed = true;
}
await database.SaveChangesAsync();
}
}

View file

@ -17,7 +17,11 @@ public class ModerationCase
public CaseType Type { get; set; }
public string Description { get; set; }
public string Reason { get; set; } = "";
public string ModeratorNotes { get; set; } = "";
public bool Processed { get; set; } = false;
public DateTime CreatedAt { get; set; }
@ -61,7 +65,7 @@ public class ModerationCase
=> new()
{
Type = CaseType.UserBan,
Description = $"Banned for reason '{reason}'\nModeration notes: {modNotes}",
Reason = $"Banned for reason '{reason}'\nModeration notes: {modNotes}",
CreatorId = caseCreator,
CreatedAt = DateTime.Now,
ExpiresAt = caseExpires,

View file

@ -53,9 +53,9 @@ public static class RepeatingTaskHandler
taskQueue.Enqueue(task);
Thread.Sleep(500); // Doesn't need to be that precise.
}
catch
catch(Exception e)
{
// ignored
Logger.Warn($"Error occured while processing repeating tasks: \n{e}", LogArea.Maintenace);
}
}
}

View file

@ -0,0 +1,51 @@
using LBPUnion.ProjectLighthouse;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(Database))]
[Migration("20220805234507_AddModNotesToCase")]
public partial class AddModNotesToCase : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "Description",
table: "Cases",
newName: "Reason");
migrationBuilder.AddColumn<string>(
name: "ModeratorNotes",
table: "Cases",
type: "longtext",
nullable: false)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.AddColumn<bool>(
name: "Processed",
table: "Cases",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ModeratorNotes",
table: "Cases");
migrationBuilder.DropColumn(
name: "Processed",
table: "Cases");
migrationBuilder.RenameColumn(
name: "Reason",
table: "Cases",
newName: "Description");
}
}
}

View file

@ -47,10 +47,6 @@ namespace ProjectLighthouse.Migrations
b.Property<int>("CreatorId")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime?>("DismissedAt")
.HasColumnType("datetime(6)");
@ -60,6 +56,17 @@ namespace ProjectLighthouse.Migrations
b.Property<DateTime?>("ExpiresAt")
.HasColumnType("datetime(6)");
b.Property<string>("ModeratorNotes")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("Processed")
.HasColumnType("tinyint(1)");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Type")
.HasColumnType("int");