Moderation entfernt, JSON-API unter /api
- Moderationsseite und Melde-Funktion (report) komplett ausgebaut; folgt als eigenständiges Projekt - alle API-Endpunkte unter /api, dort ausschließlich JSON: auch 404, 405, Rate-Limit (429) und Panics (500) - Fehler nur über HTTP-Status; stille DB-Fehler in stats, logout und Vote-Zählern liefern jetzt 500 statt Nullen - /auth/headerbar entfernt (Frontend nutzt /api/user/info) - Frontend auf /api und statusbasierte Auswertung umgestellt - notes/api.md neu als Referenz der aktuellen API Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
2714fdb1a5
commit
030a5bd943
+103
-73
@@ -84,7 +84,7 @@ func registerAndLogin(t *testing.T, srv *httptest.Server, username string) *http
|
||||
t.Helper()
|
||||
c := newClient(t)
|
||||
|
||||
resp := postForm(t, c, srv.URL+"/auth/newuser", url.Values{
|
||||
resp := postForm(t, c, srv.URL+"/api/auth/newuser", url.Values{
|
||||
"user": {username}, "pass1": {"supersecret1"}, "pass2": {"supersecret1"},
|
||||
})
|
||||
resp.Body.Close()
|
||||
@@ -92,7 +92,7 @@ func registerAndLogin(t *testing.T, srv *httptest.Server, username string) *http
|
||||
t.Fatalf("register %s: status %d", username, resp.StatusCode)
|
||||
}
|
||||
|
||||
resp = postForm(t, c, srv.URL+"/auth/login", url.Values{
|
||||
resp = postForm(t, c, srv.URL+"/api/auth/login", url.Values{
|
||||
"user": {username}, "pass": {"supersecret1"}, "timeout": {"86400"},
|
||||
})
|
||||
resp.Body.Close()
|
||||
@@ -105,7 +105,7 @@ func registerAndLogin(t *testing.T, srv *httptest.Server, username string) *http
|
||||
// createEntry erstellt einen Beitrag und liefert dessen pid.
|
||||
func createEntry(t *testing.T, c *http.Client, srv *httptest.Server, content string) int64 {
|
||||
t.Helper()
|
||||
resp := postForm(t, c, srv.URL+"/entry/create", url.Values{"content": {content}})
|
||||
resp := postForm(t, c, srv.URL+"/api/entry/create", url.Values{"content": {content}})
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusCreated {
|
||||
t.Fatalf("create entry: status %d", resp.StatusCode)
|
||||
@@ -119,44 +119,34 @@ func createEntry(t *testing.T, c *http.Client, srv *httptest.Server, content str
|
||||
return out.PID
|
||||
}
|
||||
|
||||
func TestRegisterLoginHeaderbar(t *testing.T) {
|
||||
func TestRegisterLoginSession(t *testing.T) {
|
||||
srv := newTestServer(t)
|
||||
c := registerAndLogin(t, srv, "alice")
|
||||
|
||||
resp, err := c.Get(srv.URL + "/auth/headerbar")
|
||||
if got := getStatus(t, c, srv.URL+"/api/auth/sessioninfo"); got != http.StatusOK {
|
||||
t.Fatalf("sessioninfo nach Login: erwartet 200, bekam %d", got)
|
||||
}
|
||||
// Anonymer Client hat keine Session.
|
||||
if got := getStatus(t, newClient(t), srv.URL+"/api/auth/sessioninfo"); got != http.StatusUnauthorized {
|
||||
t.Fatalf("sessioninfo anonym: erwartet 401, bekam %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
// getStatus macht einen GET und liefert nur den Statuscode.
|
||||
func getStatus(t *testing.T, c *http.Client, urlStr string) int {
|
||||
t.Helper()
|
||||
resp, err := c.Get(urlStr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var h struct {
|
||||
LoggedIn bool `json:"loggedin"`
|
||||
}
|
||||
json.NewDecoder(resp.Body).Decode(&h)
|
||||
if !h.LoggedIn {
|
||||
t.Fatal("erwartete loggedin=true nach Login")
|
||||
}
|
||||
|
||||
// Anonymer Client ist nicht eingeloggt.
|
||||
anon := newClient(t)
|
||||
resp2, err := anon.Get(srv.URL + "/auth/headerbar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp2.Body.Close()
|
||||
var h2 struct {
|
||||
LoggedIn bool `json:"loggedin"`
|
||||
}
|
||||
json.NewDecoder(resp2.Body).Decode(&h2)
|
||||
if h2.LoggedIn {
|
||||
t.Fatal("anonymer Client sollte nicht eingeloggt sein")
|
||||
}
|
||||
resp.Body.Close()
|
||||
return resp.StatusCode
|
||||
}
|
||||
|
||||
func TestFeedEmptyThenPopulated(t *testing.T) {
|
||||
srv := newTestServer(t)
|
||||
|
||||
resp, err := http.Get(srv.URL + "/entry/feed/0")
|
||||
resp, err := http.Get(srv.URL + "/api/entry/feed/0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -170,7 +160,7 @@ func TestFeedEmptyThenPopulated(t *testing.T) {
|
||||
alice := registerAndLogin(t, srv, "alice")
|
||||
createEntry(t, alice, srv, "hallo welt")
|
||||
|
||||
resp, err = http.Get(srv.URL + "/entry/feed/0")
|
||||
resp, err = http.Get(srv.URL + "/api/entry/feed/0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -189,7 +179,7 @@ func TestCreateEntryRequiresAuth(t *testing.T) {
|
||||
srv := newTestServer(t)
|
||||
|
||||
anon := newClient(t)
|
||||
resp := postForm(t, anon, srv.URL+"/entry/create", url.Values{"content": {"x"}})
|
||||
resp := postForm(t, anon, srv.URL+"/api/entry/create", url.Values{"content": {"x"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusUnauthorized {
|
||||
t.Fatalf("create ohne Login: erwartet 401, bekam %d", resp.StatusCode)
|
||||
@@ -209,7 +199,7 @@ func TestVoting(t *testing.T) {
|
||||
pid := createEntry(t, alice, srv, "vote me")
|
||||
|
||||
vote := func(c *http.Client, mode string) tally {
|
||||
resp := postForm(t, c, fmt.Sprintf("%s/entry/%d/vote", srv.URL, pid), url.Values{"mode": {mode}})
|
||||
resp := postForm(t, c, fmt.Sprintf("%s/api/entry/%d/vote", srv.URL, pid), url.Values{"mode": {mode}})
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("vote %s: status %d", mode, resp.StatusCode)
|
||||
@@ -237,7 +227,7 @@ func TestVoteRequiresAuthAndValidMode(t *testing.T) {
|
||||
srv := newTestServer(t)
|
||||
alice := registerAndLogin(t, srv, "alice")
|
||||
pid := createEntry(t, alice, srv, "x")
|
||||
voteURL := fmt.Sprintf("%s/entry/%d/vote", srv.URL, pid)
|
||||
voteURL := fmt.Sprintf("%s/api/entry/%d/vote", srv.URL, pid)
|
||||
|
||||
anon := newClient(t)
|
||||
resp := postForm(t, anon, voteURL, url.Values{"mode": {"left"}})
|
||||
@@ -258,7 +248,7 @@ func TestBump(t *testing.T) {
|
||||
alice := registerAndLogin(t, srv, "alice")
|
||||
bob := registerAndLogin(t, srv, "bob")
|
||||
pid := createEntry(t, alice, srv, "bump me")
|
||||
bumpURL := fmt.Sprintf("%s/entry/%d/bump", srv.URL, pid)
|
||||
bumpURL := fmt.Sprintf("%s/api/entry/%d/bump", srv.URL, pid)
|
||||
|
||||
// Anonym: 401.
|
||||
resp := postForm(t, newClient(t), bumpURL, url.Values{})
|
||||
@@ -292,9 +282,9 @@ func TestBump(t *testing.T) {
|
||||
|
||||
// Gelöschter Beitrag lässt sich nicht bumpen.
|
||||
del := createEntry(t, alice, srv, "weg gleich")
|
||||
resp = postForm(t, alice, fmt.Sprintf("%s/entry/%d/delete", srv.URL, del), url.Values{})
|
||||
resp = postForm(t, alice, fmt.Sprintf("%s/api/entry/%d/delete", srv.URL, del), url.Values{})
|
||||
resp.Body.Close()
|
||||
resp = postForm(t, alice, fmt.Sprintf("%s/entry/%d/bump", srv.URL, del), url.Values{})
|
||||
resp = postForm(t, alice, fmt.Sprintf("%s/api/entry/%d/bump", srv.URL, del), url.Values{})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("bump gelöscht: erwartet 404, bekam %d", resp.StatusCode)
|
||||
@@ -304,7 +294,7 @@ func TestBump(t *testing.T) {
|
||||
// createReply erstellt eine Antwort auf parentPID und liefert deren pid.
|
||||
func createReply(t *testing.T, c *http.Client, srv *httptest.Server, content string, parentPID int64) int64 {
|
||||
t.Helper()
|
||||
resp := postForm(t, c, srv.URL+"/entry/create", url.Values{
|
||||
resp := postForm(t, c, srv.URL+"/api/entry/create", url.Values{
|
||||
"content": {content}, "reply_to": {fmt.Sprint(parentPID)},
|
||||
})
|
||||
defer resp.Body.Close()
|
||||
@@ -336,7 +326,7 @@ type threadJSON struct {
|
||||
|
||||
func getThread(t *testing.T, srv *httptest.Server, pid int64) threadJSON {
|
||||
t.Helper()
|
||||
resp, err := http.Get(fmt.Sprintf("%s/entry/%d/thread", srv.URL, pid))
|
||||
resp, err := http.Get(fmt.Sprintf("%s/api/entry/%d/thread", srv.URL, pid))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -378,7 +368,7 @@ func TestThreading(t *testing.T) {
|
||||
}
|
||||
|
||||
// Hauptfeed: nur der Root, keine Antworten.
|
||||
resp, _ := http.Get(srv.URL + "/entry/feed/0")
|
||||
resp, _ := http.Get(srv.URL + "/api/entry/feed/0")
|
||||
var feed []struct {
|
||||
PID int64 `json:"pid"`
|
||||
}
|
||||
@@ -389,7 +379,7 @@ func TestThreading(t *testing.T) {
|
||||
}
|
||||
|
||||
// Profil-Feed: alle drei Beiträge (Root + Antworten).
|
||||
resp, _ = http.Get(srv.URL + "/u/alice/feed/0")
|
||||
resp, _ = http.Get(srv.URL + "/api/u/alice/feed/0")
|
||||
var profile []struct {
|
||||
PID int64 `json:"pid"`
|
||||
}
|
||||
@@ -406,7 +396,7 @@ func TestEditEntry(t *testing.T) {
|
||||
bob := registerAndLogin(t, srv, "bob")
|
||||
|
||||
pid := createEntry(t, alice, srv, "original")
|
||||
editURL := fmt.Sprintf("%s/entry/%d/edit", srv.URL, pid)
|
||||
editURL := fmt.Sprintf("%s/api/entry/%d/edit", srv.URL, pid)
|
||||
|
||||
// Eigentümer bearbeitet -> 200, neuer Inhalt sichtbar.
|
||||
resp := postForm(t, alice, editURL, url.Values{"content": {"korrigiert"}})
|
||||
@@ -433,14 +423,14 @@ func TestEditEntry(t *testing.T) {
|
||||
}
|
||||
|
||||
// Unbekannte pid -> 404.
|
||||
resp = postForm(t, alice, srv.URL+"/entry/999999/edit", url.Values{"content": {"x"}})
|
||||
resp = postForm(t, alice, srv.URL+"/api/entry/999999/edit", url.Values{"content": {"x"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("edit unbekannt: erwartet 404, bekam %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// Nach Soft-Delete ist der Beitrag nicht mehr bearbeitbar (uid=0) -> 403.
|
||||
postForm(t, alice, fmt.Sprintf("%s/entry/%d/delete", srv.URL, pid), url.Values{}).Body.Close()
|
||||
postForm(t, alice, fmt.Sprintf("%s/api/entry/%d/delete", srv.URL, pid), url.Values{}).Body.Close()
|
||||
resp = postForm(t, alice, editURL, url.Values{"content": {"wieder da"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
@@ -456,7 +446,7 @@ func TestSoftDelete(t *testing.T) {
|
||||
root := createEntry(t, alice, srv, "wurzel")
|
||||
reply := createReply(t, alice, srv, "antwort", root)
|
||||
|
||||
delURL := fmt.Sprintf("%s/entry/%d/delete", srv.URL, root)
|
||||
delURL := fmt.Sprintf("%s/api/entry/%d/delete", srv.URL, root)
|
||||
|
||||
// Fremder darf nicht löschen.
|
||||
resp := postForm(t, bob, delURL, url.Values{})
|
||||
@@ -482,7 +472,7 @@ func TestSoftDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
// Der gelöschte Root erscheint weiterhin im Hauptfeed (Thread bleibt erreichbar).
|
||||
feedResp, _ := http.Get(srv.URL + "/entry/feed/0")
|
||||
feedResp, _ := http.Get(srv.URL + "/api/entry/feed/0")
|
||||
var feed []threadEntry
|
||||
json.NewDecoder(feedResp.Body).Decode(&feed)
|
||||
feedResp.Body.Close()
|
||||
@@ -491,7 +481,7 @@ func TestSoftDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
// Nicht existierender Beitrag -> 404.
|
||||
resp = postForm(t, alice, srv.URL+"/entry/999999/delete", url.Values{})
|
||||
resp = postForm(t, alice, srv.URL+"/api/entry/999999/delete", url.Values{})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("delete unbekannt: erwartet 404, bekam %d", resp.StatusCode)
|
||||
@@ -504,21 +494,21 @@ func TestRenameUser(t *testing.T) {
|
||||
registerAndLogin(t, srv, "bob")
|
||||
|
||||
// Zu kurz -> 400.
|
||||
resp := postForm(t, alice, srv.URL+"/user/rename", url.Values{"user": {"ab"}})
|
||||
resp := postForm(t, alice, srv.URL+"/api/user/rename", url.Values{"user": {"ab"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusBadRequest {
|
||||
t.Fatalf("zu kurz: erwartet 400, bekam %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// Bereits vergeben -> 409.
|
||||
resp = postForm(t, alice, srv.URL+"/user/rename", url.Values{"user": {"bob"}})
|
||||
resp = postForm(t, alice, srv.URL+"/api/user/rename", url.Values{"user": {"bob"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusConflict {
|
||||
t.Fatalf("vergeben: erwartet 409, bekam %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// Gültig -> 200 + neuer Name.
|
||||
resp = postForm(t, alice, srv.URL+"/user/rename", url.Values{"user": {"alice2"}})
|
||||
resp = postForm(t, alice, srv.URL+"/api/user/rename", url.Values{"user": {"alice2"}})
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("rename: erwartet 200, bekam %d", resp.StatusCode)
|
||||
@@ -532,12 +522,12 @@ func TestRenameUser(t *testing.T) {
|
||||
}
|
||||
|
||||
// Profil unter dem neuen Namen erreichbar, alter Name weg.
|
||||
r2, _ := http.Get(srv.URL + "/u/alice2/info")
|
||||
r2, _ := http.Get(srv.URL + "/api/u/alice2/info")
|
||||
r2.Body.Close()
|
||||
if r2.StatusCode != http.StatusOK {
|
||||
t.Fatalf("/u/alice2/info: erwartet 200, bekam %d", r2.StatusCode)
|
||||
}
|
||||
r3, _ := http.Get(srv.URL + "/u/alice/info")
|
||||
r3, _ := http.Get(srv.URL + "/api/u/alice/info")
|
||||
r3.Body.Close()
|
||||
if r3.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("/u/alice/info: erwartet 404, bekam %d", r3.StatusCode)
|
||||
@@ -554,14 +544,14 @@ func TestDeleteUser(t *testing.T) {
|
||||
reply := createReply(t, bob, srv, "bobs antwort", root)
|
||||
|
||||
// Falsches Passwort -> 403.
|
||||
resp := postForm(t, alice, srv.URL+"/user/delete", url.Values{"pass1": {"falsch"}})
|
||||
resp := postForm(t, alice, srv.URL+"/api/user/delete", url.Values{"pass1": {"falsch"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Fatalf("falsches Passwort: erwartet 403, bekam %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// Richtiges Passwort -> 200.
|
||||
resp = postForm(t, alice, srv.URL+"/user/delete", url.Values{"pass1": {"supersecret1"}})
|
||||
resp = postForm(t, alice, srv.URL+"/api/user/delete", url.Values{"pass1": {"supersecret1"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("delete: erwartet 200, bekam %d", resp.StatusCode)
|
||||
@@ -569,7 +559,7 @@ func TestDeleteUser(t *testing.T) {
|
||||
|
||||
// Login danach schlägt fehl.
|
||||
fresh := newClient(t)
|
||||
resp = postForm(t, fresh, srv.URL+"/auth/login", url.Values{
|
||||
resp = postForm(t, fresh, srv.URL+"/api/auth/login", url.Values{
|
||||
"user": {"alice"}, "pass": {"supersecret1"}, "timeout": {"86400"},
|
||||
})
|
||||
resp.Body.Close()
|
||||
@@ -613,34 +603,74 @@ func TestLogoutPost(t *testing.T) {
|
||||
srv := newTestServer(t)
|
||||
c := registerAndLogin(t, srv, "alice")
|
||||
|
||||
resp, err := c.Get(srv.URL + "/auth/logout")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
if got := getStatus(t, c, srv.URL+"/api/auth/logout"); got != http.StatusMethodNotAllowed {
|
||||
t.Fatalf("GET logout: erwartet 405, bekam %d", got)
|
||||
}
|
||||
resp.Body.Close()
|
||||
// GET fällt in den FileServer-Catch-All -> 404. Hauptsache: kein Logout.
|
||||
if resp.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("GET logout: erwartet 404, bekam %d", resp.StatusCode)
|
||||
if got := getStatus(t, c, srv.URL+"/api/auth/sessioninfo"); got != http.StatusOK {
|
||||
t.Fatalf("GET logout darf nicht ausloggen, sessioninfo: %d", got)
|
||||
}
|
||||
|
||||
resp = postForm(t, c, srv.URL+"/auth/logout", url.Values{})
|
||||
resp := postForm(t, c, srv.URL+"/api/auth/logout", url.Values{})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("POST logout: erwartet 200, bekam %d", resp.StatusCode)
|
||||
}
|
||||
if got := getStatus(t, c, srv.URL+"/api/auth/sessioninfo"); got != http.StatusUnauthorized {
|
||||
t.Fatalf("nach Logout: erwartet 401, bekam %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err = c.Get(srv.URL + "/auth/headerbar")
|
||||
// TestAPIErrorsAreJSON prüft, dass auch Fehler außerhalb der Handler (unbekannter
|
||||
// Pfad, falsche Methode, Rate-Limit, Panic) als JSON mit passendem Status
|
||||
// hinausgehen.
|
||||
func TestAPIErrorsAreJSON(t *testing.T) {
|
||||
srv := newTestServer(t)
|
||||
|
||||
check := func(name string, resp *http.Response, wantStatus int, wantCode string) {
|
||||
t.Helper()
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != wantStatus {
|
||||
t.Fatalf("%s: erwartet %d, bekam %d", name, wantStatus, resp.StatusCode)
|
||||
}
|
||||
if ct := resp.Header.Get("Content-Type"); ct != "application/json" {
|
||||
t.Fatalf("%s: Content-Type %q", name, ct)
|
||||
}
|
||||
var body struct {
|
||||
Error apiErrorBody `json:"error"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil || body.Error.Code != wantCode {
|
||||
t.Fatalf("%s: erwartet code %q, bekam %+v (%v)", name, wantCode, body, err)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := http.Get(srv.URL + "/api/gibtsnicht")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var h struct {
|
||||
LoggedIn bool `json:"loggedin"`
|
||||
check("unbekannter Pfad", resp, http.StatusNotFound, "api.not_found")
|
||||
|
||||
resp, err = http.Get(srv.URL + "/api/entry/create")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
json.NewDecoder(resp.Body).Decode(&h)
|
||||
if h.LoggedIn {
|
||||
t.Fatal("nach Logout sollte loggedin=false sein")
|
||||
check("falsche Methode", resp, http.StatusMethodNotAllowed, "api.method_not_allowed")
|
||||
|
||||
limited := limitByIP(1, time.Minute)(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {}))
|
||||
for i, want := range []int{http.StatusOK, http.StatusTooManyRequests} {
|
||||
rec := httptest.NewRecorder()
|
||||
limited.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/", nil))
|
||||
if rec.Code != want {
|
||||
t.Fatalf("rate-limit Anfrage %d: erwartet %d, bekam %d", i+1, want, rec.Code)
|
||||
}
|
||||
if want == http.StatusTooManyRequests {
|
||||
check("rate-limit", rec.Result(), want, "rate.limited")
|
||||
}
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
recoverJSON(http.HandlerFunc(func(http.ResponseWriter, *http.Request) { panic("kaputt") })).
|
||||
ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil))
|
||||
check("panic", rec.Result(), http.StatusInternalServerError, "internal")
|
||||
}
|
||||
|
||||
// TestCrossOriginPostRejected prüft den CSRF-Schutz: POSTs mit fremdem
|
||||
@@ -650,7 +680,7 @@ func TestCrossOriginPostRejected(t *testing.T) {
|
||||
c := registerAndLogin(t, srv, "alice")
|
||||
|
||||
post := func(origin string) int {
|
||||
req, err := http.NewRequest(http.MethodPost, srv.URL+"/entry/create",
|
||||
req, err := http.NewRequest(http.MethodPost, srv.URL+"/api/entry/create",
|
||||
strings.NewReader(url.Values{"content": {"x"}}.Encode()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -706,13 +736,13 @@ func TestBlockTOREntry(t *testing.T) {
|
||||
srv := newTestServer(t)
|
||||
c := registerAndLogin(t, srv, "toruser")
|
||||
|
||||
resp := postFormFrom(t, c, srv.URL+"/entry/create", "10.89.1.2", url.Values{"content": {"aus tor"}})
|
||||
resp := postFormFrom(t, c, srv.URL+"/api/entry/create", "10.89.1.2", url.Values{"content": {"aus tor"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Fatalf("TOR-Beitrag: erwartet 403, bekam %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
resp = postFormFrom(t, c, srv.URL+"/entry/create", "203.0.113.7", url.Values{"content": {"normal"}})
|
||||
resp = postFormFrom(t, c, srv.URL+"/api/entry/create", "203.0.113.7", url.Values{"content": {"normal"}})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusCreated {
|
||||
t.Fatalf("Nicht-TOR-Beitrag: erwartet 201, bekam %d", resp.StatusCode)
|
||||
|
||||
Reference in New Issue
Block a user