133 lines
3.4 KiB
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
|
|
}
|