carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package console
2
3import (
4 "bytes"
5 "encoding/json"
6 "net/http"
7 "net/http/httptest"
8 "testing"
9 "time"
10
11 "github.com/carlosframework/platform/internal/release"
12)
13
14func TestHostClaimRoutesArePersonOperatorFlagGatedAndInert(t *testing.T) {
15 st := openGatedStore(t)
16 rel := release.NewDirStore(t.TempDir())
17 disabled, err := NewServer(Config{Origin: "https://console.example", Keymail: "https://keymail.example", Releases: rel}, st)
18 if err != nil {
19 t.Fatal(err)
20 }
21 path := "/api/cli/ops/hosts/app.example.com/resolve/inspect"
22 ghostStatus, ghostBody := serveHostClaim(t, disabled, "/unknown-host-claim-route", "")
23 if status, body := serveHostClaim(t, disabled, path, ""); status != ghostStatus || !bytes.Equal(body, ghostBody) {
24 t.Fatalf("flag-off route = %d %q, want unknown route %d %q", status, body, ghostStatus, ghostBody)
25 }
26
27 token := mintHostClaimToken(t, st, "paul@keymail.dev")
28 enabled, err := NewServer(Config{Origin: "https://console.example", Keymail: "https://keymail.example", Releases: rel, HostClaim: true}, st)
29 if err != nil {
30 t.Fatal(err)
31 }
32 if status, _ := serveHostClaim(t, enabled, path, ""); status != http.StatusUnauthorized {
33 t.Fatalf("unsigned enabled status = %d", status)
34 }
35 if status, _ := serveHostClaim(t, enabled, path, token); status != http.StatusNotFound {
36 t.Fatalf("enabled member status = %d", status)
37 }
38 if err := st.SetOperator("paul@keymail.dev", true); err != nil {
39 t.Fatal(err)
40 }
41 status, body := serveHostClaim(t, enabled, path, token)
42 if status != http.StatusServiceUnavailable {
43 t.Fatalf("flag-on status = %d, body %s", status, body)
44 }
45 var out map[string]string
46 if err := json.Unmarshal(body, &out); err != nil {
47 t.Fatal(err)
48 }
49 if out["error"] != hostClaimUnavailable {
50 t.Fatalf("refusal = %q", out["error"])
51 }
52
53 status, body = serveHostClaim(t, enabled, "/api/cli/ops/hosts/app.example.com/resolve", token)
54 if status != http.StatusServiceUnavailable {
55 t.Fatalf("mutation route = %d, body %s", status, body)
56 }
57}
58
59func mintHostClaimToken(t *testing.T, st *Store, address string) string {
60 t.Helper()
61 now := time.Now()
62 userCode, deviceCode, err := st.NewCLIAuth("test@host", "192.0.2.1", now)
63 if err != nil {
64 t.Fatal(err)
65 }
66 if err := st.ApproveCLIAuth(userCode, address, now); err != nil {
67 t.Fatal(err)
68 }
69 status, token, _, err := st.PollCLIAuth(deviceCode, now)
70 if err != nil || status != CLIAuthApproved || token == "" {
71 t.Fatalf("mint token = %q %v", status, err)
72 }
73 return token
74}
75
76func serveHostClaim(t *testing.T, srv *Server, path, bearer string) (int, []byte) {
77 t.Helper()
78 req := httptest.NewRequest(http.MethodPost, path, bytes.NewBufferString(`{}`))
79 req.Header.Set("Content-Type", "application/json")
80 if bearer != "" {
81 req.Header.Set("Authorization", "Bearer "+bearer)
82 }
83 rec := httptest.NewRecorder()
84 srv.ServeHTTP(rec, req)
85 return rec.Code, rec.Body.Bytes()
86}
87