Skip to content
quarry Artifact [023644bff7]
Login

Artifact [023644bff7]

Artifact 023644bff78a8e7f8b8325632c616ce6fb3483c4d4ea71e482eb09db7aaf631c:


package web

import (
	"context"
	"net/http"
	"net/http/httptest"
	"testing"

	"craftdesign.group/quarry/internal/api"
	"craftdesign.group/quarry/internal/ops"
)

// The attachment read routes carry the reader's identity into the op,
// the way every gated page does. Without it a private repository —
// which the op layer keeps invisible to whoever cannot read it — was
// invisible to its own members on exactly these routes.
func TestAttachmentReadRoutesCarryTheReadersIdentity(t *testing.T) {
	var saw []string
	r := ops.NewRegistry()
	type linkOut struct {
		External bool   `json:"external"`
		Download string `json:"download"`
		Inline   string `json:"inline"`
	}
	if err := ops.Register(r, ops.Op[viewIn, linkOut]{
		Name: "attachment.link", Caps: "jr", Doc: "test stub", Kind: ops.Query, Auth: ops.Anonymous,
		Route: "GET /api/v1/r/{repo}/attachment/{hash}/link",
		Run: func(ctx context.Context, in viewIn) (linkOut, error) {
			saw = append(saw, ops.User(ctx))
			return linkOut{External: true, Download: "https://bucket.example/x"}, nil
		},
	}); err != nil {
		t.Fatal(err)
	}
	verify := Verify(func(repo, user, pass string, need ops.Auth) api.Decision { return api.Allowed })
	h := HandlerWith(r, nil, nil, []Option{WithSessions(fakeSessions{user: "dan", roles: map[string]ops.Auth{"": ops.Admin}})}, verify)
	srv := httptest.NewServer(h)
	t.Cleanup(srv.Close)
	client := &http.Client{CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }}

	req, _ := http.NewRequest("GET", srv.URL+"/r/alpha/attachment/abc/get", nil)
	req.AddCookie(&http.Cookie{Name: sessionCookie, Value: "good"})
	resp, err := client.Do(req)
	if err != nil {
		t.Fatal(err)
	}
	resp.Body.Close()
	if resp.StatusCode != http.StatusFound {
		t.Fatalf("FAIL: signed-in reader got %d, want a redirect to the bucket", resp.StatusCode)
	}
	anon, _ := http.NewRequest("GET", srv.URL+"/r/alpha/attachment/abc/get", nil)
	resp, err = client.Do(anon)
	if err != nil {
		t.Fatal(err)
	}
	resp.Body.Close()
	if len(saw) != 2 || saw[0] != "dan" || saw[1] != "" {
		t.Fatalf("FAIL: the op saw %q, want the member first and then nobody", saw)
	}
	t.Log("ok: the link op learns who is asking, so the read gate can answer per reader")
}