From 7a78e5d869468049af72580a6f7c0fb6f70676ec Mon Sep 17 00:00:00 2001
From: wangchuxiao <wangchuxiao97@outlook.com>
Date: Tue, 10 May 2022 16:53:58 +0800
Subject: [PATCH] update app

---
 cmd/open_im_api/main.go                       |   2 +
 .../api/third/minio_storage_credential.go     | 127 ++++++++++++++++++
 pkg/base_info/minio_api_struct.go             |  31 +++++
 3 files changed, 160 insertions(+)

diff --git a/cmd/open_im_api/main.go b/cmd/open_im_api/main.go
index e5d7c9930..cd774627b 100644
--- a/cmd/open_im_api/main.go
+++ b/cmd/open_im_api/main.go
@@ -106,6 +106,8 @@ func main() {
 		thirdGroup.POST("/ali_oss_credential", apiThird.AliOSSCredential)
 		thirdGroup.POST("/minio_storage_credential", apiThird.MinioStorageCredential)
 		thirdGroup.POST("/minio_upload", apiThird.MinioUploadFile)
+		thirdGroup.POST("/upload_update_app", apiThird.UploadUpdateApp)
+		thirdGroup.POST("/get_download_url", apiThird.GetDownloadURL)
 	}
 	//Message
 	chatGroup := r.Group("/msg")
diff --git a/internal/api/third/minio_storage_credential.go b/internal/api/third/minio_storage_credential.go
index 7a6926360..f1c4401e6 100644
--- a/internal/api/third/minio_storage_credential.go
+++ b/internal/api/third/minio_storage_credential.go
@@ -4,16 +4,19 @@ import (
 	apiStruct "Open_IM/pkg/base_info"
 	"Open_IM/pkg/common/config"
 	"Open_IM/pkg/common/constant"
+	imdb "Open_IM/pkg/common/db/mysql_model/im_mysql_model"
 	"Open_IM/pkg/common/log"
 	"Open_IM/pkg/common/token_verify"
 	_ "Open_IM/pkg/common/token_verify"
 	"Open_IM/pkg/utils"
 	"context"
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"github.com/minio/minio-go/v7"
 	_ "github.com/minio/minio-go/v7"
 	cr "github.com/minio/minio-go/v7/pkg/credentials"
 	"net/http"
+	"path"
 )
 
 func MinioUploadFile(c *gin.Context) {
@@ -147,3 +150,127 @@ func MinioStorageCredential(c *gin.Context) {
 	resp.StsEndpointURL = config.Config.Credential.Minio.Endpoint
 	c.JSON(http.StatusOK, gin.H{"errCode": 0, "errMsg": "", "data": resp})
 }
+
+func UploadUpdateApp(c *gin.Context) {
+	var (
+		req  apiStruct.UploadUpdateAppReq
+		resp apiStruct.UploadUpdateAppResp
+	)
+	if err := c.Bind(&req); err != nil {
+		log.NewError(req.OperationID, utils.GetSelfFuncName(), "BindJSON failed ", err.Error())
+		c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
+		return
+	}
+	log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req: ", req)
+
+	fileObj, err := req.File.Open()
+	if err != nil {
+		log.NewError(req.OperationID, utils.GetSelfFuncName(), "Open file error", err.Error())
+		c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "Open file error" + err.Error()})
+		return
+	}
+	yamlObj, err := req.Yaml.Open()
+	if err != nil {
+		log.NewError(req.OperationID, utils.GetSelfFuncName(), "Open Yaml error", err.Error())
+		c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "Open Yaml error" + err.Error()})
+		return
+	}
+
+	// v2.0.9_app_linux v2.0.9_yaml_linux
+
+	//file, err := c.FormFile("file")
+	//if err != nil {
+	//	log.NewError(req.OperationID, utils.GetSelfFuncName(), "FormFile failed", err.Error())
+	//	c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "missing file arg: " + err.Error()})
+	//	return
+	//}
+	//fileObj, err := file.Open()
+	//if err != nil {
+	//	log.NewError(req.OperationID, utils.GetSelfFuncName(), "Open file error", err.Error())
+	//	c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "invalid file path" + err.Error()})
+	//	return
+	//}
+	//
+	//yaml, err := c.FormFile("yaml")
+	//if err != nil {
+	//	log.NewError(req.OperationID, utils.GetSelfFuncName(), "FormFile failed", err.Error())
+	//	c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "missing file arg: " + err.Error()})
+	//	return
+	//}
+	//yamlObj, err := yaml.Open()
+	//if err != nil {
+	//	log.NewError(req.OperationID, utils.GetSelfFuncName(), "Open file error", err.Error())
+	//	c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "invalid file path" + err.Error()})
+	//	return
+	//}
+	newFileName, newYamlName, err := utils.GetUploadAppNewName(req.Type, req.Version, req.File.Filename, req.Yaml.Filename)
+	if err != nil {
+		log.NewError(req.OperationID, utils.GetSelfFuncName(), "GetUploadAppNewName failed", err.Error())
+		c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "invalid file type" + err.Error()})
+		return
+	}
+	fmt.Println(req.OperationID, utils.GetSelfFuncName(), "name: ", config.Config.Credential.Minio.AppBucket, newFileName, fileObj, req.File.Size)
+	fmt.Println(req.OperationID, utils.GetSelfFuncName(), "name: ", config.Config.Credential.Minio.AppBucket, newYamlName, yamlObj, req.Yaml.Size)
+
+	_, err = MinioClient.PutObject(context.Background(), config.Config.Credential.Minio.AppBucket, newFileName, fileObj, req.File.Size, minio.PutObjectOptions{ContentType: path.Ext(newFileName)})
+	if err != nil {
+		log.NewError(req.OperationID, utils.GetSelfFuncName(), "PutObject file error")
+		c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "PutObject file error" + err.Error()})
+		return
+	}
+	_, err = MinioClient.PutObject(context.Background(), config.Config.Credential.Minio.AppBucket, newYamlName, yamlObj, req.Yaml.Size, minio.PutObjectOptions{ContentType: path.Ext(newYamlName)})
+	if err != nil {
+		log.NewError(req.OperationID, utils.GetSelfFuncName(), "PutObject yaml error")
+		c.JSON(http.StatusInternalServerError, gin.H{"errCode": 500, "errMsg": "PutObject yaml error" + err.Error()})
+		return
+	}
+	if err := imdb.UpdateAppVersion(req.Type, req.Version, req.ForceUpdate, newFileName, newYamlName); err != nil {
+		log.NewError(req.OperationID, utils.GetSelfFuncName(), "UpdateAppVersion error", err.Error())
+		resp.ErrCode = http.StatusInternalServerError
+		resp.ErrMsg = err.Error()
+		c.JSON(http.StatusInternalServerError, resp)
+		return
+	}
+	log.NewInfo(req.OperationID, utils.GetSelfFuncName())
+	c.JSON(http.StatusOK, resp)
+}
+
+func GetDownloadURL(c *gin.Context) {
+	var (
+		req  apiStruct.GetDownloadURLReq
+		resp apiStruct.GetDownloadURLResp
+	)
+	defer func() {
+		log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "resp: ", resp)
+	}()
+	if err := c.Bind(&req); err != nil {
+		log.NewError("0", utils.GetSelfFuncName(), "BindJSON failed ", err.Error())
+		c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": err.Error()})
+		return
+	}
+	log.NewInfo(req.OperationID, utils.GetSelfFuncName(), "req: ", req)
+	//fileName, yamlName, err := utils.GetUploadAppNewName(req.Type, req.Version, req.)
+	//if err != nil {
+	//	log.NewError(req.OperationID, utils.GetSelfFuncName(), "GetUploadAppNewName failed", err.Error())
+	//	c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "invalid file type" + err.Error()})
+	//	return
+	//}
+	app, err := imdb.GetNewestVersion(req.Type)
+	if err != nil {
+		log.NewError(req.OperationID, utils.GetSelfFuncName(), "getNewestVersion failed", err.Error())
+		c.JSON(http.StatusBadRequest, gin.H{"errCode": 400, "errMsg": "getNewestVersion failed" + err.Error()})
+		return
+	}
+	if app.Version != req.Version {
+		resp.Data.HasNewVersion = true
+		if app.ForceUpdate == true {
+			resp.Data.ForceUpdate = true
+		}
+		resp.Data.YamlURL = config.Config.Credential.Minio.Endpoint + "/" + config.Config.Credential.Minio.AppBucket + "/" + app.YamlName
+		resp.Data.FileURL = config.Config.Credential.Minio.Endpoint + "/" + config.Config.Credential.Minio.AppBucket + "/" + app.FileName
+		c.JSON(http.StatusOK, resp)
+	} else {
+		resp.Data.HasNewVersion = false
+		c.JSON(http.StatusOK, resp)
+	}
+}
diff --git a/pkg/base_info/minio_api_struct.go b/pkg/base_info/minio_api_struct.go
index 6d3b0ecac..8a3f2d00a 100644
--- a/pkg/base_info/minio_api_struct.go
+++ b/pkg/base_info/minio_api_struct.go
@@ -1,5 +1,7 @@
 package base_info
 
