Skip to content

Commit

Permalink
Refactor constants in Refresh.Common (#628)
Browse files Browse the repository at this point in the history
  • Loading branch information
Beyley authored Aug 11, 2024
2 parents 899fed9 + c2c0e09 commit d632de0
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 55 deletions.
9 changes: 0 additions & 9 deletions Refresh.Common/Constants/FakeUserConstants.cs

This file was deleted.

20 changes: 20 additions & 0 deletions Refresh.Common/Constants/SystemUsers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Refresh.Common.Constants;

public static class SystemUsers
{
/// <summary>
/// A system user represents a user that doesn't technically exist. (well, it does for now until postgres or something)
/// This can be used for levels belonging to users who have deleted their accounts, or for re-uploads.
/// </summary>
public const char SystemPrefix = '!';
/// <summary>
/// Reserved for clans. https://github.com/LittleBigRefresh/Refresh/issues/77
/// </summary>
public const char ClanPrefix = '$';

public const string DeletedUserName = "!DeletedUser";
public const string DeletedUserDescription = "I'm a fake user that represents deleted users for levels.";

public const string UnknownUserName = "!Unknown";
public const string UnknownUserDescription = "I'm a fake user that represents a non existent publisher for re-published levels.";
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
namespace Refresh.Common.Constants;

public static class UgcConstantLimits
public static class UgcLimits
{
// Object limits
public const int MaximumLevels = 9_999;

// String limits
public const int TitleLimit = 64;
public const int DescriptionLimit = 512;
}
30 changes: 15 additions & 15 deletions Refresh.GameServer/Database/GameDatabaseContext.Levels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ public partial class GameDatabaseContext // Levels
{
public bool AddLevel(GameLevel level)
{
if (level.Title is { Length: > UgcConstantLimits.TitleLimit })
level.Title = level.Title[..UgcConstantLimits.TitleLimit];
if (level.Title is { Length: > UgcLimits.TitleLimit })
level.Title = level.Title[..UgcLimits.TitleLimit];

if (level.Description is { Length: > UgcConstantLimits.DescriptionLimit })
level.Description = level.Description[..UgcConstantLimits.DescriptionLimit];
if (level.Description is { Length: > UgcLimits.DescriptionLimit })
level.Description = level.Description[..UgcLimits.DescriptionLimit];

if (level.Publisher == null) throw new InvalidOperationException("Cannot create a level without a publisher");

Expand Down Expand Up @@ -68,11 +68,11 @@ public GameLevel GetStoryLevelById(int id)

public GameLevel? UpdateLevel(GameLevel newLevel, GameUser author)
{
if (newLevel.Title is { Length: > UgcConstantLimits.TitleLimit })
newLevel.Title = newLevel.Title[..UgcConstantLimits.TitleLimit];
if (newLevel.Title is { Length: > UgcLimits.TitleLimit })
newLevel.Title = newLevel.Title[..UgcLimits.TitleLimit];

if (newLevel.Description is { Length: > UgcConstantLimits.DescriptionLimit })
newLevel.Description = newLevel.Description[..UgcConstantLimits.DescriptionLimit];
if (newLevel.Description is { Length: > UgcLimits.DescriptionLimit })
newLevel.Description = newLevel.Description[..UgcLimits.DescriptionLimit];

// Verify if this level is able to be republished
GameLevel? oldLevel = this.GetLevelById(newLevel.LevelId);
Expand Down Expand Up @@ -116,11 +116,11 @@ public GameLevel GetStoryLevelById(int id)

public GameLevel? UpdateLevel(ApiEditLevelRequest body, GameLevel level)
{
if (body.Title is { Length: > UgcConstantLimits.TitleLimit })
body.Title = body.Title[..UgcConstantLimits.TitleLimit];
if (body.Title is { Length: > UgcLimits.TitleLimit })
body.Title = body.Title[..UgcLimits.TitleLimit];

if (body.Description is { Length: > UgcConstantLimits.DescriptionLimit })
body.Description = body.Description[..UgcConstantLimits.DescriptionLimit];
if (body.Description is { Length: > UgcLimits.DescriptionLimit })
body.Description = body.Description[..UgcLimits.DescriptionLimit];

this.Write(() =>
{
Expand Down Expand Up @@ -186,17 +186,17 @@ private IQueryable<GameLevel> GetLevelsByGameVersion(TokenGame gameVersion)
[Pure]
public DatabaseList<GameLevel> GetLevelsByUser(GameUser user, int count, int skip, LevelFilterSettings levelFilterSettings, GameUser? accessor)
{
if (user.Username == FakeUserConstants.DeletedUserName)
if (user.Username == SystemUsers.DeletedUserName)
{
return new DatabaseList<GameLevel>(this.GetLevelsByGameVersion(levelFilterSettings.GameVersion).FilterByLevelFilterSettings(accessor, levelFilterSettings).Where(l => l.Publisher == null), skip, count);
}

if (user.Username == FakeUserConstants.UnknownUserName)
if (user.Username == SystemUsers.UnknownUserName)
{
return new DatabaseList<GameLevel>(this.GetLevelsByGameVersion(levelFilterSettings.GameVersion).FilterByLevelFilterSettings(null, levelFilterSettings).Where(l => l.IsReUpload && String.IsNullOrEmpty(l.OriginalPublisher)), skip, count);
}

if (user.Username.StartsWith(FakeUserConstants.Prefix))
if (user.Username.StartsWith(SystemUsers.SystemPrefix))
{
string withoutPrefix = user.Username[1..];
return new DatabaseList<GameLevel>(this.GetLevelsByGameVersion(levelFilterSettings.GameVersion).FilterByLevelFilterSettings(accessor, levelFilterSettings).Where(l => l.OriginalPublisher == withoutPrefix), skip, count);
Expand Down
10 changes: 5 additions & 5 deletions Refresh.GameServer/Database/GameDatabaseContext.Users.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,27 @@ public partial class GameDatabaseContext // Users
: this.GameUsers.FirstOrDefault(u => u.Username.Equals(username, StringComparison.OrdinalIgnoreCase));

// If that failed and the username is the deleted user, then we need to create the backing deleted user
if (username == FakeUserConstants.DeletedUserName && user == null)
if (username == SystemUsers.DeletedUserName && user == null)
{
this.Write(() =>
{
this.GameUsers.Add(user = new GameUser
{
Username = FakeUserConstants.DeletedUserName,
Description = "I'm a fake user that represents deleted users for levels.",
Username = SystemUsers.DeletedUserName,
Description = SystemUsers.DeletedUserDescription,
FakeUser = true,
});
});
}
// If that failed and the username is a fake re-upload user, then we need to create the backing fake user
else if (username.StartsWith(FakeUserConstants.Prefix) && user == null)
else if (username.StartsWith(SystemUsers.SystemPrefix) && user == null)
{
this.Write(() =>
{
this.GameUsers.Add(user = new GameUser
{
Username = username,
Description = "I'm a fake user that represents a non existent publisher for re-published levels.",
Description = SystemUsers.UnknownUserDescription,
FakeUser = true,
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,11 @@ public static GameLevelResponse FromHash(string hash, DataContext dataContext)
{
string publisher;
if (!old.IsReUpload)
publisher = FakeUserConstants.DeletedUserName;
publisher = SystemUsers.DeletedUserName;
else
publisher = string.IsNullOrEmpty(old.OriginalPublisher)
? FakeUserConstants.UnknownUserName
: FakeUserConstants.Prefix + old.OriginalPublisher;
? SystemUsers.UnknownUserName
: SystemUsers.SystemPrefix + old.OriginalPublisher;

response.Handle = new SerializedUserHandle
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Xml.Serialization;
using Refresh.Common.Constants;
using Refresh.GameServer.Authentication;
using Refresh.GameServer.Endpoints.ApiV3.DataTypes;
using Refresh.GameServer.Endpoints.Game.Levels.FilterSettings;
Expand All @@ -13,8 +14,6 @@ namespace Refresh.GameServer.Endpoints.Game.DataTypes.Response;
[XmlRoot("user")]
public class GameUserResponse : IDataConvertableFrom<GameUserResponse, GameUser>
{
public const int MaximumLevels = 9_999;

[XmlAttribute("type")] public string Type { get; set; } = "user";
[XmlElement("biography")] public required string Description { get; set; }
[XmlElement("location")] public required GameLocation Location { get; set; }
Expand Down Expand Up @@ -72,9 +71,9 @@ public class GameUserResponse : IDataConvertableFrom<GameUserResponse, GameUser>
PhotosByMeCount = old.IsManaged ? dataContext.Database.GetTotalPhotosByUser(old) : 0,
PhotosWithMeCount = old.IsManaged ? dataContext.Database.GetTotalPhotosWithUser(old) : 0,

EntitledSlots = MaximumLevels,
EntitledSlotsLBP2 = MaximumLevels,
EntitledSlotsLBP3 = MaximumLevels,
EntitledSlots = UgcLimits.MaximumLevels,
EntitledSlotsLBP2 = UgcLimits.MaximumLevels,
EntitledSlotsLBP3 = UgcLimits.MaximumLevels,
UsedSlots = 0,
UsedSlotsLBP2 = 0,
UsedSlotsLBP3 = 0,
Expand Down Expand Up @@ -110,21 +109,21 @@ public class GameUserResponse : IDataConvertableFrom<GameUserResponse, GameUser>
case TokenGame.LittleBigPlanet3: {
//Match all LBP3 levels
response.UsedSlotsLBP3 = dataContext.Database.GetTotalLevelsPublishedByUser(old, TokenGame.LittleBigPlanet3);
response.FreeSlotsLBP3 = MaximumLevels - response.UsedSlotsLBP3;
response.FreeSlotsLBP3 = UgcLimits.MaximumLevels - response.UsedSlotsLBP3;
//Fill out LBP2/LBP1 levels
goto case TokenGame.LittleBigPlanet2;
}
case TokenGame.LittleBigPlanet2: {
//Match all LBP2 levels
response.UsedSlotsLBP2 = dataContext.Database.GetTotalLevelsPublishedByUser(old, TokenGame.LittleBigPlanet2);
response.FreeSlotsLBP2 = MaximumLevels - response.UsedSlotsLBP2;
response.FreeSlotsLBP2 = UgcLimits.MaximumLevels - response.UsedSlotsLBP2;
//Fill out LBP1 levels
goto case TokenGame.LittleBigPlanet1;
}
case TokenGame.LittleBigPlanetVita: {
//Match all LBP Vita levels
response.UsedSlotsLBP2 = dataContext.Database.GetTotalLevelsPublishedByUser(old, TokenGame.LittleBigPlanetVita);
response.FreeSlotsLBP2 = MaximumLevels - response.UsedSlotsLBP2;
response.FreeSlotsLBP2 = UgcLimits.MaximumLevels - response.UsedSlotsLBP2;

//Apply Vita-specific icon hash
response.Handle.IconHash = old.VitaIconHash;
Expand All @@ -133,13 +132,13 @@ public class GameUserResponse : IDataConvertableFrom<GameUserResponse, GameUser>
case TokenGame.LittleBigPlanet1: {
//Match all LBP1 levels
response.UsedSlots = dataContext.Database.GetTotalLevelsPublishedByUser(old, TokenGame.LittleBigPlanet1);
response.FreeSlots = MaximumLevels - response.UsedSlots;
response.FreeSlots = UgcLimits.MaximumLevels - response.UsedSlots;
break;
}
case TokenGame.LittleBigPlanetPSP: {
//Match all LBP PSP levels
response.UsedSlots = dataContext.Database.GetTotalLevelsPublishedByUser(old, TokenGame.LittleBigPlanetPSP);
response.FreeSlots = MaximumLevels - response.UsedSlots;
response.FreeSlots = UgcLimits.MaximumLevels - response.UsedSlots;

// Apply PSP-specific icon hash
response.Handle.IconHash = old.PspIconHash;
Expand All @@ -161,7 +160,7 @@ public class GameUserResponse : IDataConvertableFrom<GameUserResponse, GameUser>
{
// only beta levels
response.UsedSlots = dataContext.Database.GetTotalLevelsPublishedByUser(old, TokenGame.BetaBuild);
response.FreeSlots = MaximumLevels - response.UsedSlotsLBP2;
response.FreeSlots = UgcLimits.MaximumLevels - response.UsedSlotsLBP2;

// use the same values for LBP3 and LBP2 since they're all shared under one count
response.UsedSlotsLBP3 = response.UsedSlots;
Expand Down
8 changes: 4 additions & 4 deletions Refresh.GameServer/Endpoints/Game/Levels/PublishEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ public class PublishEndpoints : EndpointGroup
/// <returns>Whether validation succeeded</returns>
private static bool VerifyLevel(GameLevelRequest body, DataContext dataContext)
{
if (body.Title.Length > UgcConstantLimits.TitleLimit)
body.Title = body.Title[..UgcConstantLimits.TitleLimit];
if (body.Title.Length > UgcLimits.TitleLimit)
body.Title = body.Title[..UgcLimits.TitleLimit];

if (body.Description.Length > UgcConstantLimits.DescriptionLimit)
body.Description = body.Description[..UgcConstantLimits.DescriptionLimit];
if (body.Description.Length > UgcLimits.DescriptionLimit)
body.Description = body.Description[..UgcLimits.DescriptionLimit];

if (body.MaxPlayers is > 4 or < 0 || body.MinPlayers is > 4 or < 0)
return false;
Expand Down
6 changes: 3 additions & 3 deletions Refresh.GameServer/Endpoints/Game/UserEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Bunkum.Core.Storage;
using Bunkum.Listener.Protocol;
using Bunkum.Protocols.Http;
using Refresh.Common.Constants;
using Refresh.GameServer.Authentication;
using Refresh.GameServer.Database;
using Refresh.GameServer.Endpoints.Game.DataTypes.Response;
Expand Down Expand Up @@ -129,10 +130,9 @@ public SerializedFriendsList GetFriends(RequestContext context, GameDatabaseCont
return null;
}

const int maxDescriptionLength = 4096;
if (data.Description is { Length: > maxDescriptionLength })
if (data.Description is { Length: > UgcLimits.DescriptionLimit })
{
database.AddErrorNotification("Profile update failed", $"Your profile failed to update because the description was too long. The max length is {maxDescriptionLength}.", user);
database.AddErrorNotification("Profile update failed", $"Your profile failed to update because the description was too long. The max length is {UgcLimits.DescriptionLimit} characters.", user);
return null;
}

Expand Down
8 changes: 4 additions & 4 deletions RefreshTests.GameServer/Tests/Levels/PublishEndpointsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void LevelWithLongTitleGetsTruncated()
{
LevelId = 0,
IsAdventure = false,
Title = new string('*', UgcConstantLimits.TitleLimit * 2),
Title = new string('*', UgcLimits.TitleLimit * 2),
IconHash = "g0",
Description = "Normal length",
Location = new GameLocation(),
Expand All @@ -117,7 +117,7 @@ public void LevelWithLongTitleGetsTruncated()

message = client.PostAsync("/lbp/publish", new StringContent(level.AsXML())).Result;
Assert.That(message.StatusCode, Is.EqualTo(OK));
Assert.That(message.Content.ReadAsXML<GameLevelResponse>().Title.Length, Is.EqualTo(UgcConstantLimits.TitleLimit));
Assert.That(message.Content.ReadAsXML<GameLevelResponse>().Title.Length, Is.EqualTo(UgcLimits.TitleLimit));
}

[Test]
Expand All @@ -134,7 +134,7 @@ public void LevelWithLongDescriptionGetsTruncated()
IsAdventure = false,
Title = "Normal Title!",
IconHash = "g0",
Description = new string('=', UgcConstantLimits.DescriptionLimit * 2),
Description = new string('=', UgcLimits.DescriptionLimit * 2),
Location = new GameLocation(),
GameVersion = 0,
RootResource = TEST_ASSET_HASH,
Expand All @@ -156,7 +156,7 @@ public void LevelWithLongDescriptionGetsTruncated()

message = client.PostAsync("/lbp/publish", new StringContent(level.AsXML())).Result;
Assert.That(message.StatusCode, Is.EqualTo(OK));
Assert.That(message.Content.ReadAsXML<GameLevelResponse>().Description.Length, Is.EqualTo(UgcConstantLimits.DescriptionLimit));
Assert.That(message.Content.ReadAsXML<GameLevelResponse>().Description.Length, Is.EqualTo(UgcLimits.DescriptionLimit));
}

[Test]
Expand Down

0 comments on commit d632de0

Please sign in to comment.