mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-05-17 07:12:32 +00:00
* Initial work for serialization refactor * Experiment with new naming conventions * Mostly implement user and slot serialization. Still needs to be fine tuned to match original implementation Many things are left in a broken state like website features/api endpoints/lbp3 categories * Fix release building * Migrate scores, reviews, and more to new serialization system. Many things are still broken but progress is steadily being made * Fix Api responses and migrate serialization for most types * Make serialization better and fix bugs Fix recursive PrepareSerialization when recursive item is set during root item's PrepareSerialization, items, should be properly indexed in order but it's only tested to 1 level of recursion * Fix review serialization * Fix user serialization producing malformed SQL query * Remove DefaultIfEmpty query * MariaDB doesn't like double nested queries * Fix LBP1 tag counter * Implement lbp3 categories and add better deserialization handling * Implement expression tree caching to speed up reflection and write new serializer tests * Remove Game column from UserEntity and rename DatabaseContextModelSnapshot.cs back to DatabaseModelSnapshot.cs * Make UserEntity username not required * Fix recursive serialization of lists and add relevant unit tests * Actually commit the migration * Fix LocationTests to use new deserialization class * Fix comments not serializing the right author username * Replace all occurrences of StatusCode with their respective ASP.NET named result instead of StatusCode(403) everything is now in the form of Forbid() * Fix SlotBase.ConvertToEntity and LocationTests * Fix compilation error * Give Location a default value in GameUserSlot and GameUser * Reimplement stubbed website functions * Convert grief reports to new serialization system * Update DatabaseModelSnapshot and bump dotnet tool version * Remove unused directives * Fix broken type reference * Fix rated comments on website * Don't include banned users in website comments * Optimize score submission * Fix slot id calculating in in-game comment posting * Move serialization interfaces to types folder and add more documentation * Allow uploading of versus scores
186 lines
No EOL
6.6 KiB
C#
186 lines
No EOL
6.6 KiB
C#
#nullable enable
|
|
using System.Text.Json;
|
|
using LBPUnion.ProjectLighthouse.Database;
|
|
using LBPUnion.ProjectLighthouse.Extensions;
|
|
using LBPUnion.ProjectLighthouse.Files;
|
|
using LBPUnion.ProjectLighthouse.Helpers;
|
|
using LBPUnion.ProjectLighthouse.Logging;
|
|
using LBPUnion.ProjectLighthouse.Servers.GameServer.Types.Users;
|
|
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
|
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
|
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
|
|
using LBPUnion.ProjectLighthouse.Types.Levels;
|
|
using LBPUnion.ProjectLighthouse.Types.Logging;
|
|
using LBPUnion.ProjectLighthouse.Types.Serialization;
|
|
using LBPUnion.ProjectLighthouse.Types.Users;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers;
|
|
|
|
[ApiController]
|
|
[Authorize]
|
|
[Route("LITTLEBIGPLANETPS3_XML/")]
|
|
[Produces("text/xml")]
|
|
public class UserController : ControllerBase
|
|
{
|
|
private readonly DatabaseContext database;
|
|
|
|
public UserController(DatabaseContext database)
|
|
{
|
|
this.database = database;
|
|
}
|
|
|
|
[HttpGet("user/{username}")]
|
|
public async Task<IActionResult> GetUser(string username)
|
|
{
|
|
UserEntity? user = await this.database.Users.FirstOrDefaultAsync(u => u.Username == username);
|
|
if (user == null) return this.NotFound();
|
|
|
|
return this.Ok(GameUser.CreateFromEntity(user, this.GetToken().GameVersion));
|
|
}
|
|
|
|
[HttpGet("users")]
|
|
public async Task<IActionResult> GetUserAlt([FromQuery(Name = "u")] string[] userList)
|
|
{
|
|
List<MinimalUserProfile> minimalUserList = new();
|
|
foreach (string username in userList)
|
|
{
|
|
MinimalUserProfile? profile = await this.database.Users.Where(u => u.Username == username)
|
|
.Select(u => new MinimalUserProfile
|
|
{
|
|
UserHandle = new NpHandle(u.Username, u.IconHash),
|
|
})
|
|
.FirstOrDefaultAsync();
|
|
if (profile == null) continue;
|
|
minimalUserList.Add(profile);
|
|
}
|
|
|
|
return this.Ok(new MinimalUserListResponse(minimalUserList));
|
|
}
|
|
|
|
[HttpPost("updateUser")]
|
|
public async Task<IActionResult> UpdateUser()
|
|
{
|
|
GameTokenEntity token = this.GetToken();
|
|
|
|
UserEntity? user = await this.database.UserFromGameToken(token);
|
|
if (user == null) return this.Forbid();
|
|
|
|
UserUpdate? update = await this.DeserializeBody<UserUpdate>("updateUser", "user");
|
|
|
|
if (update == null) return this.BadRequest();
|
|
|
|
SanitizationHelper.SanitizeStringsInClass(update);
|
|
|
|
if (update.Biography != null)
|
|
{
|
|
if (update.Biography.Length > 512) return this.BadRequest();
|
|
|
|
user.Biography = update.Biography;
|
|
}
|
|
|
|
if (update.Location != null) user.Location = update.Location;
|
|
|
|
// ReSharper disable once LoopCanBeConvertedToQuery
|
|
foreach (string? resource in new[]{update.IconHash, update.YayHash, update.MehHash, update.BooHash, update.PlanetHash,})
|
|
{
|
|
if (resource == "0") continue;
|
|
|
|
if (resource != null && !resource.StartsWith('g') && !FileHelper.ResourceExists(resource))
|
|
{
|
|
return this.BadRequest();
|
|
}
|
|
}
|
|
|
|
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.Slots != null)
|
|
{
|
|
update.Slots = update.Slots.Where(s => s.Type == SlotType.User)
|
|
.Where(s => s.Location != null)
|
|
.Where(s => s.SlotId != 0).ToList();
|
|
foreach (UserUpdateSlot? updateSlot in update.Slots)
|
|
{
|
|
SlotEntity? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == updateSlot.SlotId);
|
|
if (slot == null) continue;
|
|
|
|
if (slot.CreatorId != token.UserId) continue;
|
|
|
|
slot.Location = updateSlot.Location!;
|
|
}
|
|
}
|
|
|
|
if (update.PlanetHashLBP2CC != null) user.PlanetHashLBP2CC = update.PlanetHashLBP2CC;
|
|
|
|
if (update.PlanetHash != null)
|
|
{
|
|
switch (token.GameVersion)
|
|
{
|
|
case GameVersion.LittleBigPlanet2: // LBP2 planets will apply to LBP3
|
|
{
|
|
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.
|
|
{
|
|
string bodyString = await this.ReadBodyAsync();
|
|
Logger.Warn($"User with invalid gameVersion '{token.GameVersion}' tried to set earth hash: \n" +
|
|
$"body: '{bodyString}'",
|
|
LogArea.Resources);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
await this.database.SaveChangesAsync();
|
|
|
|
return this.Ok();
|
|
}
|
|
|
|
[HttpPost("update_my_pins")]
|
|
[Produces("text/json")]
|
|
public async Task<IActionResult> UpdateMyPins()
|
|
{
|
|
UserEntity? user = await this.database.UserFromGameToken(this.GetToken());
|
|
if (user == null) return this.Forbid();
|
|
|
|
string bodyString = await this.ReadBodyAsync();
|
|
|
|
Pins? pinJson = JsonSerializer.Deserialize<Pins>(bodyString);
|
|
if (pinJson?.ProfilePins == null) return this.BadRequest();
|
|
|
|
// Sometimes the update gets called periodically as pin progress updates via playing,
|
|
// may not affect equipped profile pins however, so check before setting it.
|
|
string currentPins = user.Pins;
|
|
string newPins = string.Join(",", pinJson.ProfilePins);
|
|
|
|
if (string.Equals(currentPins, newPins)) return this.Ok("[{\"StatusCode\":200}]");
|
|
|
|
user.Pins = newPins;
|
|
await this.database.SaveChangesAsync();
|
|
|
|
return this.Ok("[{\"StatusCode\":200}]");
|
|
}
|
|
} |