302 lines
9.0 KiB
Go
302 lines
9.0 KiB
Go
package versions_handler
|
|
|
|
import (
|
|
"errors"
|
|
"gorm.io/gorm"
|
|
"log"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"autolibrary.top/webserver/backend/database/versions_database"
|
|
"autolibrary.top/webserver/backend/models/versions_model"
|
|
"autolibrary.top/webserver/utils"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
/*
|
|
These handlers are used to manage download versions.
|
|
*/
|
|
|
|
// GetLatestDownload returns the newest published stable release, or null.
|
|
func GetLatestDownload(c *gin.Context) {
|
|
var version versions_model.DownloadVersion
|
|
err := versions_database.DB.Where("type = ? AND release_date <= ?", "stable", utils.NowInShanghai()).Order("release_date DESC, id DESC").First(&version).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
c.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "msg": "No stable release available", "data": nil})
|
|
return
|
|
}
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"code": http.StatusInternalServerError, "msg": "Unable to load latest release", "data": nil})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "msg": "Latest stable release", "data": version})
|
|
}
|
|
|
|
// GET /download/versions?page={number}&per_page={number<=50}
|
|
func GetDownloadVersions(c *gin.Context) {
|
|
// Parse page and perPage parameters
|
|
pageStr := c.Query("page")
|
|
perPageStr := c.Query("per_page")
|
|
|
|
// Default values for page and perPage
|
|
if pageStr == "" {
|
|
pageStr = "1"
|
|
}
|
|
if perPageStr == "" {
|
|
perPageStr = "9"
|
|
}
|
|
|
|
page, err := strconv.Atoi(pageStr)
|
|
if err != nil {
|
|
log.Printf("[E] GET > try to get downloads, but got invalid parameter: 'page=%s'", pageStr)
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": http.StatusBadRequest,
|
|
"msg": "GET > try to get downloads, but got invalid parameter: 'page'",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
perPage, err := strconv.Atoi(perPageStr)
|
|
if err != nil {
|
|
log.Printf("[E] GET > try to get downloads (page=%d), but got invalid parameter: 'per_page=%s'", page, perPageStr)
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": http.StatusBadRequest,
|
|
"msg": "GET > try to get downloads, but got invalid parameter: 'per_page'",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
// constrain page and perPage parameters
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if perPage <= 0 || perPage > 50 {
|
|
perPage = 9
|
|
}
|
|
|
|
// Calculate offset
|
|
offset := (page - 1) * perPage
|
|
|
|
var downloads []versions_model.DownloadVersion
|
|
result := versions_database.DB.Order("id DESC").Limit(perPage).Offset(offset).Find(&downloads)
|
|
if result.Error != nil {
|
|
log.Printf("[E] GET > occur an error when get downloads (page=%d, per_page=%d): %v", page, perPage, result.Error)
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": http.StatusInternalServerError,
|
|
"msg": "GET > occur an error when get downloads",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
var total int64
|
|
result = versions_database.DB.Model(&versions_model.DownloadVersion{}).Count(&total)
|
|
if result.Error != nil {
|
|
log.Printf("[E] GET > occur an error when get downloads (page=%d, per_page=%d): %v", page, perPage, result.Error)
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": http.StatusInternalServerError,
|
|
"msg": "GET > occur an error when get downloads",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
totalPages := int(total) / perPage
|
|
if int(total)%perPage != 0 {
|
|
totalPages++
|
|
}
|
|
pageMeta := gin.H{
|
|
"page": page,
|
|
"per_page": perPage,
|
|
"total": total,
|
|
"total_pages": totalPages,
|
|
"has_next": page < totalPages,
|
|
}
|
|
|
|
log.Printf("[I] GET > get downloads (page=%d, per_page=%d) successful", page, perPage)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": http.StatusOK,
|
|
"msg": "GET > get downloads successful",
|
|
"data": gin.H{
|
|
"downloads": downloads,
|
|
"meta": pageMeta,
|
|
},
|
|
})
|
|
}
|
|
|
|
// GET /download/versions/:id
|
|
func GetDownloadVersionByID(c *gin.Context) {
|
|
id, err := strconv.Atoi(c.Param("id"))
|
|
if err != nil {
|
|
log.Printf("[E] GET > try to get download, but got invalid id: '%s'", c.Param("id"))
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": http.StatusBadRequest,
|
|
"msg": "GET > try to get download, but got invalid id",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
var download versions_model.DownloadVersion
|
|
result := versions_database.DB.First(&download, id)
|
|
if result.Error != nil {
|
|
log.Printf("[E] GET > download (id=%d) can not found: %v", id, result.Error)
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
"code": http.StatusNotFound,
|
|
"msg": "GET > download can not found",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
log.Printf("[I] GET > get download (id=%d) successful", id)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": http.StatusOK,
|
|
"msg": "GET > get download successful",
|
|
"data": download,
|
|
})
|
|
}
|
|
|
|
// POST /download/versions
|
|
func PostDownloadVersion(c *gin.Context) {
|
|
var download versions_model.DownloadVersion
|
|
if err := c.ShouldBindJSON(&download); err != nil {
|
|
log.Printf("[E] POST > try to create download, but got invalid request data: %v", err)
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": http.StatusBadRequest,
|
|
"msg": "POST > try to create download, but got invalid request data",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
download.CreatedAt = utils.NowInShanghai()
|
|
result := versions_database.DB.Create(&download)
|
|
if result.Error != nil {
|
|
log.Printf("[E] POST > occur an error when create download: %v", result.Error)
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": http.StatusInternalServerError,
|
|
"msg": "POST > occur an error when create download",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
id := strconv.FormatUint(uint64(download.ID), 10)
|
|
log.Printf("[I] POST > create download (id=%s) successful", id)
|
|
c.JSON(http.StatusCreated, gin.H{
|
|
"code": http.StatusCreated,
|
|
"msg": "POST > create download successful",
|
|
"data": download,
|
|
})
|
|
}
|
|
|
|
// PUT /download/versions/:id
|
|
func PutDownloadVersionByID(c *gin.Context) {
|
|
id, err := strconv.Atoi(c.Param("id"))
|
|
if err != nil {
|
|
log.Printf("[E] PUT > try to update download, but got invalid id: '%s'", c.Param("id"))
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": http.StatusBadRequest,
|
|
"msg": "PUT > try to update download, but got invalid id",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
var updateDownload versions_model.DownloadVersion
|
|
if err = c.ShouldBindJSON(&updateDownload); err != nil {
|
|
log.Printf("[E] PUT > try to update download (id=%d), but got invalid request data: %v", id, err)
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": http.StatusBadRequest,
|
|
"msg": "PUT > try to update download, but got invalid request data",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
var existingDownload versions_model.DownloadVersion
|
|
result := versions_database.DB.First(&existingDownload, id)
|
|
if result.Error != nil {
|
|
log.Printf("[E] PUT > download (id=%d) can not found: %v", id, result.Error)
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
"code": http.StatusNotFound,
|
|
"msg": "PUT > download can not found",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
result = versions_database.DB.Model(&versions_model.DownloadVersion{}).Where("id = ?", id).Updates(updateDownload)
|
|
if result.Error != nil {
|
|
log.Printf("[E] PUT > occur an error when update download (id=%d): %v", id, result.Error)
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": http.StatusInternalServerError,
|
|
"msg": "PUT > occur an error when update download",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
// post check after update
|
|
var updatedDownload versions_model.DownloadVersion
|
|
if result = versions_database.DB.First(&updatedDownload, id); result.Error == nil {
|
|
log.Printf("[I] PUT > update download (id=%d) successful", id)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": http.StatusOK,
|
|
"msg": "PUT > update download successful",
|
|
"data": updatedDownload,
|
|
})
|
|
} else {
|
|
log.Printf("[W] PUT > update successful but failed to retrieve updated download (id=%d): %v", id, result.Error)
|
|
c.JSON(http.StatusAccepted, gin.H{
|
|
"code": http.StatusAccepted,
|
|
"msg": "PUT > update successful but failed to retrieve updated download",
|
|
"data": nil,
|
|
})
|
|
}
|
|
}
|
|
|
|
// DELETE /download/versions/:id
|
|
func DeleteDownloadVersionByID(c *gin.Context) {
|
|
id, err := strconv.Atoi(c.Param("id"))
|
|
if err != nil {
|
|
log.Printf("[E] DELETE > try to delete download, but got invalid id: %s", c.Param("id"))
|
|
c.JSON(http.StatusBadRequest, gin.H{
|
|
"code": http.StatusBadRequest,
|
|
"msg": "DELETE > try to delete download, but got invalid id",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
result := versions_database.DB.Delete(&versions_model.DownloadVersion{}, id)
|
|
if result.Error != nil {
|
|
log.Printf("[E] DELETE > occur an error when delete download (id=%d): %v", id, result.Error)
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": http.StatusInternalServerError,
|
|
"msg": "DELETE > occur an error when delete download",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
log.Printf("[E] DELETE > try to delete download (id=%d), but RowsAffected is 0", id)
|
|
c.JSON(http.StatusNotFound, gin.H{
|
|
"code": http.StatusNotFound,
|
|
"msg": "DELETE > delete download has no effect",
|
|
"data": nil,
|
|
})
|
|
return
|
|
}
|
|
|
|
log.Printf("[I] DELETE > delete download (id=%d) successful", id)
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": http.StatusOK,
|
|
"msg": "DELETE > delete download successful",
|
|
"data": nil,
|
|
})
|
|
}
|