From 2a963567b5655528c77ff77766acc488b27ffd0f Mon Sep 17 00:00:00 2001 From: jvyden Date: Sat, 18 Dec 2021 15:17:48 -0500 Subject: [PATCH] Add support for banning a user --- .../.idea/dataSources.xml | 2 +- .../Controllers/LoginController.cs | 2 +- .../Website/Admin/AdminSlotController.cs | 6 +- .../Website/Admin/AdminUserController.cs | 61 +++++++++++++++++++ ...0211217000749_AddBannedPropertiesToUser.cs | 41 +++++++++++++ .../Migrations/DatabaseModelSnapshot.cs | 6 ++ ProjectLighthouse/Pages/UserPage.cshtml | 22 +++++++ ProjectLighthouse/Pages/UserPage.cshtml.cs | 3 +- ProjectLighthouse/Startup.cs | 47 +++++++++----- ProjectLighthouse/Types/User.cs | 4 ++ 10 files changed, 173 insertions(+), 21 deletions(-) create mode 100644 ProjectLighthouse/Controllers/Website/Admin/AdminUserController.cs create mode 100644 ProjectLighthouse/Migrations/20211217000749_AddBannedPropertiesToUser.cs diff --git a/.idea/.idea.ProjectLighthouse/.idea/dataSources.xml b/.idea/.idea.ProjectLighthouse/.idea/dataSources.xml index 702fe04b..c8fd1969 100644 --- a/.idea/.idea.ProjectLighthouse/.idea/dataSources.xml +++ b/.idea/.idea.ProjectLighthouse/.idea/dataSources.xml @@ -8,7 +8,7 @@ jdbc:mysql://localhost:3306/lighthouse $ProjectFileDir$ - + mariadb true org.mariadb.jdbc.Driver diff --git a/ProjectLighthouse/Controllers/LoginController.cs b/ProjectLighthouse/Controllers/LoginController.cs index a8126a94..f475ecb1 100644 --- a/ProjectLighthouse/Controllers/LoginController.cs +++ b/ProjectLighthouse/Controllers/LoginController.cs @@ -52,7 +52,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers if (token == null) return this.StatusCode(403, ""); User? user = await this.database.UserFromGameToken(token, true); - if (user == null) return this.StatusCode(403, ""); + if (user == null || user.Banned) return this.StatusCode(403, ""); if (ServerSettings.Instance.UseExternalAuth) { diff --git a/ProjectLighthouse/Controllers/Website/Admin/AdminSlotController.cs b/ProjectLighthouse/Controllers/Website/Admin/AdminSlotController.cs index 70c973ef..4787f1a7 100644 --- a/ProjectLighthouse/Controllers/Website/Admin/AdminSlotController.cs +++ b/ProjectLighthouse/Controllers/Website/Admin/AdminSlotController.cs @@ -19,7 +19,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers.Website.Admin this.database = database; } - [Route("teamPick")] + [HttpGet("teamPick")] public async Task TeamPick([FromRoute] int id) { User? user = this.database.UserFromWebRequest(this.Request); @@ -35,7 +35,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers.Website.Admin return this.Ok(); } - [Route("removeTeamPick")] + [HttpGet("removeTeamPick")] public async Task RemoveTeamPick([FromRoute] int id) { User? user = this.database.UserFromWebRequest(this.Request); @@ -51,7 +51,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers.Website.Admin return this.Ok(); } - [Route("delete")] + [HttpGet("delete")] public async Task DeleteLevel([FromRoute] int id) { User? user = this.database.UserFromWebRequest(this.Request); diff --git a/ProjectLighthouse/Controllers/Website/Admin/AdminUserController.cs b/ProjectLighthouse/Controllers/Website/Admin/AdminUserController.cs new file mode 100644 index 00000000..96e74702 --- /dev/null +++ b/ProjectLighthouse/Controllers/Website/Admin/AdminUserController.cs @@ -0,0 +1,61 @@ +#nullable enable +using System.Linq; +using System.Threading.Tasks; +using LBPUnion.ProjectLighthouse.Types; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace LBPUnion.ProjectLighthouse.Controllers.Website.Admin +{ + [ApiController] + [Route("admin/user/{id:int}")] + public class AdminUserController : ControllerBase + { + private readonly Database database; + + public AdminUserController(Database database) + { + this.database = database; + } + + [HttpGet("ban")] + public async Task BanUser([FromRoute] int id) + { + User? user = this.database.UserFromWebRequest(this.Request); + if (user == null || !user.IsAdmin) return this.StatusCode(403, ""); + + User? targetedUser = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id); + ; + if (targetedUser == null) return this.NotFound(); + + targetedUser.Banned = true; + targetedUser.BannedReason = $"Banned by admin {user.Username} (id: {user.UserId})"; + + // invalidate all currently active gametokens + this.database.GameTokens.RemoveRange(this.database.GameTokens.Where(t => t.UserId == targetedUser.UserId)); + + // invalidate all currently active webtokens + this.database.WebTokens.RemoveRange(this.database.WebTokens.Where(t => t.UserId == targetedUser.UserId)); + + await this.database.SaveChangesAsync(); + return this.Redirect($"/user/{targetedUser.UserId}"); + } + + [HttpGet("unban")] + public async Task UnbanUser([FromRoute] int id) + { + User? user = this.database.UserFromWebRequest(this.Request); + if (user == null || !user.IsAdmin) return this.StatusCode(403, ""); + + User? targetedUser = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id); + ; + if (targetedUser == null) return this.NotFound(); + + targetedUser.Banned = false; + targetedUser.BannedReason = null; + + await this.database.SaveChangesAsync(); + return this.Redirect($"/user/{targetedUser.UserId}"); + } + } +} \ No newline at end of file diff --git a/ProjectLighthouse/Migrations/20211217000749_AddBannedPropertiesToUser.cs b/ProjectLighthouse/Migrations/20211217000749_AddBannedPropertiesToUser.cs new file mode 100644 index 00000000..6f2f5a64 --- /dev/null +++ b/ProjectLighthouse/Migrations/20211217000749_AddBannedPropertiesToUser.cs @@ -0,0 +1,41 @@ +using LBPUnion.ProjectLighthouse; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ProjectLighthouse.Migrations +{ + [DbContext(typeof(Database))] + [Migration("20211217000749_AddBannedPropertiesToUser")] + public partial class AddBannedPropertiesToUser : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Banned", + table: "Users", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "BannedReason", + table: "Users", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Banned", + table: "Users"); + + migrationBuilder.DropColumn( + name: "BannedReason", + table: "Users"); + } + } +} diff --git a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs index 4afc7b51..def721ba 100644 --- a/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs +++ b/ProjectLighthouse/Migrations/DatabaseModelSnapshot.cs @@ -541,6 +541,12 @@ namespace ProjectLighthouse.Migrations .ValueGeneratedOnAdd() .HasColumnType("int"); + b.Property("Banned") + .HasColumnType("tinyint(1)"); + + b.Property("BannedReason") + .HasColumnType("longtext"); + b.Property("Biography") .HasColumnType("longtext"); diff --git a/ProjectLighthouse/Pages/UserPage.cshtml b/ProjectLighthouse/Pages/UserPage.cshtml index 128a7883..a6c7a5af 100644 --- a/ProjectLighthouse/Pages/UserPage.cshtml +++ b/ProjectLighthouse/Pages/UserPage.cshtml @@ -10,12 +10,27 @@ Model.ShowTitleInPage = false; } +@if (Model.User != null && Model.User.IsAdmin && Model.ProfileUser.Banned) +{ +
+

