test: expect signed one-time material uploads

- TestUploadTicket: HMAC under the jz.bm.upload.v1: label, expiry,
  malformed and foreign tickets, single use through the cache
- TestSignedMaterialUploadRefusesBadTickets, TestCreateMaterialUploadNeedsCaller
- TestRoutes, TestBMMCP and TestManageBucketKey expect the upload-url
  route, the uploads route with its two buckets and the upload tool
- compile-only stubs
This commit is contained in:
2026-10-28 15:07:30 +01:00
parent 93066c63ea
commit ce6ac0a78e
7 changed files with 364 additions and 4 deletions

View File

@@ -4,6 +4,7 @@ import (
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"testing"
@@ -17,6 +18,7 @@ import (
"git.golem15.com/golem15/summercms/modules/party"
"git.golem15.com/golem15/summercms/modules/surf"
bm "git.golem15.com/jakub/sm-bm-plugin"
"git.golem15.com/jakub/sm-bm-plugin/controllers/api"
)
const (
@@ -140,6 +142,7 @@ func TestRoutes(t *testing.T) {
"DELETE /api/v1/bm/materials/{id}",
"POST /api/v1/bm/materials/{id}/files",
"POST /api/v1/bm/materials/{id}/files/inline",
"POST /api/v1/bm/materials/{id}/files/upload-url",
"DELETE /api/v1/bm/materials/{id}/files/{file}",
"GET /api/v1/bm/courses",
"GET /api/v1/bm/courses/{id}",
@@ -167,7 +170,7 @@ func TestRoutes(t *testing.T) {
"POST /api/v1/bm/seed",
}
var got []string
sawFeed := false
sawFeed, sawUploads := false, false
for _, rt := range router.Routes() {
if rt.PluginID != "jz.bm" {
continue
@@ -189,6 +192,16 @@ func TestRoutes(t *testing.T) {
sawFeed = true
continue
}
if rt.Method+" "+rt.Pattern == "POST /_bm/api/v1/uploads/{ticket}" {
// The signed material upload: no bearer (the ticket is the
// credential), throttled per IP and per ticket, body capped.
want := []string{"throttle:jz.bm.upload-ip", "throttle:jz.bm.upload-ticket", "body.limit:" + strconv.Itoa(api.MaterialFilesBodyLimit)}
if !slices.Equal(rt.Middleware, want) {
t.Errorf("the signed upload has middleware %v, want %v", rt.Middleware, want)
}
sawUploads = true
continue
}
got = append(got, rt.Method+" "+rt.Pattern)
if strings.HasPrefix(rt.Pattern, bm.TokenPrefix+"/") {
// The token twins of the student API: the user API token guard
@@ -210,6 +223,12 @@ func TestRoutes(t *testing.T) {
if !sawFeed {
t.Error("GET /_bm/calendar/{token} is not registered")
}
if !sawUploads {
t.Error("POST /_bm/api/v1/uploads/{ticket} is not registered")
}
if api.UploadPath != bm.APIPrefix+"/uploads/" {
t.Errorf("api.UploadPath = %q, want %q", api.UploadPath, bm.APIPrefix+"/uploads/")
}
if !slices.Equal(got, want) {
t.Errorf("routes =\n%v\nwant\n%v", got, want)
}