e2e/websignup_test.go

v1.22.0
gitbay/e2e/websignup_test.go history · blame · raw

91 lines · 3577 bytes

 1package e2e
 2
 3import (
 4	"fmt"
 5	"net/url"
 6	"os"
 7	"strings"
 8	"testing"
 9)
10
11func TestWebSignup(t *testing.T) {
12	smtp := startFakeSMTP(t)
13	inst := startInstanceWith(t, fmt.Sprintf(
14		"[web]\nmode = \"accounts\"\n[registration]\nmode = \"invite\"\n[mail]\nsmtp_host = %q\nfrom = \"noreply@gitbay.test\"\n",
15		smtp.addr))
16
17	// The landing page advertises signup; the form renders.
18	status, body := inst.get(t, "/")
19	if status != 200 || !strings.Contains(body, `href="/register"`) {
20		t.Fatalf("landing signup link: %d", status)
21	}
22	status, body = inst.get(t, "/register")
23	if status != 200 || !strings.Contains(body, "invite-only") || !strings.Contains(body, `name="key"`) {
24		t.Fatalf("register form: %d\n%s", status, body)
25	}
26	// The login page tells a brand-new visitor how to get an account.
27	status, body = inst.get(t, "/login")
28	if status != 200 || !strings.Contains(body, `href="/register"`) || !strings.Contains(body, "invite-only") {
29		t.Fatalf("login signup hint: %d\n%s", status, body)
30	}
31
32	// Invite issued over the admin path; redeemed through the browser.
33	inst.admin(t, "admin", "invite", "--email", "erin@example.test")
34	inviteCode := extractCode(t, smtp.waitMail(t, 0))
35	key := inst.newKey(t, "erin")
36	pub, err := os.ReadFile(key + ".pub")
37	if err != nil {
38		t.Fatal(err)
39	}
40
41	browser := newBrowser(t)
42	// A garbage key re-renders the form with the error, keeping the input.
43	_, body = browserPost(t, browser, inst.base()+"/register", url.Values{
44		"username": {"erin"}, "invite": {inviteCode}, "key": {"not a key"}})
45	if !strings.Contains(body, "does not parse as an SSH public key") || !strings.Contains(body, `value="erin"`) {
46		t.Fatalf("bad key handling:\n%s", body)
47	}
48	// A bad invite fails without burning anything.
49	_, body = browserPost(t, browser, inst.base()+"/register", url.Values{
50		"username": {"erin"}, "invite": {"deadbeef"}, "key": {string(pub)}})
51	if !strings.Contains(body, "invalid or already used") {
52		t.Fatalf("bad invite:\n%s", body)
53	}
54	// The real thing: account is active immediately (invite proves the mailbox).
55	status, body = browserPost(t, browser, inst.base()+"/register", url.Values{
56		"username": {"erin"}, "invite": {inviteCode}, "key": {string(pub)}})
57	if status != 200 || !strings.Contains(body, "welcome, erin") {
58		t.Fatalf("signup: %d\n%s", status, body)
59	}
60	out, errOut, code := inst.ssh(t, key, "", "whoami")
61	if code != 0 || !strings.Contains(out, "erin") {
62		t.Fatalf("ssh after web signup: exit %d, %s%s", code, out, errOut)
63	}
64	// The invite is burned: reusing it (fresh browser, fresh key) fails.
65	key2 := inst.newKey(t, "mallory")
66	pub2, _ := os.ReadFile(key2 + ".pub")
67	_, body = browserPost(t, newBrowser(t), inst.base()+"/register", url.Values{
68		"username": {"mallory"}, "invite": {inviteCode}, "key": {string(pub2)}})
69	if !strings.Contains(body, "invalid or already used") {
70		t.Fatalf("invite reuse:\n%s", body)
71	}
72}
73
74func TestWebSignupClosedInstance(t *testing.T) {
75	inst := startInstanceWith(t, "[web]\nmode = \"accounts\"\n")
76	// Closed registration: no signup route at all, and no landing hint.
77	if status, _ := inst.get(t, "/register"); status != 404 {
78		t.Fatalf("register on closed instance: %d", status)
79	}
80	_, body := inst.get(t, "/")
81	if strings.Contains(body, `href="/register"`) {
82		t.Fatal("closed landing advertises signup")
83	}
84	_, body = inst.get(t, "/login")
85	if strings.Contains(body, `href="/register"`) {
86		t.Fatal("closed login page advertises signup")
87	}
88	if !strings.Contains(body, "not accepting new accounts") {
89		t.Fatalf("closed login page says nothing about accounts:\n%s", body)
90	}
91}