Files
MosisService/portal/internal/api/handlers/store.go

146 lines
3.9 KiB
Go

package handlers
import (
"fmt"
"net/http"
"strconv"
"github.com/go-chi/chi/v5"
"omixlab.com/mosis-portal/internal/database"
"omixlab.com/mosis-portal/internal/storage"
)
// StoreHandler handles public store endpoints
type StoreHandler struct {
db *database.DB
storage *storage.Storage
}
// NewStoreHandler creates a new store handler
func NewStoreHandler(db *database.DB, store *storage.Storage) *StoreHandler {
return &StoreHandler{db: db, storage: store}
}
// ListApps returns published apps for the store
func (h *StoreHandler) ListApps(w http.ResponseWriter, r *http.Request) {
// Parse query parameters
query := r.URL.Query().Get("q")
category := r.URL.Query().Get("category")
sort := r.URL.Query().Get("sort")
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
if page < 1 {
page = 1
}
if limit < 1 || limit > 100 {
limit = 20
}
apps, total, err := h.db.ListPublishedApps(r.Context(), query, category, sort, page, limit)
if err != nil {
Error(w, "failed to list apps: "+err.Error(), http.StatusInternalServerError)
return
}
JSON(w, http.StatusOK, map[string]interface{}{
"apps": apps,
"total": total,
"pagination": map[string]interface{}{
"page": page,
"limit": limit,
"total": total,
"total_pages": (total + limit - 1) / limit,
},
})
}
// GetApp returns a published app by package ID
func (h *StoreHandler) GetApp(w http.ResponseWriter, r *http.Request) {
packageID := chi.URLParam(r, "packageID")
app, err := h.db.GetPublishedApp(r.Context(), packageID)
if err != nil {
Error(w, "app not found", http.StatusNotFound)
return
}
JSON(w, http.StatusOK, app)
}
// Download returns download info for the latest version of an app
func (h *StoreHandler) Download(w http.ResponseWriter, r *http.Request) {
packageID := chi.URLParam(r, "packageID")
// Get app to find developer ID
app, err := h.db.GetAppByPackageID(r.Context(), packageID)
if err != nil {
Error(w, "app not found", http.StatusNotFound)
return
}
version, err := h.db.GetLatestPublishedVersion(r.Context(), packageID)
if err != nil {
Error(w, "no published version found", http.StatusNotFound)
return
}
// Build download URL
downloadURL := fmt.Sprintf("/downloads/%s/%s/%d/package.mosis",
app.DeveloperID, app.ID, version.VersionCode)
JSON(w, http.StatusOK, map[string]interface{}{
"download_url": downloadURL,
"version": version.VersionName,
"version_code": version.VersionCode,
"size": version.PackageSize,
"signature": version.Signature,
})
}
// DownloadVersion returns download info for a specific version
func (h *StoreHandler) DownloadVersion(w http.ResponseWriter, r *http.Request) {
packageID := chi.URLParam(r, "packageID")
versionCodeStr := chi.URLParam(r, "versionCode")
versionCode, err := strconv.Atoi(versionCodeStr)
if err != nil {
Error(w, "invalid version code", http.StatusBadRequest)
return
}
// Get app to find developer ID
app, err := h.db.GetAppByPackageID(r.Context(), packageID)
if err != nil {
Error(w, "app not found", http.StatusNotFound)
return
}
version, err := h.db.GetPublishedVersionByCode(r.Context(), packageID, versionCode)
if err != nil {
Error(w, "version not found", http.StatusNotFound)
return
}
// Build download URL
downloadURL := fmt.Sprintf("/downloads/%s/%s/%d/package.mosis",
app.DeveloperID, app.ID, version.VersionCode)
JSON(w, http.StatusOK, map[string]interface{}{
"download_url": downloadURL,
"version": version.VersionName,
"version_code": version.VersionCode,
"size": version.PackageSize,
"signature": version.Signature,
})
}
// CheckUpdates checks for app updates
func (h *StoreHandler) CheckUpdates(w http.ResponseWriter, r *http.Request) {
// Parse request body for installed apps
// For now, return empty updates
JSON(w, http.StatusOK, map[string]interface{}{
"updates": []interface{}{},
})
}