1
0

2 Commity 96dfefab51 ... 6c2e92f560

Autor SHA1 Správa Dátum
  DESKTOP-HN5QP3V\Administrator 6c2e92f560 Merge branch 'develop' 4 týždňov pred
  DESKTOP-HN5QP3V\Administrator 0b7e1ea776 提交增加 advar上传 正式服标识 上传版本检测 1 mesiac pred

+ 52 - 0
app/api/v1/version.go

@@ -10,6 +10,8 @@ import (
 	"github.com/gin-gonic/gin"
 )
 
+const versionExternalConfigKey = "version_external_config"
+
 func isOldVersion(v string) bool {
 	// 比如 < 1.2.0 都算老版本
 	return v <= "1.0.67"
@@ -102,6 +104,56 @@ func VersionEdit(c *gin.Context) {
 	}
 }
 
+func VersionProd(c *gin.Context) {
+	var appG = app.Gin{C: c}
+	service := service.VersionProdService{}
+	if err := c.ShouldBind(&service); err == nil {
+		res := service.Update()
+		appG.Response(http.StatusOK, e.SUCCESS, res)
+	} else {
+		appG.Response(http.StatusOK, e.INVALID_PARAMS, err.Error())
+	}
+}
+
+func VersionExternalConfig(c *gin.Context) {
+	var appG = app.Gin{C: c}
+	svc, ok := c.Get(versionExternalConfigKey)
+	if !ok {
+		appG.Response(http.StatusOK, e.INVALID_PARAMS, "missing version external auth")
+		return
+	}
+	service, ok := svc.(*service.VersionExternalConfigService)
+	if !ok {
+		appG.Response(http.StatusOK, e.INVALID_PARAMS, "invalid version external auth")
+		return
+	}
+	if res := service.Save(); res == nil {
+		appG.Response(http.StatusOK, e.SUCCESS, res)
+	} else {
+		appG.Response(http.StatusOK, e.INVALID_PARAMS, res.Error())
+	}
+}
+
+func VersionExternalAuth() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		var appG = app.Gin{C: c}
+		service := service.VersionExternalConfigService{}
+		if err := c.ShouldBind(&service); err != nil {
+			appG.Response(http.StatusOK, e.INVALID_PARAMS, err.Error())
+			c.Abort()
+			return
+		}
+		if err := service.ValidateAuth(); err != nil {
+			appG.Response(http.StatusOK, e.INVALID_PARAMS, err.Error())
+			c.Abort()
+			return
+		}
+
+		c.Set(versionExternalConfigKey, &service)
+		c.Next()
+	}
+}
+
 func VersionDelete(c *gin.Context) {
 	var appG = app.Gin{C: c}
 	service := service.VersionDeleteService{}

+ 2 - 0
app/router/router.go

@@ -65,6 +65,7 @@ func registerVersionRouter(r *gin.Engine) {
 	{
 		apiv1.POST("version/check", v1.CheckVersion)
 		apiv1.POST("version/server", v1.ServerVersion)
+		apiv1.POST("version/external", v1.VersionExternalAuth(), v1.VersionExternalConfig)
 		apiv1.GET("channel/all", v1.ChannelAll)
 	}
 }
@@ -81,6 +82,7 @@ func registerAdminRouter(r *gin.Engine) {
 			authed.GET("versions", v1.ShowVersions)
 			authed.POST("version", v1.VersionCreate)
 			authed.PUT("version", v1.VersionEdit)
+			authed.PUT("version/prod", v1.VersionProd)
 			authed.DELETE("version/:key", v1.VersionDelete)
 			authed.POST("version/reload", v1.ReloadVersion)
 			authed.GET("channel/list", v1.ChannelList)

+ 6 - 0
app/service/channel.go

@@ -75,6 +75,7 @@ func (s *ChannelListService) List() (interface{}, error) {
 type ChannelCreateService struct {
 	Name        string `json:"name" binding:"required"`
 	Code        string `json:"code" binding:"required"`
+	Platform    string `json:"platform" binding:"required"`
 	Description string `json:"description"`
 	Status      *bool  `json:"status"`
 }
@@ -83,6 +84,7 @@ func (s *ChannelCreateService) Create() error {
 	c := &channel.Channel{
 		Name:        s.Name,
 		Code:        s.Code,
+		Platform:    s.Platform,
 		Description: s.Description,
 		Status:      true,
 	}
@@ -97,6 +99,7 @@ type ChannelUpdateService struct {
 	ID          string  `json:"id" binding:"required"`
 	Name        *string `json:"name"`
 	Code        *string `json:"code"`
+	Platform    *string `json:"platform"`
 	Description *string `json:"description"`
 	Status      *bool   `json:"status"`
 }
@@ -114,6 +117,9 @@ func (s *ChannelUpdateService) Update() error {
 	if s.Code != nil {
 		updateDoc["code"] = *s.Code
 	}
+	if s.Platform != nil {
+		updateDoc["platform"] = *s.Platform
+	}
 	if s.Description != nil {
 		updateDoc["description"] = *s.Description
 	}

+ 115 - 0
app/service/version.go

@@ -2,14 +2,22 @@ package service
 
 import (
 	"context"
+	"errors"
+	"fmt"
+	"strconv"
+	"time"
+
 	"dsbqj-admin/app/task"
 	"dsbqj-admin/model/mongo/version"
+	"dsbqj-admin/tool"
 
 	"github.com/kamva/mgm/v3"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 )
 
+const versionExternalReqTimeoutSec = 30 * 60
+
 type VersionReloadService struct {
 }
 
@@ -130,6 +138,113 @@ func (service *VersionEditService) Edit() error {
 	return err
 }
 
+type VersionProdService struct {
+	Id     string `json:"id" binding:"required"`
+	IsProd bool   `json:"isProd"`
+}
+
+func (service *VersionProdService) Update() error {
+	objectId, err := primitive.ObjectIDFromHex(service.Id)
+	if err != nil {
+		return err
+	}
+
+	coll := mgm.Coll(&version.Version{})
+	var current version.Version
+	if err := coll.FindByID(objectId, &current); err != nil {
+		return err
+	}
+
+	if service.IsProd {
+		if _, err := coll.UpdateMany(
+			context.Background(),
+			bson.M{"_id": bson.M{"$ne": objectId}},
+			bson.M{"$set": bson.M{"isProd": false}},
+		); err != nil {
+			return err
+		}
+	}
+
+	_, err = coll.UpdateOne(
+		context.Background(),
+		bson.M{"_id": objectId},
+		bson.M{"$set": bson.M{"isProd": service.IsProd}},
+	)
+	return err
+}
+
+type VersionExternalConfigService struct {
+	Channel string  `form:"channel" json:"channel" binding:"required"`
+	Version string  `form:"version" json:"version" binding:"required"`
+	AbVer   *string `form:"abVer" json:"abVer"`
+	MD5     *string `form:"md5" json:"md5"`
+	TimeSec int64   `form:"timesec" json:"timesec" binding:"required"`
+	Sign    string  `form:"sign" json:"sign" binding:"required"`
+}
+
+func (service *VersionExternalConfigService) Save() error {
+	if service.AbVer == nil && service.MD5 == nil {
+		return errors.New("abVer or md5 is required")
+	}
+
+	filterDoc := bson.M{
+		"channel": service.Channel,
+		"version": service.Version,
+	}
+
+	coll := mgm.Coll(&version.Version{})
+	var current version.Version
+	if err := coll.First(filterDoc, &current); err != nil {
+		return errors.New("version not found")
+	}
+	if current.IsProd {
+		return errors.New("production version does not allow external upload")
+	}
+
+	updateDoc := bson.M{}
+	if service.AbVer != nil {
+		updateDoc["abVer"] = *service.AbVer
+	}
+	if service.MD5 != nil {
+		updateDoc["md5"] = *service.MD5
+	}
+
+	_, err := coll.UpdateOne(
+		context.Background(),
+		bson.M{"_id": current.ID},
+		bson.M{"$set": updateDoc},
+	)
+	return err
+}
+
+func (service *VersionExternalConfigService) ValidateAuth() error {
+	deltaTime := time.Now().Unix() - service.TimeSec
+	if deltaTime < 0 {
+		deltaTime = -deltaTime
+	}
+	if deltaTime > versionExternalReqTimeoutSec {
+		return fmt.Errorf("timesec timeout")
+	}
+
+	params := map[string]any{
+		"channel": service.Channel,
+		"version": service.Version,
+		"timesec": strconv.FormatInt(service.TimeSec, 10),
+	}
+	if service.AbVer != nil {
+		params["abVer"] = *service.AbVer
+	}
+	if service.MD5 != nil {
+		params["md5"] = *service.MD5
+	}
+
+	sign := tool.GenSign(params)
+	if sign != service.Sign {
+		return fmt.Errorf("sign error")
+	}
+	return nil
+}
+
 type VersionDeleteService struct {
 	Id string `json:"id" binding:"required"`
 }

+ 1 - 0
model/mongo/channel/channel.go

@@ -11,6 +11,7 @@ type Channel struct {
 	mgm.DefaultModel `bson:",inline"`
 	Name             string `bson:"name" json:"name"`
 	Code             string `bson:"code" json:"code"`
+	Platform         string `bson:"platform" json:"platform"`
 	Description      string `bson:"description" json:"description"`
 	Status           bool   `bson:"status" json:"status"`
 }

+ 3 - 0
model/mongo/version/version.go

@@ -12,5 +12,8 @@ type Version struct {
 	Name             string `bson:"name" json:"name"`
 	CDN              string `bson:"cdn" json:"cdn"`
 	Url              string `bson:"url" json:"url"`
+	AbVer            string `bson:"abVer" json:"abVer"`
+	MD5              string `bson:"md5" json:"md5"`
 	Default          bool   `bson:"default" json:"default"`
+	IsProd           bool   `bson:"isProd" json:"isProd"`
 }

+ 2 - 0
pkg/serializer/channel.go

@@ -9,6 +9,7 @@ type ChannelResponse struct {
 	ID          string `json:"id"`
 	Name        string `json:"name"`
 	Code        string `json:"code"`
+	Platform    string `json:"platform"`
 	Description string `json:"description"`
 	Status      bool   `json:"status"`
 	CreateTime  string `json:"createTime"`
@@ -23,6 +24,7 @@ func BuildChannel(c *channel.Channel) *ChannelResponse {
 		ID:          c.ID.Hex(),
 		Name:        c.Name,
 		Code:        c.Code,
+		Platform:    c.Platform,
 		Description: c.Description,
 		Status:      c.Status,
 		CreateTime:  c.GetCreateTime(),