Files
cmr-mini/backend/internal/httpapi/handlers/admin_asset_handler.go

133 lines
3.4 KiB
Go

package handlers
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"io"
"net/http"
"os"
"cmr-backend/internal/apperr"
"cmr-backend/internal/httpx"
"cmr-backend/internal/service"
)
type AdminAssetHandler struct {
service *service.AdminAssetService
}
func NewAdminAssetHandler(service *service.AdminAssetService) *AdminAssetHandler {
return &AdminAssetHandler{service: service}
}
func (h *AdminAssetHandler) ListAssets(w http.ResponseWriter, r *http.Request) {
result, err := h.service.ListManagedAssets(r.Context(), parseAdminLimit(r))
if err != nil {
httpx.WriteError(w, err)
return
}
httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}
func (h *AdminAssetHandler) GetAsset(w http.ResponseWriter, r *http.Request) {
result, err := h.service.GetManagedAsset(r.Context(), r.PathValue("assetPublicID"))
if err != nil {
httpx.WriteError(w, err)
return
}
httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}
func (h *AdminAssetHandler) RegisterLink(w http.ResponseWriter, r *http.Request) {
var req service.RegisterLinkAssetInput
if err := httpx.DecodeJSON(r, &req); err != nil {
httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body: "+err.Error()))
return
}
result, err := h.service.RegisterExternalLink(r.Context(), req)
if err != nil {
httpx.WriteError(w, err)
return
}
httpx.WriteJSON(w, http.StatusCreated, map[string]any{"data": result})
}
func (h *AdminAssetHandler) UploadFile(w http.ResponseWriter, r *http.Request) {
if err := r.ParseMultipartForm(64 << 20); err != nil {
httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_multipart", "invalid multipart form: "+err.Error()))
return
}
file, header, err := r.FormFile("file")
if err != nil {
httpx.WriteError(w, apperr.New(http.StatusBadRequest, "file_required", "multipart file field 'file' is required"))
return
}
defer file.Close()
tmpFile, err := os.CreateTemp("", "cmr-upload-*"+header.Filename)
if err != nil {
httpx.WriteError(w, err)
return
}
tmpPath := tmpFile.Name()
defer os.Remove(tmpPath)
hash := sha256.New()
written, err := io.Copy(io.MultiWriter(tmpFile, hash), file)
if err != nil {
tmpFile.Close()
httpx.WriteError(w, err)
return
}
if err := tmpFile.Close(); err != nil {
httpx.WriteError(w, err)
return
}
input := service.UploadAssetFileInput{
AssetType: r.FormValue("assetType"),
AssetCode: r.FormValue("assetCode"),
Version: r.FormValue("version"),
Title: stringPtrOrNil(r.FormValue("title")),
ObjectDir: stringPtrOrNil(r.FormValue("objectDir")),
FileName: header.Filename,
ContentType: header.Header.Get("Content-Type"),
FileSize: written,
Checksum: hex.EncodeToString(hash.Sum(nil)),
TempPath: tmpPath,
Status: r.FormValue("status"),
Metadata: parseMetadataJSON(r.FormValue("metadataJson")),
}
result, err := h.service.UploadAssetFile(r.Context(), input)
if err != nil {
httpx.WriteError(w, err)
return
}
httpx.WriteJSON(w, http.StatusCreated, map[string]any{
"data": result,
"meta": map[string]any{
"uploadedBytes": written,
"checksumSha256": input.Checksum,
},
})
}
func stringPtrOrNil(value string) *string {
if value == "" {
return nil
}
return &value
}
func parseMetadataJSON(raw string) map[string]any {
if raw == "" {
return nil
}
var payload map[string]any
_ = json.Unmarshal([]byte(raw), &payload)
return payload
}