Files
dify-plus/admin/server/api/v1/gaia/app_version.go
T
npc0-hue df9bed2950 fear: admin添加app应用版本管理
system-features添加
2026-02-09 09:11:58 +08:00

300 lines
9.4 KiB
Go

package gaia
import (
"strconv"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
gaiaReq "github.com/flipped-aurora/gin-vue-admin/server/model/gaia/request"
"github.com/flipped-aurora/gin-vue-admin/server/service"
"github.com/flipped-aurora/gin-vue-admin/server/utils"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type AppVersionApi struct{}
var appVersionService = service.ServiceGroupApp.GaiaServiceGroup.AppVersionService
// GetLatest 客户端获取最新版本(公开接口)
// @Tags AppVersion
// @Summary 客户端获取最新版本
// @accept application/json
// @Produce application/json
// @Param platform query string true "平台(如 win32/darwin/linux)"
// @Param arch query string false "架构(可选,未传或未匹配时取该 platform 第一个包)"
// @Param token query string false "Token(若后台配置了则必填)"
// @Success 200 {object} response.Response "获取成功"
// @Router /latest [get]
func (appVersionApi *AppVersionApi) GetLatest(c *gin.Context) {
platform := c.Query("platform")
arch := c.Query("arch")
token := c.Query("token")
if platform == "" {
response.FailWithMessage("platform is required", c)
return
}
resp, code := appVersionService.GetLatest(platform, arch, token)
if code == 401 {
response.NoAuth("token required or invalid", c)
return
}
if code == 404 {
response.FailWithMessage("no package for this platform/arch", c)
return
}
if code != 200 {
global.GVA_LOG.Error("GetLatest failed", zap.Int("code", code))
response.FailWithMessage("internal error", c)
return
}
response.OkWithData(resp, c)
}
func buildDownloadUrl(c *gin.Context) func(string) string {
prefix := global.GVA_CONFIG.System.RouterPrefix
return func(path string) string {
scheme := "https"
if c.GetHeader("X-Forwarded-Proto") != "" {
scheme = c.GetHeader("X-Forwarded-Proto")
} else if c.Request.TLS == nil {
scheme = "http"
}
host := c.Request.Host
if path == "" {
return ""
}
if path[0] != '/' {
path = "/" + path
}
if prefix != "" {
return scheme + "://" + host + prefix + path
}
return scheme + "://" + host + path
}
}
// GetTokenConfig 管理端获取全局 Token 配置
// @Tags AppVersion
// @Summary 管理端获取全局 Token 配置
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {object} response.Response "获取成功"
// @Router /gaia/app-version/token [get]
func (appVersionApi *AppVersionApi) GetTokenConfig(c *gin.Context) {
cfg, err := appVersionService.GetTokenConfig()
if err != nil {
global.GVA_LOG.Error("获取Token配置失败!", zap.Error(err))
response.FailWithMessage("获取失败:"+err.Error(), c)
return
}
response.OkWithData(cfg, c)
}
// SetTokenConfig 管理端设置全局 Token
// @Tags AppVersion
// @Summary 管理端设置全局 Token
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body gaiaReq.AppVersionTokenConfig true "Token 配置"
// @Success 200 {object} response.Response "设置成功"
// @Router /gaia/app-version/token [put]
func (appVersionApi *AppVersionApi) SetTokenConfig(c *gin.Context) {
var req gaiaReq.AppVersionTokenConfig
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
if err := appVersionService.SetTokenConfig(req); err != nil {
global.GVA_LOG.Error("设置Token配置失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
return
}
response.Ok(c)
}
// RevealToken 输入登录密码验证后返回明文 Token
// @Tags AppVersion
// @Summary 输入登录密码验证后返回明文 Token
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body gaiaReq.AppVersionTokenReveal true "密码"
// @Success 200 {object} response.Response "获取成功"
// @Router /gaia/app-version/token/reveal [post]
func (appVersionApi *AppVersionApi) RevealToken(c *gin.Context) {
var req gaiaReq.AppVersionTokenReveal
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
userID := utils.GetUserID(c)
token, err := appVersionService.RevealToken(userID, req.Password)
if err != nil {
global.GVA_LOG.Error("RevealToken失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(gin.H{"token": token}, c)
}
// ListReleases 版本列表
// @Tags AppVersion
// @Summary 版本列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {object} response.Response "获取成功"
// @Router /gaia/app-version/releases [get]
func (appVersionApi *AppVersionApi) ListReleases(c *gin.Context) {
list, err := appVersionService.ListReleases()
if err != nil {
global.GVA_LOG.Error("获取版本列表失败!", zap.Error(err))
response.FailWithMessage("获取失败:"+err.Error(), c)
return
}
response.OkWithData(list, c)
}
// CreateRelease 新增版本
// @Tags AppVersion
// @Summary 新增版本
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body gaiaReq.AppVersionReleaseCreate true "版本信息"
// @Success 200 {object} response.Response "创建成功"
// @Router /gaia/app-version/releases [post]
func (appVersionApi *AppVersionApi) CreateRelease(c *gin.Context) {
var req gaiaReq.AppVersionReleaseCreate
if err := c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
r, err := appVersionService.CreateRelease(req)
if err != nil {
global.GVA_LOG.Error("创建版本失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(r, c)
}
// GetRelease 获取单个版本详情
// @Tags AppVersion
// @Summary 获取单个版本详情
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param id path int true "版本 ID"
// @Success 200 {object} response.Response "获取成功"
// @Router /gaia/app-version/releases/:id [get]
func (appVersionApi *AppVersionApi) GetRelease(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的版本 id", c)
return
}
detail, err := appVersionService.GetReleaseByID(uint(id))
if err != nil {
global.GVA_LOG.Error("获取版本详情失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(detail, c)
}
// UpdateRelease 更新版本信息
// @Tags AppVersion
// @Summary 更新版本信息
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param id path int true "版本 ID"
// @Param data body gaiaReq.AppVersionReleaseUpdate true "版本信息"
// @Success 200 {object} response.Response "更新成功"
// @Router /gaia/app-version/releases/:id [put]
func (appVersionApi *AppVersionApi) UpdateRelease(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的版本 id", c)
return
}
var req gaiaReq.AppVersionReleaseUpdate
if err = c.ShouldBindJSON(&req); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
if err = appVersionService.UpdateRelease(uint(id), req); err != nil {
global.GVA_LOG.Error("更新版本失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
return
}
response.Ok(c)
}
// UploadToRelease 上传安装包到指定版本(根据文件名自动识别平台/架构)
// @Tags AppVersion
// @Summary 上传安装包到指定版本
// @Security ApiKeyAuth
// @accept multipart/form-data
// @Produce application/json
// @Param id path int true "版本 ID"
// @Param file formData file true "安装包文件"
// @Success 200 {object} response.Response "上传成功"
// @Router /gaia/app-version/releases/:id/upload [post]
func (appVersionApi *AppVersionApi) UploadToRelease(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的版本 id", c)
return
}
file, err := c.FormFile("file")
if err != nil {
response.FailWithMessage("请选择文件: "+err.Error(), c)
return
}
if err = appVersionService.UploadPackageToRelease(uint(id), file, buildDownloadUrl(c)); err != nil {
global.GVA_LOG.Error("上传安装包失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
return
}
response.Ok(c)
}
// DeleteDownload 删除指定版本下某 platform/arch 的包
// @Tags AppVersion
// @Summary 删除指定版本下某 platform/arch 的包
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param id path int true "版本 ID"
// @Param platform query string true "平台"
// @Param arch query string true "架构"
// @Success 200 {object} response.Response "删除成功"
// @Router /gaia/app-version/releases/:id/download [delete]
func (appVersionApi *AppVersionApi) DeleteDownload(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
response.FailWithMessage("无效的版本 id", c)
return
}
var q gaiaReq.AppVersionDeleteQuery
if err = c.ShouldBindQuery(&q); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
if err = appVersionService.DeleteDownload(uint(id), q.Platform, q.Arch); err != nil {
global.GVA_LOG.Error("删除安装包失败!", zap.Error(err))
response.FailWithMessage(err.Error(), c)
return
}
response.Ok(c)
}