From 0d6e40a75dba64bd66192d621bd3a35b0b532194 Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 19 Mar 2022 18:05:20 -0500 Subject: [PATCH] Clean up updateUser and some small changes (#246) * Clean up updateUser and other minor changes * Check if null or whitespace instead of checking string length Co-authored-by: jvyden --- .../GameApi/Resources/ResourcesController.cs | 5 +- .../Controllers/GameApi/UserController.cs | 164 ++++++------------ ProjectLighthouse/Database.cs | 2 +- ProjectLighthouse/Pages/UserPage.cshtml | 9 +- ProjectLighthouse/Types/UserUpdate.cs | 29 ++++ 5 files changed, 91 insertions(+), 118 deletions(-) create mode 100644 ProjectLighthouse/Types/UserUpdate.cs diff --git a/ProjectLighthouse/Controllers/GameApi/Resources/ResourcesController.cs b/ProjectLighthouse/Controllers/GameApi/Resources/ResourcesController.cs index 63d30d9e..0e2d5ae1 100644 --- a/ProjectLighthouse/Controllers/GameApi/Resources/ResourcesController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Resources/ResourcesController.cs @@ -82,7 +82,8 @@ public class ResourcesController : ControllerBase string path = FileHelper.GetResourcePath(hash); FileHelper.EnsureDirectoryCreated(assetsDirectory); - if (FileHelper.ResourceExists(hash)) this.Ok(); // no reason to fail if it's already uploaded + // lbp treats code 409 as success and as an indicator that the file is already present + if (FileHelper.ResourceExists(hash)) this.Conflict(); Logger.Log($"Processing resource upload (hash: {hash})", LoggerLevelResources.Instance); LbpFile file = new(await BinaryHelper.ReadFromPipeReader(this.Request.BodyReader)); @@ -90,7 +91,7 @@ public class ResourcesController : ControllerBase if (!FileHelper.IsFileSafe(file)) { Logger.Log($"File is unsafe (hash: {hash}, type: {file.FileType})", LoggerLevelResources.Instance); - return this.UnprocessableEntity(); + return this.Conflict(); } string calculatedHash = file.Hash; diff --git a/ProjectLighthouse/Controllers/GameApi/UserController.cs b/ProjectLighthouse/Controllers/GameApi/UserController.cs index 62c99565..1a8f05b0 100644 --- a/ProjectLighthouse/Controllers/GameApi/UserController.cs +++ b/ProjectLighthouse/Controllers/GameApi/UserController.cs @@ -5,7 +5,7 @@ using System.IO; using System.Linq; using System.Text.Json; using System.Threading.Tasks; -using System.Xml; +using System.Xml.Serialization; using LBPUnion.ProjectLighthouse.Serialization; using LBPUnion.ProjectLighthouse.Types; using LBPUnion.ProjectLighthouse.Types.Profiles; @@ -69,130 +69,66 @@ public class UserController : ControllerBase User user = userAndToken.Value.Item1; GameToken gameToken = userAndToken.Value.Item2; - XmlReaderSettings settings = new() - { - Async = true, // this is apparently not default - }; - bool locationChanged = false; + this.Request.Body.Position = 0; + string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); + // xml hack so we can use one class to deserialize different root names + string rootElement = bodyString.Contains("updateUser") ? "updateUser" : "user"; + XmlSerializer serializer = new(typeof(UserUpdate), new XmlRootAttribute(rootElement)); + UserUpdate? update = (UserUpdate?) serializer.Deserialize(new StringReader(bodyString)); - // this is an absolute mess, but necessary because LBP only sends what changed - // - // example for changing profile card location: - // - // - // 1234 - // 1234 - // - // - // - // example for changing biography: - // - // biography stuff - // - // - // if you find a way to make it not stupid feel free to replace this - using (XmlReader reader = XmlReader.Create(this.Request.Body, settings)) + if (update == null) return this.BadRequest(); + + if (update.Biography != null) user.Biography = update.Biography; + + if (update.IconHash != null) user.IconHash = update.IconHash; + + if (update.YayHash != null) user.YayHash = update.YayHash; + + if (update.MehHash != null) user.MehHash = update.MehHash; + + if (update.BooHash != null) user.BooHash = update.BooHash; + + if (update.PlanetHash != null) { - List path = new(); // you can think of this as a file path in the XML, like -> -> - while (await reader.ReadAsync()) // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault - switch (reader.NodeType) + switch (gameToken.GameVersion) + { + case GameVersion.LittleBigPlanet2: // LBP2 planets will apply to LBP3 { - case XmlNodeType.Element: - path.Add(reader.Name); - break; - case XmlNodeType.Text: - switch (path[1]) - { - case "biography": - { - user.Biography = await reader.GetValueAsync(); - break; - } - case "location": - { - locationChanged = true; // if we're here then we're probably about to change the location. - // ReSharper disable once ConvertIfStatementToSwitchStatement - if (path[2] == "x") - user.Location.X = Convert.ToInt32 - (await reader.GetValueAsync()); // GetValue only returns a string, i guess we just hope its a number lol - else if (path[2] == "y") user.Location.Y = Convert.ToInt32(await reader.GetValueAsync()); - break; - } - case "icon": - { - user.IconHash = await reader.GetValueAsync(); - break; - } - case "planets": - { - switch (gameToken.GameVersion) - { - case GameVersion.LittleBigPlanet2: // LBP2 planets will apply to LBP3 - { - user.PlanetHashLBP2 = await reader.GetValueAsync(); - user.PlanetHashLBP3 = await reader.GetValueAsync(); - break; - } - case GameVersion.LittleBigPlanet3: // LBP3 and vita can only apply to their own games, only set 1 here - { - user.PlanetHashLBP3 = await reader.GetValueAsync(); - break; - } - case GameVersion.LittleBigPlanetVita: - { - user.PlanetHashLBPVita = await reader.GetValueAsync(); - break; - } - case GameVersion.LittleBigPlanet1: - case GameVersion.LittleBigPlanetPSP: - case GameVersion.Unknown: - default: // The rest do not support custom earths. - { - throw new ArgumentException($"invalid gameVersion {gameToken.GameVersion} for setting earth"); - } - } - break; - } - case "yay2": - { - user.YayHash = await reader.GetValueAsync(); - break; - } - case "meh2": - { - user.MehHash = await reader.GetValueAsync(); - break; - } - case "boo2": - { - user.BooHash = await reader.GetValueAsync(); - break; - } - } - - break; - case XmlNodeType.EndElement: - path.RemoveAt(path.Count - 1); - break; + user.PlanetHashLBP2 = update.PlanetHash; + user.PlanetHashLBP3 = update.PlanetHash; + break; } + case GameVersion.LittleBigPlanet3: // LBP3 and vita can only apply to their own games, only set 1 here + { + user.PlanetHashLBP3 = update.PlanetHash; + break; + } + case GameVersion.LittleBigPlanetVita: + { + user.PlanetHashLBPVita = update.PlanetHash; + break; + } + case GameVersion.LittleBigPlanet1: + case GameVersion.LittleBigPlanetPSP: + case GameVersion.Unknown: + default: // The rest do not support custom earths. + { + throw new ArgumentException($"invalid gameVersion {gameToken.GameVersion} for setting earth"); + } + } } - // the way location on a user card works is stupid and will not save with the way below as-is, so we do the following: - if (locationChanged) // only modify the database if we modify here + if (update.Location != null) { - Location? l = await this.database.Locations.FirstOrDefaultAsync(l => l.Id == user.LocationId); // find the location in the database again + Location? loc = await this.database.Locations.FirstOrDefaultAsync(l => l.Id == user.LocationId); + if (loc == null) throw new Exception("User loc is null, this should never happen."); - if (l == null) throw new Exception("this shouldn't happen ever but we handle this"); - - // set the location in the database to the one we modified above - l.X = user.Location.X; - l.Y = user.Location.Y; - - // now both are in sync, and will update in the database. + loc.X = update.Location.X; + loc.Y = update.Location.Y; } - if (this.database.ChangeTracker.HasChanges()) await this.database.SaveChangesAsync(); // save the user to the database if we changed anything + if (this.database.ChangeTracker.HasChanges()) await this.database.SaveChangesAsync(); return this.Ok(); } diff --git a/ProjectLighthouse/Database.cs b/ProjectLighthouse/Database.cs index d21ccc57..9c38ff41 100644 --- a/ProjectLighthouse/Database.cs +++ b/ProjectLighthouse/Database.cs @@ -75,7 +75,7 @@ public class Database : DbContext Username = username, Password = password, LocationId = l.Id, - Biography = username + " hasn't introduced themselves yet.", + Biography = "", EmailAddress = emailAddress, }; this.Users.Add(user); diff --git a/ProjectLighthouse/Pages/UserPage.cshtml b/ProjectLighthouse/Pages/UserPage.cshtml index 61200e7f..3e6953e1 100644 --- a/ProjectLighthouse/Pages/UserPage.cshtml +++ b/ProjectLighthouse/Pages/UserPage.cshtml @@ -83,7 +83,14 @@

Biography

-

@Model.ProfileUser.Biography

+ @if (string.IsNullOrWhiteSpace(Model.ProfileUser.Biography)) + { +

@Model.ProfileUser.Username hasn't introduced themselves yet

+ } + else + { +

@Model.ProfileUser.Biography

+ }
diff --git a/ProjectLighthouse/Types/UserUpdate.cs b/ProjectLighthouse/Types/UserUpdate.cs new file mode 100644 index 00000000..a193ec8c --- /dev/null +++ b/ProjectLighthouse/Types/UserUpdate.cs @@ -0,0 +1,29 @@ +#nullable enable +using System.Xml.Serialization; +using LBPUnion.ProjectLighthouse.Types.Profiles; + +namespace LBPUnion.ProjectLighthouse.Types; + +public class UserUpdate +{ + [XmlElement("location")] + public Location? Location; + + [XmlElement("biography")] + public string? Biography; + + [XmlElement("icon")] + public string? IconHash; + + [XmlElement("planets")] + public string? PlanetHash; + + [XmlElement("yay2")] + public string? YayHash; + + [XmlElement("meh2")] + public string? MehHash; + + [XmlElement("boo2")] + public string? BooHash; +} \ No newline at end of file