Skip to content

Commit

Permalink
Add per-user filesize quotas
Browse files Browse the repository at this point in the history
  • Loading branch information
Beyley committed Mar 23, 2024
1 parent 422934f commit 8673128
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 3 deletions.
4 changes: 4 additions & 0 deletions Refresh.GameServer/Configuration/GameServerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ protected override void Migrate(int oldVer, dynamic oldConfig) {}
public string WebExternalUrl { get; set; } = "https://refresh.example.com";
public bool AllowInvalidTextureGuids { get; set; } = false;
public bool BlockAssetUploads { get; set; } = false;
/// <summary>
/// The amount of data the user is allowed to upload before all resource uploads get blocked, defaults to 100mb.
/// </summary>
public int UserFilesizeQuota { get; set; } = 100 * 1_048_576;
}
8 changes: 8 additions & 0 deletions Refresh.GameServer/Database/GameDatabaseContext.Users.cs
Original file line number Diff line number Diff line change
Expand Up @@ -352,4 +352,12 @@ public void ForceUserTokenPlatform(Token token, TokenPlatform platform)
token.TokenPlatform = platform;
});
}

public void IncrementUserFilesizeQuota(GameUser user, int amount)
{
this._realm.Write(() =>
{
user.FilesizeQuotaUsage += amount;
});
}
}
11 changes: 10 additions & 1 deletion Refresh.GameServer/Database/GameDatabaseProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected GameDatabaseProvider(IDateTimeProvider time)
this._time = time;
}

protected override ulong SchemaVersion => 116;
protected override ulong SchemaVersion => 117;

protected override string Filename => "refreshGameServer.realm";

Expand Down Expand Up @@ -173,6 +173,15 @@ protected override void Migrate(Migration migration, ulong oldVersion)

// In version 102 we split the Vita icon hash from the PS3 icon hash
if (oldVersion < 102) newUser.VitaIconHash = "0";

//In version 117, we started tracking the amount of data the user has uploaded to the server
if (oldVersion < 117)
{
newUser.FilesizeQuotaUsage = migration.NewRealm.All<GameAsset>()
.AsEnumerable()
.Where(a => a.OriginalUploader?.UserId == newUser.UserId)
.Sum(a => a.SizeInBytes);
}
}

IQueryable<dynamic>? oldLevels = migration.OldRealm.DynamicApi.All("GameLevel");
Expand Down
12 changes: 10 additions & 2 deletions Refresh.GameServer/Endpoints/Game/ResourceEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ public Response UploadAsset(RequestContext context, string hash, string type, by

if (dataStore.ExistsInStore(assetPath))
return Conflict;


if (body.Length + user.FilesizeQuotaUsage > config.UserFilesizeQuota)
{
context.Logger.LogWarning(BunkumCategory.UserContent, "User {0} has hit the filesize quota ({1} bytes), rejecting.", user.Username, config.UserFilesizeQuota);
return RequestEntityTooLarge;
}

if (body.Length > 1_048_576 * 2)
{
context.Logger.LogWarning(BunkumCategory.UserContent, "{0} is above 2MB ({1} bytes), rejecting.", hash, body.Length);
Expand Down Expand Up @@ -70,7 +76,9 @@ public Response UploadAsset(RequestContext context, string hash, string type, by

gameAsset.OriginalUploader = user;
database.AddAssetToDatabase(gameAsset);


database.IncrementUserFilesizeQuota(user, body.Length);

return OK;
}

Expand Down
5 changes: 5 additions & 0 deletions Refresh.GameServer/Types/UserData/GameUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public partial class GameUser : IRealmObject, IRateLimitUser
/// The <see cref="IconHash"/>, except only for clients in beta mode.
/// </summary>
public string BetaIconHash { get; set; } = "0";

/// <summary>
/// The cumulative size of all the assets the user has uploaded
/// </summary>
public int FilesizeQuotaUsage { get; set; }

public string Description { get; set; } = "";
public GameLocation Location { get; set; } = GameLocation.Zero;
Expand Down
32 changes: 32 additions & 0 deletions RefreshTests.GameServer/Tests/Assets/AssetUploadTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,38 @@ public void CanUploadAsset(bool psp)
Assert.That(response.StatusCode, Is.EqualTo(OK));
}

[TestCase(false)]
[TestCase(true)]
public void CannotUploadAssetPastFillingFilesizeQuota(bool psp)
{
using TestContext context = this.GetServer();

context.Server.Value.GameServerConfig.UserFilesizeQuota = 8;

context.Server.Value.Server.AddService<ImportService>();
GameUser user = context.CreateUser();
using HttpClient client = context.GetAuthenticatedClient(TokenType.Game, user);
if(psp)
client.DefaultRequestHeaders.UserAgent.TryParseAdd("LBPPSP CLIENT");

ReadOnlySpan<byte> data1 = "TEX a"u8;
ReadOnlySpan<byte> data2 = "TEX b"u8;

string hash1 = BitConverter.ToString(SHA1.HashData(data1))
.Replace("-", "")
.ToLower();

string hash2 = BitConverter.ToString(SHA1.HashData(data2))
.Replace("-", "")
.ToLower();

HttpResponseMessage response = client.PostAsync("/lbp/upload/" + hash1, new ByteArrayContent(data1.ToArray())).Result;
Assert.That(response.StatusCode, Is.EqualTo(OK));

response = client.PostAsync("/lbp/upload/" + hash2, new ByteArrayContent(data2.ToArray())).Result;
Assert.That(response.StatusCode, Is.EqualTo(RequestEntityTooLarge));
}

[TestCase(false)]
[TestCase(true)]
public void CannotUploadAssetWhenBlocked(bool psp)
Expand Down

0 comments on commit 8673128

Please sign in to comment.