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

@ -27,26 +27,11 @@ public class ModerationCaseController : ControllerBase
@case.DismissedAt = DateTime.Now; @case.DismissedAt = DateTime.Now;
@case.DismisserId = user.UserId; @case.DismisserId = user.UserId;
@case.Processed = false;
await this.database.SaveChangesAsync(); await this.database.SaveChangesAsync();
return this.Ok(); 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;
await this.database.SaveChangesAsync();
return this.Ok();
}
} }

View file

@ -35,7 +35,7 @@ public class CasePage : BaseLayout
.Include(c => c.Dismisser) .Include(c => c.Dismisser)
.OrderByDescending(c => c.CaseId) .OrderByDescending(c => c.CaseId)
.ToListAsync(); .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.PageNumber = pageNumber;
this.PageAmount = Math.Max(1, (int)Math.Ceiling((double)this.CaseCount / ServerStatics.PageSize)); 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() ModerationCase @case = new()
{ {
Type = (CaseType)type, Type = (CaseType)type,
Description = description, Reason = description,
ExpiresAt = expires, ExpiresAt = expires,
CreatedAt = DateTime.Now, CreatedAt = DateTime.Now,
CreatorId = 1, CreatorId = 1,

View file

@ -49,14 +49,24 @@
<p><strong>Affected user:</strong> <a href="/user/@user.UserId">@user.Username</a></p> <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.Reason</pre>
<pre>@Model.Description</pre>
} }
else 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) @if (!Model.Dismissed)
@ -66,11 +76,4 @@
<span>Dismiss</span> <span>Dismiss</span>
</a> </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> </div>

View file

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

@ -16,8 +16,12 @@ public class ModerationCase
public int CaseId { get; set; } public int CaseId { get; set; }
public CaseType Type { get; set; } 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; } public DateTime CreatedAt { get; set; }
@ -61,7 +65,7 @@ public class ModerationCase
=> new() => new()
{ {
Type = CaseType.UserBan, Type = CaseType.UserBan,
Description = $"Banned for reason '{reason}'\nModeration notes: {modNotes}", Reason = $"Banned for reason '{reason}'\nModeration notes: {modNotes}",
CreatorId = caseCreator, CreatorId = caseCreator,
CreatedAt = DateTime.Now, CreatedAt = DateTime.Now,
ExpiresAt = caseExpires, ExpiresAt = caseExpires,

View file

@ -53,9 +53,9 @@ public static class RepeatingTaskHandler
taskQueue.Enqueue(task); taskQueue.Enqueue(task);
Thread.Sleep(500); // Doesn't need to be that precise. 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") b.Property<int>("CreatorId")
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime?>("DismissedAt") b.Property<DateTime?>("DismissedAt")
.HasColumnType("datetime(6)"); .HasColumnType("datetime(6)");
@ -60,6 +56,17 @@ namespace ProjectLighthouse.Migrations
b.Property<DateTime?>("ExpiresAt") b.Property<DateTime?>("ExpiresAt")
.HasColumnType("datetime(6)"); .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") b.Property<int>("Type")
.HasColumnType("int"); .HasColumnType("int");