package main
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"craftdesign.group/quarry/internal/oltp"
)
// fleetForm posts a fleet form as a person on their password.
func (g siteRig) fleetForm(user, path string, v url.Values) (int, string) {
req := httptest.NewRequest(http.MethodPost, path, strings.NewReader(v.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(user, doorPassword)
w := httptest.NewRecorder()
g.h.ServeHTTP(w, req)
return w.Code, w.Body.String()
}
// A site admin holds no letters on other people's repositories (#318),
// so their settings pages are closed to them; the fleet row is where
// they stop serving or delete one. Every row offers stopping; only a
// store this node created offers deleting, behind the name typed back.
func TestTheFleetRowStopsAndDeletesForASiteAdmin(t *testing.T) {
g := newSiteRig(t)
code, body := g.doAs("dmestas", http.MethodGet, "/fleet", doorPassword, "", nil)
if code != http.StatusOK {
t.Fatalf("fleet: %d", code)
}
if n := strings.Count(body, `data-hook="fleet-row-menu"`); n < 4 {
t.Errorf("FAIL: %d row menus, want one for every store", n)
}
if n := strings.Count(body, `data-hook="fleet-stop"`); n < 4 {
t.Errorf("FAIL: %d stop-serving forms, want one for every store", n)
}
if !strings.Contains(body, `href="/fleet?delete=pub"`) {
t.Error("FAIL: no delete link for pub, which this node created")
}
if strings.Contains(body, `href="/fleet?delete=secret"`) {
t.Error("FAIL: a delete link for secret, which this node did not create")
}
if _, body := g.doAs("dmestas", http.MethodGet, "/fleet?delete=pub", doorPassword, "", nil); !strings.Contains(body, `data-hook="fleet-delete"`) {
t.Error("FAIL: no confirmation for deleting pub")
}
if _, body := g.doAs("dmestas", http.MethodGet, "/fleet?delete=secret", doorPassword, "", nil); strings.Contains(body, `data-hook="fleet-delete"`) {
t.Error("FAIL: a confirmation for deleting secret, which this node did not create")
}
if code, body := g.fleetForm("dmestas", "/fleet/repo/delete", url.Values{"repo": {"pub"}, "confirm": {"pub"}}); code != http.StatusSeeOther {
t.Errorf("FAIL: the site admin's delete of alice's pub: %d %s", code, body)
}
if strings.Join(g.regs.deleted, ",") != "pub" {
t.Errorf("FAIL: deleted %v, want pub", g.regs.deleted)
}
}
// The fleet delete calls repo.delete in-process, so the op holds the
// line itself: an account with no letters on a store deletes nothing
// from the fleet, and a site token's session cannot destroy a private
// store it holds no grant on.
func TestTheFleetDeleteHoldsTheOpsLine(t *testing.T) {
g := newSiteRig(t)
if err := g.db.AddAccount("bob", doorPassword, false); err != nil {
t.Fatal(err)
}
if code, _ := g.fleetForm("bob", "/fleet/repo/delete", url.Values{"repo": {"pub"}, "confirm": {"pub"}}); code == http.StatusSeeOther {
t.Error("FAIL: bob, with no letters on pub, deleted it from the fleet")
}
_, siteTok := g.mint(t, oltp.ScopeAPI, oltp.ScopeWeb, oltp.ScopeSite)
cookie := g.session(t, siteTok)
if code, _ := g.form("/fleet/repo/delete", cookie, url.Values{"repo": {"secret"}, "confirm": {"secret"}}); code == http.StatusSeeOther {
t.Error("FAIL: the site session deleted secret, private and ungranted")
}
if len(g.regs.deleted) != 0 {
t.Errorf("FAIL: deleted %v", g.regs.deleted)
}
}