Integrate asset metadata/storage support, TypeScript client asset APIs, docs updates, and the Leaflet demo while resolving conflicts with recent challenge IP/login persistence changes on main. Made-with: Cursor
This commit is contained in:
@@ -40,6 +40,10 @@ func (a *API) Routes() http.Handler {
|
||||
mux.HandleFunc("POST /v1/collections/{id}/features", a.createFeature)
|
||||
mux.HandleFunc("GET /v1/collections/{id}/features", a.listFeatures)
|
||||
mux.HandleFunc("DELETE /v1/features/{id}", a.deleteFeature)
|
||||
mux.HandleFunc("POST /v1/assets", a.createAsset)
|
||||
mux.HandleFunc("PATCH /v1/assets/{id}", a.patchAsset)
|
||||
mux.HandleFunc("POST /v1/assets/{id}/signed-upload", a.signedUpload)
|
||||
mux.HandleFunc("GET /v1/assets/{id}/download", a.downloadAsset)
|
||||
|
||||
mux.Handle("/web/", http.StripPrefix("/web/", staticFiles))
|
||||
mux.Handle("/libs/", http.StripPrefix("/libs/", libsFiles))
|
||||
@@ -97,8 +101,11 @@ func statusFromErr(err error) int {
|
||||
errors.Is(err, app.ErrInviteExhaust):
|
||||
return http.StatusBadRequest
|
||||
case errors.Is(err, app.ErrCollectionMiss), errors.Is(err, app.ErrFeatureMiss),
|
||||
errors.Is(err, app.ErrAssetMiss),
|
||||
errors.Is(err, store.ErrNotFound):
|
||||
return http.StatusNotFound
|
||||
case errors.Is(err, app.ErrStorageNotConfigured):
|
||||
return http.StatusServiceUnavailable
|
||||
default:
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
@@ -361,3 +368,108 @@ func (a *API) deleteFeature(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (a *API) createAsset(w http.ResponseWriter, r *http.Request) {
|
||||
user, err := a.authUser(r)
|
||||
if err != nil {
|
||||
writeErr(w, err)
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
FeatureID string `json:"featureId"`
|
||||
Checksum string `json:"checksum"`
|
||||
Ext string `json:"ext"`
|
||||
Kind string `json:"kind"`
|
||||
MimeType string `json:"mimeType"`
|
||||
SizeBytes int64 `json:"sizeBytes"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
IsPublic *bool `json:"isPublic"`
|
||||
}
|
||||
if err := readJSON(r, &req); err != nil {
|
||||
writeErr(w, app.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
asset, created, err := a.service.CreateOrLinkAsset(user, app.CreateAssetInput{
|
||||
FeatureID: req.FeatureID,
|
||||
Checksum: req.Checksum,
|
||||
Ext: req.Ext,
|
||||
Kind: req.Kind,
|
||||
MimeType: req.MimeType,
|
||||
SizeBytes: req.SizeBytes,
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
Visibility: req.IsPublic,
|
||||
})
|
||||
if err != nil {
|
||||
writeErr(w, err)
|
||||
return
|
||||
}
|
||||
status := http.StatusOK
|
||||
if created {
|
||||
status = http.StatusCreated
|
||||
}
|
||||
writeJSON(w, status, map[string]interface{}{
|
||||
"asset": asset,
|
||||
"link": "/v1/assets/" + asset.ID + "/download",
|
||||
})
|
||||
}
|
||||
|
||||
func (a *API) patchAsset(w http.ResponseWriter, r *http.Request) {
|
||||
user, err := a.authUser(r)
|
||||
if err != nil {
|
||||
writeErr(w, err)
|
||||
return
|
||||
}
|
||||
assetID := r.PathValue("id")
|
||||
var req struct {
|
||||
IsPublic bool `json:"isPublic"`
|
||||
}
|
||||
if err := readJSON(r, &req); err != nil {
|
||||
writeErr(w, app.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
asset, err := a.service.SetAssetPublic(user, assetID, req.IsPublic)
|
||||
if err != nil {
|
||||
writeErr(w, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]interface{}{"asset": asset, "link": "/v1/assets/" + asset.ID + "/download"})
|
||||
}
|
||||
|
||||
func (a *API) signedUpload(w http.ResponseWriter, r *http.Request) {
|
||||
user, err := a.authUser(r)
|
||||
if err != nil {
|
||||
writeErr(w, err)
|
||||
return
|
||||
}
|
||||
assetID := r.PathValue("id")
|
||||
var req struct {
|
||||
ContentType string `json:"contentType"`
|
||||
}
|
||||
if err := readJSON(r, &req); err != nil {
|
||||
writeErr(w, app.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
url, err := a.service.SignedUploadURL(user, assetID, req.ContentType)
|
||||
if err != nil {
|
||||
writeErr(w, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]string{"url": url, "method": http.MethodPut})
|
||||
}
|
||||
|
||||
func (a *API) downloadAsset(w http.ResponseWriter, r *http.Request) {
|
||||
user, err := a.authUser(r)
|
||||
if err != nil {
|
||||
writeErr(w, err)
|
||||
return
|
||||
}
|
||||
assetID := r.PathValue("id")
|
||||
url, err := a.service.SignedDownloadURL(user, assetID)
|
||||
if err != nil {
|
||||
writeErr(w, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, url, http.StatusFound)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user