144 lines
4.9 KiB
Go
144 lines
4.9 KiB
Go
package web
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"ymhut-box/server/unified-management/internal/notices"
|
|
"ymhut-box/server/unified-management/internal/releases"
|
|
)
|
|
|
|
func (r *router) handleAdminReleases(w http.ResponseWriter, req *http.Request) {
|
|
path := cleanPath(req.URL.Path)
|
|
if strings.HasPrefix(path, "/api/admin/releases/notices") {
|
|
r.handleAdminReleaseNotices(w, req)
|
|
return
|
|
}
|
|
switch path {
|
|
case "/api/admin/releases/packages":
|
|
if req.Method != http.MethodPost {
|
|
writeError(w, http.StatusMethodNotAllowed, "METHOD_NOT_ALLOWED", errors.New("POST required"))
|
|
return
|
|
}
|
|
if err := req.ParseMultipartForm(256 << 20); err != nil {
|
|
writeError(w, http.StatusBadRequest, "INVALID_UPLOAD", err)
|
|
return
|
|
}
|
|
file, header, err := req.FormFile("file")
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "FILE_REQUIRED", err)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
pkg, err := r.releases.SaveUploadedPackage(req, file, releases.UploadOptions{
|
|
FileName: firstNonEmpty(req.FormValue("fileName"), header.Filename),
|
|
Version: req.FormValue("version"),
|
|
Platform: req.FormValue("platform"),
|
|
Arch: req.FormValue("arch"),
|
|
Channel: req.FormValue("channel"),
|
|
Notes: req.FormValue("notes"),
|
|
UpdateManifest: req.FormValue("updateManifest") == "true" || req.FormValue("updateManifest") == "1",
|
|
}, "admin")
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "PACKAGE_UPLOAD_FAILED", err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "package": pkg})
|
|
case "/api/admin/releases":
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "manifest": r.releases.Manifest(req)})
|
|
case "/api/admin/releases/legacy-preview":
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "updateInfo": r.releases.LegacyUpdateInfo(req), "toolStatus": r.releases.StaticJSON("tool-status.json")})
|
|
default:
|
|
http.NotFound(w, req)
|
|
}
|
|
}
|
|
|
|
func (r *router) handleAdminReleaseNotices(w http.ResponseWriter, req *http.Request) {
|
|
if r.notices == nil {
|
|
writeError(w, http.StatusNotFound, "NOTICES_DISABLED", errors.New("release notices are not configured"))
|
|
return
|
|
}
|
|
path := cleanPath(req.URL.Path)
|
|
if req.Method == http.MethodPost && path == "/api/admin/releases/notices/import" {
|
|
if err := r.notices.Import(req.Context()); err != nil {
|
|
writeError(w, http.StatusInternalServerError, "NOTICE_IMPORT_FAILED", err)
|
|
return
|
|
}
|
|
items, _ := r.notices.List(100)
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "items": items})
|
|
return
|
|
}
|
|
if req.Method == http.MethodGet && path == "/api/admin/releases/notices" {
|
|
items, err := r.notices.List(100)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "NOTICE_LIST_FAILED", err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "items": items})
|
|
return
|
|
}
|
|
rest := strings.TrimPrefix(path, "/api/admin/releases/notices/")
|
|
if rest == "" || rest == path {
|
|
http.NotFound(w, req)
|
|
return
|
|
}
|
|
parts := strings.Split(rest, "/")
|
|
version := parts[0]
|
|
if req.Method == http.MethodGet && len(parts) == 1 {
|
|
doc, err := r.notices.Get(version)
|
|
if err != nil {
|
|
writeError(w, http.StatusNotFound, "NOTICE_NOT_FOUND", err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
|
|
return
|
|
}
|
|
if req.Method == http.MethodPut && len(parts) == 1 {
|
|
var body notices.SaveRequest
|
|
if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
|
|
writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", err)
|
|
return
|
|
}
|
|
doc, err := r.notices.Save(req.Context(), version, body, "admin")
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "NOTICE_SAVE_FAILED", err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
|
|
return
|
|
}
|
|
if req.Method == http.MethodPost && len(parts) == 2 && parts[1] == "validate" {
|
|
var body notices.SaveRequest
|
|
if err := json.NewDecoder(req.Body).Decode(&body); err != nil {
|
|
writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", err)
|
|
return
|
|
}
|
|
doc, err := r.notices.Validate(req.Context(), version, body)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "NOTICE_VALIDATE_FAILED", err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
|
|
return
|
|
}
|
|
if req.Method == http.MethodPost && len(parts) == 2 && parts[1] == "restore" {
|
|
var body struct {
|
|
RevisionID int64 `json:"revisionId"`
|
|
}
|
|
if err := json.NewDecoder(req.Body).Decode(&body); err != nil || body.RevisionID <= 0 {
|
|
writeError(w, http.StatusBadRequest, "INVALID_PAYLOAD", errors.New("revisionId is required"))
|
|
return
|
|
}
|
|
doc, err := r.notices.Restore(req.Context(), version, body.RevisionID, "admin")
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "NOTICE_RESTORE_FAILED", err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]any{"ok": true, "document": doc})
|
|
return
|
|
}
|
|
http.NotFound(w, req)
|
|
}
|