71 lines
3.2 KiB
Go
71 lines
3.2 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"testing"
|
|
)
|
|
|
|
// Every door that takes an mc_uuid refuses text that is not a UUID with 400
|
|
// bad_mc_uuid. The columns are Postgres uuids, and such text used to reach the
|
|
// database, fail there with 22P02 and come back as a 500. A UUID in another
|
|
// spelling is stored and echoed in the one Postgres gives back.
|
|
func TestMCUUIDMustBeAUUID(t *testing.T) {
|
|
repo := newFakeRepo()
|
|
repo.byName["survival"] = &ServerRecord{Name: "survival", OwnerID: "u1"}
|
|
repo.claimOK["survival"] = true
|
|
repo.seedUser(UserView{ID: "u2", Username: "alice", Role: "user"})
|
|
cl := newFakeCluster()
|
|
cl.byName["survival"] = &ServerInfo{Name: "survival", AutostartPolicy: "public"}
|
|
api := newTestAPI(repo, cl)
|
|
api.External = staticExternal{p: &Principal{UserID: "owner1", Role: "owner", ViaAdminAccess: true}}
|
|
ih, eh := api.InternalHandler(), api.ExternalHandler()
|
|
|
|
const bad = "not-a-uuid"
|
|
body := `{"mc_uuid":"` + bad + `"}`
|
|
for _, c := range []struct {
|
|
h http.Handler
|
|
method, path, body string
|
|
}{
|
|
{ih, "POST", "/api/v1/internal/servers/survival/join-event", body},
|
|
{ih, "POST", "/api/v1/internal/servers/survival/wake", body},
|
|
{ih, "POST", "/api/v1/internal/servers/survival/claim", body},
|
|
{ih, "GET", "/api/v1/internal/player/menu-access/" + bad, ""},
|
|
{ih, "POST", "/api/v1/internal/account/link/code", body},
|
|
{ih, "GET", "/api/v1/internal/account/link/status/" + bad, ""},
|
|
{ih, "POST", "/api/v1/internal/account/migrate/start", body},
|
|
{ih, "GET", "/api/v1/internal/player/blacklist/" + bad, ""},
|
|
{eh, "PUT", "/api/v1/servers/survival/allowlist/" + bad, `{"can_wake":true}`},
|
|
{eh, "DELETE", "/api/v1/users/u2/links/" + bad, ""},
|
|
{eh, "POST", "/api/v1/users/u2/links", body},
|
|
} {
|
|
w := do(c.h, c.method, c.path, c.body, jsonHeader)
|
|
if w.Code != http.StatusBadRequest || decodeErr(t, w) != "bad_mc_uuid" {
|
|
t.Errorf("%s %s with %q: code = %d body %s, want 400 bad_mc_uuid", c.method, c.path, bad, w.Code, w.Body.String())
|
|
}
|
|
}
|
|
if len(repo.joins) != 0 || len(repo.linkCodes) != 0 || len(repo.links) != 0 || len(repo.audits) != 0 {
|
|
t.Fatalf("a refused mc_uuid wrote joins=%v codes=%v links=%v audits=%v", repo.joins, repo.linkCodes, repo.links, repo.audits)
|
|
}
|
|
|
|
const spelled, canonical = " 069A79F444E94726A5BEFCA90E38AAF5 ", "069a79f4-44e9-4726-a5be-fca90e38aaf5"
|
|
w := do(eh, "POST", "/api/v1/users/u2/links", `{"mc_uuid":"`+spelled+`"}`, jsonHeader)
|
|
var linked struct {
|
|
MCUUID string `json:"mc_uuid"`
|
|
}
|
|
if err := json.Unmarshal(w.Body.Bytes(), &linked); err != nil || w.Code != http.StatusOK || linked.MCUUID != canonical {
|
|
t.Fatalf("link of %q: code = %d body %s, want 200 echoing %s", spelled, w.Code, w.Body.String(), canonical)
|
|
}
|
|
if repo.links[canonical] != "u2" || len(repo.links) != 1 {
|
|
t.Fatalf("links = %v, want only %s → u2", repo.links, canonical)
|
|
}
|
|
if w := do(ih, "POST", "/api/v1/internal/account/link/code", `{"mc_uuid":"`+spelled+`"}`, jsonHeader); w.Code != http.StatusCreated {
|
|
t.Fatalf("link code for %q: code = %d body %s, want 201", spelled, w.Code, w.Body.String())
|
|
}
|
|
for _, lc := range repo.linkCodes {
|
|
if lc.mcUUID != canonical {
|
|
t.Fatalf("link code minted for %q, want %s", lc.mcUUID, canonical)
|
|
}
|
|
}
|
|
}
|