e2e/accountdelete_test.go
68 lines · 2745 bytes
1 symbol in this file
1package e2e
2
3import (
4 "fmt"
5 "net/url"
6 "os"
7 "regexp"
8 "strings"
9 "testing"
10)
11
12// Self-service deletion (#322): a request over SSH mails a link, the link
13// schedules the purge and disables the account, a narrower key is refused
14// and cannot cancel, and a full-scope key cancels by signing in.
15func TestAccountDeleteFlow(t *testing.T) {
16 t.Parallel()
17 smtp := startFakeSMTP(t)
18 inst := startInstanceWith(t, fmt.Sprintf(
19 "[web]\nmode = \"accounts\"\n[mail]\nsmtp_host = %q\nfrom = \"noreply@gitbay.test\"\n",
20 smtp.addr))
21 key := inst.newKey(t, "erin")
22 inst.admin(t, "admin", "user", "create", "erin", "--key", key+".pub",
23 "--email", "erin@example.test", "--verified")
24 gitKey := inst.newKey(t, "erin-git")
25 pub, err := os.ReadFile(gitKey + ".pub")
26 if err != nil {
27 t.Fatal(err)
28 }
29 if _, errOut, code := inst.ssh(t, key, string(pub), "keys", "add", "--scope", "git"); code != 0 {
30 t.Fatalf("keys add: %s", errOut)
31 }
32
33 if _, errOut, code := inst.ssh(t, key, "", "account", "delete", "--confirm", "erin"); code != 0 {
34 t.Fatalf("account delete: exit %d %s", code, errOut)
35 }
36 mail := smtp.waitFor(t, "erin@example.test", "/settings/delete?token=")
37 link := regexp.MustCompile(`/settings/delete\?token=[A-Za-z0-9_-]+`).FindString(mail)
38 if link == "" {
39 t.Fatalf("no link in mail:\n%s", mail)
40 }
41
42 browser := newBrowser(t)
43 if status, body := browserGet(t, browser, inst.base()+link); status != 200 || !strings.Contains(body, "Delete erin") {
44 t.Fatalf("GET link: %d", status)
45 }
46 if _, _, code := inst.ssh(t, key, "", "whoami"); code != 0 {
47 t.Fatal("opening the page changed the account")
48 }
49 if status, body := browserPost(t, browser, inst.base()+link, url.Values{}); status != 200 || !strings.Contains(body, "Deletion scheduled") {
50 t.Fatalf("POST link: %d\n%s", status, body)
51 }
52
53 if _, errOut, code := inst.ssh(t, gitKey, "", "whoami"); code != 4 || !strings.Contains(errOut, "scheduled for deletion") {
54 t.Fatalf("git key while scheduled: exit %d %s", code, errOut)
55 }
56 if out := inst.admin(t, "admin", "user", "show", "erin", "--json"); !strings.Contains(out, `"delete_after"`) {
57 t.Fatalf("show lacks the schedule:\n%s", out)
58 }
59 if _, errOut, code := inst.ssh(t, key, "", "whoami"); code != 0 || !strings.Contains(errOut, "deletion of your account was cancelled") {
60 t.Fatalf("full key while scheduled: exit %d %s", code, errOut)
61 }
62 if out := inst.admin(t, "admin", "user", "show", "erin", "--json"); strings.Contains(out, `"delete_after"`) || !strings.Contains(out, `"state":"active"`) {
63 t.Fatalf("not restored:\n%s", out)
64 }
65 if _, errOut, _ := inst.ssh(t, gitKey, "", "whoami"); strings.Contains(errOut, "scheduled for deletion") {
66 t.Fatal("git key still told the account is scheduled after the cancel")
67 }
68}