refactor(auth): decouple Steam handler from request DTO shape
Translation middleware now extracts viewer_id/steam_id/steam_session_ticket from the decrypted msgpack dict into HttpContext.Items before the typed DTO deserialize. The Steam handler reads from there instead of re-parsing Request.Body — so authed action DTOs no longer need to inherit BaseRequest to keep the auth fields alive through the msgpack→DTO→JSON pivot. Retires the recurring footgun documented in docs/superpowers/specs/2026-06-02-baseRequest-auth-footgun-improvement.md (2026-05-25 basic-puzzle, 2026-05-28 deck-code, 2026-06-02 Phase 3 Bot, 2026-06-10 profile/index + item_acquire_history/info + user_mypage/update). Pinned by AuthDecouplingTests — posts an encrypted msgpack body to /profile/index (DTO does not inherit BaseRequest) through the real translation middleware + auth handler and asserts 200. Adds an EncryptedMsgpackHelper + useRealAuthHandler factory flag, reusable for future wire-shape tests. ProfileIndexRequest, ItemAcquireHistoryInfoRequest, and UserMyPageUpdateRequest revert to the naked shape — the per-DTO workarounds become vestigial under the new architecture. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -24,15 +24,17 @@ namespace SVSim.UnitTests.Infrastructure;
|
||||
/// header-driven test versions, and exposes a <see cref="SeedViewerAsync"/> helper for tests
|
||||
/// to create realistic viewer rows.
|
||||
/// </summary>
|
||||
internal sealed class SVSimTestFactory : WebApplicationFactory<Program>
|
||||
internal class SVSimTestFactory : WebApplicationFactory<Program>
|
||||
{
|
||||
private readonly SqliteConnection _connection;
|
||||
private long _nextSeededShortUdid = 400_000_001;
|
||||
private readonly bool _freeplayEnabled;
|
||||
private readonly bool _useRealAuthHandler;
|
||||
|
||||
public SVSimTestFactory(bool freeplayEnabled = false)
|
||||
public SVSimTestFactory(bool freeplayEnabled = false, bool useRealAuthHandler = false)
|
||||
{
|
||||
_freeplayEnabled = freeplayEnabled;
|
||||
_useRealAuthHandler = useRealAuthHandler;
|
||||
// SQLite :memory: lives only as long as a connection is open — keep ours open for the
|
||||
// factory's lifetime so the DbContext can reattach to the same DB across scopes.
|
||||
_connection = new SqliteConnection("DataSource=:memory:");
|
||||
@@ -48,7 +50,19 @@ internal sealed class SVSimTestFactory : WebApplicationFactory<Program>
|
||||
builder.ConfigureTestServices(services =>
|
||||
{
|
||||
ReplaceDbContext(services);
|
||||
ReplaceAuthHandler(services);
|
||||
if (!_useRealAuthHandler)
|
||||
{
|
||||
ReplaceAuthHandler(services);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Real auth handler stays in place; bypass the live Steam SDK so synthetic
|
||||
// tickets validate without touching Steam.
|
||||
var steamServer = services.FirstOrDefault(d => d.ServiceType == typeof(SVSim.EmulatedEntrypoint.Services.ISteamServer));
|
||||
if (steamServer is not null) services.Remove(steamServer);
|
||||
services.AddSingleton<SVSim.EmulatedEntrypoint.Services.ISteamServer,
|
||||
SVSim.EmulatedEntrypoint.Services.DevAlwaysValidSteamServer>();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user