mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
f628ccfd35
newAPIService never supplied SteamLogin, so POST /v1/session/steam always returned 503 auth_unavailable in production. The only implementation was cmd/testkit-api's fake, which derives an identity from the ticket string itself and accepts anything -- so the passing integration path was neither deployable nor secure. On the client side the game started with an empty token and a loopback base URL, and no production code called configure() or login_steam(); the menu entered matchmaking directly, so every request failed ERR_UNAUTHORIZED before reaching the network. Add a real ISteamUserAuth/AuthenticateUserTicket adapter behind an interface, so the production login path is testable with only the Valve call stubbed. It rejects family-shared copies (the account playing does not own the app) and, by default, VAC- or publisher-banned accounts, and refuses malformed tickets locally rather than forwarding them. Crucially it separates our faults from the player's: a Valve outage or a revoked publisher key returns 503, not 401. Answering 401 would tell a legitimate player their login failed and send them to fix an account that is fine while the real fault went unnoticed. A banned identity now returns 403 rather than a misleading 503. Sign-in is configuration-gated on the publisher key and App ID: without them the endpoint keeps returning 503, since silently accepting an unverified ticket would be worse than refusing to authenticate. A returning player keeps the player ID they already had, so ratings, penalties and bans follow the account rather than the session. Client side: acquire a web-API ticket through GodotSteam's async signal -- requesting one returns a handle, not a ticket -- using the existing dynamic-call pattern so stock Godot still parses the project. The endpoint is configurable for release builds, and matchmaking completes sign-in before it will queue. Verified against real PostgreSQL; 232 Godot tests pass.
30 lines
1.6 KiB
GDScript
30 lines
1.6 KiB
GDScript
extends "res://tests/test_case.gd"
|
|
|
|
const SteamBootstrap = preload("res://scripts/steam_bootstrap.gd")
|
|
|
|
|
|
|
|
|
|
# Web-API ticket acquisition (task 7.6). Nothing in the project could obtain a
|
|
# ticket before, so ControlPlaneClient.login_steam() had no production caller.
|
|
# These run on stock Godot, which has no GodotSteam symbols, so they cover the
|
|
# pure encoding and the unavailable path rather than a live Steam session.
|
|
func test_web_api_ticket_is_unsupported_without_the_steam_runtime() -> void:
|
|
if SteamBootstrap.is_runtime_available():
|
|
return
|
|
assert_true(not SteamBootstrap.supports_web_api_ticket(), "no ticket support without the custom build")
|
|
assert_eq(SteamBootstrap.request_web_api_ticket(), 0, "requesting a ticket yields no handle")
|
|
# Must not throw on stock Godot; cancelling a handle we never got is a no-op.
|
|
SteamBootstrap.cancel_web_api_ticket(0)
|
|
SteamBootstrap.cancel_web_api_ticket(17)
|
|
|
|
|
|
func test_web_api_ticket_encoding_is_lowercase_hex() -> void:
|
|
# The publisher Web API expects the raw ticket bytes hex encoded; the
|
|
# backend rejects anything non-hex before it forwards a ticket to Valve.
|
|
assert_eq(SteamBootstrap.encode_web_api_ticket(PackedByteArray()), "", "an empty ticket encodes to nothing")
|
|
assert_eq(SteamBootstrap.encode_web_api_ticket(PackedByteArray([0x00, 0x0f, 0xa5, 0xff])), "000fa5ff", "bytes are zero-padded lowercase hex")
|
|
var encoded := SteamBootstrap.encode_web_api_ticket(PackedByteArray([1, 2, 3, 4, 250]))
|
|
assert_eq(encoded.length(), 10, "each byte becomes exactly two characters")
|
|
assert_eq(encoded, encoded.to_lower(), "encoding is lowercase")
|