+ User is banned! +

+

Reason: @Model.ProfileUser.BannedReason

+ + + Unban User + +
+} +

@Model.Title

@Model.ProfileUser!.Status

+
@Model.ProfileUser.Hearts @Model.ProfileUser.Comments @@ -49,6 +64,13 @@ Reset Password } + @if (Model.User != null && Model.User.IsAdmin && !Model.ProfileUser.Banned) + { + + + Ban User + + }
diff --git a/ProjectLighthouse/Pages/UserPage.cshtml.cs b/ProjectLighthouse/Pages/UserPage.cshtml.cs index 0240ab59..e903ff09 100644 --- a/ProjectLighthouse/Pages/UserPage.cshtml.cs +++ b/ProjectLighthouse/Pages/UserPage.cshtml.cs @@ -24,8 +24,9 @@ namespace LBPUnion.ProjectLighthouse.Pages public async Task OnGet([FromRoute] int userId) { + bool canViewBannedUsers = this.User != null && this.User.IsAdmin; this.ProfileUser = await this.Database.Users.FirstOrDefaultAsync(u => u.UserId == userId); - if (this.ProfileUser == null) return this.NotFound(); + if (this.ProfileUser == null || !canViewBannedUsers && this.ProfileUser.Banned) return this.NotFound(); this.Photos = await this.Database.Photos.OrderByDescending(p => p.Timestamp).Where(p => p.CreatorId == userId).Take(5).ToListAsync(); this.Comments = await this.Database.Comments.Include diff --git a/ProjectLighthouse/Startup.cs b/ProjectLighthouse/Startup.cs index fe68aea5..cecb0370 100644 --- a/ProjectLighthouse/Startup.cs +++ b/ProjectLighthouse/Startup.cs @@ -87,11 +87,34 @@ namespace LBPUnion.ProjectLighthouse Stopwatch requestStopwatch = new(); requestStopwatch.Start(); + context.Request.EnableBuffering(); // Allows us to reset the position of Request.Body for later logging + // Log all headers. // foreach (KeyValuePair header in context.Request.Headers) Logger.Log($"{header.Key}: {header.Value}"); - context.Request.EnableBuffering(); // Allows us to reset the position of Request.Body for later logging + await next(context); // Handle the request so we can get the status code from it + requestStopwatch.Stop(); + + Logger.Log + ( + $"{context.Response.StatusCode}, {requestStopwatch.ElapsedMilliseconds}ms: {context.Request.Method} {context.Request.Path}{context.Request.QueryString}", + LoggerLevelHttp.Instance + ); + + if (context.Request.Method == "POST") + { + context.Request.Body.Position = 0; + Logger.Log(await new StreamReader(context.Request.Body).ReadToEndAsync(), LoggerLevelHttp.Instance); + } + } + ); + + // Digest check + app.Use + ( + async (context, next) => + { // Client digest check. if (!context.Request.Cookies.TryGetValue("MM_AUTH", out string authCookie)) authCookie = string.Empty; string digestPath = context.Request.Path; @@ -119,7 +142,7 @@ namespace LBPUnion.ProjectLighthouse Stream oldResponseStream = context.Response.Body; context.Response.Body = responseBuffer; - await next(); // Handle the request so we can get the status code from it + await next(context); // Handle the request so we can get the server digest hash // Compute the server digest hash. if (computeDigests) @@ -138,7 +161,13 @@ namespace LBPUnion.ProjectLighthouse responseBuffer.Position = 0; await responseBuffer.CopyToAsync(oldResponseStream); context.Response.Body = oldResponseStream; + } + ); + app.Use + ( + async (context, next) => + { #nullable enable // Log LastContact for LBP1. This is done on LBP2/3/V on a Match request. if (context.Request.Path.ToString().StartsWith("/LITTLEBIGPLANETPS3_XML")) @@ -153,19 +182,7 @@ namespace LBPUnion.ProjectLighthouse } #nullable disable - requestStopwatch.Stop(); - - Logger.Log - ( - $"{context.Response.StatusCode}, {requestStopwatch.ElapsedMilliseconds}ms: {context.Request.Method} {context.Request.Path}{context.Request.QueryString}", - LoggerLevelHttp.Instance - ); - - if (context.Request.Method == "POST") - { - context.Request.Body.Position = 0; - Logger.Log(await new StreamReader(context.Request.Body).ReadToEndAsync(), LoggerLevelHttp.Instance); - } + await next(context); } ); diff --git a/ProjectLighthouse/Types/User.cs b/ProjectLighthouse/Types/User.cs index 726c706e..b941d656 100644 --- a/ProjectLighthouse/Types/User.cs +++ b/ProjectLighthouse/Types/User.cs @@ -125,6 +125,10 @@ namespace LBPUnion.ProjectLighthouse.Types } #nullable disable + public bool Banned { get; set; } + + public string BannedReason { get; set; } + public string Serialize(GameVersion gameVersion = GameVersion.LittleBigPlanet1) { string user = LbpSerializer.TaggedStringElement("npHandle", this.Username, "icon", this.IconHash) +