add upload api
This commit is contained in:
parent
a90dd9bc50
commit
77da1ffd94
4 changed files with 249 additions and 0 deletions
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"update_server/internal/apikeys"
|
||||
"update_server/internal/db"
|
||||
"update_server/internal/releases"
|
||||
)
|
||||
|
||||
var errInvalidReleaseID = errors.New("invalid release id")
|
||||
|
|
@ -144,6 +145,71 @@ func (h *handler) apiReleaseDownload(w http.ResponseWriter, r *http.Request) {
|
|||
http.ServeContent(w, r, release.Filename, release.UpdatedAt, file)
|
||||
}
|
||||
|
||||
func (h *handler) apiUploadRelease(w http.ResponseWriter, r *http.Request) {
|
||||
state, ok := apikeys.FromContext(r.Context())
|
||||
if !ok {
|
||||
writeAPIKeyAuthError(w, http.StatusUnauthorized, "api key authentication required")
|
||||
return
|
||||
}
|
||||
|
||||
project, err := h.accessibleProjectBySlug(r, state.APIKey)
|
||||
if err != nil {
|
||||
h.writeClientResourceError(w, err, "project lookup failed")
|
||||
return
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxUploadRequestLimit(h.config.MaxUploadBytes))
|
||||
if err := r.ParseMultipartForm(16 << 20); err != nil {
|
||||
if isMaxBytesError(err) {
|
||||
writeJSON(w, http.StatusRequestEntityTooLarge, map[string]any{"error": fmt.Sprintf("upload exceeds the configured %d MB limit", maxUploadMegabytes(h.config.MaxUploadBytes))})
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{"error": "upload form could not be read"})
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if r.MultipartForm != nil {
|
||||
_ = r.MultipartForm.RemoveAll()
|
||||
}
|
||||
}()
|
||||
|
||||
file, header, err := r.FormFile("artifact")
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{"error": "artifact file is required"})
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
result, err := h.releases.Upload(r.Context(), releases.UploadParams{
|
||||
ProjectID: project.ID,
|
||||
Version: r.FormValue("version"),
|
||||
Build: r.FormValue("build"),
|
||||
ReleaseNotes: r.FormValue("release_notes"),
|
||||
OriginalFilename: header.Filename,
|
||||
DeclaredType: header.Header.Get("Content-Type"),
|
||||
Reader: file,
|
||||
})
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, db.ErrNotFound):
|
||||
writeJSON(w, http.StatusNotFound, map[string]any{"error": "resource not found"})
|
||||
case errors.Is(err, db.ErrConflict):
|
||||
writeJSON(w, http.StatusConflict, map[string]any{"error": "release version and build already exist for this project"})
|
||||
default:
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
releasePayload := apiReleasePayload(*result.Release)
|
||||
w.Header().Set("Location", releasePayload.MetadataURL)
|
||||
writeJSON(w, http.StatusCreated, map[string]any{
|
||||
"project": apiProjectPayload(*result.Project),
|
||||
"release": releasePayload,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *handler) accessibleProjectBySlug(r *http.Request, apiKey db.APIKey) (*db.Project, error) {
|
||||
projectSlug := strings.TrimSpace(chi.URLParam(r, "projectSlug"))
|
||||
if projectSlug == "" {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue