Skip to content
quarry Artifact [94aa5397a4]
Login

Artifact [94aa5397a4]

Artifact 94aa5397a43ccca0cce813e37464d0dfc01fea2319ecb8db833697422115e2ad:


package ops

import (
	"context"
	"encoding/json"
	"strings"
	"testing"
)

type truthIn struct {
	Repo string `json:"repo" validate:"required,max=64"`
}

// specFor builds a spec from one registry and returns it decoded.
func specFor(t *testing.T, r *Registry) map[string]any {
	t.Helper()
	spec, err := Spec(r, "quarry", "0.0.0-test")
	if err != nil {
		t.Fatal(err)
	}
	raw, err := json.Marshal(spec)
	if err != nil {
		t.Fatal(err)
	}
	var doc map[string]any
	if err := json.Unmarshal(raw, &doc); err != nil {
		t.Fatal(err)
	}
	return doc
}

// The spec declares the scheme that authenticates and no other.
//
// It declared a bearer token on 147 of 209 operations, and the router
// has never accepted one: Authorization: Bearer answers 401, and the
// 401 advertises Basic. A client generated from the document could not
// make a single call and had nothing in the document saying why
// (a907073c, G-5).
func TestTheSpecDeclaresBasicAndNoBearer(t *testing.T) {
	r := NewRegistry()
	if err := Register(r, Op[truthIn, struct{}]{Name: "truth.write", Kind: Command, Auth: Token, Caps: "i",
		Route: "POST /api/v1/r/{repo}/truth", Doc: "test double",
		Run: func(context.Context, truthIn) (struct{}, error) { return struct{}{}, nil }}); err != nil {
		t.Fatal(err)
	}
	doc := specFor(t, r)
	schemes := doc["components"].(map[string]any)["securitySchemes"].(map[string]any)
	if _, ok := schemes["bearerToken"]; ok {
		t.Fatal("FAIL: the spec still declares a bearer scheme the router rejects")
	}
	basic, ok := schemes["basicAuth"].(map[string]any)
	if !ok || basic["scheme"] != "basic" {
		t.Fatalf("FAIL: basicAuth not declared as http/basic: %v", schemes)
	}
	op := doc["paths"].(map[string]any)["/api/v1/r/{repo}/truth"].(map[string]any)["post"].(map[string]any)
	sec := op["security"].([]any)[0].(map[string]any)
	if _, ok := sec["basicAuth"]; !ok {
		t.Fatalf("FAIL: the operation's security requirement is not basicAuth: %v", sec)
	}
	t.Log("ok: basicAuth declared, bearerToken gone, operations require basicAuth")
}

// An operation's capability letters and their scope travel with it, and
// its summary says so. The auth level is the router's floor, not the
// gate: mirror.list is "token" and refuses every ordinary account
// because it needs capability a (763c5c89).
func TestAnOperationPublishesTheCapabilityItsGateNeeds(t *testing.T) {
	r := NewRegistry()
	if err := Register(r, Op[truthIn, struct{}]{Name: "truth.admin", Kind: Query, Auth: Token, Caps: "a", Scope: ScopeFleet,
		Route: "GET /api/v1/truth", Doc: "List everything.",
		Run: func(context.Context, truthIn) (struct{}, error) { return struct{}{}, nil }}); err != nil {
		t.Fatal(err)
	}
	if err := Register(r, Op[truthIn, struct{}]{Name: "truth.either", Kind: Command, Auth: Token, Caps: "kf",
		Route: "POST /api/v1/r/{repo}/truth", Doc: "Write something",
		Run: func(context.Context, truthIn) (struct{}, error) { return struct{}{}, nil }}); err != nil {
		t.Fatal(err)
	}
	doc := specFor(t, r)
	paths := doc["paths"].(map[string]any)
	admin := paths["/api/v1/truth"].(map[string]any)["get"].(map[string]any)
	if admin["x-quarry-caps"] != "a" || admin["x-quarry-auth"] != "token" {
		t.Fatalf("FAIL: caps/level = %v / %v", admin["x-quarry-caps"], admin["x-quarry-auth"])
	}
	if s := admin["summary"].(string); !strings.Contains(s, "Needs capability a on the "+ScopeFleet.String()) {
		t.Fatalf("FAIL: the summary does not say what the gate needs: %q", s)
	}
	either := paths["/api/v1/r/{repo}/truth"].(map[string]any)["post"].(map[string]any)
	if s := either["summary"].(string); !strings.Contains(s, "capability k or f") {
		t.Fatalf("FAIL: a two-letter gate is not read as either: %q", s)
	}
	t.Logf("ok: %q", admin["summary"])
}