diff --git a/internal/web/uploads_handler_test.go b/internal/web/uploads_handler_test.go index 1b9fdcd..a94400a 100644 --- a/internal/web/uploads_handler_test.go +++ b/internal/web/uploads_handler_test.go @@ -3,6 +3,7 @@ package web_test import ( "bytes" "context" + "log/slog" "mime/multipart" "net/http" "net/http/httptest" @@ -336,3 +337,21 @@ func TestUploadPage_AlsoCarriesTheVideoNotice(t *testing.T) { assert.Contains(t, body(t, do(t, app, get("/uploads/"+id))), "Only its audio was used") } + +func TestUploadPost_ARejectionIsLoggedWithItsReasonAndNeverTheFilenameOrTitle(t *testing.T) { + // Rejections are synchronous and leave no row, so without a log line an operator + // cannot tell "the user never retried" from "the page refused it". The reason is + // operational; the filename and title are the user's private content. + var buf bytes.Buffer + app, _ := newUploadApp(t, uploads.Probe{Duration: time.Minute, HasVideo: true}, 1<<20) + app.Log = slog.New(slog.NewTextHandler(&buf, nil)) + + rec := do(t, app, uploadReq(t, "Secret project notes", "client-acme-roadmap.mp4", []byte("x"))) + + require.Equal(t, http.StatusUnprocessableEntity, rec.Code) + logged := buf.String() + assert.Contains(t, logged, "upload rejected") + assert.Contains(t, logged, "reason=no_audio") + assert.NotContains(t, logged, "Secret project notes", "the title is private content") + assert.NotContains(t, logged, "client-acme-roadmap", "the filename is private content") +}