mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-26 07:28:45 -07:00
feat: Implement room blob version clamp toggle; add settings endpoint and UI support for managing version clamping of imported rooms
This commit is contained in:
@@ -1499,6 +1499,7 @@ public class AdminController(
|
||||
row.WeeklyChallengesCompletedRequired,
|
||||
row.ProfanityFilterDisabled,
|
||||
row.AllAvatarItemsOwned,
|
||||
row.RoomBlobVersionClampDisabled,
|
||||
row.UpdatedAt,
|
||||
});
|
||||
}
|
||||
@@ -1526,6 +1527,7 @@ public class AdminController(
|
||||
row.WeeklyChallengesCompletedRequired,
|
||||
row.ProfanityFilterDisabled,
|
||||
row.AllAvatarItemsOwned,
|
||||
row.RoomBlobVersionClampDisabled,
|
||||
row.UpdatedAt,
|
||||
});
|
||||
}
|
||||
@@ -1552,6 +1554,35 @@ public class AdminController(
|
||||
row.WeeklyChallengesCompletedRequired,
|
||||
row.ProfanityFilterDisabled,
|
||||
row.AllAvatarItemsOwned,
|
||||
row.RoomBlobVersionClampDisabled,
|
||||
row.UpdatedAt,
|
||||
});
|
||||
}
|
||||
|
||||
public sealed record RoomBlobVersionClampToggleRequest(bool Disabled);
|
||||
|
||||
/// <summary>POST <c>api/admin/v1/settings/room-blob-version-clamp</c> —
|
||||
/// flip the CDN's PersistedRoomData version clamp. While active (the
|
||||
/// default), room-data blobs are served with their two top-level version
|
||||
/// varints clamped down to the March-2023 client's maxima so rooms
|
||||
/// imported from modern RecNet exports don't trip the client's
|
||||
/// "update Rec Room to visit this room" gate. Disabling serves every
|
||||
/// blob byte-for-byte as stored. Takes effect on the next blob download
|
||||
/// (plus up to a minute of edge cache).</summary>
|
||||
[HttpPost("settings/room-blob-version-clamp")]
|
||||
public async Task<ActionResult> SetRoomBlobVersionClampDisabled([FromBody] RoomBlobVersionClampToggleRequest body)
|
||||
{
|
||||
var row = await serverSettings.SetRoomBlobVersionClampDisabledAsync(body.Disabled);
|
||||
await LogAsync(body.Disabled ? "room_blob_version_clamp_disabled" : "room_blob_version_clamp_enabled", "system", 0, "");
|
||||
await db.SaveChangesAsync();
|
||||
return Ok(new
|
||||
{
|
||||
row.SignupsDisabled,
|
||||
row.GlobalFriendsEnabled,
|
||||
row.WeeklyChallengesCompletedRequired,
|
||||
row.ProfanityFilterDisabled,
|
||||
row.AllAvatarItemsOwned,
|
||||
row.RoomBlobVersionClampDisabled,
|
||||
row.UpdatedAt,
|
||||
});
|
||||
}
|
||||
@@ -1667,6 +1698,7 @@ public class AdminController(
|
||||
row.WeeklyChallengesCompletedRequired,
|
||||
row.ProfanityFilterDisabled,
|
||||
row.AllAvatarItemsOwned,
|
||||
row.RoomBlobVersionClampDisabled,
|
||||
row.UpdatedAt,
|
||||
});
|
||||
}
|
||||
@@ -1690,6 +1722,7 @@ public class AdminController(
|
||||
row.WeeklyChallengesCompletedRequired,
|
||||
row.ProfanityFilterDisabled,
|
||||
row.AllAvatarItemsOwned,
|
||||
row.RoomBlobVersionClampDisabled,
|
||||
row.UpdatedAt,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ public class CdnController(
|
||||
IObjectStorage storage,
|
||||
ImageSignatureService signatures,
|
||||
DorkNetDbContext db,
|
||||
ServerSettingsService serverSettings,
|
||||
ILogger<CdnController> logger) : ControllerBase
|
||||
{
|
||||
/// <summary>1x1 transparent PNG used for missing image files.
|
||||
@@ -494,12 +495,38 @@ public class CdnController(
|
||||
}
|
||||
}
|
||||
|
||||
// Modern-authored saves (RecNet zip exports, 2024+ clients)
|
||||
// stamp PersistedRoomVersion values past what the March-2023
|
||||
// client knows, and it rejects the whole room with the
|
||||
// "update Rec Room to visit this room" gate before spawning
|
||||
// anything. Clamp the two top-level version varints down to
|
||||
// the 2023 maxima on the way out; blobs already at or below
|
||||
// them pass through byte-identical. Admins can bypass the
|
||||
// clamp from the SPA's server-settings page.
|
||||
var clampedRoomVersions = false;
|
||||
if (IsRoomDataName(fileName) &&
|
||||
!await serverSettings.IsRoomBlobVersionClampDisabledAsync())
|
||||
{
|
||||
var (clamped, clampChanged) = RoomDataBlobService.ClampVersionsFor2023(s3Bytes);
|
||||
if (clampChanged)
|
||||
{
|
||||
logger.LogInformation(
|
||||
"[cdn] clamped persisted-room versions to 2023 maxima host={Host} file={File} bytes={Bytes}",
|
||||
Request.Host.Host, fileName, clamped.Length);
|
||||
s3Bytes = clamped;
|
||||
clampedRoomVersions = true;
|
||||
}
|
||||
}
|
||||
|
||||
logger.LogInformation("[cdn] s3 hit host={Host} file={File} bytes={Bytes}",
|
||||
Request.Host.Host, fileName, s3Bytes.Length);
|
||||
// Allow CF edge to cache for an hour. RoomDataBlobs are
|
||||
// content-addressed by hash so the same BlobName never
|
||||
// serves different bytes — safe to cache aggressively.
|
||||
Response.Headers.CacheControl = overlaidRoomRoleData
|
||||
// Overlaid/clamped responses depend on runtime settings, so
|
||||
// keep their edge TTL short enough that admin toggles land
|
||||
// within a minute.
|
||||
Response.Headers.CacheControl = overlaidRoomRoleData || clampedRoomVersions
|
||||
? "public, max-age=60"
|
||||
: "public, max-age=3600";
|
||||
signatures.AddContentSignature(Response, s3Bytes);
|
||||
@@ -654,6 +681,15 @@ public class CdnController(
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Blob names that carry PersistedRoomData: subroom scene
|
||||
/// saves (<c>.room</c>), room-level role/meta blobs (<c>.meta</c>)
|
||||
/// and our synthetic <c>room_<id>_*.dat</c> defaults.</summary>
|
||||
private static bool IsRoomDataName(string name)
|
||||
{
|
||||
var ext = Path.GetExtension(name).ToLowerInvariant();
|
||||
return ext is ".room" or ".meta" or ".dat";
|
||||
}
|
||||
|
||||
private static bool IsImageName(string name)
|
||||
{
|
||||
var ext = Path.GetExtension(name).ToLowerInvariant();
|
||||
|
||||
Reference in New Issue
Block a user