fix #63: require deletion token on DELETE /api/pastes/{id}
- DELETE now demands the create-time deletion token (Authorization header: Bearer/Token/bare, or ?token= query param), compared with the constant-time store.DeletionTokenEqual. 403 otherwise. - Creator-browser deletes via the /mine button (matching vwr cookie, #37) remain allowed; other browsers and plain API clients get 403. - Regression tests: no token, wrong token (header+query), correct token (header+query), creator-cookie path, token extraction. - Adapted TestSoftDelete to pass the deletion token. - docs/API.md delete section updated. - Based on #58's SoftDelete (bool, error) signature.
This commit is contained in:
@@ -42,7 +42,9 @@ func TestCreateAndGetPaste(t *testing.T) {
|
||||
if rec.Code != 201 {
|
||||
t.Fatalf("create: got %d want 201: %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
var created struct{ ID string `json:"id"` }
|
||||
var created struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
json.Unmarshal(rec.Body.Bytes(), &created)
|
||||
if len(created.ID) != 6 {
|
||||
t.Fatalf("unexpected id: %q", created.ID)
|
||||
@@ -73,7 +75,9 @@ func TestPasswordProtection(t *testing.T) {
|
||||
req := httptest.NewRequest("POST", "/api/pastes", strings.NewReader(body))
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
var created struct{ ID string `json:"id"` }
|
||||
var created struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
json.Unmarshal(rec.Body.Bytes(), &created)
|
||||
|
||||
// without password -> 401
|
||||
@@ -133,10 +137,14 @@ func TestSoftDelete(t *testing.T) {
|
||||
req := httptest.NewRequest("POST", "/api/pastes", strings.NewReader(`{"content":"bye"}`))
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
var created struct{ ID string `json:"id"` }
|
||||
var created struct {
|
||||
ID string `json:"id"`
|
||||
DeletionToken string `json:"deletion_token"`
|
||||
}
|
||||
json.Unmarshal(rec.Body.Bytes(), &created)
|
||||
|
||||
req = httptest.NewRequest("DELETE", "/api/pastes/"+created.ID, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+created.DeletionToken)
|
||||
rec = httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
if rec.Code != 200 {
|
||||
@@ -166,7 +174,7 @@ func TestListPublicExcludesUnlisted(t *testing.T) {
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
var resp struct {
|
||||
Total int `json:"total"`
|
||||
Total int `json:"total"`
|
||||
Items []map[string]any `json:"items"`
|
||||
}
|
||||
json.Unmarshal(rec.Body.Bytes(), &resp)
|
||||
@@ -182,7 +190,9 @@ func TestSweepSoftDeletesAfterGrace(t *testing.T) {
|
||||
req := httptest.NewRequest("POST", "/api/pastes", strings.NewReader(`{"content":"gone soon"}`))
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
var created struct{ ID string `json:"id"` }
|
||||
var created struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
json.Unmarshal(rec.Body.Bytes(), &created)
|
||||
|
||||
s.store.SoftDelete(created.ID)
|
||||
@@ -218,7 +228,9 @@ func TestRawEndpoint(t *testing.T) {
|
||||
req := httptest.NewRequest("POST", "/api/pastes", strings.NewReader(`{"content":"raw content here"}`))
|
||||
rec := httptest.NewRecorder()
|
||||
h.ServeHTTP(rec, req)
|
||||
var created struct{ ID string `json:"id"` }
|
||||
var created struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
json.Unmarshal(rec.Body.Bytes(), &created)
|
||||
|
||||
req = httptest.NewRequest("GET", "/raw/"+created.ID, nil)
|
||||
|
||||
Reference in New Issue
Block a user