Fix slot version bug and other improvements (#281)

* Fix slot version bug and other improvements

* Fix upload tests not authenticating

Co-authored-by: jvyden <jvyden@jvyden.xyz>
This commit is contained in:
Josh 2022-04-13 14:00:45 -05:00 committed by GitHub
parent 3aecccedf2
commit 216cd2e198
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 104 additions and 35 deletions

View file

@ -4,6 +4,7 @@ using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Tests; using LBPUnion.ProjectLighthouse.Tests;
using LBPUnion.ProjectLighthouse.Types;
using Xunit; using Xunit;
namespace ProjectLighthouse.Tests.GameApiTests; namespace ProjectLighthouse.Tests.GameApiTests;
@ -19,7 +20,9 @@ public class UploadTests : LighthouseServerTest
[Fact] [Fact]
public async Task ShouldNotAcceptScript() public async Task ShouldNotAcceptScript()
{ {
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestScript.ff"); LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestScript.ff", loginResult.AuthTicket);
Assert.False(response.StatusCode == HttpStatusCode.Forbidden); Assert.False(response.StatusCode == HttpStatusCode.Forbidden);
Assert.False(response.IsSuccessStatusCode); Assert.False(response.IsSuccessStatusCode);
} }
@ -27,7 +30,9 @@ public class UploadTests : LighthouseServerTest
[Fact] [Fact]
public async Task ShouldNotAcceptFarc() public async Task ShouldNotAcceptFarc()
{ {
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestFarc.farc"); LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestFarc.farc", loginResult.AuthTicket);
Assert.False(response.StatusCode == HttpStatusCode.Forbidden); Assert.False(response.StatusCode == HttpStatusCode.Forbidden);
Assert.False(response.IsSuccessStatusCode); Assert.False(response.IsSuccessStatusCode);
} }
@ -35,7 +40,9 @@ public class UploadTests : LighthouseServerTest
[Fact] [Fact]
public async Task ShouldNotAcceptGarbage() public async Task ShouldNotAcceptGarbage()
{ {
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestGarbage.bin"); LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestGarbage.bin", loginResult.AuthTicket);
Assert.False(response.StatusCode == HttpStatusCode.Forbidden); Assert.False(response.StatusCode == HttpStatusCode.Forbidden);
Assert.False(response.IsSuccessStatusCode); Assert.False(response.IsSuccessStatusCode);
} }
@ -43,7 +50,9 @@ public class UploadTests : LighthouseServerTest
[Fact] [Fact]
public async Task ShouldAcceptTexture() public async Task ShouldAcceptTexture()
{ {
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestTexture.tex"); LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestTexture.tex", loginResult.AuthTicket);
Assert.False(response.StatusCode == HttpStatusCode.Forbidden); Assert.False(response.StatusCode == HttpStatusCode.Forbidden);
Assert.True(response.IsSuccessStatusCode); Assert.True(response.IsSuccessStatusCode);
} }
@ -51,7 +60,9 @@ public class UploadTests : LighthouseServerTest
[Fact] [Fact]
public async Task ShouldAcceptLevel() public async Task ShouldAcceptLevel()
{ {
HttpResponseMessage response = await this.UploadFileEndpointRequest("ExampleFiles/TestLevel.lvl"); LoginResult loginResult = await this.Authenticate();
HttpResponseMessage response = await this.AuthenticatedUploadFileEndpointRequest("ExampleFiles/TestLevel.lvl", loginResult.AuthTicket);
Assert.False(response.StatusCode == HttpStatusCode.Forbidden); Assert.False(response.StatusCode == HttpStatusCode.Forbidden);
Assert.True(response.IsSuccessStatusCode); Assert.True(response.IsSuccessStatusCode);
} }

View file

@ -73,6 +73,16 @@ public class LighthouseServerTest
return await this.Client.PostAsync($"/LITTLEBIGPLANETPS3_XML/upload/{hash}", new ByteArrayContent(bytes)); return await this.Client.PostAsync($"/LITTLEBIGPLANETPS3_XML/upload/{hash}", new ByteArrayContent(bytes));
} }
public async Task<HttpResponseMessage> AuthenticatedUploadFileEndpointRequest(string filePath, string mmAuth)
{
byte[] bytes = await File.ReadAllBytesAsync(filePath);
string hash = HashHelper.Sha1Hash(bytes).ToLower();
using HttpRequestMessage requestMessage = new(HttpMethod.Post, $"/LITTLEBIGPLANETPS3_XML/upload/{hash}");
requestMessage.Headers.Add("Cookie", mmAuth);
requestMessage.Content = new ByteArrayContent(bytes);
return await this.Client.SendAsync(requestMessage);
}
public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath) public async Task<HttpResponseMessage> UploadFileRequest(string endpoint, string filePath)
=> await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath))); => await this.Client.PostAsync(endpoint, new StringContent(await File.ReadAllTextAsync(filePath)));

