mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-11-09 07:39:19 -05:00
npm metadata rewriting depended on handler.Proxy, which pulls SQL drivers, cloud SDKs and metrics into its import graph. Move the transformation into internal/metadata/npm with explicit policy, evaluation time, public URL and hosted-version inputs, and share the JSON scanner between npm and Composer through internal/jsonscan. Rebased onto main: rewritten tarball URLs are still logged once per document, now through an OnTarballsRewritten callback that reports the count.
161 lines
6.3 KiB
Go
161 lines
6.3 KiB
Go
package npm
|
|
|
|
import (
|
|
"bytes"
|
|
_ "embed"
|
|
"encoding/json"
|
|
"errors"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/git-pkgs/cooldown"
|
|
)
|
|
|
|
//go:embed testdata/packument.json
|
|
var packument []byte
|
|
|
|
func TestRewriteCallbacks(t *testing.T) {
|
|
options := Options{ProxyURL: "https://proxy.example", Cooldown: &cooldown.Config{Default: "7d"},
|
|
DeniedVersions: map[string]bool{"2.0.0": true}, EvaluatedAt: time.Date(2030, 1, 1, 0, 0, 0, 0, time.UTC)}
|
|
want, kept, err := Rewrite("@example/widgets", packument, options)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var rewrites, filtered int
|
|
options.OnTarballsRewritten = func(count int) {
|
|
rewrites++
|
|
if count != 1 {
|
|
t.Errorf("rewrite count = %d, want 1", count)
|
|
}
|
|
}
|
|
options.OnCooldownFilter = func(version, publishedAt string) {
|
|
filtered++
|
|
if version != "3.0.0" || publishedAt != "2099-01-01T00:00:00Z" {
|
|
t.Errorf("filter event: %s, %s", version, publishedAt)
|
|
}
|
|
}
|
|
out, gotKept, err := Rewrite("@example/widgets", packument, options)
|
|
if err != nil || !bytes.Equal(out, want) || !slices.Equal(gotKept, kept) || rewrites != 1 || filtered != 1 {
|
|
t.Fatalf("callbacks: rewrites=%d, filtered=%d, kept=%v, error=%v", rewrites, filtered, gotKept, err)
|
|
}
|
|
}
|
|
|
|
func TestRewriteHostedOverride(t *testing.T) {
|
|
options := Options{
|
|
ProxyURL: "https://proxy.example",
|
|
Cooldown: &cooldown.Config{Default: "7d"},
|
|
DeniedVersions: map[string]bool{"2.0.0": true},
|
|
EvaluatedAt: time.Date(2030, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
LocalVersions: []LocalVersion{{Version: "3.0.0", PublishedAt: "2030-01-01T00:00:00Z",
|
|
Entry: json.RawMessage(`{"version":"3.0.0","dist":{"tarball":"https://proxy.example/npm/@example%2Fwidgets/-/widgets-3.0.0.tgz","integrity":"sha512-local"}}`)}},
|
|
}
|
|
before := bytes.Clone(packument)
|
|
localBefore := bytes.Clone(options.LocalVersions[0].Entry)
|
|
out, kept, err := Rewrite("@example/widgets", packument, options)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
slices.Sort(kept)
|
|
if !slices.Equal(kept, []string{"1.0.0", "3.0.0"}) {
|
|
t.Fatalf("kept = %v", kept)
|
|
}
|
|
var doc struct {
|
|
Versions map[string]json.RawMessage `json:"versions"`
|
|
Tags map[string]string `json:"dist-tags"`
|
|
Time map[string]string `json:"time"`
|
|
}
|
|
if err := json.Unmarshal(out, &doc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(doc.Versions) != 2 || !bytes.Equal(doc.Versions["3.0.0"], localBefore) || doc.Time["3.0.0"] != options.LocalVersions[0].PublishedAt {
|
|
t.Fatalf("hosted override lost: %s", out)
|
|
}
|
|
if len(doc.Tags) != 1 || doc.Tags["latest"] != "1.0.0" || doc.Time["2.0.0"] != "" || doc.Time["created"] == "" {
|
|
t.Fatalf("policy output: %s", out)
|
|
}
|
|
for _, want := range []string{"12345678901234567890", "<b>Widgets & tools</b>", "https://proxy.example/npm/@example%2Fwidgets/-/widgets-1.0.0.tgz"} {
|
|
if !strings.Contains(string(out), want) {
|
|
t.Errorf("output lost %q", want)
|
|
}
|
|
}
|
|
if !bytes.Equal(packument, before) || !bytes.Equal(options.LocalVersions[0].Entry, localBefore) || len(options.DeniedVersions) != 1 || !options.DeniedVersions["2.0.0"] {
|
|
t.Fatal("rewrite mutated its input")
|
|
}
|
|
again, _, err := Rewrite("@example/widgets", packument, options)
|
|
if err != nil || !bytes.Equal(out, again) {
|
|
t.Fatalf("repeat changed output: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestVersionPolicyErrors(t *testing.T) {
|
|
options := Options{ProxyURL: "https://proxy.example", Cooldown: &cooldown.Config{Default: "7d"},
|
|
DeniedVersions: map[string]bool{"2.0.0": true}, EvaluatedAt: time.Date(2030, 1, 1, 0, 0, 0, 0, time.UTC)}
|
|
for _, tc := range []struct {
|
|
specifier string
|
|
want error
|
|
}{
|
|
{"1.0.0", nil}, {"latest", nil}, {"2.0.0", ErrVersionDenied}, {"3.0.0", ErrVersionNotFound}, {"beta", ErrVersionNotFound}, {"missing", ErrVersionNotFound},
|
|
} {
|
|
t.Run(tc.specifier, func(t *testing.T) {
|
|
var counts []int
|
|
options := options
|
|
options.OnTarballsRewritten = func(count int) { counts = append(counts, count) }
|
|
out, err := Version("@example/widgets", tc.specifier, packument, options)
|
|
if !errors.Is(err, tc.want) {
|
|
t.Fatalf("error = %v, want %v", err, tc.want)
|
|
}
|
|
// The packument is reported once; picking one version out of it
|
|
// is not a second report.
|
|
if !slices.Equal(counts, []int{1}) {
|
|
t.Errorf("rewrite reports = %v, want [1]", counts)
|
|
}
|
|
if tc.want == nil && (!bytes.Contains(out, []byte(`"version": "1.0.0"`)) || !bytes.Contains(out, []byte("https://proxy.example/npm/@example%2Fwidgets/-/widgets-1.0.0.tgz"))) {
|
|
t.Fatalf("resolved version: %s", out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRewriteCooldownEvaluationTime(t *testing.T) {
|
|
body := []byte(`{"versions":{"1.0.0":{}},"time":{"1.0.0":"2030-01-01T00:00:00Z"}}`)
|
|
boundary := time.Date(2030, 1, 8, 0, 0, 0, 0, time.UTC)
|
|
options := Options{Cooldown: &cooldown.Config{Default: "7d"}}
|
|
for _, tc := range []struct {
|
|
at time.Time
|
|
count int
|
|
}{
|
|
{boundary.Add(-time.Nanosecond), 0}, {boundary, 1}, {boundary.Add(time.Second), 1},
|
|
} {
|
|
options.EvaluatedAt = tc.at
|
|
_, kept, err := Rewrite("@example/widgets", body, options)
|
|
if err != nil || len(kept) != tc.count {
|
|
t.Errorf("at %s: kept %v, error %v", tc.at, kept, err)
|
|
}
|
|
}
|
|
options.Cooldown = &cooldown.Config{Default: "7d", Packages: map[string]string{"pkg:npm/%40example/widgets": "0"}}
|
|
options.EvaluatedAt = boundary.Add(-time.Hour)
|
|
_, kept, err := Rewrite("@example/widgets", body, options)
|
|
if err != nil || len(kept) != 1 {
|
|
t.Fatalf("scoped exemption: kept %v, error %v", kept, err)
|
|
}
|
|
}
|
|
|
|
func TestRewriteVersionDocument(t *testing.T) {
|
|
body := []byte(`{"name":"@example/widgets","version":"1.0.0","dist":{"tarball":"https://cdn.example/abcdef.tgz"}}`)
|
|
options := Options{ProxyURL: "https://proxy.example"}
|
|
out, kept, err := Rewrite("@example/widgets", body, options)
|
|
if err != nil || !slices.Equal(kept, []string{"1.0.0"}) || !bytes.Contains(out, []byte("https://proxy.example/npm/@example%2Fwidgets/-/widgets-1.0.0.tgz")) {
|
|
t.Fatalf("rewrite: %s, %v, %v", out, kept, err)
|
|
}
|
|
var counts []int
|
|
options.OnTarballsRewritten = func(count int) { counts = append(counts, count) }
|
|
if _, _, err := Rewrite("@example/widgets", body, options); err != nil || !slices.Equal(counts, []int{1}) {
|
|
t.Fatalf("version document reported %v, %v", counts, err)
|
|
}
|
|
options.DeniedVersions = map[string]bool{"1.0.0": true}
|
|
if _, _, err := Rewrite("@example/widgets", body, options); !errors.Is(err, ErrVersionDenied) {
|
|
t.Fatalf("denied version: %v", err)
|
|
}
|
|
}
|