zhangzengfei
2023-09-05 63645d248c765244488cd34dbc1bb6528ca6b7c7
version-control/controller/controller.go
@@ -1,1042 +1,1042 @@
package controller
import (
   "encoding/json"
   "fmt"
   "io/ioutil"
   "net/http"
   "os"
   "os/exec"
   "path"
   "path/filepath"
   "sort"
   "strconv"
   "strings"
   "time"
   "vamicro/extend/code"
   "vamicro/extend/util"
   "vamicro/version-control/models"
   "vamicro/version-control/routers"
   "vamicro/version-control/service"
   "basic.com/valib/bhomeclient.git"
   "basic.com/valib/c_bhomebus.git/proto/source/bhome_msg"
   "basic.com/valib/licence.git"
   "basic.com/valib/logger.git"
   "github.com/gin-gonic/gin"
)
type (
   VersionRouter struct {
      routers.Router
   }
)
const (
   basePath = "/version"
   manifest = "dist/bin/manifest.ini"
   zipDir   = "dist/bin"
)
var (
   CheckVersion              *VersionRouter
   Upgrade                   *VersionRouter
   UploadDist                *VersionRouter
   SettingFetch              *VersionRouter
   SettingPush               *VersionRouter
   UpdateNotice              *VersionRouter
   DelayNotice               *VersionRouter
   PreUpLoad                 *VersionRouter
   UpgradePreUpLoad          *VersionRouter
   RollBack                  *VersionRouter
   Authorization             *VersionRouter
   GetSn                     *VersionRouter
   Qrcode                    *VersionRouter
   AuthorizationUpload       *VersionRouter
   CancelAuthorization       *VersionRouter
   CancelAuthorizationUpload *VersionRouter
   ShopMakeSmsCod         *VersionRouter
   ShopCenterLogin        *VersionRouter
   ShopCenterGetOrderList *VersionRouter
   AuthActiveByOrder      *VersionRouter
   AutoBakShow     *VersionRouter
   AutoBakConfSet  *VersionRouter
   AutoBakRightNow *VersionRouter
   BackupListShow  *VersionRouter
   BackupRecov     *VersionRouter
   Ms *bhomeclient.MicroNode
)
func init() {
   CheckVersion = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "check",
         Handles: []gin.HandlerFunc{versionCheckHandle},
      },
   }
   UploadDist = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "upload",
         Handles: []gin.HandlerFunc{uploadDistHandle},
      },
   }
   Upgrade = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "upgrade",
         Handles: []gin.HandlerFunc{upgradeHandle},
      },
   }
   SettingFetch = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "settings",
         Handles: []gin.HandlerFunc{settingFetchHandle},
      },
   }
   SettingPush = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "setting/update",
         Handles: []gin.HandlerFunc{settingPushHandle},
      },
   }
   UpdateNotice = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "notice",
         Handles: []gin.HandlerFunc{updateNoticeHandle},
      },
   }
   DelayNotice = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "notice/delay",
         Handles: []gin.HandlerFunc{delayNoticeHandle},
      },
   }
   PreUpLoad = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "upload/zip",
         Handles: []gin.HandlerFunc{preUploadDistHandle},
      },
   }
   UpgradePreUpLoad = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "upgrade/zip",
         Handles: []gin.HandlerFunc{upgradePreUploadHandle},
      },
   }
   RollBack = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "rollback",
         Handles: []gin.HandlerFunc{RollBackHandle},
      },
   }
   Authorization = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "authorization",
         Handles: []gin.HandlerFunc{AuthorizationHandle},
      },
   }
   AuthorizationUpload = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "authorization/upload",
         Handles: []gin.HandlerFunc{AuthorizationUploadHandle},
      },
   }
   GetSn = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "sn",
         Handles: []gin.HandlerFunc{GetSnHandle},
      },
   }
   Qrcode = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "offline/qrcode",
         Handles: []gin.HandlerFunc{QrcodeHandle},
      },
   }
   CancelAuthorization = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "cancelAuthorization",
         Handles: []gin.HandlerFunc{CancelAuthorizationHandle},
      },
   }
   CancelAuthorizationUpload = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "cancelAuthorization/upload",
         Handles: []gin.HandlerFunc{CancelAuthorizationUploadHandle},
      },
   }
   ShopMakeSmsCod = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "auth/shop/smsCode",
         Handles: []gin.HandlerFunc{shopMakSmsHandle},
      },
   }
   ShopCenterLogin = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "auth/shop/login",
         Handles: []gin.HandlerFunc{shopCenterLoginHandle},
      },
   }
   ShopCenterGetOrderList = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "auth/shop/getOrderList",
         Handles: []gin.HandlerFunc{shopCenterGetOrderListHandle},
      },
   }
   AuthActiveByOrder = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "auth/shop/activeByOrder",
         Handles: []gin.HandlerFunc{authActiveByOrderHandle},
      },
   }
   AutoBakShow = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "autoBak/config",
         Handles: []gin.HandlerFunc{ShowAutoBakConf},
      },
   }
   AutoBakConfSet = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "autoBak/saveConf",
         Handles: []gin.HandlerFunc{SaveAutoBakConf},
      },
   }
   AutoBakRightNow = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "autoBak/backupRN",
         Handles: []gin.HandlerFunc{BackupRN},
      },
   }
   BackupListShow = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "autoBak/list",
         Handles: []gin.HandlerFunc{BackupList},
      },
   }
   BackupRecov = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "autoBak/recover",
         Handles: []gin.HandlerFunc{BackupRecover},
      },
   }
}
func (r *VersionRouter) GetPath() string {
   return path.Join(basePath, r.Path)
}
//在系统配置app中,给页面调用,判断提醒有没有程序是否需要升级
func versionCheckHandle(c *gin.Context) {
   _, version, intro := service.CheckVersion()
   curVersion := service.GetCurVersion()
   //curEnv, _ := service.GetRunVersionEnv()
   //hasNewVersion := len(programs) > 0
   hasNewVersion := version != curVersion
   if version == "" {
      hasNewVersion = false
      version = curVersion
   }
   c.JSON(http.StatusOK, gin.H{
      "code": 200,
      "msg":  "ok",
      "data": map[string]interface{}{
         "hasNewVersion":  hasNewVersion,
         "newVersion":     version,
         "newVersionInfo": intro,
         "curVersion":     curVersion,
         "curVersionPath": curVersion,
      },
   })
}
func preUploadDistHandle(c *gin.Context) {
   file, err := c.FormFile("archive")
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   UpgradePath := service.GetPreUploadPath()
   err = os.RemoveAll(UpgradePath)
   if nil == err {
      _ = os.MkdirAll(UpgradePath, 0777)
   } else {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle remove pre upload path failed, err:", err.Error())
      return
   }
   fileMd5 := service.GetMd5(file.Filename) + ".tgz"
   if err = c.SaveUploadedFile(file, path.Join(UpgradePath, fileMd5)); err != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle save file failed, err:", err.Error())
      return
   }
   logger.Info("uploadDistHandle saved to temp file ok:", fileMd5)
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "ok",
      "data": map[string]string{"id": fileMd5},
   })
}
func upgradePreUploadHandle(c *gin.Context) {
   upid := c.Query("id")
   if upid == "" {
      util.ResponseFormat(c, code.RequestParamError, "id不能为空")
      return
   }
   UpgradePath := service.GetPreUploadPath()
   upZip := path.Join(UpgradePath, upid)
   if !util.FileExists(upZip) {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "升级包未找到!",
         "data": []*models.Program{},
      })
      logger.Error("upgradePreUploadHandle upload file not found:", upZip)
      return
   }
   logger.Info("开始升级!")
   apps, err := service.UpgradeViaZip(upZip)
   logger.Info("系统升级完成!!")
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": apps,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": apps,
      })
      killApp(apps)
   }
}
//在离线的情况,使用tgz包直接在内网上传离线安装包
func uploadDistHandle(c *gin.Context) {
   file, err := c.FormFile("archive")
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   UpgradePath := service.GetPreUploadPath()
   tmpFile, err := ioutil.TempFile(UpgradePath, "dist-*.tgz")
   if nil != err {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle create temp file failed, err:", err.Error())
      return
   }
   defer func() {
      tmpFile.Close()
      os.Remove(tmpFile.Name())
   }()
   if err = c.SaveUploadedFile(file, tmpFile.Name()); err != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle save file failed, err:", err.Error())
      return
   }
   logger.Info("uploadDistHandle saved to temp file ok:", tmpFile.Name())
   apps, err := service.UpgradeViaZip(tmpFile.Name())
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": apps,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": apps,
      })
   }
}
func upgradeHandle(c *gin.Context) {
   apps, err := service.OnlineUpgrade()
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": apps,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": apps,
      })
      //_ = syscall.Kill(syscall.Getpid(), syscall.SIGINT)
      killApp(apps)
   }
}
func killApp(apps []*models.Program) {
   //循环杀死升级应用进程
   versionControl := ""
   for _, app := range apps {
      if app.Name == "version-control" {
         versionControl = app.Name
         continue
      }
      if app.Type == "sys" || app.Type == "app" {
         command := "pkill " + app.Name
         result, err := execCommand(command)
         logger.Info("执行命令【", command, "】")
         logger.Info("执行结果【", result, "err:,", err, "】")
      }
   }
   if versionControl != "" {
      command := "pkill " + versionControl
      result, err := execCommand(command)
      logger.Info("执行命令【", command, "】")
      logger.Info("执行结果【", result, "\n err:,", err, "】")
   }
}
//执行命令
func execCommand(cmd string) ([]byte, error) {
   return exec.Command("/bin/bash", "-c", cmd).Output()
}
//获取配置
func settingFetchHandle(c *gin.Context) {
   var model models.SysSetting
   settings, err := model.GetAllSetting()
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": settings,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": settings,
      })
   }
}
//更新配置
func settingPushHandle(c *gin.Context) {
   name := c.PostForm("name")
   value := c.PostForm("value")
   setting := models.SysSetting{Name: name, Value: value}
   err := setting.SaveSetting(true)
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": []interface{}{},
      })
   } else {
      data, _ := json.Marshal(setting)
      var nodes []bhome_msg.BHAddress
      nodes = append(nodes, bhome_msg.BHAddress{})
      go Ms.PublishNetTimeout(nodes, service.SysUpdateConfigTopic, data, 10)
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": []interface{}{},
      })
   }
}
func updateNoticeHandle(c *gin.Context) {
   notice := service.GetUpdateNotice()
   uid, ok := c.Get("uid")
   if ok {
      LastNoticeTime, ok := notice.NoticeUser[uid.(string)]
      if ok {
         notice.LastNoticeTime = int64(LastNoticeTime)
      }
   }
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "ok",
      "data": notice,
   })
}
func delayNoticeHandle(c *gin.Context) {
   delaySecond := c.PostForm("delaySecond")
   second, err := strconv.Atoi(delaySecond)
   if nil == err {
      uid, ok := c.Get("uid")
      if ok {
         notice := service.DelayNotice(uid.(string), second)
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "ok",
            "data": notice,
         })
      } else {
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "未找到用户",
            "data": []interface{}{},
         })
      }
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "参数错误",
         "data": []interface{}{},
      })
   }
}
func RollBackHandle(c *gin.Context) {
   version := c.PostForm("version")
   err := service.Rollback(version)
   if nil == err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": []interface{}{},
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "回滚失败," + err.Error(),
         "data": []interface{}{},
      })
   }
}
func sn() map[string]interface{} {
   data := make(map[string]interface{}, 0)
   sn := util.GetSn()
   data["sn"] = sn
   auth := util.GetAuthorization()
   data["expireTime"] = ""
   authInfo, err := util.GetAuthorizationInfo(auth)
   //logger.Debug("授权信息:", authInfo, err, licence.GetMachineCode())
   if err == nil && authInfo.MachineCode == licence.GetMachineCode() {
      expireUt := time.Unix(authInfo.ExpirationTime, 0)
      expireTimeStr := expireUt.Format("2006-01-02 15:04:05")
      data["expireTime"] = expireTimeStr
      data["expire"] = false
      if authInfo.ActivateCode != "" {
         data["sn"] = authInfo.ActivateCode
      }
      if authInfo.DevCount == -1 { //试用版
         data["sn"] = ""
      }
      if time.Now().Sub(expireUt) > 0 {
         data["expire"] = true
         data["sn"] = ""
      }
      if data["sn"] != "" {
         data["authorization"] = auth
      }
      data["edition"] = authInfo.Edition
      data["installTime"] = authInfo.InstallTime
      if authInfo.Edition == "" || authInfo.InstallTime == "" {
         if eii, err := util.GetEdtionSetFromIns(); err == nil {
            if authInfo.Edition == "" {
               data["edition"] = eii.Edition
            }
            if authInfo.InstallTime == "" {
               data["installTime"] = eii.InstallTime
            }
         }
      }
   } else {
      //测试版
      eii, err := util.GetEdtionSetFromIns()
      if err == nil {
         insT, _ := time.ParseInLocation("2006-01-02 15:04:05", eii.InstallTime, time.Local)
         if eii.OrderAuth != nil && eii.OrderAuth.ProductId != "" && eii.OrderAuth.OrderId != "" {
            data["sn"] = ""
            expireT := insT.AddDate(eii.OrderAuth.ServeYear, 0, 0)
            data["expireTime"] = expireT.Format("2006-01-02 15:04:05")
            if time.Now().Sub(expireT) > 0 {
               data["expire"] = true
            } else {
               data["expire"] = false
            }
         } else {
            data["sn"] = ""
            expireT := insT.AddDate(0, 0, eii.Setting.TrialDays)
            data["expireTime"] = expireT.Format("2006-01-02 15:04:05")
            if time.Now().Sub(expireT) > 0 {
               data["expire"] = true
            } else {
               data["expire"] = false
            }
         }
         data["edition"] = eii.Edition
         data["installTime"] = eii.InstallTime
      } else {
         logger.Error("Install info missing")
         data["sn"] = ""
         data["authorization"] = ""
         data["expire"] = true
         data["edition"] = "trial"
         data["installTime"] = ""
      }
   }
   data["q"] = service.GetQ()
   return data
}
func GetSnHandle(c *gin.Context) {
   data := sn()
   /*   set := logc.RuleServerPushLog{}
      set.TaskName = "Test"
      set.Type = 0
      set.Info = "111222111"
      uuid, _ := uuid.GenerateUUID()
      set.ID = uuid
      data2, _ := json.Marshal(set)
      var nodes []bhome_msg.BHAddress
      nodes = append(nodes, bhome_msg.BHAddress{})
      go Ms.PublishNetTimeout(nodes, "ruleServerLogSaveTopic", data2, 10)*/
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "ok",
      "data": data,
   })
}
func QrcodeHandle(c *gin.Context) {
   png, url, err := service.GenQRCode()
   if nil == err {
      c.Header("content-disposition", `attachment; filename=qrcode.png`)
      c.Header("qrcode-url", url)
      c.Data(200, "image/png", png)
      return
   }
   logger.Error("QrcodeHandle err!!!")
   c.JSON(http.StatusInternalServerError, gin.H{
      "code": http.StatusBadRequest,
      "msg":  "生成二维码失败",
      "data": "",
   })
}
func AuthorizationUploadHandle(c *gin.Context) {
   codeF, err := c.FormFile("code") //就是商城中生成的产品密钥订单下载的文件
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   F, err := codeF.Open()
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   buffer := make([]byte, codeF.Size)
   _, err = F.Read(buffer)
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   code := string(buffer)
   if "" == code {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "产品密钥不能为空",
         "data": []interface{}{},
      })
      return
   }
   _, err = service.Authorization(code, true)
   if nil == err || strings.Contains(err.Error(), "成功") {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": string(code),
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "激活失败," + err.Error(),
         "data": []interface{}{},
      })
   }
}
func AuthorizationHandle(c *gin.Context) {
   code := c.PostForm("code") //产品密钥的内容,就是商城中生成的产品密钥订单下载的文件内容
   if "" == code {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "产品密钥不能为空",
         "data": []interface{}{},
      })
      return
   }
   _, err := service.Authorization(code, true)
   if nil == err || strings.Contains(err.Error(), "成功") {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": []interface{}{},
      })
   } else {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "激活失败," + err.Error(),
         "data": []interface{}{},
      })
   }
}
func CancelAuthorizationHandle(c *gin.Context) {
   q := c.PostForm("q")
   supperPasswd := c.PostForm("passwd")
   down := c.PostForm("down")
   err, authCode := service.CancelAuthorization(supperPasswd, q)
   if err != nil && !strings.Contains(err.Error(), "成功") {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []interface{}{},
      })
   } else {
      if "1" == down {
         c.Header("content-disposition", `attachment; filename=authorization.txt`)
         ///c.Header("qrcode-url", url)
         c.Data(200, "text/plain", []byte(authCode))
      } else {
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "ok",
            "data": authCode,
         })
      }
   }
}
func CancelAuthorizationUploadHandle(c *gin.Context) {
   q, err := c.FormFile("q")
   supperPasswd := c.PostForm("passwd")
   down := c.PostForm("down")
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   F, err := q.Open()
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   buffer := make([]byte, q.Size)
   _, err = F.Read(buffer)
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   err, authinfo := service.CancelAuthorization(supperPasswd, string(buffer))
   if nil == err {
      if "1" == down {
         c.Header("content-disposition", `attachment; filename=authorization.txt`)
         ///c.Header("qrcode-url", url)
         c.Data(200, "text/plain", []byte(authinfo))
      } else {
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "ok",
            "data": authinfo,
         })
      }
   } else {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []interface{}{},
      })
   }
}
func ShowAutoBakConf(c *gin.Context) {
   var ab models.AutoBackupConf
   i, e := ab.Select()
   if e == nil && i > 0 {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "查询成功",
         "data": ab,
      })
      return
   }
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "查询成功",
      "data": models.AutoBackupConf{
         Dir: util.GetVamicroPath() + "/backup_auto",
      },
   })
}
func SaveAutoBakConf(c *gin.Context) {
   var reqBody models.AutoBackupConf
   err := c.BindJSON(&reqBody)
   if err != nil {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []models.AutoBackupConf{},
      })
      return
   }
   fmt.Println("go here 1 ", reqBody)
   reqBody.Dir = util.GetVamicroPath() + "/backup_auto"
   var ab models.AutoBackupConf
   i, _ := ab.Select()
   if i > 0 {
      fmt.Println("go here 2 ", reqBody)
      if reqBody.Update() {
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "更新成功",
            "data": reqBody,
         })
      } else {
         c.JSON(http.StatusInternalServerError, gin.H{
            "code": http.StatusInternalServerError,
            "msg":  "更新失败",
            "data": nil,
         })
      }
   } else {
      fmt.Println("go here 3 ")
      if reqBody.Insert() {
         fmt.Println("go here 4 ")
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "保存成功",
            "data": reqBody,
         })
      } else {
         c.JSON(http.StatusInternalServerError, gin.H{
            "code": http.StatusInternalServerError,
            "msg":  "保存失败",
            "data": nil,
         })
      }
   }
}
//立即备份操作
func BackupRN(c *gin.Context) {
   var ab models.AutoBackupConf
   i, e := ab.Select()
   if i == 0 || e != nil {
      ab.Dir = util.GetVamicroPath() + "/backup_auto"
   }
   err := service.DoAutoBackup(&ab)
   if err != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "立即备份失败:" + err.Error(),
         "data": nil,
      })
      return
   }
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "立即备份成功",
      "data": nil,
   })
}
//显示备份列表
func BackupList(c *gin.Context) {
   var ab models.AutoBackupConf
   i, e := ab.Select()
   if i == 0 || e != nil {
      ab.Dir = util.GetVamicroPath() + "/backup_auto/"
   } else {
      if !strings.HasSuffix(ab.Dir, "/") {
         ab.Dir = ab.Dir + "/"
      }
   }
   backList := make([]string, 0)
   err := filepath.Walk(ab.Dir, func(src string, f os.FileInfo, err error) error {
      if src == ab.Dir {
         return nil
      }
      if f.IsDir() {
         depth := strings.Count(src, "/") - strings.Count(ab.Dir, "/")
         if depth != 0 {
            return filepath.SkipDir
         }
         _, e := time.ParseInLocation("2006-01-02-15-04-05", f.Name(), time.Local)
         if e != nil {
            return e
         }
         backList = append(backList, f.Name())
      }
      return nil
   })
   if err != nil {
      logger.Error("filepath.Walk ab.dir err:", err)
   }
   sort.Sort(sort.Reverse(sort.StringSlice(backList))) //降序排序
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "查询成功",
      "data": backList,
   })
}
//根据指定的还原节点进行还原操作
func BackupRecover(c *gin.Context) {
   bakDir := c.PostForm("bakDir")
   if bakDir == "" {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "参数有误,bakDir不能为空",
         "data": nil,
      })
      return
   }
   var ab models.AutoBackupConf
   i, e := ab.Select()
   if i == 0 || e != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "备份设置为空",
         "data": nil,
      })
      return
   }
   fd := ab.Dir + "/" + bakDir
   if !util.DirExists(fd) {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "当前备份文件夹已不存在,请检查",
         "data": nil,
      })
      return
   }
   //执行还原操作
   err := service.DoBackupRecover(fd)
   if err != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "还原失败:" + err.Error(),
         "data": nil,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "还原成功",
         "data": nil,
      })
   }
}
package controller
import (
   "encoding/json"
   "fmt"
   "io/ioutil"
   "net/http"
   "os"
   "os/exec"
   "path"
   "path/filepath"
   "sort"
   "strconv"
   "strings"
   "time"
   "vamicro/extend/code"
   "vamicro/extend/util"
   "vamicro/version-control/models"
   "vamicro/version-control/routers"
   "vamicro/version-control/service"
   "basic.com/valib/bhomeclient.git"
   "basic.com/valib/c_bhomebus.git/proto/source/bhome_msg"
   "basic.com/valib/licence.git"
   "basic.com/valib/logger.git"
   "github.com/gin-gonic/gin"
)
type (
   VersionRouter struct {
      routers.Router
   }
)
const (
   basePath = "/version"
   manifest = "dist/bin/manifest.ini"
   zipDir   = "dist/bin"
)
var (
   CheckVersion              *VersionRouter
   Upgrade                   *VersionRouter
   UploadDist                *VersionRouter
   SettingFetch              *VersionRouter
   SettingPush               *VersionRouter
   UpdateNotice              *VersionRouter
   DelayNotice               *VersionRouter
   PreUpLoad                 *VersionRouter
   UpgradePreUpLoad          *VersionRouter
   RollBack                  *VersionRouter
   Authorization             *VersionRouter
   GetSn                     *VersionRouter
   Qrcode                    *VersionRouter
   AuthorizationUpload       *VersionRouter
   CancelAuthorization       *VersionRouter
   CancelAuthorizationUpload *VersionRouter
   ShopMakeSmsCod         *VersionRouter
   ShopCenterLogin        *VersionRouter
   ShopCenterGetOrderList *VersionRouter
   AuthActiveByOrder      *VersionRouter
   AutoBakShow     *VersionRouter
   AutoBakConfSet  *VersionRouter
   AutoBakRightNow *VersionRouter
   BackupListShow  *VersionRouter
   BackupRecov     *VersionRouter
   Ms *bhomeclient.MicroNode
)
func init() {
   CheckVersion = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "check",
         Handles: []gin.HandlerFunc{versionCheckHandle},
      },
   }
   UploadDist = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "upload",
         Handles: []gin.HandlerFunc{uploadDistHandle},
      },
   }
   Upgrade = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "upgrade",
         Handles: []gin.HandlerFunc{upgradeHandle},
      },
   }
   SettingFetch = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "settings",
         Handles: []gin.HandlerFunc{settingFetchHandle},
      },
   }
   SettingPush = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "setting/update",
         Handles: []gin.HandlerFunc{settingPushHandle},
      },
   }
   UpdateNotice = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "notice",
         Handles: []gin.HandlerFunc{updateNoticeHandle},
      },
   }
   DelayNotice = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "notice/delay",
         Handles: []gin.HandlerFunc{delayNoticeHandle},
      },
   }
   PreUpLoad = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "upload/zip",
         Handles: []gin.HandlerFunc{preUploadDistHandle},
      },
   }
   UpgradePreUpLoad = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "upgrade/zip",
         Handles: []gin.HandlerFunc{upgradePreUploadHandle},
      },
   }
   RollBack = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "rollback",
         Handles: []gin.HandlerFunc{RollBackHandle},
      },
   }
   Authorization = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "authorization",
         Handles: []gin.HandlerFunc{AuthorizationHandle},
      },
   }
   AuthorizationUpload = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "authorization/upload",
         Handles: []gin.HandlerFunc{AuthorizationUploadHandle},
      },
   }
   GetSn = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "sn",
         Handles: []gin.HandlerFunc{GetSnHandle},
      },
   }
   Qrcode = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "offline/qrcode",
         Handles: []gin.HandlerFunc{QrcodeHandle},
      },
   }
   CancelAuthorization = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "cancelAuthorization",
         Handles: []gin.HandlerFunc{CancelAuthorizationHandle},
      },
   }
   CancelAuthorizationUpload = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet, http.MethodPost},
         Path:    "cancelAuthorization/upload",
         Handles: []gin.HandlerFunc{CancelAuthorizationUploadHandle},
      },
   }
   ShopMakeSmsCod = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "auth/shop/smsCode",
         Handles: []gin.HandlerFunc{shopMakSmsHandle},
      },
   }
   ShopCenterLogin = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "auth/shop/login",
         Handles: []gin.HandlerFunc{shopCenterLoginHandle},
      },
   }
   ShopCenterGetOrderList = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "auth/shop/getOrderList",
         Handles: []gin.HandlerFunc{shopCenterGetOrderListHandle},
      },
   }
   AuthActiveByOrder = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "auth/shop/activeByOrder",
         Handles: []gin.HandlerFunc{authActiveByOrderHandle},
      },
   }
   AutoBakShow = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "autoBak/config",
         Handles: []gin.HandlerFunc{ShowAutoBakConf},
      },
   }
   AutoBakConfSet = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "autoBak/saveConf",
         Handles: []gin.HandlerFunc{SaveAutoBakConf},
      },
   }
   AutoBakRightNow = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "autoBak/backupRN",
         Handles: []gin.HandlerFunc{BackupRN},
      },
   }
   BackupListShow = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodGet},
         Path:    "autoBak/list",
         Handles: []gin.HandlerFunc{BackupList},
      },
   }
   BackupRecov = &VersionRouter{
      routers.Router{
         Methods: []string{http.MethodPost},
         Path:    "autoBak/recover",
         Handles: []gin.HandlerFunc{BackupRecover},
      },
   }
}
func (r *VersionRouter) GetPath() string {
   return path.Join(basePath, r.Path)
}
//在系统配置app中,给页面调用,判断提醒有没有程序是否需要升级
func versionCheckHandle(c *gin.Context) {
   _, version, intro := service.CheckVersion()
   curVersion := service.GetCurVersion()
   //curEnv, _ := service.GetRunVersionEnv()
   //hasNewVersion := len(programs) > 0
   hasNewVersion := version != curVersion
   if version == "" {
      hasNewVersion = false
      version = curVersion
   }
   c.JSON(http.StatusOK, gin.H{
      "code": 200,
      "msg":  "ok",
      "data": map[string]interface{}{
         "hasNewVersion":  hasNewVersion,
         "newVersion":     version,
         "newVersionInfo": intro,
         "curVersion":     curVersion,
         "curVersionPath": curVersion,
      },
   })
}
func preUploadDistHandle(c *gin.Context) {
   file, err := c.FormFile("archive")
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   UpgradePath := service.GetPreUploadPath()
   err = os.RemoveAll(UpgradePath)
   if nil == err {
      _ = os.MkdirAll(UpgradePath, 0777)
   } else {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle remove pre upload path failed, err:", err.Error())
      return
   }
   fileMd5 := service.GetMd5(file.Filename) + ".tgz"
   if err = c.SaveUploadedFile(file, path.Join(UpgradePath, fileMd5)); err != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle save file failed, err:", err.Error())
      return
   }
   logger.Info("uploadDistHandle saved to temp file ok:", fileMd5)
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "ok",
      "data": map[string]string{"id": fileMd5},
   })
}
func upgradePreUploadHandle(c *gin.Context) {
   upid := c.Query("id")
   if upid == "" {
      util.ResponseFormat(c, code.RequestParamError, "id不能为空")
      return
   }
   UpgradePath := service.GetPreUploadPath()
   upZip := path.Join(UpgradePath, upid)
   if !util.FileExists(upZip) {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "升级包未找到!",
         "data": []*models.Program{},
      })
      logger.Error("upgradePreUploadHandle upload file not found:", upZip)
      return
   }
   logger.Info("开始升级!")
   apps, err := service.UpgradeViaZip(upZip)
   logger.Info("系统升级完成!!")
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": apps,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": apps,
      })
      killApp(apps)
   }
}
//在离线的情况,使用tgz包直接在内网上传离线安装包
func uploadDistHandle(c *gin.Context) {
   file, err := c.FormFile("archive")
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   UpgradePath := service.GetPreUploadPath()
   tmpFile, err := ioutil.TempFile(UpgradePath, "dist-*.tgz")
   if nil != err {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle create temp file failed, err:", err.Error())
      return
   }
   defer func() {
      tmpFile.Close()
      os.Remove(tmpFile.Name())
   }()
   if err = c.SaveUploadedFile(file, tmpFile.Name()); err != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("uploadDistHandle save file failed, err:", err.Error())
      return
   }
   logger.Info("uploadDistHandle saved to temp file ok:", tmpFile.Name())
   apps, err := service.UpgradeViaZip(tmpFile.Name())
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": apps,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": apps,
      })
   }
}
func upgradeHandle(c *gin.Context) {
   apps, err := service.OnlineUpgrade()
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": apps,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": apps,
      })
      //_ = syscall.Kill(syscall.Getpid(), syscall.SIGINT)
      killApp(apps)
   }
}
func killApp(apps []*models.Program) {
   //循环杀死升级应用进程
   versionControl := ""
   for _, app := range apps {
      if app.Name == "version-control" {
         versionControl = app.Name
         continue
      }
      if app.Type == "sys" || app.Type == "app" {
         command := "pkill " + app.Name
         result, err := execCommand(command)
         logger.Info("执行命令【", command, "】")
         logger.Info("执行结果【", result, "err:,", err, "】")
      }
   }
   if versionControl != "" {
      command := "pkill " + versionControl
      result, err := execCommand(command)
      logger.Info("执行命令【", command, "】")
      logger.Info("执行结果【", result, "\n err:,", err, "】")
   }
}
//执行命令
func execCommand(cmd string) ([]byte, error) {
   return exec.Command("/bin/bash", "-c", cmd).Output()
}
//获取配置
func settingFetchHandle(c *gin.Context) {
   var model models.SysSetting
   settings, err := model.GetAllSetting()
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": settings,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": settings,
      })
   }
}
//更新配置
func settingPushHandle(c *gin.Context) {
   name := c.PostForm("name")
   value := c.PostForm("value")
   setting := models.SysSetting{Name: name, Value: value}
   err := setting.SaveSetting(true)
   if nil != err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  err.Error(),
         "data": []interface{}{},
      })
   } else {
      data, _ := json.Marshal(setting)
      var nodes []bhome_msg.BHAddress
      nodes = append(nodes, bhome_msg.BHAddress{})
      go Ms.PublishNetTimeout(nodes, service.SysUpdateConfigTopic, data, 10)
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": []interface{}{},
      })
   }
}
func updateNoticeHandle(c *gin.Context) {
   notice := service.GetUpdateNotice()
   uid, ok := c.Get("uid")
   if ok {
      LastNoticeTime, ok := notice.NoticeUser[uid.(string)]
      if ok {
         notice.LastNoticeTime = int64(LastNoticeTime)
      }
   }
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "ok",
      "data": notice,
   })
}
func delayNoticeHandle(c *gin.Context) {
   delaySecond := c.PostForm("delaySecond")
   second, err := strconv.Atoi(delaySecond)
   if nil == err {
      uid, ok := c.Get("uid")
      if ok {
         notice := service.DelayNotice(uid.(string), second)
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "ok",
            "data": notice,
         })
      } else {
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "未找到用户",
            "data": []interface{}{},
         })
      }
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "参数错误",
         "data": []interface{}{},
      })
   }
}
func RollBackHandle(c *gin.Context) {
   version := c.PostForm("version")
   err := service.Rollback(version)
   if nil == err {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": []interface{}{},
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "回滚失败," + err.Error(),
         "data": []interface{}{},
      })
   }
}
func sn() map[string]interface{} {
   data := make(map[string]interface{}, 0)
   sn := util.GetSn()
   data["sn"] = sn
   auth := util.GetAuthorization()
   data["expireTime"] = ""
   authInfo, err := util.GetAuthorizationInfo(auth)
   //logger.Debug("授权信息:", authInfo, err, licence.GetMachineCode())
   if err == nil && authInfo.MachineCode == licence.GetMachineCode() {
      expireUt := time.Unix(authInfo.ExpirationTime, 0)
      expireTimeStr := expireUt.Format("2006-01-02 15:04:05")
      data["expireTime"] = expireTimeStr
      data["expire"] = false
      if authInfo.ActivateCode != "" {
         data["sn"] = authInfo.ActivateCode
      }
      if authInfo.DevCount == -1 { //试用版
         data["sn"] = ""
      }
      if time.Now().Sub(expireUt) > 0 {
         data["expire"] = true
         data["sn"] = ""
      }
      if data["sn"] != "" {
         data["authorization"] = auth
      }
      data["edition"] = authInfo.Edition
      data["installTime"] = authInfo.InstallTime
      if authInfo.Edition == "" || authInfo.InstallTime == "" {
         if eii, err := util.GetEdtionSetFromIns(); err == nil {
            if authInfo.Edition == "" {
               data["edition"] = eii.Edition
            }
            if authInfo.InstallTime == "" {
               data["installTime"] = eii.InstallTime
            }
         }
      }
   } else {
      //测试版
      eii, err := util.GetEdtionSetFromIns()
      if err == nil {
         insT, _ := time.ParseInLocation("2006-01-02 15:04:05", eii.InstallTime, time.Local)
         if eii.OrderAuth != nil && eii.OrderAuth.ProductId != "" && eii.OrderAuth.OrderId != "" {
            data["sn"] = ""
            expireT := insT.AddDate(eii.OrderAuth.ServeYear, 0, 0)
            data["expireTime"] = expireT.Format("2006-01-02 15:04:05")
            if time.Now().Sub(expireT) > 0 {
               data["expire"] = true
            } else {
               data["expire"] = false
            }
         } else {
            data["sn"] = ""
            expireT := insT.AddDate(0, 0, eii.Setting.TrialDays)
            data["expireTime"] = expireT.Format("2006-01-02 15:04:05")
            if time.Now().Sub(expireT) > 0 {
               data["expire"] = true
            } else {
               data["expire"] = false
            }
         }
         data["edition"] = eii.Edition
         data["installTime"] = eii.InstallTime
      } else {
         logger.Error("Install info missing")
         data["sn"] = ""
         data["authorization"] = ""
         data["expire"] = true
         data["edition"] = "trial"
         data["installTime"] = ""
      }
   }
   data["q"] = service.GetQ()
   return data
}
func GetSnHandle(c *gin.Context) {
   data := sn()
   /*   set := logc.RuleServerPushLog{}
      set.TaskName = "Test"
      set.Type = 0
      set.Info = "111222111"
      uuid, _ := uuid.GenerateUUID()
      set.ID = uuid
      data2, _ := json.Marshal(set)
      var nodes []bhome_msg.BHAddress
      nodes = append(nodes, bhome_msg.BHAddress{})
      go Ms.PublishNetTimeout(nodes, "ruleServerLogSaveTopic", data2, 10)*/
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "ok",
      "data": data,
   })
}
func QrcodeHandle(c *gin.Context) {
   png, url, err := service.GenQRCode()
   if nil == err {
      c.Header("content-disposition", `attachment; filename=qrcode.png`)
      c.Header("qrcode-url", url)
      c.Data(200, "image/png", png)
      return
   }
   logger.Error("QrcodeHandle err!!!")
   c.JSON(http.StatusInternalServerError, gin.H{
      "code": http.StatusBadRequest,
      "msg":  "生成二维码失败",
      "data": "",
   })
}
func AuthorizationUploadHandle(c *gin.Context) {
   codeF, err := c.FormFile("code") //就是商城中生成的产品密钥订单下载的文件
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   F, err := codeF.Open()
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   buffer := make([]byte, codeF.Size)
   _, err = F.Read(buffer)
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   code := string(buffer)
   if "" == code {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "产品密钥不能为空",
         "data": []interface{}{},
      })
      return
   }
   _, err = service.Authorization(code, true)
   if nil == err || strings.Contains(err.Error(), "成功") {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": string(code),
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "激活失败," + err.Error(),
         "data": []interface{}{},
      })
   }
}
func AuthorizationHandle(c *gin.Context) {
   code := c.PostForm("code") //产品密钥的内容,就是商城中生成的产品密钥订单下载的文件内容
   if "" == code {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "产品密钥不能为空",
         "data": []interface{}{},
      })
      return
   }
   _, err := service.Authorization(code, true)
   if nil == err || strings.Contains(err.Error(), "成功") {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "ok",
         "data": []interface{}{},
      })
   } else {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "激活失败," + err.Error(),
         "data": []interface{}{},
      })
   }
}
func CancelAuthorizationHandle(c *gin.Context) {
   q := c.PostForm("q")
   supperPasswd := c.PostForm("passwd")
   down := c.PostForm("down")
   err, authCode := service.CancelAuthorization(supperPasswd, q)
   if err != nil && !strings.Contains(err.Error(), "成功") {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []interface{}{},
      })
   } else {
      if "1" == down {
         c.Header("content-disposition", `attachment; filename=authorization.txt`)
         ///c.Header("qrcode-url", url)
         c.Data(200, "text/plain", []byte(authCode))
      } else {
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "ok",
            "data": authCode,
         })
      }
   }
}
func CancelAuthorizationUploadHandle(c *gin.Context) {
   q, err := c.FormFile("q")
   supperPasswd := c.PostForm("passwd")
   down := c.PostForm("down")
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   F, err := q.Open()
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   buffer := make([]byte, q.Size)
   _, err = F.Read(buffer)
   if nil != err {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []*models.Program{},
      })
      logger.Error("AuthorizationUploadHandle upload field is not filled with a file, err:", err.Error())
      return
   }
   err, authinfo := service.CancelAuthorization(supperPasswd, string(buffer))
   if nil == err {
      if "1" == down {
         c.Header("content-disposition", `attachment; filename=authorization.txt`)
         ///c.Header("qrcode-url", url)
         c.Data(200, "text/plain", []byte(authinfo))
      } else {
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "ok",
            "data": authinfo,
         })
      }
   } else {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []interface{}{},
      })
   }
}
func ShowAutoBakConf(c *gin.Context) {
   var ab models.AutoBackupConf
   i, e := ab.Select()
   if e == nil && i > 0 {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "查询成功",
         "data": ab,
      })
      return
   }
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "查询成功",
      "data": models.AutoBackupConf{
         Dir: util.GetVamicroPath() + "/backup_auto",
      },
   })
}
func SaveAutoBakConf(c *gin.Context) {
   var reqBody models.AutoBackupConf
   err := c.BindJSON(&reqBody)
   if err != nil {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  err.Error(),
         "data": []models.AutoBackupConf{},
      })
      return
   }
   fmt.Println("go here 1 ", reqBody)
   reqBody.Dir = util.GetVamicroPath() + "/backup_auto"
   var ab models.AutoBackupConf
   i, _ := ab.Select()
   if i > 0 {
      fmt.Println("go here 2 ", reqBody)
      if reqBody.Update() {
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "更新成功",
            "data": reqBody,
         })
      } else {
         c.JSON(http.StatusInternalServerError, gin.H{
            "code": http.StatusInternalServerError,
            "msg":  "更新失败",
            "data": nil,
         })
      }
   } else {
      fmt.Println("go here 3 ")
      if reqBody.Insert() {
         fmt.Println("go here 4 ")
         c.JSON(http.StatusOK, gin.H{
            "code": http.StatusOK,
            "msg":  "保存成功",
            "data": reqBody,
         })
      } else {
         c.JSON(http.StatusInternalServerError, gin.H{
            "code": http.StatusInternalServerError,
            "msg":  "保存失败",
            "data": nil,
         })
      }
   }
}
//立即备份操作
func BackupRN(c *gin.Context) {
   var ab models.AutoBackupConf
   i, e := ab.Select()
   if i == 0 || e != nil {
      ab.Dir = util.GetVamicroPath() + "/backup_auto"
   }
   err := service.DoAutoBackup(&ab)
   if err != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "立即备份失败:" + err.Error(),
         "data": nil,
      })
      return
   }
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "立即备份成功",
      "data": nil,
   })
}
//显示备份列表
func BackupList(c *gin.Context) {
   var ab models.AutoBackupConf
   i, e := ab.Select()
   if i == 0 || e != nil {
      ab.Dir = util.GetVamicroPath() + "/backup_auto/"
   } else {
      if !strings.HasSuffix(ab.Dir, "/") {
         ab.Dir = ab.Dir + "/"
      }
   }
   backList := make([]string, 0)
   err := filepath.Walk(ab.Dir, func(src string, f os.FileInfo, err error) error {
      if src == ab.Dir {
         return nil
      }
      if f.IsDir() {
         depth := strings.Count(src, "/") - strings.Count(ab.Dir, "/")
         if depth != 0 {
            return filepath.SkipDir
         }
         _, e := time.ParseInLocation("2006-01-02-15-04-05", f.Name(), time.Local)
         if e != nil {
            return e
         }
         backList = append(backList, f.Name())
      }
      return nil
   })
   if err != nil {
      logger.Error("filepath.Walk ab.dir err:", err)
   }
   sort.Sort(sort.Reverse(sort.StringSlice(backList))) //降序排序
   c.JSON(http.StatusOK, gin.H{
      "code": http.StatusOK,
      "msg":  "查询成功",
      "data": backList,
   })
}
//根据指定的还原节点进行还原操作
func BackupRecover(c *gin.Context) {
   bakDir := c.PostForm("bakDir")
   if bakDir == "" {
      c.JSON(http.StatusBadRequest, gin.H{
         "code": http.StatusBadRequest,
         "msg":  "参数有误,bakDir不能为空",
         "data": nil,
      })
      return
   }
   var ab models.AutoBackupConf
   i, e := ab.Select()
   if i == 0 || e != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "备份设置为空",
         "data": nil,
      })
      return
   }
   fd := ab.Dir + "/" + bakDir
   if !util.DirExists(fd) {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "当前备份文件夹已不存在,请检查",
         "data": nil,
      })
      return
   }
   //执行还原操作
   err := service.DoBackupRecover(fd)
   if err != nil {
      c.JSON(http.StatusInternalServerError, gin.H{
         "code": http.StatusInternalServerError,
         "msg":  "还原失败:" + err.Error(),
         "data": nil,
      })
   } else {
      c.JSON(http.StatusOK, gin.H{
         "code": http.StatusOK,
         "msg":  "还原成功",
         "data": nil,
      })
   }
}