View file

@ -1,5 +1,4 @@
#nullable enable #nullable enable
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -20,6 +19,13 @@ namespace LBPUnion.ProjectLighthouse.Controllers.GameApi.Resources;
[Route("LITTLEBIGPLANETPS3_XML")] [Route("LITTLEBIGPLANETPS3_XML")]
public class ResourcesController : ControllerBase public class ResourcesController : ControllerBase
{ {
private readonly Database database;
public ResourcesController(Database database)
{
this.database = database;
}
[HttpPost("showModerated")] [HttpPost("showModerated")]
public IActionResult ShowModerated() => this.Ok(LbpSerializer.BlankElement("resources")); public IActionResult ShowModerated() => this.Ok(LbpSerializer.BlankElement("resources"));
@ -27,6 +33,9 @@ public class ResourcesController : ControllerBase
[HttpPost("showNotUploaded")] [HttpPost("showNotUploaded")]
public async Task<IActionResult> FilterResources() public async Task<IActionResult> FilterResources()
{ {
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();
XmlSerializer serializer = new(typeof(ResourceList)); XmlSerializer serializer = new(typeof(ResourceList));
@ -42,8 +51,11 @@ public class ResourcesController : ControllerBase
} }
[HttpGet("r/{hash}")] [HttpGet("r/{hash}")]
public IActionResult GetResource(string hash) public async Task<IActionResult> GetResource(string hash)
{ {
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
string path = FileHelper.GetResourcePath(hash); string path = FileHelper.GetResourcePath(hash);
if (FileHelper.ResourceExists(hash)) return this.File(IOFile.OpenRead(path), "application/octet-stream"); if (FileHelper.ResourceExists(hash)) return this.File(IOFile.OpenRead(path), "application/octet-stream");
@ -63,21 +75,21 @@ public class ResourcesController : ControllerBase
} }
LbpFile? file = LbpFile.FromHash(hash); LbpFile? file = LbpFile.FromHash(hash);
if (file != null) if (file != null && ImageHelper.LbpFileToPNG(file))
{
if (ImageHelper.LbpFileToPNG(file))
{ {
return this.File(IOFile.OpenRead(path), "image/png"); return this.File(IOFile.OpenRead(path), "image/png");
} }
}
return this.NotFound(); return this.NotFound();
} }
// TODO: check if this is a valid hash // TODO: check if this is a valid hash
[HttpPost("upload/{hash}/unattributed")]
[HttpPost("upload/{hash}")] [HttpPost("upload/{hash}")]
public async Task<IActionResult> UploadResource(string hash) public async Task<IActionResult> UploadResource(string hash)
{ {
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
string assetsDirectory = FileHelper.ResourcePath; string assetsDirectory = FileHelper.ResourcePath;
string path = FileHelper.GetResourcePath(hash); string path = FileHelper.GetResourcePath(hash);

View file

@ -76,7 +76,6 @@ public class PublishController : ControllerBase
[HttpPost("publish")] [HttpPost("publish")]
public async Task<IActionResult> Publish() public async Task<IActionResult> Publish()
{ {
// User user = await this.database.UserFromGameRequest(this.Request);
(User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request); (User, GameToken)? userAndToken = await this.database.UserAndGameTokenFromRequest(this.Request);
if (userAndToken == null) return this.StatusCode(403, ""); if (userAndToken == null) return this.StatusCode(403, "");
@ -94,9 +93,9 @@ public class PublishController : ControllerBase
if (slot.Name.Length > 100) return this.BadRequest(); if (slot.Name.Length > 100) return this.BadRequest();
foreach (string resource in slot.Resources) if (slot.Resources.Any(resource => !FileHelper.ResourceExists(resource)))
{ {
if (!FileHelper.ResourceExists(resource)) return this.BadRequest(); return this.BadRequest();
} }
LbpFile? rootLevel = LbpFile.FromHash(slot.RootLevel); LbpFile? rootLevel = LbpFile.FromHash(slot.RootLevel);
@ -148,7 +147,14 @@ public class PublishController : ControllerBase
slot.TeamPick = oldSlot.TeamPick; slot.TeamPick = oldSlot.TeamPick;
// Only update a slot's gameVersion if the level was actually change // Only update a slot's gameVersion if the level was actually change
if (oldSlot.RootLevel != slot.RootLevel) slot.GameVersion = gameToken.GameVersion; if (oldSlot.RootLevel != slot.RootLevel)
{
slot.GameVersion = gameToken.GameVersion;
}
else
{
slot.GameVersion = oldSlot.GameVersion;
}
if (slot.MinimumPlayers == 0 || slot.MaximumPlayers == 0) if (slot.MinimumPlayers == 0 || slot.MaximumPlayers == 0)
{ {

View file

@ -28,7 +28,6 @@
</div> </div>
<input type="submit" class="ui blue button"> <input type="submit" class="ui blue button">
</form> </form>
<br>
} }
@for(int i = 0; i < Model.Comments.Count; i++) @for(int i = 0; i < Model.Comments.Count; i++)

View file

@ -51,7 +51,7 @@
} }
<div class="cardStatsUnderTitle"> <div class="cardStatsUnderTitle">
<i class="pink heart icon" title="Hearts"></i> <span>@Model.Hearts</span> <i class="pink heart icon" title="Hearts"></i> <span>@Model.Hearts</span>
<i class="blue play icon" title="Plays"></i> <span>@Model.Plays</span> <i class="blue play icon" title="Plays"></i> <span>@Model.PlaysUnique</span>
<i class="green thumbs up icon" title="Yays"></i> <span>@Model.Thumbsup</span> <i class="green thumbs up icon" title="Yays"></i> <span>@Model.Thumbsup</span>
<i class="red thumbs down icon" title="Boos"></i> <span>@Model.Thumbsdown</span> <i class="red thumbs down icon" title="Boos"></i> <span>@Model.Thumbsdown</span>

View file

@ -1,6 +1,7 @@
@page "/slot/{id:int}" @page "/slot/{id:int}"
@using System.Web @using System.Web
@using LBPUnion.ProjectLighthouse.Helpers.Extensions @using LBPUnion.ProjectLighthouse.Helpers.Extensions
@using LBPUnion.ProjectLighthouse.Types
@using LBPUnion.ProjectLighthouse.Types.Reviews @using LBPUnion.ProjectLighthouse.Types.Reviews
@using LBPUnion.ProjectLighthouse.Types.Settings @using LBPUnion.ProjectLighthouse.Types.Settings
@model LBPUnion.ProjectLighthouse.Pages.SlotPage @model LBPUnion.ProjectLighthouse.Pages.SlotPage
@ -81,16 +82,23 @@
} }
<div class="ui divider"></div> <div class="ui divider"></div>
@foreach (Review review in Model.Reviews) @for (int i = 0; i < Model.Reviews.Count; i++)
{ {
Review review = Model.Reviews[i];
string faceHash = review.Thumb switch { string faceHash = review.Thumb switch {
-1 => review.Reviewer.BooHash, -1 => review.Reviewer?.BooHash,
0 => review.Reviewer.MehHash, 0 => review.Reviewer?.MehHash,
1 => review.Reviewer.YayHash, 1 => review.Reviewer?.YayHash,
_ => throw new ArgumentOutOfRangeException(), _ => throw new ArgumentOutOfRangeException(),
}; };
if (string.IsNullOrWhiteSpace(faceHash))
{
faceHash = ServerSettings.Instance.MissingIconHash;
}
string faceAlt = review.Thumb switch { string faceAlt = review.Thumb switch {
-1 => "Boo!", -1 => "Boo!",
0 => "Meh.", 0 => "Meh.",
@ -106,7 +114,24 @@
<img class="cardIcon slotCardIcon" src="@ServerSettings.Instance.ExternalUrl/gameAssets/@faceHash" alt="@faceAlt" title="@faceAlt" style="min-width: @(size)px; width: @(size)px; height: @(size)px"> <img class="cardIcon slotCardIcon" src="@ServerSettings.Instance.ExternalUrl/gameAssets/@faceHash" alt="@faceAlt" title="@faceAlt" style="min-width: @(size)px; width: @(size)px; height: @(size)px">
</div> </div>
<div class="cardStats"> <div class="cardStats">
<h3 style="margin-bottom: 5px;">@review.Reviewer.Username</h3> <h3 style="margin-bottom: 5px;">@review.Reviewer?.Username</h3>
@if (review.Deleted)
{
if (review.DeletedBy == DeletedBy.LevelAuthor)
{
<p>
<i>This review has been deleted by the level author.</i>
</p>
}
else
{
<p>
<i>This review has been deleted by a moderator.</i>
</p>
}
}
else
{
@if (review.Labels.Length > 1) @if (review.Labels.Length > 1)
{ {
@foreach (string reviewLabel in review.Labels) @foreach (string reviewLabel in review.Labels)
@ -121,12 +146,18 @@
</p> </p>
} }
else else
{
{ {
<p>@review.Text</p> <p>@review.Text</p>
} }
}
}
</div> </div>
</div> </div>
<br> @if (i != Model.Reviews.Count - 1)
{
<div class="ui divider"></div>
}
} }
</div> </div>
</div> </div>