package forge import ( "net/http" "net/url" "strconv" "strings" "testing" ) func TestModeration(t *testing.T) { s, h := testServer(t) alice, _ := s.store.CreateUser("alice", "correct horse") bob, _ := s.store.CreateUser("bob", "correct horse") boss, _ := s.store.CreateUser("boss", "correct horse") s.store.SetAdmin("boss", true) s.store.CreateRepo(alice, "proj", "", Public, "") s.store.CreateRepo(alice, "hidden", "", Private, "") a, _ := s.store.CreateSession(alice.ID) b, _ := s.store.CreateSession(bob.ID) admin, _ := s.store.CreateSession(boss.ID) if w := post(h, "/~alice/proj/issues/new", url.Values{"title": {"spam"}, "body": {"x"}}, b); w.Code != http.StatusSeeOther { t.Fatalf("issue: %d", w.Code) } if w := post(h, "/report", url.Values{"kind": {"issue"}, "target": {"alice/proj#1"}, "reason": {"spam"}}, a); w.Code != 200 { t.Fatalf("report: %d %s", w.Code, w.Body.String()) } if w := post(h, "/report", url.Values{"kind": {"issue"}, "target": {"alice/proj#1"}, "reason": {"spam"}}, a); w.Code != 400 { t.Error("duplicate report accepted") } if w := post(h, "/report", url.Values{"kind": {"repo"}, "target": {"alice/hidden"}, "reason": {"x"}}, b); w.Code != 404 { t.Error("report reveals a private repository") } if w := get(h, "/admin?s=reports", admin); !strings.Contains(w.Body.String(), "alice/proj#1") { t.Error("report missing from admin") } if w := get(h, "/admin?s=reports", b); w.Code == 200 { t.Error("non-admin sees reports") } rep := s.store.Reports("open")[0] if w := post(h, "/admin", url.Values{"s": {"reports"}, "action": {"moderate"}, "report": {itoa(rep.ID)}, "do": {"ban"}}, admin); strings.Contains(w.Header().Get("Location"), "error") { t.Fatalf("ban: %s", w.Header().Get("Location")) } if !s.store.IsBanned(bob.ID) || s.store.IsBanned(alice.ID) { t.Error("ban hit the wrong account") } s.store.SetBanned("bob", false) b, _ = s.store.CreateSession(bob.ID) if len(s.store.Reports("open")) != 0 { t.Error("report still open") } if w := post(h, "/block", url.Values{"name": {"bob"}}, a); w.Code != http.StatusSeeOther { t.Fatalf("block: %d", w.Code) } if w := post(h, "/~alice/proj/issues/new", url.Values{"title": {"again"}}, b); w.Code != 403 { t.Errorf("blocked user opened an issue: %d", w.Code) } if w := post(h, "/~alice/proj/issues/1/comment", url.Values{"body": {"hi"}}, b); w.Code != 403 { t.Errorf("blocked user commented: %d", w.Code) } if w := post(h, "/~alice/proj/star", nil, b); w.Code != 403 { t.Errorf("blocked user starred: %d", w.Code) } if w := post(h, "/~alice/follow", nil, b); w.Code != 403 { t.Errorf("blocked user followed: %d", w.Code) } if w := post(h, "/~alice/proj/fork", nil, b); w.Code != 403 { t.Errorf("blocked user forked: %d", w.Code) } if !strings.Contains(get(h, "/settings", a).Body.String(), "~bob") { t.Error("blocked list missing from settings") } post(h, "/block", url.Values{"name": {"bob"}, "action": {"unblock"}}, a) if s.store.Blocked(alice.ID, bob.ID) { t.Error("unblock failed") } if w := post(h, "/block", url.Values{"name": {"bob"}}, b); w.Code != 400 { t.Error("blocked yourself") } for i := 0; i < threadsPerHour; i++ { s.store.CreateIssue(Repo{ID: 1}, bob, "t", "") } if w := post(h, "/~alice/proj/issues/new", url.Values{"title": {"flood"}}, b); w.Code != 429 { t.Errorf("issue flood not limited: %d", w.Code) } } func itoa(n int64) string { return strconv.FormatInt(n, 10) }