mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-07-23 13:41:31 +00:00
Merge branch 'main' into account-banning
This commit is contained in:
commit
d7e48c41c7
17 changed files with 444 additions and 45 deletions
|
@ -43,41 +43,59 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
|||
}
|
||||
if (loginData == null) return this.BadRequest();
|
||||
|
||||
IPAddress? ipAddress = this.HttpContext.Connection.RemoteIpAddress;
|
||||
if (ipAddress == null) return this.StatusCode(403, ""); // 403 probably isnt the best status code for this, but whatever
|
||||
IPAddress? remoteIpAddress = this.HttpContext.Connection.RemoteIpAddress;
|
||||
if (remoteIpAddress == null) return this.StatusCode(403, ""); // 403 probably isnt the best status code for this, but whatever
|
||||
|
||||
string userLocation = ipAddress.ToString();
|
||||
string ipAddress = remoteIpAddress.ToString();
|
||||
|
||||
GameToken? token = await this.database.AuthenticateUser(loginData, userLocation, titleId);
|
||||
if (token == null) return this.StatusCode(403, "");
|
||||
// Get an existing token from the IP & username
|
||||
GameToken? token = await this.database.GameTokens.Include
|
||||
(t => t.User)
|
||||
.FirstOrDefaultAsync(t => t.UserLocation == ipAddress && t.User.Username == loginData.Username && !t.Used);
|
||||
|
||||
if (token == null) // If we cant find an existing token, try to generate a new one
|
||||
{
|
||||
token = await this.database.AuthenticateUser(loginData, ipAddress, titleId);
|
||||
if (token == null) return this.StatusCode(403, ""); // If not, then 403.
|
||||
}
|
||||
|
||||
User? user = await this.database.UserFromGameToken(token, true);
|
||||
if (user == null || user.Banned) return this.StatusCode(403, "");
|
||||
|
||||
if (ServerSettings.Instance.UseExternalAuth)
|
||||
{
|
||||
string ipAddressAndName = $"{token.UserLocation}|{user.Username}";
|
||||
if (DeniedAuthenticationHelper.RecentlyDenied(ipAddressAndName) || DeniedAuthenticationHelper.GetAttempts(ipAddressAndName) > 3)
|
||||
if (ServerSettings.Instance.BlockDeniedUsers)
|
||||
{
|
||||
this.database.AuthenticationAttempts.RemoveRange
|
||||
(this.database.AuthenticationAttempts.Include(a => a.GameToken).Where(a => a.GameToken.UserId == user.UserId));
|
||||
string ipAddressAndName = $"{token.UserLocation}|{user.Username}";
|
||||
if (DeniedAuthenticationHelper.RecentlyDenied(ipAddressAndName) || DeniedAuthenticationHelper.GetAttempts(ipAddressAndName) > 3)
|
||||
{
|
||||
this.database.AuthenticationAttempts.RemoveRange
|
||||
(this.database.AuthenticationAttempts.Include(a => a.GameToken).Where(a => a.GameToken.UserId == user.UserId));
|
||||
|
||||
DeniedAuthenticationHelper.AddAttempt(ipAddressAndName);
|
||||
DeniedAuthenticationHelper.AddAttempt(ipAddressAndName);
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
return this.StatusCode(403, "");
|
||||
await this.database.SaveChangesAsync();
|
||||
return this.StatusCode(403, "");
|
||||
}
|
||||
}
|
||||
|
||||
AuthenticationAttempt authAttempt = new()
|
||||
if (this.database.UserApprovedIpAddresses.Where(a => a.UserId == user.UserId).Select(a => a.IpAddress).Contains(ipAddress))
|
||||
{
|
||||
GameToken = token,
|
||||
GameTokenId = token.TokenId,
|
||||
Timestamp = TimestampHelper.Timestamp,
|
||||
IPAddress = userLocation,
|
||||
Platform = token.GameVersion == GameVersion.LittleBigPlanetVita ? Platform.Vita : Platform.PS3, // TODO: properly identify RPCS3
|
||||
};
|
||||
token.Approved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationAttempt authAttempt = new()
|
||||
{
|
||||
GameToken = token,
|
||||
GameTokenId = token.TokenId,
|
||||
Timestamp = TimestampHelper.Timestamp,
|
||||
IPAddress = ipAddress,
|
||||
Platform = token.GameVersion == GameVersion.LittleBigPlanetVita ? Platform.Vita : Platform.PS3, // TODO: properly identify RPCS3
|
||||
};
|
||||
|
||||
this.database.AuthenticationAttempts.Add(authAttempt);
|
||||
this.database.AuthenticationAttempts.Add(authAttempt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -86,9 +104,18 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
|||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
||||
Logger.Log($"Successfully logged in user {user.Username} as {token.GameVersion} client ({titleId})", LoggerLevelLogin.Instance);
|
||||
if (!token.Approved) return this.StatusCode(403, "");
|
||||
|
||||
// Create a new room on LBP2+/Vita
|
||||
Logger.Log($"Successfully logged in user {user.Username} as {token.GameVersion} client ({titleId})", LoggerLevelLogin.Instance);
|
||||
// After this point we are now considering this session as logged in.
|
||||
|
||||
// We just logged in with the token. Mark it as used so someone else doesnt try to use it,
|
||||
// and so we don't pick the same token up when logging in later.
|
||||
token.Used = true;
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
||||
// Create a new room on LBP2/3/Vita
|
||||
if (token.GameVersion != GameVersion.LittleBigPlanet1) RoomHelper.CreateRoom(user);
|
||||
|
||||
return this.Ok
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#nullable enable
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Kettu;
|
||||
|
@ -22,25 +23,44 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
|||
}
|
||||
|
||||
[HttpGet("eula")]
|
||||
public IActionResult Eula() => this.Ok(ServerSettings.Instance.EulaText + "\n" + $"{EulaHelper.License}\n");
|
||||
public async Task<IActionResult> Eula()
|
||||
{
|
||||
User? user = await this.database.UserFromGameRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
return this.Ok(ServerSettings.Instance.EulaText + "\n" + $"{EulaHelper.License}\n");
|
||||
}
|
||||
|
||||
[HttpGet("announce")]
|
||||
public async Task<IActionResult> Announce()
|
||||
{
|
||||
User user = await this.database.UserFromGameRequest(this.Request, true);
|
||||
#if !DEBUG
|
||||
User? user = await this.database.UserFromGameRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
#else
|
||||
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
|
||||
|
||||
if (ServerSettings.Instance.UseExternalAuth)
|
||||
return this.Ok
|
||||
(
|
||||
"Please stay on this screen.\n" +
|
||||
$"Before continuing, you must approve this session at {ServerSettings.Instance.ExternalUrl}.\n" +
|
||||
"Please keep in mind that if the session is denied you may have to wait up to 5-10 minutes to try logging in again.\n" +
|
||||
"Once approved, you may press X and continue.\n\n" +
|
||||
ServerSettings.Instance.EulaText
|
||||
);
|
||||
if (userAndToken == null) return this.StatusCode(403, "");
|
||||
|
||||
return this.Ok($"You are now logged in as {user.Username} (id: {user.UserId}).\n\n" + ServerSettings.Instance.EulaText);
|
||||
// ReSharper disable once PossibleInvalidOperationException
|
||||
User user = userAndToken.Value.Item1;
|
||||
GameToken gameToken = userAndToken.Value.Item2;
|
||||
#endif
|
||||
|
||||
return this.Ok
|
||||
(
|
||||
$"You are now logged in as {user.Username}.\n\n" +
|
||||
#if DEBUG
|
||||
"---DEBUG INFO---\n" +
|
||||
$"user.UserId: {user.UserId}\n" +
|
||||
$"token.Approved: {gameToken.Approved}\n" +
|
||||
$"token.Used: {gameToken.Used}\n" +
|
||||
$"token.UserLocation: {gameToken.UserLocation}\n" +
|
||||
$"token.GameVersion: {gameToken.GameVersion}\n" +
|
||||
"---DEBUG INFO---\n\n" +
|
||||
#endif
|
||||
ServerSettings.Instance.EulaText
|
||||
);
|
||||
}
|
||||
|
||||
[HttpGet("notification")]
|
||||
|
@ -52,7 +72,7 @@ namespace LBPUnion.ProjectLighthouse.Controllers
|
|||
[HttpPost("filter")]
|
||||
public async Task<IActionResult> Filter()
|
||||
{
|
||||
User user = await this.database.UserFromGameRequest(this.Request);
|
||||
User? user = await this.database.UserFromGameRequest(this.Request);
|
||||
if (user == null) return this.StatusCode(403, "");
|
||||
|
||||
string loggedText = await new StreamReader(this.Request.Body).ReadToEndAsync();
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Controllers.Website.ExternalAuth
|
||||
{
|
||||
[ApiController]
|
||||
[Route("/authentication")]
|
||||
public class AutoApprovalController : ControllerBase
|
||||
{
|
||||
private readonly Database database;
|
||||
|
||||
public AutoApprovalController(Database database)
|
||||
{
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
[HttpGet("autoApprove/{id:int}")]
|
||||
public async Task<IActionResult> AutoApprove([FromRoute] int id)
|
||||
{
|
||||
User? user = this.database.UserFromWebRequest(this.Request);
|
||||
if (user == null) return this.Redirect("/login");
|
||||
|
||||
AuthenticationAttempt? authAttempt = await this.database.AuthenticationAttempts.Include
|
||||
(a => a.GameToken)
|
||||
.FirstOrDefaultAsync(a => a.AuthenticationAttemptId == id);
|
||||
|
||||
if (authAttempt == null) return this.BadRequest();
|
||||
if (authAttempt.GameToken.UserId != user.UserId) return this.Redirect("/login");
|
||||
|
||||
authAttempt.GameToken.Approved = true;
|
||||
|
||||
UserApprovedIpAddress approvedIpAddress = new()
|
||||
{
|
||||
UserId = user.UserId,
|
||||
User = user,
|
||||
IpAddress = authAttempt.IPAddress,
|
||||
};
|
||||
|
||||
this.database.UserApprovedIpAddresses.Add(approvedIpAddress);
|
||||
this.database.AuthenticationAttempts.Remove(authAttempt);
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
||||
return this.Redirect("/authentication");
|
||||
}
|
||||
|
||||
[HttpGet("revokeAutoApproval/{id:int}")]
|
||||
public async Task<IActionResult> RevokeAutoApproval([FromRoute] int id)
|
||||
{
|
||||
User? user = this.database.UserFromWebRequest(this.Request);
|
||||
if (user == null) return this.Redirect("/login");
|
||||
|
||||
UserApprovedIpAddress? approvedIpAddress = await this.database.UserApprovedIpAddresses.FirstOrDefaultAsync(a => a.UserApprovedIpAddressId == id);
|
||||
if (approvedIpAddress == null) return this.BadRequest();
|
||||
if (approvedIpAddress.UserId != user.UserId) return this.Redirect("/login");
|
||||
|
||||
this.database.UserApprovedIpAddresses.Remove(approvedIpAddress);
|
||||
|
||||
await this.database.SaveChangesAsync();
|
||||
|
||||
return this.Redirect("/authentication/autoApprovals");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ namespace LBPUnion.ProjectLighthouse
|
|||
public DbSet<AuthenticationAttempt> AuthenticationAttempts { get; set; }
|
||||
public DbSet<Review> Reviews { get; set; }
|
||||
public DbSet<RatedReview> RatedReviews { get; set; }
|
||||
public DbSet<UserApprovedIpAddress> UserApprovedIpAddresses { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||
=> options.UseMySql(ServerSettings.Instance.DbConnectionString, MySqlServerVersion.LatestSupportedServerVersion);
|
||||
|
@ -66,7 +67,6 @@ namespace LBPUnion.ProjectLighthouse
|
|||
#nullable enable
|
||||
public async Task<GameToken?> AuthenticateUser(LoginData loginData, string userLocation, string titleId = "")
|
||||
{
|
||||
// TODO: don't use psn name to authenticate
|
||||
User? user = await this.Users.FirstOrDefaultAsync(u => u.Username == loginData.Username);
|
||||
if (user == null) return null;
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
using LBPUnion.ProjectLighthouse;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ProjectLighthouse.Migrations
|
||||
{
|
||||
[DbContext(typeof(Database))]
|
||||
[Migration("20211213195540_AddUserApprovedIpAddresses")]
|
||||
public partial class AddUserApprovedIpAddresses : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "UserApprovedIpAddresses",
|
||||
columns: table => new
|
||||
{
|
||||
UserApprovedIpAddressId = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
UserId = table.Column<int>(type: "int", nullable: false),
|
||||
IpAddress = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_UserApprovedIpAddresses", x => x.UserApprovedIpAddressId);
|
||||
table.ForeignKey(
|
||||
name: "FK_UserApprovedIpAddresses_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserApprovedIpAddresses_UserId",
|
||||
table: "UserApprovedIpAddresses",
|
||||
column: "UserId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "UserApprovedIpAddresses");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using LBPUnion.ProjectLighthouse;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ProjectLighthouse.Migrations
|
||||
{
|
||||
[DbContext(typeof(Database))]
|
||||
[Migration("20211214005427_AddUsedBoolToGameToken")]
|
||||
public partial class AddUsedBoolToGameToken : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// Incompatible with old tokens
|
||||
migrationBuilder.Sql("DELETE FROM AuthenticationAttempts");
|
||||
migrationBuilder.Sql("DELETE FROM GameTokens");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "Used",
|
||||
table: "GameTokens",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GameTokens_UserId",
|
||||
table: "GameTokens",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GameTokens_Users_UserId",
|
||||
table: "GameTokens",
|
||||
column: "UserId",
|
||||
principalTable: "Users",
|
||||
principalColumn: "UserId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GameTokens_Users_UserId",
|
||||
table: "GameTokens");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_GameTokens_UserId",
|
||||
table: "GameTokens");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Used",
|
||||
table: "GameTokens");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,6 +55,9 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Property<int>("GameVersion")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("Used")
|
||||
.HasColumnType("tinyint(1)");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
|
@ -66,6 +69,8 @@ namespace ProjectLighthouse.Migrations
|
|||
|
||||
b.HasKey("TokenId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("GameTokens");
|
||||
});
|
||||
|
||||
|
@ -593,6 +598,25 @@ namespace ProjectLighthouse.Migrations
|
|||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.UserApprovedIpAddress", b =>
|
||||
{
|
||||
b.Property<int>("UserApprovedIpAddressId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("IpAddress")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.HasKey("UserApprovedIpAddressId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UserApprovedIpAddresses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.WebToken", b =>
|
||||
{
|
||||
b.Property<int>("TokenId")
|
||||
|
@ -621,6 +645,17 @@ namespace ProjectLighthouse.Migrations
|
|||
b.Navigation("GameToken");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.GameToken", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.HeartedProfile", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "HeartedUser")
|
||||
|
@ -835,6 +870,17 @@ namespace ProjectLighthouse.Migrations
|
|||
|
||||
b.Navigation("Location");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.UserApprovedIpAddress", b =>
|
||||
{
|
||||
b.HasOne("LBPUnion.ProjectLighthouse.Types.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
@{
|
||||
Layout = "Layouts/BaseLayout";
|
||||
Model.Title = "Authentication";
|
||||
}
|
||||
<h1>Authentication</h1>
|
||||
|
||||
@if (Model.AuthenticationAttempts.Count == 0)
|
||||
{
|
||||
|
@ -14,22 +14,48 @@
|
|||
else
|
||||
{
|
||||
<p>You have @Model.AuthenticationAttempts.Count authentication attempts pending.</p>
|
||||
<a href="/authentication/denyAll">
|
||||
<button class="ui small red button">Deny all</button>
|
||||
</a>
|
||||
@if (Model.IpAddress != null)
|
||||
{
|
||||
<p>This device's IP address is <b>@(Model.IpAddress.ToString())</b>. If this matches with an authentication attempt below, then it's safe to assume the authentication attempt came from the same network as this device.</p>
|
||||
}
|
||||
}
|
||||
|
||||
<a href="/authentication/autoApprovals">
|
||||
<button class="ui small blue button">
|
||||
<i class="cog icon"></i>
|
||||
<span>Manage automatically approved IP addresses</span>
|
||||
</button>
|
||||
</a>
|
||||
<a href="/authentication/denyAll">
|
||||
<button class="ui small red button">
|
||||
<i class="x icon"></i>
|
||||
<span>Deny all</span>
|
||||
</button>
|
||||
</a>
|
||||
|
||||
@foreach (AuthenticationAttempt authAttempt in Model.AuthenticationAttempts)
|
||||
{
|
||||
DateTimeOffset timestamp = DateTimeOffset.FromUnixTimeSeconds(authAttempt.Timestamp);
|
||||
<div class="ui red segment">
|
||||
<p>A <b>@authAttempt.Platform</b> authentication request was logged at <b>@timestamp.ToString("MM/dd/yyyy @ h:mm tt") UTC</b> from the IP address <b>@authAttempt.IPAddress</b>.</p>
|
||||
<div>
|
||||
<a href="/authentication/autoApprove/@authAttempt.AuthenticationAttemptId">
|
||||
<button class="ui tiny green button">
|
||||
<i class="check icon"></i>
|
||||
<span>Automatically approve every time</span>
|
||||
</button>
|
||||
</a>
|
||||
<a href="/authentication/approve/@authAttempt.AuthenticationAttemptId">
|
||||
<button class="ui tiny green button">Approve</button>
|
||||
<button class="ui tiny yellow button">
|
||||
<i class="check icon"></i>
|
||||
<span>Approve this time</span>
|
||||
</button>
|
||||
</a>
|
||||
<a href="/authentication/deny/@authAttempt.AuthenticationAttemptId">
|
||||
<button class="ui tiny red button">Deny</button>
|
||||
<button class="ui tiny red button">
|
||||
<i class="x icon"></i>
|
||||
<span>Deny</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Pages.Layouts;
|
||||
using LBPUnion.ProjectLighthouse.Types;
|
||||
|
@ -13,12 +15,17 @@ namespace LBPUnion.ProjectLighthouse.Pages.ExternalAuth
|
|||
{
|
||||
|
||||
public List<AuthenticationAttempt> AuthenticationAttempts;
|
||||
|
||||
public IPAddress? IpAddress;
|
||||
public AuthenticationPage(Database database) : base(database)
|
||||
{}
|
||||
|
||||
public async Task<IActionResult> OnGet()
|
||||
{
|
||||
if (!ServerSettings.Instance.UseExternalAuth) return this.NotFound();
|
||||
if (this.User == null) return this.StatusCode(403, "");
|
||||
|
||||
this.IpAddress = this.HttpContext.Connection.RemoteIpAddress;
|
||||
|
||||
this.AuthenticationAttempts = this.Database.AuthenticationAttempts.Include
|
||||
(a => a.GameToken)
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
@page "/authentication/autoApprovals"
|
||||
@using LBPUnion.ProjectLighthouse.Types
|
||||
@model LBPUnion.ProjectLighthouse.Pages.ExternalAuth.ManageUserApprovedIpAddressesPage
|
||||
|
||||
@{
|
||||
Layout = "Layouts/BaseLayout";
|
||||
Model.Title = "Automatically approved IP addresses";
|
||||
}
|
||||
|
||||
|
||||
@foreach (UserApprovedIpAddress approvedIpAddress in Model.ApprovedIpAddresses)
|
||||
{
|
||||
<div class="ui blue segment">
|
||||
<p>@approvedIpAddress.IpAddress</p>
|
||||
<a href="/authentication/revokeAutoApproval/@approvedIpAddress.UserApprovedIpAddressId">
|
||||
<button class="ui red button">
|
||||
<i class="trash icon"></i>
|
||||
<span>Revoke</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
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.ExternalAuth
|
||||
{
|
||||
public class ManageUserApprovedIpAddressesPage : BaseLayout
|
||||
{
|
||||
public ManageUserApprovedIpAddressesPage(Database database) : base(database)
|
||||
{}
|
||||
|
||||
public List<UserApprovedIpAddress> ApprovedIpAddresses;
|
||||
|
||||
public async Task<IActionResult> OnGet()
|
||||
{
|
||||
User? user = this.Database.UserFromWebRequest(this.Request);
|
||||
if (user == null) return this.Redirect("/login");
|
||||
|
||||
this.ApprovedIpAddresses = await this.Database.UserApprovedIpAddresses.Where(a => a.UserId == user.UserId).ToListAsync();
|
||||
|
||||
return this.Page();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
@page "/"
|
||||
@using LBPUnion.ProjectLighthouse.Types
|
||||
@using LBPUnion.ProjectLighthouse.Types.Settings
|
||||
@model LBPUnion.ProjectLighthouse.Pages.LandingPage
|
||||
|
||||
@{
|
||||
|
@ -11,6 +12,12 @@
|
|||
@if (Model.User != null)
|
||||
{
|
||||
<p>You are currently logged in as <b>@Model.User.Username</b>.</p>
|
||||
if (ServerSettings.Instance.UseExternalAuth && Model.AuthenticationAttemptsCount > 0)
|
||||
{
|
||||
<p>
|
||||
<b>You have @Model.AuthenticationAttemptsCount authentication attempts pending. Click <a href="/authentication">here</a> to view them.</b>
|
||||
</p>
|
||||
}
|
||||
}
|
||||
|
||||
@if (Model.PlayersOnlineCount == 1)
|
||||
|
@ -21,6 +28,7 @@
|
|||
<a href="/user/@user.UserId">@user.Username</a>
|
||||
}
|
||||
}
|
||||
|
||||
else if (Model.PlayersOnlineCount == 0)
|
||||
{
|
||||
<p>There are no users online. Why not hop on?</p>
|
||||
|
|
|
@ -16,6 +16,8 @@ namespace LBPUnion.ProjectLighthouse.Pages
|
|||
public List<User> PlayersOnline;
|
||||
|
||||
public int PlayersOnlineCount;
|
||||
|
||||
public int AuthenticationAttemptsCount;
|
||||
public LandingPage(Database database) : base(database)
|
||||
{}
|
||||
|
||||
|
@ -27,6 +29,13 @@ namespace LBPUnion.ProjectLighthouse.Pages
|
|||
|
||||
this.PlayersOnlineCount = await StatisticsHelper.RecentMatches();
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
this.AuthenticationAttemptsCount = await this.Database.AuthenticationAttempts.Include
|
||||
(a => a.GameToken)
|
||||
.CountAsync(a => a.GameToken.UserId == user.UserId);
|
||||
}
|
||||
|
||||
List<int> userIds = await this.Database.LastContacts.Where(l => TimestampHelper.Timestamp - l.Timestamp < 300).Select(l => l.UserId).ToListAsync();
|
||||
|
||||
this.PlayersOnline = await this.Database.Users.Where(u => userIds.Contains(u.UserId)).ToListAsync();
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
@using LBPUnion.ProjectLighthouse.Types
|
||||
@using LBPUnion.ProjectLighthouse.Types.Profiles
|
||||
@using LBPUnion.ProjectLighthouse.Types.Settings
|
||||
@using System.Web;
|
||||
@using System.IO;
|
||||
@model LBPUnion.ProjectLighthouse.Pages.UserPage
|
||||
|
||||
@{
|
||||
|
@ -114,9 +116,12 @@
|
|||
@foreach (Comment comment in Model.Comments!)
|
||||
{
|
||||
DateTimeOffset timestamp = DateTimeOffset.FromUnixTimeSeconds(comment.Timestamp / 1000);
|
||||
StringWriter messageWriter = new StringWriter();
|
||||
HttpUtility.HtmlDecode(comment.Message, messageWriter);
|
||||
String decodedMessage = messageWriter.ToString();
|
||||
<div>
|
||||
<b><a href="/user/@comment.PosterUserId">@comment.Poster.Username</a>: </b>
|
||||
<span>@comment.Message</span>
|
||||
<span>@decodedMessage</span>
|
||||
<p>
|
||||
<i>@timestamp.ToString("MM/dd/yyyy @ h:mm tt") UTC</i>
|
||||
</p>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types
|
||||
{
|
||||
|
@ -10,12 +11,19 @@ namespace LBPUnion.ProjectLighthouse.Types
|
|||
|
||||
public int UserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public User User { get; set; }
|
||||
|
||||
public string UserToken { get; set; }
|
||||
|
||||
public string UserLocation { get; set; }
|
||||
|
||||
public GameVersion GameVersion { get; set; }
|
||||
|
||||
public bool Approved { get; set; } = false;
|
||||
// Set by /authentication webpage
|
||||
public bool Approved { get; set; }
|
||||
|
||||
// Set to true on login
|
||||
public bool Used { get; set; }
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings
|
|||
public class ServerSettings
|
||||
{
|
||||
|
||||
public const int CurrentConfigVersion = 12; // MUST BE INCREMENTED FOR EVERY CONFIG CHANGE!
|
||||
public const int CurrentConfigVersion = 13; // MUST BE INCREMENTED FOR EVERY CONFIG CHANGE!
|
||||
static ServerSettings()
|
||||
{
|
||||
if (ServerStatics.IsUnitTesting) return; // Unit testing, we don't want to read configurations here since the tests will provide their own
|
||||
|
@ -97,6 +97,8 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings
|
|||
|
||||
public string GoogleAnalyticsId { get; set; } = "";
|
||||
|
||||
public bool BlockDeniedUsers = true;
|
||||
|
||||
#region Meta
|
||||
|
||||
[NotNull]
|
||||
|
|
18
ProjectLighthouse/Types/UserApprovedIpAddress.cs
Normal file
18
ProjectLighthouse/Types/UserApprovedIpAddress.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace LBPUnion.ProjectLighthouse.Types
|
||||
{
|
||||
public class UserApprovedIpAddress
|
||||
{
|
||||
[Key]
|
||||
public int UserApprovedIpAddressId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
||||
[ForeignKey(nameof(UserId))]
|
||||
public User User { get; set; }
|
||||
|
||||
public string IpAddress { get; set; }
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue