Add proper ban page when logging in (#773)

* Add proper ban page upon logging in

* Remove two extra line break tags that don't need to be there

* Fix timestamp formatting

* Properly display timestamps in correct timezone

* Fix formatting issues with ban page

* Remove extra parenthesis which would be rendered on-page

* Add to redirect middleware to prevent navigating to other pages

* Small nitpick, renaming UserBannedPage to BannedUserPage

* Resolve nitpicks from reviewers

* Remove un-necessary log message in LoginForm

* Fix ban reason translatable string argument

* Word choice nitpick ("Ban Created" -> "Ban Issued")

* Final adjustments and nitpicks, visual and grammatical

* Resolve requested changes from reviewers
This commit is contained in:
koko 2023-05-30 15:25:31 -04:00 committed by GitHub
commit 21dbdff20a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 203 additions and 23 deletions

View file

@ -10,7 +10,7 @@
@{
Layout = "Layouts/BaseLayout";
Model.ShowTitleInPage = false;
bool isMobile = Request.IsMobile();
string language = Model.GetLanguage();
string timeZone = Model.GetTimeZone();
@ -25,7 +25,9 @@
if (Model.PendingAuthAttempts > 0)
{
<p>
<b><a href="/authentication">@Model.Translate(LandingPageStrings.AuthAttemptsPending, Model.PendingAuthAttempts)</a></b>
<b>
<a href="/authentication">@Model.Translate(LandingPageStrings.AuthAttemptsPending, Model.PendingAuthAttempts)</a>
</b>
</p>
}
}
@ -48,13 +50,13 @@
int i = 0;
foreach (UserEntity user in Model.PlayersOnline)
{
i++;
i++;
@await user.ToLink(Html, ViewData, language, timeZone, true)
@* whitespace has forced my hand *@
if (i != Model.PlayersOnline.Count)
{
<span>,</span>
}
}
}
}
@ -63,7 +65,9 @@
<div class="@(isMobile ? "" : "ui center aligned grid")">
<div class="eight wide column">
<div class="ui inverted pink segment">
<h1><i class="star icon"></i>@Model.Translate(LandingPageStrings.LatestTeamPicks)</h1>
<h1>
<i class="star icon"></i>@Model.Translate(LandingPageStrings.LatestTeamPicks)
</h1>
<div class="ui divider"></div>
<div class="ui left aligned segment">
@foreach (SlotEntity slot in Model.LatestTeamPicks!) @* Can't reach a point where this is null *@
@ -80,7 +84,9 @@
}
<div class="eight wide column">
<div class="ui inverted blue segment">
<h1><i class="globe americas icon"></i>@Model.Translate(LandingPageStrings.NewestLevels)</h1>
<h1>
<i class="globe americas icon"></i>@Model.Translate(LandingPageStrings.NewestLevels)
</h1>
<div class="ui divider"></div>
<div class="ui left aligned segment">
@foreach (SlotEntity slot in Model.NewestLevels!) @* Can't reach a point where this is null *@

View file

