feat(admin): 添加APK管理功能
实现APK文件的上传、下载和列表功能 - 新增APKInfo数据结构 - 添加/admin/apk/upload、/admin/apk/download和/admin/apk/list路由 - 实现APK存储服务方法 - 添加相关测试用例
This commit is contained in:
@@ -212,6 +212,78 @@ func (h *Handler) AdminReleases(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]any{"releases": releases})
|
||||
}
|
||||
|
||||
func (h *Handler) AdminUploadAPK(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.authorizeAdmin(w, r) {
|
||||
return
|
||||
}
|
||||
if r.Method != http.MethodPost {
|
||||
writeJSON(w, http.StatusMethodNotAllowed, map[string]any{"error": "Expected POST."})
|
||||
return
|
||||
}
|
||||
runtimeVersion := r.URL.Query().Get("runtimeVersion")
|
||||
if runtimeVersion == "" {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{"error": "runtimeVersion is required"})
|
||||
return
|
||||
}
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
if !strings.HasPrefix(contentType, "application/vnd.android.package-archive") &&
|
||||
!strings.HasPrefix(contentType, "application/octet-stream") {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{"error": "Content-Type must be application/vnd.android.package-archive or application/octet-stream"})
|
||||
return
|
||||
}
|
||||
maxSize := int64(500 * 1024 * 1024)
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxSize)
|
||||
path, err := h.svc.SaveAPK(runtimeVersion, r.Body)
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"runtimeVersion": runtimeVersion,
|
||||
"path": path,
|
||||
"message": "APK uploaded successfully",
|
||||
})
|
||||
}
|
||||
|
||||
func (h *Handler) AdminDownloadAPK(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.authorizeAdmin(w, r) {
|
||||
return
|
||||
}
|
||||
if r.Method != http.MethodGet {
|
||||
writeJSON(w, http.StatusMethodNotAllowed, map[string]any{"error": "Expected GET."})
|
||||
return
|
||||
}
|
||||
runtimeVersion := r.URL.Query().Get("runtimeVersion")
|
||||
if runtimeVersion == "" {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{"error": "runtimeVersion is required"})
|
||||
return
|
||||
}
|
||||
apkPath, err := h.svc.GetAPKPath(runtimeVersion)
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusNotFound, map[string]any{"error": fmt.Sprintf("APK for runtimeVersion %s not found", runtimeVersion)})
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/vnd.android.package-archive")
|
||||
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.apk", runtimeVersion))
|
||||
http.ServeFile(w, r, apkPath)
|
||||
}
|
||||
|
||||
func (h *Handler) AdminListAPKs(w http.ResponseWriter, r *http.Request) {
|
||||
if !h.authorizeAdmin(w, r) {
|
||||
return
|
||||
}
|
||||
if r.Method != http.MethodGet {
|
||||
writeJSON(w, http.StatusMethodNotAllowed, map[string]any{"error": "Expected GET."})
|
||||
return
|
||||
}
|
||||
apks, err := h.svc.ListAPKs()
|
||||
if err != nil {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{"apks": apks})
|
||||
}
|
||||
|
||||
func (h *Handler) authorizeAdmin(w http.ResponseWriter, r *http.Request) bool {
|
||||
if h.adminToken == "" {
|
||||
writeJSON(w, http.StatusForbidden, map[string]any{"error": "ADMIN_TOKEN is not configured"})
|
||||
|
||||
Reference in New Issue
Block a user