From 5751f876765f4ace0fd8f856e39afad96a53cd7f Mon Sep 17 00:00:00 2001 From: Atulin <11233299+Atulin@users.noreply.github.com> Date: Mon, 29 Apr 2024 02:30:14 +0200 Subject: [PATCH] Better infractions - Moved them to the admin area - Added moderator message logging - Some minor other changes --- .../Admin/Api/V1/Cache/CacheController.cs | 21 +++++---------- .../Infractions/Commands/CreateInfraction.cs | 13 ++++++++- .../Commands/DeactivateInfraction.cs | 18 ++++++++++--- .../V1/Infractions/InfractionsController.cs | 27 +++++++++---------- .../Queries/GetInfractionDetails.cs | 2 +- .../Infractions/Queries/GetUserInfractions.cs | 2 +- .../Api/V1/Telemetry/TelemetryController.cs | 9 +++---- Ogma3/Areas/Admin/Pages/Infractions.cshtml | 2 +- Ogma3/Areas/Admin/Pages/Users.cshtml | 2 +- .../Constants/ModeratorActionTemplates.cs | 11 ++++++++ Ogma3/Infrastructure/Logging/Telegram.cs | 6 +++-- 11 files changed, 66 insertions(+), 47 deletions(-) rename Ogma3/{ => Areas/Admin}/Api/V1/Infractions/Commands/CreateInfraction.cs (80%) rename Ogma3/{ => Areas/Admin}/Api/V1/Infractions/Commands/DeactivateInfraction.cs (63%) rename Ogma3/{ => Areas/Admin}/Api/V1/Infractions/InfractionsController.cs (57%) rename Ogma3/{ => Areas/Admin}/Api/V1/Infractions/Queries/GetInfractionDetails.cs (96%) rename Ogma3/{ => Areas/Admin}/Api/V1/Infractions/Queries/GetUserInfractions.cs (94%) diff --git a/Ogma3/Areas/Admin/Api/V1/Cache/CacheController.cs b/Ogma3/Areas/Admin/Api/V1/Cache/CacheController.cs index 035e19a9..a8aa5412 100644 --- a/Ogma3/Areas/Admin/Api/V1/Cache/CacheController.cs +++ b/Ogma3/Areas/Admin/Api/V1/Cache/CacheController.cs @@ -10,21 +10,12 @@ namespace Ogma3.Areas.Admin.Api.V1.Cache; [Route("admin/api/[controller]", Name = nameof(CacheController))] [ApiController] [Authorize(Roles = RoleNames.Admin)] -public class CacheController : ControllerBase +public class CacheController(IMemoryCache cache, ILogger logger) : ControllerBase { - private readonly IMemoryCache _cache; - private readonly ILogger _logger; - - public CacheController(IMemoryCache cache, ILogger logger) - { - _cache = cache; - _logger = logger; - } - [HttpGet] public ActionResult GetCache() { - if (_cache is MemoryCache mc) + if (cache is MemoryCache mc) { return Ok(mc.Count); } @@ -36,16 +27,16 @@ public ActionResult GetCache() [IgnoreAntiforgeryToken] public ActionResult DeleteCache() { - _logger.LogWarning("Purging all caches..."); + logger.LogWarning("Purging all caches..."); - if (_cache is MemoryCache mc) + if (cache is MemoryCache mc) { mc.Compact(1.0); - _logger.LogWarning("Cache purged!"); + logger.LogWarning("Cache purged!"); return Ok("Cache purged!"); } - _logger.LogWarning("Could not purge cache!"); + logger.LogWarning("Could not purge cache!"); return new ServerErrorObjectResult("Could not purge cache!"); } } \ No newline at end of file diff --git a/Ogma3/Api/V1/Infractions/Commands/CreateInfraction.cs b/Ogma3/Areas/Admin/Api/V1/Infractions/Commands/CreateInfraction.cs similarity index 80% rename from Ogma3/Api/V1/Infractions/Commands/CreateInfraction.cs rename to Ogma3/Areas/Admin/Api/V1/Infractions/Commands/CreateInfraction.cs index fac79a16..cb55d6ca 100644 --- a/Ogma3/Api/V1/Infractions/Commands/CreateInfraction.cs +++ b/Ogma3/Areas/Admin/Api/V1/Infractions/Commands/CreateInfraction.cs @@ -7,12 +7,14 @@ using Microsoft.Extensions.Caching.Memory; using Ogma3.Data; using Ogma3.Data.Infractions; +using Ogma3.Data.ModeratorActions; +using Ogma3.Infrastructure.Constants; using Ogma3.Infrastructure.Extensions; using Ogma3.Infrastructure.Mediator.Bases; using Ogma3.Infrastructure.Middleware; using Ogma3.Services.UserService; -namespace Ogma3.Api.V1.Infractions.Commands; +namespace Ogma3.Areas.Admin.Api.V1.Infractions.Commands; public static class CreateInfraction { @@ -35,6 +37,7 @@ public class Handler(ApplicationDbContext context, IUserService userService, IMe public async ValueTask> Handle(Command request, CancellationToken cancellationToken) { if (userService.User?.GetNumericId() is not { } uid) return Unauthorized(); + if (userService.User?.GetUsername() is not { } modName) return Unauthorized(); var (userId, reason, dateTime, type) = request; var infraction = new Infraction @@ -46,6 +49,14 @@ public async ValueTask> Handle(Command request, Cancellat Type = type, }; context.Infractions.Add(infraction); + + var action = new ModeratorAction + { + StaffMemberId = uid, + Description = ModeratorActionTemplates.Infractions.Create(uid, modName, infraction.Id, reason, type), + }; + context.ModeratorActions.Add(action); + await context.SaveChangesAsync(cancellationToken); if (infraction.Type == InfractionType.Ban) diff --git a/Ogma3/Api/V1/Infractions/Commands/DeactivateInfraction.cs b/Ogma3/Areas/Admin/Api/V1/Infractions/Commands/DeactivateInfraction.cs similarity index 63% rename from Ogma3/Api/V1/Infractions/Commands/DeactivateInfraction.cs rename to Ogma3/Areas/Admin/Api/V1/Infractions/Commands/DeactivateInfraction.cs index 702d8741..3d88b261 100644 --- a/Ogma3/Api/V1/Infractions/Commands/DeactivateInfraction.cs +++ b/Ogma3/Areas/Admin/Api/V1/Infractions/Commands/DeactivateInfraction.cs @@ -6,11 +6,13 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Ogma3.Data; +using Ogma3.Data.ModeratorActions; +using Ogma3.Infrastructure.Constants; using Ogma3.Infrastructure.Extensions; using Ogma3.Infrastructure.Mediator.Bases; using Ogma3.Services.UserService; -namespace Ogma3.Api.V1.Infractions.Commands; +namespace Ogma3.Areas.Admin.Api.V1.Infractions.Commands; public static class DeactivateInfraction { @@ -20,7 +22,8 @@ public class Handler(ApplicationDbContext context, IUserService userService) : B { public async ValueTask> Handle(Command request, CancellationToken cancellationToken) { - if (userService.User?.GetNumericId() is not { } _uid) return Unauthorized(); + if (userService.User?.GetNumericId() is not { } uid) return Unauthorized(); + if (userService.User?.GetUsername() is not { } modName) return Unauthorized(); var infraction = await context.Infractions .Where(i => i.Id == request.InfractionId) @@ -29,11 +32,18 @@ public async ValueTask> Handle(Command request, Cancellat if (infraction is null) return NotFound(); infraction.RemovedAt = DateTime.Now; - infraction.RemovedById = _uid; + infraction.RemovedById = uid; + + var action = new ModeratorAction + { + StaffMemberId = uid, + Description = ModeratorActionTemplates.Infractions.Lift(uid, modName, infraction.Id, infraction.Type), + }; + context.ModeratorActions.Add(action); await context.SaveChangesAsync(cancellationToken); - return Ok(new Response(infraction.Id, _uid, infraction.UserId)); + return Ok(new Response(infraction.Id, uid, infraction.UserId)); } } diff --git a/Ogma3/Api/V1/Infractions/InfractionsController.cs b/Ogma3/Areas/Admin/Api/V1/Infractions/InfractionsController.cs similarity index 57% rename from Ogma3/Api/V1/Infractions/InfractionsController.cs rename to Ogma3/Areas/Admin/Api/V1/Infractions/InfractionsController.cs index ca5e80cf..f99570f7 100644 --- a/Ogma3/Api/V1/Infractions/InfractionsController.cs +++ b/Ogma3/Areas/Admin/Api/V1/Infractions/InfractionsController.cs @@ -4,35 +4,32 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Ogma3.Api.V1.Infractions.Commands; -using Ogma3.Api.V1.Infractions.Queries; +using Ogma3.Areas.Admin.Api.V1.Infractions.Commands; +using Ogma3.Areas.Admin.Api.V1.Infractions.Queries; using Ogma3.Infrastructure.Constants; -namespace Ogma3.Api.V1.Infractions; +namespace Ogma3.Areas.Admin.Api.V1.Infractions; [Route("api/[controller]", Name = nameof(InfractionsController))] [ApiController] [Authorize(Roles = $"{RoleNames.Admin},{RoleNames.Moderator}")] -public class InfractionsController : ControllerBase +public class InfractionsController(IMediator mediator) : ControllerBase { - private readonly IMediator _mediator; - public InfractionsController(IMediator mediator) => _mediator = mediator; - [HttpGet] - public async Task>> GetInfractionsAsync([FromQuery] long id) - => await _mediator.Send(new GetUserInfractions.Query(id)); + public async Task>> GetInfractionsAsync([FromQuery] GetUserInfractions.Query query) + => await mediator.Send(query); [HttpGet("details")] - public async Task> GetInfractionDetails([FromQuery] long id) - => await _mediator.Send(new GetInfractionDetails.Query(id)); + public async Task> GetInfractionDetails([FromQuery] GetInfractionDetails.Query query) + => await mediator.Send(query); [HttpPost] public async Task> AddInfraction(CreateInfraction.Command command) - => await _mediator.Send(command); + => await mediator.Send(command); - [HttpDelete("{id:long}")] + [HttpDelete("{InfractionId:long}")] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(DeactivateInfraction.Response), StatusCodes.Status200OK)] - public async Task> DeactivateInfraction(long id) - => await _mediator.Send(new DeactivateInfraction.Command(id)); + public async Task> DeactivateInfraction([FromRoute] DeactivateInfraction.Command command) + => await mediator.Send(command); } \ No newline at end of file diff --git a/Ogma3/Api/V1/Infractions/Queries/GetInfractionDetails.cs b/Ogma3/Areas/Admin/Api/V1/Infractions/Queries/GetInfractionDetails.cs similarity index 96% rename from Ogma3/Api/V1/Infractions/Queries/GetInfractionDetails.cs rename to Ogma3/Areas/Admin/Api/V1/Infractions/Queries/GetInfractionDetails.cs index 0c3c8ce3..78bb65ba 100644 --- a/Ogma3/Api/V1/Infractions/Queries/GetInfractionDetails.cs +++ b/Ogma3/Areas/Admin/Api/V1/Infractions/Queries/GetInfractionDetails.cs @@ -9,7 +9,7 @@ using Ogma3.Data.Infractions; using Ogma3.Infrastructure.Mediator.Bases; -namespace Ogma3.Api.V1.Infractions.Queries; +namespace Ogma3.Areas.Admin.Api.V1.Infractions.Queries; public static class GetInfractionDetails { diff --git a/Ogma3/Api/V1/Infractions/Queries/GetUserInfractions.cs b/Ogma3/Areas/Admin/Api/V1/Infractions/Queries/GetUserInfractions.cs similarity index 94% rename from Ogma3/Api/V1/Infractions/Queries/GetUserInfractions.cs rename to Ogma3/Areas/Admin/Api/V1/Infractions/Queries/GetUserInfractions.cs index f57c736e..92168f19 100644 --- a/Ogma3/Api/V1/Infractions/Queries/GetUserInfractions.cs +++ b/Ogma3/Areas/Admin/Api/V1/Infractions/Queries/GetUserInfractions.cs @@ -9,7 +9,7 @@ using Ogma3.Data; using Ogma3.Infrastructure.Mediator.Bases; -namespace Ogma3.Api.V1.Infractions.Queries; +namespace Ogma3.Areas.Admin.Api.V1.Infractions.Queries; public static class GetUserInfractions { diff --git a/Ogma3/Areas/Admin/Api/V1/Telemetry/TelemetryController.cs b/Ogma3/Areas/Admin/Api/V1/Telemetry/TelemetryController.cs index c54e4afe..033dcf59 100644 --- a/Ogma3/Areas/Admin/Api/V1/Telemetry/TelemetryController.cs +++ b/Ogma3/Areas/Admin/Api/V1/Telemetry/TelemetryController.cs @@ -10,16 +10,13 @@ namespace Ogma3.Areas.Admin.Api.V1.Telemetry; [Route("admin/api/[controller]", Name = nameof(TelemetryController))] [ApiController] [Authorize] -public class TelemetryController : ControllerBase +public class TelemetryController(IMediator mediator) : ControllerBase { - private readonly IMediator _mediator; - public TelemetryController(IMediator mediator) => _mediator = mediator; - [HttpGet(nameof(GetTableInfo))] public async Task>> GetTableInfo() - => await _mediator.Send(new GetTableInfo.Query()); + => await mediator.Send(new GetTableInfo.Query()); [HttpGet(nameof(GetImportantItemCounts))] public async Task>> GetImportantItemCounts() - => await _mediator.Send(new GetImportantItemCounts.Query()); + => await mediator.Send(new GetImportantItemCounts.Query()); } \ No newline at end of file diff --git a/Ogma3/Areas/Admin/Pages/Infractions.cshtml b/Ogma3/Areas/Admin/Pages/Infractions.cshtml index 8819593a..03930bdc 100644 --- a/Ogma3/Areas/Admin/Pages/Infractions.cshtml +++ b/Ogma3/Areas/Admin/Pages/Infractions.cshtml @@ -19,7 +19,7 @@ @foreach (var infraction in Model.Infractions) { - @infraction.UserUserName + @infraction.UserUserName [@infraction.UserId] @infraction.Type.ToStringFast() @infraction.Reason @infraction.ActiveUntil diff --git a/Ogma3/Areas/Admin/Pages/Users.cshtml b/Ogma3/Areas/Admin/Pages/Users.cshtml index ad311e9e..9c5695de 100644 --- a/Ogma3/Areas/Admin/Pages/Users.cshtml +++ b/Ogma3/Areas/Admin/Pages/Users.cshtml @@ -1,5 +1,5 @@ @page -@using Ogma3.Api.V1.Infractions +@using Ogma3.Areas.Admin.Api.V1.Infractions @using Ogma3.Api.V1.Users @model Users diff --git a/Ogma3/Infrastructure/Constants/ModeratorActionTemplates.cs b/Ogma3/Infrastructure/Constants/ModeratorActionTemplates.cs index bbfbd8e6..7f7b69d5 100644 --- a/Ogma3/Infrastructure/Constants/ModeratorActionTemplates.cs +++ b/Ogma3/Infrastructure/Constants/ModeratorActionTemplates.cs @@ -2,6 +2,7 @@ using System.Globalization; using Humanizer; using Humanizer.Localisation; +using Ogma3.Data.Infractions; using Ogma3.Data.Users; namespace Ogma3.Infrastructure.Constants; @@ -49,4 +50,14 @@ public static string UserBan(string bannedName, string modName, string reason) public static string UserUnban(string bannedName, string modName) => $"User **{bannedName}** was unbanned by **{modName}**"; + + public static class Infractions + { + public static string Create(long userId, string modName, long infractionId, string reason, InfractionType type) + => $"User **{userId}** was given a **{type.ToStringFast()}** infraction ({infractionId}) by **{modName}** for the following reason:\n*{reason}*"; + + public static string Lift(long userId, string modName, long infractionId, InfractionType type) + => $"User **{userId}** had their **{type.ToStringFast()}** infraction ({infractionId}) lifted by **{modName}**."; + + } } \ No newline at end of file diff --git a/Ogma3/Infrastructure/Logging/Telegram.cs b/Ogma3/Infrastructure/Logging/Telegram.cs index c73c9600..ea4b106f 100644 --- a/Ogma3/Infrastructure/Logging/Telegram.cs +++ b/Ogma3/Infrastructure/Logging/Telegram.cs @@ -7,7 +7,7 @@ namespace Ogma3.Infrastructure.Logging; public static class Telegram { - public static async Task<(string Token, string Id)> GetCredentials() + public static async Task GetCredentials() { var telegramToken = Environment.GetEnvironmentVariable("TELEGRAM_TOKEN"); @@ -27,9 +27,11 @@ public static class Telegram var split = telegramToken.Split('|'); - if (split.Length >= 2) return (Token: split[0], Id: split[1]); + if (split is [string token, string id]) return new(token, id); Log.Fatal("Expected two elements of the token, {Count} found", split.Length); throw new ArgumentException($"Expected two elements of the Telegram token, {split.Length} found"); } + + public record TelegramToken(string Token, string Id); } \ No newline at end of file