From fa849c66aeb3c2c603c9f12da8d88af1ef9075bf Mon Sep 17 00:00:00 2001 From: Beyley Thomas Date: Sat, 11 Nov 2023 11:11:03 -0800 Subject: [PATCH 1/3] TestContext: Add methods to get authenticated client for a specific game/platform --- RefreshTests.GameServer/TestContext.cs | 16 ++++++++++++++++ .../Tests/Reporting/ReportingEndpointsTests.cs | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs diff --git a/RefreshTests.GameServer/TestContext.cs b/RefreshTests.GameServer/TestContext.cs index fcfc849d..e308fdd7 100644 --- a/RefreshTests.GameServer/TestContext.cs +++ b/RefreshTests.GameServer/TestContext.cs @@ -37,6 +37,13 @@ public HttpClient GetAuthenticatedClient(TokenType type, { return this.GetAuthenticatedClient(type, out _, user, tokenExpirySeconds); } + + public HttpClient GetAuthenticatedClient(TokenType type, TokenGame game, TokenPlatform platform, + GameUser? user = null, + int tokenExpirySeconds = GameDatabaseContext.DefaultTokenExpirySeconds) + { + return this.GetAuthenticatedClient(type, game, platform, out _, user, tokenExpirySeconds); + } public HttpClient GetAuthenticatedClient(TokenType type, out string tokenData, GameUser? user = null, @@ -56,6 +63,15 @@ public HttpClient GetAuthenticatedClient(TokenType type, out string tokenData, _ => TokenPlatform.Website, }; + return this.GetAuthenticatedClient(type, game, platform, out tokenData, user, tokenExpirySeconds); + } + + public HttpClient GetAuthenticatedClient(TokenType type, TokenGame game, TokenPlatform platform, out string tokenData, + GameUser? user = null, + int tokenExpirySeconds = GameDatabaseContext.DefaultTokenExpirySeconds) + { + user ??= this.CreateUser(); + Token token = this.Database.GenerateTokenForUser(user, type, game, platform, tokenExpirySeconds); tokenData = token.TokenData; diff --git a/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs b/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs new file mode 100644 index 00000000..3cbdb20e --- /dev/null +++ b/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs @@ -0,0 +1,18 @@ +using Refresh.GameServer.Authentication; +using Refresh.GameServer.Types.Levels; +using Refresh.GameServer.Types.UserData; + +namespace RefreshTests.GameServer.Tests.Reporting; + +public class ReportingEndpointsTests : GameServerTest +{ + [Test] + public void UploadReport() + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + GameLevel level = context.CreateLevel(user); + + using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, user); + } +} \ No newline at end of file From 551b3dca1cd4e72989c01fd05c496d76fa10eb1d Mon Sep 17 00:00:00 2001 From: Beyley Thomas Date: Sat, 11 Nov 2023 12:02:26 -0800 Subject: [PATCH 2/3] ReportingEndpointsTests: Add test coverage of reporting (not photo redirection yet) --- .../Database/GameDatabaseContext.Reports.cs | 7 +- .../Reporting/ReportingEndpointsTests.cs | 169 +++++++++++++++++- 2 files changed, 174 insertions(+), 2 deletions(-) diff --git a/Refresh.GameServer/Database/GameDatabaseContext.Reports.cs b/Refresh.GameServer/Database/GameDatabaseContext.Reports.cs index bf6f3f78..e901b98a 100644 --- a/Refresh.GameServer/Database/GameDatabaseContext.Reports.cs +++ b/Refresh.GameServer/Database/GameDatabaseContext.Reports.cs @@ -7,5 +7,10 @@ public partial class GameDatabaseContext public void AddGriefReport(GameReport report) { this.AddSequentialObject(report, () => {}); - } + } + + public DatabaseList GetGriefReports(int count, int skip) + { + return new DatabaseList(this._realm.All(), skip, count); + } } \ No newline at end of file diff --git a/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs b/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs index 3cbdb20e..ab65ef0f 100644 --- a/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs +++ b/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs @@ -1,6 +1,9 @@ using Refresh.GameServer.Authentication; +using Refresh.GameServer.Database; using Refresh.GameServer.Types.Levels; +using Refresh.GameServer.Types.Report; using Refresh.GameServer.Types.UserData; +using RefreshTests.GameServer.Extensions; namespace RefreshTests.GameServer.Tests.Reporting; @@ -13,6 +16,170 @@ public void UploadReport() GameUser user = context.CreateUser(); GameLevel level = context.CreateLevel(user); - using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, user); + using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, TokenGame.LittleBigPlanet1, TokenPlatform.PS3, user); + + GameReport report = new() + { + InfoBubble = new InfoBubble[] + {}, + Type = GriefReportType.Obscene, + Marqee = new Marqee + { + Rect = new Rect + { + Top = 10, + Left = 10, + Bottom = 20, + Right = 20, + }, + }, + LevelOwner = level.Publisher!.Username, + InitialStateHash = null, + LevelType = "user", + LevelId = level.LevelId, + Description = "This is a description, sent by LBP3", + GriefStateHash = null, + JpegHash = null, + Players = new Player[] + { + new() + { + Username = user.Username, + Rectangle = new Rect + { + Top = 10, + Left = 10, + Bottom = 20, + Right = 20, + }, + Reporter = true, + IngameNow = true, + PlayerNumber = 0, + Text = "Some text", + ScreenRect = new ScreenRect + { + Rect = new Rect + { + Top = 10, + Left = 10, + Bottom = 20, + Right = 20, + }, + }, + }, + }, + ScreenElements = new ScreenElements(), + }; + + HttpResponseMessage response = client.PostAsync("/lbp/grief", new StringContent(report.AsXML())).Result; + Assert.That(response.StatusCode, Is.EqualTo(OK)); + + context.Database.Refresh(); + + DatabaseList griefReports = context.Database.GetGriefReports(10, 0); + Assert.That(griefReports.TotalItems, Is.EqualTo(1)); + List reports = griefReports.Items.ToList(); + Assert.That(reports[0].Description, Is.EqualTo(report.Description)); + Assert.That(reports[0].LevelId, Is.EqualTo(report.LevelId)); + } + + [Test] + public void CantUploadReportWithBadLevel() + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + + using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, TokenGame.LittleBigPlanet1, TokenPlatform.PS3, user); + + GameReport report = new() + { + LevelId = int.MaxValue, + }; + + HttpResponseMessage response = client.PostAsync("/lbp/grief", new StringContent(report.AsXML())).Result; + Assert.That(response.StatusCode, Is.EqualTo(BadRequest)); + } + + [Test] + public void CantUploadReportWithBadPlayerCount() + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + + using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, TokenGame.LittleBigPlanet1, TokenPlatform.PS3, user); + + GameReport report = new() + { + LevelId = 0, + Players = new Player[] + { + new() + { + Username = "hee", + }, + new() + { + Username = "haw", + }, + new() + { + Username = "ham", + }, + new() + { + Username = "burg", + }, + new() + { + Username = "er", + }, + }, + }; + + HttpResponseMessage response = client.PostAsync("/lbp/grief", new StringContent(report.AsXML())).Result; + Assert.That(response.StatusCode, Is.EqualTo(BadRequest)); + } + + [Test] + public void CantUploadReportWithBadScreenElementPlayerCount() + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + + using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, TokenGame.LittleBigPlanet1, TokenPlatform.PS3, user); + + GameReport report = new() + { + LevelId = 0, + ScreenElements = new ScreenElements + { + Player = new Player[] + { + new() + { + Username = "hee", + }, + new() + { + Username = "haw", + }, + new() + { + Username = "ham", + }, + new() + { + Username = "burg", + }, + new() + { + Username = "er", + }, + }, + }, + }; + + HttpResponseMessage response = client.PostAsync("/lbp/grief", new StringContent(report.AsXML())).Result; + Assert.That(response.StatusCode, Is.EqualTo(BadRequest)); } } \ No newline at end of file From 507fc3d7b902112a45521d2f7859f955221d1135 Mon Sep 17 00:00:00 2001 From: Beyley Thomas Date: Sat, 11 Nov 2023 15:52:45 -0800 Subject: [PATCH 3/3] ReportingEndpointsTests: Add test coverage for uploading grief report This sadly does not get us to 100% test coverage, due to it being impossible to get full test coverage of this, since there are 2 cases in that function which are completely impossible to reach, however, removing them would cause us to need to disable warnings for switch cases --- .../Database/GameDatabaseContext.Users.cs | 8 ++ .../Endpoints/Game/ModerationEndpoints.cs | 3 +- .../Endpoints/Game/ReportingEndpoints.cs | 29 ++-- Refresh.GameServer/Services/CommandService.cs | 4 +- .../Reporting/ReportingEndpointsTests.cs | 125 ++++++++++++++++++ 5 files changed, 157 insertions(+), 12 deletions(-) diff --git a/Refresh.GameServer/Database/GameDatabaseContext.Users.cs b/Refresh.GameServer/Database/GameDatabaseContext.Users.cs index d2fed487..9c08efd6 100644 --- a/Refresh.GameServer/Database/GameDatabaseContext.Users.cs +++ b/Refresh.GameServer/Database/GameDatabaseContext.Users.cs @@ -237,6 +237,14 @@ public void ResetUserPlanets(GameUser user) user.VitaPlanetsHash = "0"; }); } + + public void SetUserGriefReportRedirection(GameUser user, bool value) + { + this._realm.Write(() => + { + user.RedirectGriefReportsToPhotos = value; + }); + } #if DEBUG public void ForceUserTokenGame(Token token, TokenGame game) diff --git a/Refresh.GameServer/Endpoints/Game/ModerationEndpoints.cs b/Refresh.GameServer/Endpoints/Game/ModerationEndpoints.cs index f655de62..67d5589e 100644 --- a/Refresh.GameServer/Endpoints/Game/ModerationEndpoints.cs +++ b/Refresh.GameServer/Endpoints/Game/ModerationEndpoints.cs @@ -64,8 +64,9 @@ public string Filter(RequestContext context, CommandService commandService, stri commandService.HandleCommand(command, database, user, token); return "(Command)"; } - catch + catch(Exception ex) { + context.Logger.LogWarning(BunkumCategory.Commands, $"Error running command {body}. ex {ex}"); //do nothing } } diff --git a/Refresh.GameServer/Endpoints/Game/ReportingEndpoints.cs b/Refresh.GameServer/Endpoints/Game/ReportingEndpoints.cs index e2436470..f0217e46 100644 --- a/Refresh.GameServer/Endpoints/Game/ReportingEndpoints.cs +++ b/Refresh.GameServer/Endpoints/Game/ReportingEndpoints.cs @@ -21,15 +21,26 @@ public Response UploadReport(RequestContext context, GameDatabaseContext databas { GameLevel? level = database.GetLevelById(body.LevelId); - Size imageSize = token.TokenGame switch { - TokenGame.LittleBigPlanet1 => new Size(640, 360), - TokenGame.LittleBigPlanet2 => new Size(640, 360), - TokenGame.LittleBigPlanet3 => new Size(640, 360), - TokenGame.LittleBigPlanetVita => new Size(512, 290), - TokenGame.LittleBigPlanetPSP => new Size(480, 272), - _ => throw new ArgumentOutOfRangeException(nameof(token), $"Token game {token.TokenGame} is not allowed for grief upload!"), - }; - + Size imageSize; + switch (token.TokenGame) + { + case TokenGame.LittleBigPlanet1: + case TokenGame.LittleBigPlanet2: + case TokenGame.LittleBigPlanet3: + imageSize = new Size(640, 360); + break; + case TokenGame.LittleBigPlanetVita: + imageSize = new Size(512, 290); + break; + case TokenGame.LittleBigPlanetPSP: + imageSize = new Size(480, 272); + break; + case TokenGame.Website: + default: + context.Logger.LogWarning(BunkumCategory.Game, $"User {user} tried to upload grief report with token type {token.TokenGame}!"); + return BadRequest; + } + //If the level is specified but its invalid, return BadRequest if (body.LevelId != 0 && level == null) return BadRequest; diff --git a/Refresh.GameServer/Services/CommandService.cs b/Refresh.GameServer/Services/CommandService.cs index f443ce9b..011b31dd 100644 --- a/Refresh.GameServer/Services/CommandService.cs +++ b/Refresh.GameServer/Services/CommandService.cs @@ -106,12 +106,12 @@ public void HandleCommand(CommandInvocation command, GameDatabaseContext databas } case "griefphotoson": { - user.RedirectGriefReportsToPhotos = true; + database.SetUserGriefReportRedirection(user, true); break; } case "griefphotosoff": { - user.RedirectGriefReportsToPhotos = false; + database.SetUserGriefReportRedirection(user, false); break; } case "play": diff --git a/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs b/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs index ab65ef0f..47e57c53 100644 --- a/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs +++ b/RefreshTests.GameServer/Tests/Reporting/ReportingEndpointsTests.cs @@ -1,6 +1,7 @@ using Refresh.GameServer.Authentication; using Refresh.GameServer.Database; using Refresh.GameServer.Types.Levels; +using Refresh.GameServer.Types.Photos; using Refresh.GameServer.Types.Report; using Refresh.GameServer.Types.UserData; using RefreshTests.GameServer.Extensions; @@ -182,4 +183,128 @@ public void CantUploadReportWithBadScreenElementPlayerCount() HttpResponseMessage response = client.PostAsync("/lbp/grief", new StringContent(report.AsXML())).Result; Assert.That(response.StatusCode, Is.EqualTo(BadRequest)); } + + [TestCase(TokenGame.LittleBigPlanet1)] + [TestCase(TokenGame.LittleBigPlanet2)] + [TestCase(TokenGame.LittleBigPlanet3)] + [TestCase(TokenGame.LittleBigPlanetVita)] + [TestCase(TokenGame.LittleBigPlanetPSP)] + public void RedirectGriefReportToPhoto(TokenGame game) + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + GameLevel level = context.CreateLevel(user); + + //Enable the grief report re-direction + context.Database.SetUserGriefReportRedirection(user, true); + context.Database.Refresh(); + + using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, game, TokenPlatform.PS3, user); + + HttpResponseMessage response = client.PostAsync("/lbp/grief", new StringContent(new GameReport + { + Players = new Player[] + { + new() + { + Username = user.Username, + Rectangle = new Rect + { + Top = 10, + Left = 10, + Bottom = 20, + Right = 20, + }, + }, + }, + LevelId = level.LevelId, + }.AsXML())).Result; + Assert.That(response.StatusCode, Is.EqualTo(OK)); + + context.Database.Refresh(); + + DatabaseList photos = context.Database.GetPhotosByUser(user, 10, 0); + Assert.That(photos.TotalItems, Is.EqualTo(1)); + + GamePhoto photo = photos.Items.First(); + Assert.That(photo.Publisher.UserId, Is.EqualTo(user.UserId)); + } + + [TestCase(TokenGame.LittleBigPlanet1)] + [TestCase(TokenGame.LittleBigPlanet2)] + [TestCase(TokenGame.LittleBigPlanet3)] + [TestCase(TokenGame.LittleBigPlanetVita)] + [TestCase(TokenGame.LittleBigPlanetPSP)] + public void RedirectGriefReportToPhotoDeveloperLevel(TokenGame game) + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + GameLevel level = context.Database.GetStoryLevelById(100000); + + //Enable the grief report re-direction + context.Database.SetUserGriefReportRedirection(user, true); + context.Database.Refresh(); + + using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, game, TokenPlatform.PS3, user); + + HttpResponseMessage response = client.PostAsync("/lbp/grief", new StringContent(new GameReport + { + Players = new Player[] + { + new() + { + Username = user.Username, + Rectangle = new Rect + { + Top = 10, + Left = 10, + Bottom = 20, + Right = 20, + }, + }, + }, + LevelId = level.LevelId, + }.AsXML())).Result; + Assert.That(response.StatusCode, Is.EqualTo(OK)); + + context.Database.Refresh(); + + DatabaseList photos = context.Database.GetPhotosByUser(user, 10, 0); + Assert.That(photos.TotalItems, Is.EqualTo(1)); + + GamePhoto photo = photos.Items.First(); + Assert.That(photo.Publisher.UserId, Is.EqualTo(user.UserId)); + } + + [Test] + public void CantRedirectGriefReportToPhotoWhenWebsiteToken() + { + using TestContext context = this.GetServer(); + GameUser user = context.CreateUser(); + + //Enable the grief report re-direction + context.Database.SetUserGriefReportRedirection(user, true); + context.Database.Refresh(); + + using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, TokenGame.Website, TokenPlatform.PS3, user); + + HttpResponseMessage response = client.PostAsync("/lbp/grief", new StringContent(new GameReport + { + Players = new Player[] + { + new() + { + Username = user.Username, + Rectangle = new Rect + { + Top = 10, + Left = 10, + Bottom = 20, + Right = 20, + }, + }, + }, + }.AsXML())).Result; + Assert.That(response.StatusCode, Is.EqualTo(BadRequest)); + } } \ No newline at end of file