mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-16 14:32:02 +00:00
fix(multiplayer): validate contract ticket input
This commit is contained in:
@@ -1615,6 +1615,8 @@ Queue responses now validate the complete published shape before projection: opa
|
|||||||
|
|
||||||
The public `/api/v1` route adapters now reject non-opaque queue, proposal, assignment, and server path identifiers before delegating to the legacy handlers; adversarial route tests cover short and separator-bearing IDs.
|
The public `/api/v1` route adapters now reject non-opaque queue, proposal, assignment, and server path identifiers before delegating to the legacy handlers; adversarial route tests cover short and separator-bearing IDs.
|
||||||
|
|
||||||
|
The public queue adapter also rejects an explicitly supplied short or unsafe `ticket_id`; omitted IDs continue to be deterministically server-assigned for idempotent retries.
|
||||||
|
|
||||||
Signed MatchNet claims now also require exact JSON string/integer types for every identity, protocol, expiry, slot, team, and generation field; string-number coercion is rejected before canonical signature verification.
|
Signed MatchNet claims now also require exact JSON string/integer types for every identity, protocol, expiry, slot, team, and generation field; string-number coercion is rejected before canonical signature verification.
|
||||||
|
|
||||||
Presentation progress: a shared `Game/themes/cosmic_clash_theme.tres` now gives the menu, lobby, matchmaking, and settings surfaces consistent button, input, option, and label styling. The custom-font portion of `TODO.md` remains open until a distributable font asset is selected.
|
Presentation progress: a shared `Game/themes/cosmic_clash_theme.tres` now gives the menu, lobby, matchmaking, and settings surfaces consistent button, input, option, and label styling. The custom-font portion of `TODO.md` remains open until a distributable font asset is selected.
|
||||||
|
|||||||
@@ -453,6 +453,13 @@ func (s *Service) contractQueueCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
var fields map[string]json.RawMessage
|
var fields map[string]json.RawMessage
|
||||||
if json.Unmarshal(body, &fields) == nil {
|
if json.Unmarshal(body, &fields) == nil {
|
||||||
|
if rawTicketID, exists := fields["ticket_id"]; exists {
|
||||||
|
var ticketID string
|
||||||
|
if json.Unmarshal(rawTicketID, &ticketID) != nil || !controlPlaneResourceIDRE.MatchString(ticketID) {
|
||||||
|
writeError(w, http.StatusBadRequest, "invalid_request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
// Ticket IDs are server-assigned for the public contract. Deriving one
|
// Ticket IDs are server-assigned for the public contract. Deriving one
|
||||||
// from the authenticated request's idempotency material makes retries
|
// from the authenticated request's idempotency material makes retries
|
||||||
// converge on the same domain command without persisting adapter state.
|
// converge on the same domain command without persisting adapter state.
|
||||||
|
|||||||
@@ -281,6 +281,18 @@ func TestDocumentedContractRoutesRejectNonOpaqueResourceIDs(t *testing.T) {
|
|||||||
service := &Service{}
|
service := &Service{}
|
||||||
server := httptest.NewServer(service.Handler())
|
server := httptest.NewServer(service.Handler())
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
request, err := http.NewRequest(http.MethodPost, server.URL+"/api/v1/queue/tickets", strings.NewReader(`{"ticket_id":"short","playlist":"casual","client_build":"build-1","protocol_version":1}`))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if response, requestErr := http.DefaultClient.Do(request); requestErr != nil {
|
||||||
|
t.Fatal(requestErr)
|
||||||
|
} else {
|
||||||
|
if response.StatusCode != http.StatusBadRequest {
|
||||||
|
t.Fatalf("short supplied ticket id status = %d, want 400", response.StatusCode)
|
||||||
|
}
|
||||||
|
response.Body.Close()
|
||||||
|
}
|
||||||
paths := []string{
|
paths := []string{
|
||||||
"/api/v1/queue/tickets/short/heartbeat",
|
"/api/v1/queue/tickets/short/heartbeat",
|
||||||
"/api/v1/proposals/proposal/unsafe/accept",
|
"/api/v1/proposals/proposal/unsafe/accept",
|
||||||
|
|||||||
Reference in New Issue
Block a user