Clamp expires_in at API boundary (#60) #74

Merged
poslop merged 2 commits from issue-60-expiry-clamp into main 2026-09-09 14:26:07 +00:00
2 changed files with 46 additions and 3 deletions
Showing only changes of commit f611cc3e9e - Show all commits
+1 -3
View File
@@ -1,11 +1,11 @@
package api package api
import ( import (
"palette/internal/store"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"palette/internal/store"
"strings" "strings"
"time" "time"
@@ -143,8 +143,6 @@ func detectContentType(name string, content []byte) string {
return "text/plain" return "text/plain"
} }
func (a *apiServer) handleGetCan(w http.ResponseWriter, r *http.Request) { func (a *apiServer) handleGetCan(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id") id := chi.URLParam(r, "id")
can, err := a.store.GetCan(id) can, err := a.store.GetCan(id)
+45
View File
@@ -0,0 +1,45 @@
package api
import (
"net/http/httptest"
"testing"
)
// #60: the cans API must clamp expires_in at the boundary exactly like the
// pastes API — reject zero/negative durations and anything over the 1-year
// UI cap, accept the exact boundaries.
func TestCreateCanExpiryBounds(t *testing.T) {
s := testServer(t)
h := s.routes()
cases := []struct {
expiresIn string
wantCode int
}{
{"-1h", 400}, // negative
{"-0s", 400}, // negative zero
{"0s", 400}, // zero
{"1ns", 400}, // positive but below the 1-minute floor
{"59s", 400}, // just under the floor
{"1m", 201}, // exactly the floor
{"90s", 201}, // just over the floor
{"8760h", 201}, // exactly 1 year
{"8785h", 400}, // 1 year + 1 day: over the cap
{"87600h", 400}, // 10 years, the originally reported case
}
for _, c := range cases {
globalLimiter = newLimiter() // avoid create rate limit between cases
body, ct := multipartBody(t, map[string]string{
"json_items": `[{"title":"a.txt","content":"AAA"}]`,
"expires_in": c.expiresIn,
}, "files", "pic.txt", "file data")
req := httptest.NewRequest("POST", "/api/pastes/can", body)
req.Header.Set("Content-Type", ct)
rec := httptest.NewRecorder()
h.ServeHTTP(rec, req)
if rec.Code != c.wantCode {
t.Errorf("expires_in %q: got %d want %d (%s)",
c.expiresIn, rec.Code, c.wantCode, rec.Body.String())
}
}
}