- classes/uploads.go: tickets signed with HMAC-SHA256 under the
jz.bm.upload.v1: label (app.key), 10-minute expiry, the nonce pulled
from the cache once (duplicated from golem15.presentations on purpose)
- POST /api/v1/bm/materials/{id}/files/upload-url issues the URL with a
curl example; POST /_bm/api/v1/uploads/{ticket} takes one file part,
no bearer, throttled per IP and per ticket, user and permission
re-checked, stored through storeMaterialFile
- bm_manage_create_material_upload; README documents the file routes
47 lines
3.3 KiB
Go
47 lines
3.3 KiB
Go
package bm
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/pact"
|
|
"git.golem15.com/jakub/sm-bm-plugin/controllers/api"
|
|
)
|
|
|
|
// attachMaterialFileInput is the input of bm_manage_attach_material_file.
|
|
type attachMaterialFileInput struct {
|
|
ID uint `json:"id" path:"id" jsonschema:"the material id"`
|
|
Name string `json:"name" jsonschema:"file name with extension, for example notatki.pdf"`
|
|
Mime string `json:"mime,omitempty" jsonschema:"optional MIME type; the stored type must match"`
|
|
ContentBase64 string `json:"content_base64" jsonschema:"standard base64, at most 3000000 bytes decoded; use bm_manage_create_material_upload for larger files"`
|
|
}
|
|
|
|
// detachMaterialFileInput is the input of bm_manage_detach_material_file.
|
|
type detachMaterialFileInput struct {
|
|
ID uint `json:"id" path:"id" jsonschema:"the material id"`
|
|
File uint `json:"file" path:"file" jsonschema:"the file id, as listed in the files of bm_manage_show_material"`
|
|
}
|
|
|
|
// fileTools are the material file tools over the management API (D-10,
|
|
// D-11, D-17): attach a small file as base64, get a signed one-time upload
|
|
// URL for a larger one, and detach a file. Every description carries the
|
|
// public-file warning and says no file contents are returned.
|
|
func fileTools() []pact.MCPTool {
|
|
tool := func(name, title, desc, method, path string, input any) pact.MCPTool {
|
|
return pact.MCPTool{Name: name, Title: title, Description: desc, Guard: "user", Method: method, Path: ManagePrefix + path, Input: input}
|
|
}
|
|
return []pact.MCPTool{
|
|
tool("manage_attach_material_file", "Attach a file to a material",
|
|
"Attaches one file sent as standard base64 (at most 3000000 bytes decoded; for larger files use bm_manage_create_material_upload) to a material, after its files; a material holds at most 20. The extension and the content are checked; a sent mime must match the content. Returns the material with its files (id, absolute link, name, size and type) and a warning; 404 when the material is unknown, 422 when the file is refused. "+
|
|
api.MaterialFileWarning+" "+MCPMaterialPrivacy+writeMaterials,
|
|
http.MethodPost, "/materials/{id}/files/inline", attachMaterialFileInput{}),
|
|
tool("manage_create_material_upload", "Get an upload URL for a material file",
|
|
"Returns a one-time upload URL for one file of this material, valid for 10 minutes, bound to this material and to you, and usable once: send the file with the returned curl_example (curl -F 'file=@<path>' '<upload_url>') from a shell, so the bytes never pass through MCP. At most 50 MB, one of the listed accept extensions; the answer also has expires_at, max_bytes and a warning. A used, expired or forged URL gets 403. 404 when the material is unknown, 503 when uploads are not configured. "+
|
|
api.MaterialFileWarning+" "+MCPMaterialPrivacy+writeMaterials,
|
|
http.MethodPost, "/materials/{id}/files/upload-url", idInput{}),
|
|
tool("manage_detach_material_file", "Detach a file from a material",
|
|
"Deletes one file of a material, its row and its stored blob, so its link stops working; 404 when the material or the file is unknown or the file belongs to another material."+deleteForever+" "+
|
|
api.MaterialFileWarning+" "+MCPMaterialPrivacy+writeMaterials,
|
|
http.MethodDelete, "/materials/{id}/files/{file}", detachMaterialFileInput{}),
|
|
}
|
|
}
|