Skip to content
quarry Artifact [240a4a90b9]
Login

Artifact [240a4a90b9]

Artifact 240a4a90b92c98cadb3f87ca4498a36703126d87ff79aa0f7d24ace3280dee62:


package api

import (
	"context"
	"errors"
	"path/filepath"
	"strings"
	"testing"

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

// A repository is made in a team's namespace only by somebody who manages
// the team (RFC 0025), the rule team.repo.add already keeps: holding a
// team's name is not a way to put work under it.
func TestOnlyATeamsOwnerCreatesInIt(t *testing.T) {
	db, err := oltp.Open(filepath.Join(t.TempDir(), "o.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { db.Close() })
	for _, who := range []string{"ada", "bob"} {
		if err := db.AddAccount(who, "a-long-enough-password", false); err != nil {
			t.Fatal(err)
		}
	}
	if err := db.AddTeam("crew", "Crew", "", "ada"); err != nil {
		t.Fatal(err)
	}
	reg := &fakeRegistry{}
	r := ops.NewRegistry()
	if err := RegisterAll(r, Deps{Version: "v", Repos: NewRepos(nil), Registry: reg,
		Accounts: newFakeAccounts(), Teams: db}); err != nil {
		t.Fatal(err)
	}
	as := func(who string) context.Context { return ops.WithUser(context.Background(), who) }

	if _, err := r.Invoke(as("bob"), "repo.add", repoAddIn{Name: "widgets", Namespace: "crew", Create: true}); !errors.Is(err, ops.ErrForbidden) {
		t.Errorf("FAIL: bob created in ada's team: %v", err)
	}
	if len(reg.added) != 0 {
		t.Fatal("FAIL: a refused create reached the registry")
	}
	got, err := r.Invoke(as("bob"), "repo.name", repoNameIn{Name: "widgets", Namespace: "crew"})
	if err != nil || got.(repoNameOut).Free {
		t.Errorf("FAIL: the name check offered bob ada's team: %+v %v", got, err)
	}
	out, err := r.Invoke(as("ada"), "repo.add", repoAddIn{Name: "widgets", Namespace: "crew", Create: true})
	if err != nil {
		t.Fatalf("FAIL: ada could not create in her own team: %v", err)
	}
	// The registry places it in the team, before it takes its name.
	if o := out.(repoAddOut); o.Namespace != "crew" || o.Handle != "widgets" ||
		len(reg.added) != 1 || reg.added[0].Namespace != "crew" {
		t.Errorf("FAIL: ada's repository is %+v; the registry was asked %+v", o, reg.added)
	}
}

// What the forge sends a person names a repository by its address, not
// its key (RFC 0025): the label in text, the address in links, and a
// repoName beside the key every notification is routed by.
func TestWhatTheForgeSendsNamesARepositoryByItsAddress(t *testing.T) {
	d := Deps{Origin: "https://forge.example", Address: func(repo string) (string, string, bool) {
		switch repo {
		case "rp-k2m9x7qa":
			return "dan", "tools", true
		case "tcl":
			return "zeitforge", "tcl", true
		}
		return "", "", false
	}}
	if got := d.repoLabel("rp-k2m9x7qa"); got != "dan/tools" {
		t.Errorf("FAIL: the minted repository is labelled %q", got)
	}
	for path, want := range map[string]string{
		"/r/rp-k2m9x7qa/landing/abc": "https://forge.example/r/dan/tools/landing/abc",
		"/r/tcl":                     "https://forge.example/r/zeitforge/tcl",
		"/r/nonesuch/ticket/1":       "https://forge.example/r/nonesuch/ticket/1",
		"/me#notifications":          "https://forge.example/me#notifications",
	} {
		if got := d.link(path); got != want {
			t.Errorf("FAIL: link(%q) = %q, want %q", path, got, want)
		}
	}
	e := NotifyEvent{Workflow: "quarry-landing", To: "ada", Payload: map[string]any{"repo": "rp-k2m9x7qa"}}
	d.fireNotify(e)
	if e.Payload["repoName"] != "dan/tools" || e.Payload["repo"] != "rp-k2m9x7qa" {
		t.Errorf("FAIL: the payload reads %v", e.Payload)
	}
	if m, ok := moderationEvent("rp-k2m9x7qa", d.repoLabel("rp-k2m9x7qa"), "jan", "jva", "post", "rejected", "x", "", "l", "1"); !ok ||
		!strings.Contains(m.Payload["title"].(string), "in dan/tools") {
		t.Errorf("FAIL: the moderation notice says %v", m.Payload["title"])
	}
}