Skip to content
quarry Artifact [7e8455c934]
Login

Artifact [7e8455c934]

Artifact 7e8455c9348201e2664a01929c24d7771f4f27689c2b871e8db4031d25257b5b:


package api

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

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

func agentRig(t *testing.T) (*ops.Registry, *oltp.DB) {
	t.Helper()
	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{"dmestas", "jva", "zeitgeist", "mallory"} {
		if err := db.AddAccount(who, "a-long-enough-password", who == "dmestas"); err != nil {
			t.Fatal(err)
		}
	}
	r := ops.NewRegistry()
	if err := RegisterAll(r, Deps{Version: "v", Repos: testRepos(wikiIndex(t)),
		Teams: db, Accounts: acctAdapter{db},
		CapsFor: func(a, repo string) CapSet { return db.EffectiveCaps(a, repo) }}); err != nil {
		t.Fatal(err)
	}
	return r, db
}

// Marking is a site admin's act in both directions (RFC 0021): an
// operator is a person who can be asked, so an account naming itself
// is refused by the store, and a person makes agents with agent.new.
func TestOnlyASiteAdminMarksOrClearsAnAgent(t *testing.T) {
	r, db := agentRig(t)
	as := func(who string) context.Context { return ops.WithUser(context.Background(), who) }

	if _, err := r.Invoke(as("zeitgeist"), "account.agent",
		accountAgentIn{Name: "zeitgeist", Operator: "zeitgeist"}); !errors.Is(err, ops.ErrForbidden) {
		t.Errorf("FAIL: an account marked itself: %v", err)
	} else {
		t.Log("ok: an account may not mark itself")
	}
	if _, err := r.Invoke(as("mallory"), "account.agent",
		accountAgentIn{Name: "jva", Operator: "mallory"}); !errors.Is(err, ops.ErrForbidden) {
		t.Errorf("FAIL: a stranger marked another account: %v", err)
	} else {
		t.Log("ok: marking somebody else needs an admin")
	}
	if _, err := r.Invoke(as("dmestas"), "account.agent",
		accountAgentIn{Name: "jva", Operator: "jva"}); !errors.Is(err, ops.ErrInvalid) {
		t.Errorf("FAIL: an account became its own operator: %v", err)
	} else {
		t.Log("ok: an agent is never its own operator")
	}
	if _, err := r.Invoke(as("dmestas"), "account.agent",
		accountAgentIn{Name: "jva", Operator: "dmestas"}); err != nil {
		t.Fatalf("FAIL: the admin could not mark jva: %v", err)
	}
	if db.Operator("jva") != "dmestas" {
		t.Error("FAIL: the admin's mark did not stick")
	} else {
		t.Log("ok: an admin may mark another account, naming who answers for it")
	}
	if _, err := r.Invoke(as("jva"), "account.agent", accountAgentIn{Name: "jva"}); !errors.Is(err, ops.ErrForbidden) {
		t.Errorf("FAIL: an agent unmarked itself: %v", err)
	}
	if _, err := r.Invoke(as("dmestas"), "account.agent", accountAgentIn{Name: "jva"}); err != nil {
		t.Fatalf("FAIL: the admin could not clear the mark: %v", err)
	}
	if db.Operator("jva") != "" {
		t.Error("FAIL: the admin's clear did not stick")
	} else {
		t.Log("ok: an admin may clear a mark")
	}
}

// An operator nobody can be asked about is the thing this exists to
// end, so the name has to be an account.
func TestAnOperatorMustBeSomebodyYouCanAsk(t *testing.T) {
	r, _ := agentRig(t)
	_, err := r.Invoke(ops.WithUser(context.Background(), "dmestas"), "account.agent",
		accountAgentIn{Name: "jva", Operator: "nobody-here"})
	if err == nil {
		t.Error("FAIL: an operator who is not an account was accepted")
	} else {
		t.Logf("ok: refused — %v", err)
	}
}