mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-07-24 14:11:29 +00:00
Merge pull request #111 from LBPUnion/account-banning
Add ability to ban accounts
This commit is contained in:
commit
da0732d358
17 changed files with 241 additions and 26 deletions
|
@ -8,7 +8,7 @@
|
|||
<jdbc-url>jdbc:mysql://localhost:3306/lighthouse</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
<data-source source="LOCAL" name="Lighthouse Production" uuid="b323608d-d984-40d0-942e-2c2ea35006d8">
|
||||
<data-source source="LOCAL" name="Lighthouse Production" read-only="true" uuid="b323608d-d984-40d0-942e-2c2ea35006d8">
|
||||
<driver-ref>mariadb</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
|
||||
|
|
|
@ -73,7 +73,8 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
|||
}
|
||||
|
||||
User? user = await this.database.UserFromGameToken(token, true);
|
||||
if (user == null)
|
||||
|
||||
if (user == null || user.Banned)
|
||||
{
|
||||
Logger.Log("unable to find a user from a token, rejecting login", LoggerLevelLogin.Instance);
|
||||
return this.StatusCode(403, "");
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers.Website.Admin
|
|||
this.database = database;
|
||||
}
|
||||
|
||||
[Route("teamPick")]
|
||||
[HttpGet("teamPick")]
|
||||
public async Task<IActionResult> 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<IActionResult> 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<IActionResult> DeleteLevel([FromRoute] int id)
|
||||
{
|
||||
User? user = this.database.UserFromWebRequest(this.Request);
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#nullable enable
|
||||
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("unban")]
|
||||
public async Task<IActionResult> UnbanUser([FromRoute] int id)
|
||||
{
|
||||
User? user = this.database.UserFromWebRequest(this.Request);
|
||||
if (user == null || !user.IsAdmin) return this.NotFound();
|
||||
|
||||
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}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,11 +11,11 @@ namespace LBPUnion.ProjectLighthouse.Maintenance.Commands
|
|||
public class DeleteUserCommand : ICommand
|
||||
{
|
||||
private readonly Database database = new();
|
||||
public string Name() => "Delete/Ban User";
|
||||
public string Name() => "Delete User";
|
||||
public string[] Aliases()
|
||||
=> new[]
|
||||
{
|
||||
"deleteUser", "wipeUser", "banUser",
|
||||
"deleteUser", "wipeUser",
|
||||
};
|
||||
public string Arguments() => "<username/userId>";
|
||||
public int RequiredArgs() => 1;
|
||||
|
|
|
@ -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<bool>(
|
||||
name: "Banned",
|
||||
table: "Users",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -546,6 +546,12 @@ namespace ProjectLighthouse.Migrations
|
|||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("Banned")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<string>("BannedReason")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("Biography")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
|
|
20
ProjectLighthouse/Pages/Admin/AdminBanUserPage.cshtml
Normal file
20
ProjectLighthouse/Pages/Admin/AdminBanUserPage.cshtml
Normal file
|
@ -0,0 +1,20 @@
|
|||
@page "/admin/user/{id:int}/ban"
|
||||
@model LBPUnion.ProjectLighthouse.Pages.Admin.AdminBanUserPage
|
||||
|
||||
@{
|
||||
Layout = "Layouts/BaseLayout";
|
||||
Model.Title = "Ban " + Model.TargetedUser!.Username + "?";
|
||||
}
|
||||
|
||||
<p>Are you sure you want to ban this user?</p>
|
||||
|
||||
<form method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
|
||||
<div class="ui left labeled input">
|
||||
<label for="text" class="ui blue label">Reason: </label>
|
||||
<input type="text" name="reason" id="text">
|
||||
</div><br><br>
|
||||
|
||||
<input type="submit" value="Yes, ban @Model.TargetedUser.Username!" id="submit" class="ui red button"><br>
|
||||
</form>
|
49
ProjectLighthouse/Pages/Admin/AdminBanUserPage.cshtml.cs
Normal file
49
ProjectLighthouse/Pages/Admin/AdminBanUserPage.cshtml.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
#nullable enable
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Pages.Layouts;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Pages.Admin;
|
||||
|
||||
public class AdminBanUserPage : BaseLayout
|
||||
{
|
||||
public AdminBanUserPage(Database database) : base(database)
|
||||
{}
|
||||
|
||||
public User? TargetedUser;
|
||||
|
||||
public async Task<IActionResult> OnGet([FromRoute] int id)
|
||||
{
|
||||
User? user = this.Database.UserFromWebRequest(this.Request);
|
||||
if (user == null || !user.IsAdmin) return this.NotFound();
|
||||
|
||||
this.TargetedUser = await this.Database.Users.FirstOrDefaultAsync(u => u.UserId == id);
|
||||
if (this.TargetedUser == null) return this.NotFound();
|
||||
|
||||
return this.Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPost([FromRoute] int id, string reason)
|
||||
{
|
||||
User? user = this.Database.UserFromWebRequest(this.Request);
|
||||
if (user == null || !user.IsAdmin) return this.NotFound();
|
||||
|
||||
this.TargetedUser = await this.Database.Users.FirstOrDefaultAsync(u => u.UserId == id);
|
||||
if (this.TargetedUser == null) return this.NotFound();
|
||||
|
||||
this.TargetedUser.Banned = true;
|
||||
this.TargetedUser.BannedReason = reason;
|
||||
|
||||
// invalidate all currently active gametokens
|
||||
this.Database.GameTokens.RemoveRange(this.Database.GameTokens.Where(t => t.UserId == this.TargetedUser.UserId));
|
||||
|
||||
// invalidate all currently active webtokens
|
||||
this.Database.WebTokens.RemoveRange(this.Database.WebTokens.Where(t => t.UserId == this.TargetedUser.UserId));
|
||||
|
||||
await this.Database.SaveChangesAsync();
|
||||
return this.Redirect($"/user/{this.TargetedUser.UserId}");
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
@page "/admin"
|
||||
@using LBPUnion.ProjectLighthouse.Helpers
|
||||
@using LBPUnion.ProjectLighthouse.Maintenance
|
||||
@model LBPUnion.ProjectLighthouse.Pages.AdminPanelPage
|
||||
@model LBPUnion.ProjectLighthouse.Pages.Admin.AdminPanelPage
|
||||
|
||||
@{
|
||||
Layout = "Layouts/BaseLayout";
|
|
@ -7,7 +7,7 @@ using LBPUnion.ProjectLighthouse.Pages.Layouts;
|
|||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Pages
|
||||
namespace LBPUnion.ProjectLighthouse.Pages.Admin
|
||||
{
|
||||
public class AdminPanelPage : BaseLayout
|
||||
{
|
|
@ -24,7 +24,7 @@
|
|||
<div class="header">
|
||||
Uh oh!
|
||||
</div>
|
||||
<p>@Model.Error</p>
|
||||
<p style="white-space: pre-line">@Model.Error</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kettu;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Logging;
|
||||
using LBPUnion.ProjectLighthouse.Pages.Layouts;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
@ -36,16 +38,25 @@ namespace LBPUnion.ProjectLighthouse.Pages
|
|||
User? user = await this.Database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
||||
if (user == null)
|
||||
{
|
||||
Logger.Log($"User {username} failed to login on web due to invalid username", LoggerLevelLogin.Instance);
|
||||
this.Error = "The username or password you entered is invalid.";
|
||||
return this.Page();
|
||||
}
|
||||
|
||||
if (!BCrypt.Net.BCrypt.Verify(password, user.Password))
|
||||
{
|
||||
Logger.Log($"User {user.Username} (id: {user.UserId}) failed to login on web due to invalid password", LoggerLevelLogin.Instance);
|
||||
this.Error = "The username or password you entered is invalid.";
|
||||
return this.Page();
|
||||
}
|
||||
|
||||
if (user.Banned)
|
||||
{
|
||||
Logger.Log($"User {user.Username} (id: {user.UserId}) failed to login on web due to being banned", LoggerLevelLogin.Instance);
|
||||
this.Error = "You have been banned. Please contact an administrator for more information.\nReason: " + user.BannedReason;
|
||||
return this.Page();
|
||||
}
|
||||
|
||||
WebToken webToken = new()
|
||||
{
|
||||
UserId = user.UserId,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
Model.Title = "Password Reset Required";
|
||||
}
|
||||
|
||||
<p>An admin has deemed it necessary that you reset your password. Please do so.</p>
|
||||
<p>An administrator has deemed it necessary that you reset your password. Please do so.</p>
|
||||
|
||||
<a href="/passwordReset">
|
||||
<div class="ui blue button">Reset Password</div>
|
||||
|
|
|
@ -14,12 +14,34 @@
|
|||
Model.Description = Model.ProfileUser!.Biography;
|
||||
}
|
||||
|
||||
@if (Model.ProfileUser.Banned)
|
||||
{
|
||||
<div class="ui inverted red segment">
|
||||
<p>
|
||||
<b>User is currently banned!</b>
|
||||
</p>
|
||||
@if (Model.User != null && Model.User.IsAdmin)
|
||||
{
|
||||
<p>Reason: @Model.ProfileUser.BannedReason</p>
|
||||
<a class="ui inverted button" href="/admin/user/@Model.ProfileUser.UserId/unban">
|
||||
<i class="ban icon"></i>
|
||||
<span>Unban User</span>
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>For shame...</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="ui grid">
|
||||
<div class="eight wide column">
|
||||
<h1>@Model.Title</h1>
|
||||
<p>
|
||||
<i>@Model.ProfileUser!.Status</i>
|
||||
</p>
|
||||
|
||||
<div class="statsUnderTitle">
|
||||
<i class="pink heart icon" title="Hearts"></i> <span>@Model.ProfileUser.Hearts</span>
|
||||
<i class="blue comment icon" title="Comments"></i> <span>@Model.ProfileUser.Comments</span>
|
||||
|
@ -53,6 +75,13 @@
|
|||
<span>Reset Password</span>
|
||||
</a>
|
||||
}
|
||||
@if (Model.User != null && Model.User.IsAdmin && !Model.ProfileUser.Banned)
|
||||
{
|
||||
<a class="ui red button" href="/admin/user/@Model.ProfileUser.UserId/ban">
|
||||
<i class="ban icon"></i>
|
||||
<span>Ban User</span>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
<div class="eight wide column">
|
||||
<div class="ui blue segment">
|
||||
|
|
|
@ -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<string, StringValues> 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);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -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) +
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue