internal/control/token_test.go

v1.41.0
gitbay/internal/control/token_test.go history · blame · raw

118 lines · 3728 bytes

  1package control
  2
  3import (
  4	"bytes"
  5	"slices"
  6	"strings"
  7	"testing"
  8	"time"
  9
 10	"gitbay.org/gitbay/internal/protocol"
 11	"gitbay.org/gitbay/internal/store"
 12)
 13
 14// The minting commands, pinned: adding one to the list, or dropping
 15// one, is a decision this test makes someone take.
 16func TestMintingCommandsMarked(t *testing.T) {
 17	want := []string{
 18		"admin email verify", "admin invite", "admin user create", "email verify",
 19		"keys add", "repo deploy-key add", "repo runner add", "token create", "web login",
 20	}
 21	var got []string
 22	for _, cmd := range Commands() {
 23		if cmd.MintsCredential {
 24			got = append(got, joinPath(cmd.Path))
 25		}
 26	}
 27	slices.Sort(got)
 28	if !slices.Equal(got, want) {
 29		t.Fatalf("MintsCredential on %q, want %q", got, want)
 30	}
 31}
 32
 33// Dispatch refuses before the command runs, so no arguments are needed.
 34func TestExpiringCredentialCannotMint(t *testing.T) {
 35	exp := time.Now().Add(time.Hour)
 36	for _, cmd := range Commands() {
 37		if !cmd.MintsCredential {
 38			continue
 39		}
 40		var out, errOut bytes.Buffer
 41		c := &Ctx{User: store.User{ID: 1, Username: "root", IsAdmin: true}, Scope: "full", Expires: &exp, Stdout: &out, Stderr: &errOut}
 42		if code := Dispatch(c, cmd.Path); code != protocol.ExitDenied || !strings.Contains(errOut.String(), "expires") {
 43			t.Errorf("%s: exit %d %q, want %d and the reason", joinPath(cmd.Path), code, errOut.String(), protocol.ExitDenied)
 44		}
 45	}
 46}
 47
 48// #286: at a terminal, a token expiring in the future must not render
 49// through relAge, which clamps a future time to zero and prints
 50// "expires just now".
 51func TestTokenListFutureExpiryAtTerminal(t *testing.T) {
 52	st, _, uid := newQueueTestRepo(t)
 53	exp := time.Now().Add(90 * 24 * time.Hour)
 54	if err := st.CreateAPIToken(uid, "laptop", "h-laptop", "read", &exp, 0); err != nil {
 55		t.Fatal(err)
 56	}
 57	c, errOut := pruneCtx(st, t.TempDir(), store.User{ID: uid, Username: "alice"})
 58	c.Term = Term{Cols: 80}
 59	var out bytes.Buffer
 60	c.Stdout = &out
 61	if code := Dispatch(c, []string{"token", "list"}); code != protocol.ExitOK {
 62		t.Fatalf("exit %d: %s", code, errOut)
 63	}
 64	if strings.Contains(out.String(), "just now") {
 65		t.Fatalf("token list at a terminal printed \"just now\" for a future expiry:\n%s", out.String())
 66	}
 67	if !strings.Contains(out.String(), exp.UTC().Format("2006-01-02")) {
 68		t.Fatalf("token list:\n%s", out.String())
 69	}
 70}
 71
 72func TestTokenCreateDefaultsToReadAndRecordsCreator(t *testing.T) {
 73	st, _, uid := newQueueTestRepo(t)
 74	if err := st.CreateAPIToken(uid, "parent", "h-parent", "full", nil, 0); err != nil {
 75		t.Fatal(err)
 76	}
 77	_, parent, err := st.APITokenUser("h-parent")
 78	if err != nil {
 79		t.Fatal(err)
 80	}
 81	c, errOut := pruneCtx(st, t.TempDir(), store.User{ID: uid, Username: "alice"})
 82	c.Cfg.Limits.WriteRate = -1
 83	c.TokenID = parent.ID
 84	if code := Dispatch(c, []string{"token", "create", "--name", "child"}); code != protocol.ExitOK {
 85		t.Fatalf("exit %d: %s", code, errOut)
 86	}
 87	toks, err := st.ListAPITokens(uid)
 88	if err != nil {
 89		t.Fatal(err)
 90	}
 91	var found bool
 92	for _, tk := range toks {
 93		if tk.Name != "child" {
 94			continue
 95		}
 96		found = true
 97		if tk.Scope != "read" || tk.CreatedBy != "parent" {
 98			t.Fatalf("child: %+v", tk)
 99		}
100	}
101	if !found {
102		t.Fatal(`no token named "child"`)
103	}
104}
105
106func TestTokenCreateRefusesNonPositiveTTL(t *testing.T) {
107	st, _, uid := newQueueTestRepo(t)
108	for _, ttl := range []string{"0s", "-1h"} {
109		c, _ := pruneCtx(st, t.TempDir(), store.User{ID: uid, Username: "alice"})
110		c.Cfg.Limits.WriteRate = -1
111		if code := Dispatch(c, []string{"token", "create", "--name", "x", "--ttl", ttl}); code != protocol.ExitUsage {
112			t.Errorf("--ttl %s: exit %d", ttl, code)
113		}
114	}
115	if toks, err := st.ListAPITokens(uid); err != nil || len(toks) != 0 {
116		t.Fatalf("tokens: %+v %v", toks, err)
117	}
118}