@ -13,14 +13,14 @@ namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages;
public class LandingPage : BaseLayout
{
public LandingPage(DatabaseContext database) : base(database)
{}
public List<SlotEntity>? LatestTeamPicks;
public List<SlotEntity>? NewestLevels;
public int PendingAuthAttempts;
public List<UserEntity> PlayersOnline = new();
public List<SlotEntity>? LatestTeamPicks;
public List<SlotEntity>? NewestLevels;
public LandingPage(DatabaseContext database) : base(database)
{ }
[UsedImplicitly]
public async Task<IActionResult> OnGet()
@ -29,10 +29,12 @@ public class LandingPage : BaseLayout
if (user != null && user.PasswordResetRequired) return this.Redirect("~/passwordResetRequired");
if (user != null)
this.PendingAuthAttempts = await this.Database.PlatformLinkAttempts
.CountAsync(l => l.UserId == user.UserId);
this.PendingAuthAttempts =
await this.Database.PlatformLinkAttempts.CountAsync(l => l.UserId == user.UserId);
List<int> userIds = await this.Database.LastContacts.Where(l => TimeHelper.Timestamp - l.Timestamp < 300).Select(l => l.UserId).ToListAsync();
List<int> userIds = await this.Database.LastContacts.Where(l => TimeHelper.Timestamp - l.Timestamp < 300)
.Select(l => l.UserId)
.ToListAsync();
this.PlayersOnline = await this.Database.Users.Where(u => userIds.Contains(u.UserId)).ToListAsync();

View file

@ -0,0 +1,48 @@
@page "/banned"
@using LBPUnion.ProjectLighthouse.Configuration
@using LBPUnion.ProjectLighthouse.Localization.StringLists
@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login.BannedUserPage
@{
Layout = "Layouts/BaseLayout";
Model.Title = Model.Translate(ModerationStrings.SuspensionHeading);
string timeZone = (string?)ViewData["TimeZone"] ?? TimeZoneInfo.Local.Id;
TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
}
<div class="ui middle aligned left aligned">
<h1>@Model.Translate(ModerationStrings.SuspensionHeading)</h1>
<p>
@Model.Translate(ModerationStrings.SuspensionExplanation, ServerConfiguration.Instance.Customization.ServerName)
</p>
<p>
<span>
@if (Model.ModCase.ExpiresAt != null)
{
@Model.Translate(ModerationStrings.SuspensionExpiration, TimeZoneInfo.ConvertTime(Model.ModCase.ExpiresAt.Value, timeZoneInfo).ToString("M/d/yyyy @ h:mm tt"))
}
else
{
@Model.Translate(ModerationStrings.SuspensionExpiration, Model.Translate(ModerationStrings.DoesNotExpire))
}
</span>
<ul>
<li>@Model.Translate(ModerationStrings.LbpOnlineMultiplayer)</li>
<li>@Model.Translate(ModerationStrings.WebsiteInteractions)</li>
<li>@Model.Translate(ModerationStrings.ProfileVisibility)</li>
<li>@Model.Translate(ModerationStrings.AccountProfileManagement)</li>
</ul>
</p>
<p>
@Model.Translate(ModerationStrings.SuspensionReason, Model.ModCase.Reason)
</p>
<p>
@Model.Translate(ModerationStrings.SuspensionCircumventWarning)
</p>
</div>

View file

@ -0,0 +1,36 @@
using JetBrains.Annotations;
using LBPUnion.ProjectLighthouse.Database;
using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts;
using LBPUnion.ProjectLighthouse.Types.Entities.Moderation;
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
using LBPUnion.ProjectLighthouse.Types.Moderation.Cases;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login;
public class BannedUserPage : BaseLayout
{
public BannedUserPage(DatabaseContext database) : base(database)
{ }
public ModerationCaseEntity ModCase = null!;
[UsedImplicitly]
public async Task<IActionResult> OnGet()
{
UserEntity? user = this.Database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
if (!user.IsBanned) return this.Redirect("~/");
ModerationCaseEntity? modCase = await this.Database.Cases
.FirstOrDefaultAsync(c => c.AffectedId == user.UserId && c.Type == CaseType.UserBan);
if (modCase == null) return this.Redirect("~/");
this.ModCase = modCase;
return this.Page();
}
}

View file

@ -83,13 +83,6 @@ public class LoginForm : BaseLayout
return this.Page();
}
if (user.IsBanned)
{
Logger.Warn($"User {user.Username} (id: {user.UserId}) failed to login on web due to being banned", LogArea.Login);
this.Error = this.Translate(ErrorStrings.UserIsBanned, user.BannedReason);
return this.Page();
}
WebTokenEntity webToken = new()
{
UserId = user.UserId,
@ -120,6 +113,11 @@ public class LoginForm : BaseLayout
: this.Redirect("~/2fa" + "?redirect=" + HttpUtility.UrlEncode(redirect));
}
if (user.IsBanned)
{
return this.Redirect("~/banned");
}
if (user.PasswordResetRequired) return this.Redirect("~/passwordResetRequired");
return ServerConfiguration.Instance.Mail.MailEnabled switch

View file

@ -23,18 +23,18 @@
@if (Model.ProfileUser.IsBanned)
{
<div class="ui inverted red segment">
<h3 style="margin-bottom:3px;"><i class="ban icon"></i> This user is currently banned.</h3>
<h3 style="margin-bottom:5px;"><i class="ban icon"></i> This user is currently banned.</h3>
@if (Model.User != null && Model.User.IsModerator)
{
<b>Reason:</b>
<span>"@Model.ProfileUser.BannedReason"</span>
<span>"@Model.ProfileUser.BannedReason"</span> <br />
<p>
<i>Only you and other moderators may view the ban reason.</i>
</p>
}
else
{
<p>Users who engage in inappropriate, offensive, or violent actions will be moderated. Be sure to follow the rules!</p>
<p>This user has been banned for violating the Terms of Service. Remember to follow the rules!</p>
}
</div>
}