+import "mime/multipart"
+
 type MinioStorageCredentialReq struct {
 	OperationID string `json:"operationID"`
 }
@@ -23,3 +25,32 @@ type MinioUploadFileResp struct {
 	SnapshotURL     string `json:"snapshotURL,omitempty"`
 	SnapshotNewName string `json:"snapshotName,omitempty"`
 }
+
+type UploadUpdateAppReq struct {
+	OperationID string                `form:"operationID" binding:"required"`
+	Type        int                   `form:"type" binding:"required"`
+	Version     string                `form:"version"  binding:"required"`
+	File        *multipart.FileHeader `form:"file" binding:"required"`
+	Yaml        *multipart.FileHeader `form:"yaml" binding:"required"`
+	ForceUpdate bool                  `form:"forceUpdate"  binding:"required"`
+}
+
+type UploadUpdateAppResp struct {
+	CommResp
+}
+
+type GetDownloadURLReq struct {
+	OperationID string `json:"operationID" binding:"required"`
+	Type        int    `json:"type" binding:"required"`
+	Version     string `json:"version" binding:"required"`
+}
+
+type GetDownloadURLResp struct {
+	CommResp
+	Data struct {
+		HasNewVersion bool   `json:"hasNewVersion"`
+		ForceUpdate   bool   `json:"forceUpdate"`
+		FileURL       string `json:"fileURL"`
+		YamlURL       string `json:"yamlURL"`
+	} `json:"data"`
+}