package main
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"craftdesign.group/quarry/internal/oltp"
)
// RFC 0022 rung 1 across the doors: a repository admin mirrors a public
// repository from the API or the settings page and gets the deploy
// key's public line; a reader without `a` cannot; a private repository
// is refused at both doors; an agent holding `a` may; stopping discards
// the key.
func TestARepositoryAdminMirrorsAPublicRepositoryToGit(t *testing.T) {
g := newSiteRig(t)
if err := g.db.AddAccount("bob", doorPassword, false); err != nil {
t.Fatal(err)
}
set := "/api/v1/r/pub/git-mirror"
body := map[string]string{"remote": "[email protected]:alice/pub.git"}
if code, out := g.doAs("bob", http.MethodPost, set, doorPassword, "", body); code == http.StatusOK {
t.Errorf("FAIL: a reader without a mirrored it: %s", out)
}
code, out := g.doAs("alice", http.MethodPost, set, doorPassword, "", body)
if code != http.StatusOK || !strings.Contains(out, `"public_key":"ssh-ed25519 `) {
t.Fatalf("FAIL: the owner's enable: %d %s", code, out)
}
if strings.Contains(out, "PRIVATE") {
t.Fatalf("FAIL: the private key left the forge: %s", out)
}
if code, out := g.doAs("alice", http.MethodPost, "/api/v1/r/secret/git-mirror", doorPassword, "", body); code != http.StatusBadRequest {
t.Errorf("FAIL: a private repository: %d %s", code, out)
}
if code, out := g.doAs("alice", http.MethodPost, set, doorPassword, "",
map[string]string{"remote": "https://github.com/alice/pub.git"}); code != http.StatusBadRequest || !strings.Contains(out, "SSH") {
t.Errorf("FAIL: an HTTPS remote: %d %s", code, out)
}
// The settings page shows the key to its admin, and only to its admin.
page := func(user, repo string) string {
_, b := g.doAs(user, http.MethodGet, "/r/"+repo+"/settings", doorPassword, "", nil)
return b
}
if b := page("alice", "pub"); !strings.Contains(b, `data-hook="git-mirror-key"`) || !strings.Contains(b, "ssh-ed25519 ") {
t.Error("FAIL: the settings page does not show the deploy key")
}
if b := page("bob", "pub"); strings.Contains(b, `data-hook="git-mirror"`) {
t.Error("FAIL: a reader without a sees the mirror section")
}
if b := page("alice", "secret"); !strings.Contains(b, `data-hook="git-mirror-private"`) || strings.Contains(b, `data-hook="git-mirror-form"`) {
t.Error("FAIL: a private repository offers a mirror form")
}
// An agent holding a on a public repository may set one up
// (Decision 2).
if err := g.db.Grant("zeitgeist", "pub", oltp.RepoAdmin); err != nil {
t.Fatal(err)
}
v, _ := g.mint(t, oltp.ScopeAPI)
if code, out := g.do(http.MethodPost, set, v, "", map[string]string{"remote": "[email protected]:alice/pub.git", "branch": "trunk"}); code != http.StatusOK {
t.Errorf("FAIL: an agent holding a: %d %s", code, out)
}
// Stop mirroring from the page.
form := url.Values{"do": {"off"}}
req := httptest.NewRequest(http.MethodPost, "/r/pub/settings/git-mirror", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth("alice", doorPassword)
w := httptest.NewRecorder()
g.h.ServeHTTP(w, req)
if w.Code != http.StatusSeeOther || strings.Contains(w.Header().Get("Location"), "gme=") {
t.Fatalf("FAIL: stop mirroring: %d %s", w.Code, w.Header().Get("Location"))
}
if _, on, _ := g.db.GitMirrorOf("pub"); on {
t.Error("FAIL: the mirror outlived Stop mirroring")
}
log, _ := g.db.SettingsLog("pub", 20)
var actors []string
for _, c := range log {
if c.Field == "git-mirror" {
actors = append(actors, c.Actor+":"+c.Now)
}
}
if strings.Join(actors, " ") != "alice:off alice:on" && strings.Join(actors, " ") != "alice:on alice:off" {
t.Errorf("FAIL: the settings log: %v", actors)
}
}