package service
|
|
import (
|
"basic.com/valib/bhomeclient.git"
|
"basic.com/valib/bhomedbapi.git"
|
"basic.com/valib/c_bhomebus.git/proto/source/bhome_msg"
|
"basic.com/valib/licence.git"
|
"basic.com/valib/logger.git"
|
"basic.com/valib/version.git"
|
"context"
|
"crypto/md5"
|
"encoding/base64"
|
"encoding/json"
|
"errors"
|
"fmt"
|
"github.com/skip2/go-qrcode"
|
"io"
|
"io/ioutil"
|
"net/http"
|
"net/url"
|
"os"
|
"path"
|
"runtime"
|
"strings"
|
"sync"
|
"time"
|
"vamicro/config"
|
"vamicro/extend/util"
|
"vamicro/version-control/models"
|
"vamicro/version-control/response"
|
"vamicro/version-control/utils"
|
)
|
|
const (
|
uriVersion string = "/data/api-u/upgrade/findUpgradeVersion"
|
uriDownload string = "/data/api-p/download"
|
uriAuth string = "/data/api-s/authorization"
|
uriMobile string = "/data/api-s/fromQrcode"
|
)
|
|
type (
|
Payload struct {
|
Arch string `json:"arch"`
|
Programs []*models.Program `json:"programs"`
|
Version string `json:"version"`
|
Intro string `json:"intro"`
|
PatchUrl string `json:"patchUrl"`
|
}
|
|
UpdateInfo struct {
|
response.ResponseHead
|
Data []Payload `json:"data"`
|
}
|
|
VersionInfo struct {
|
Build string `json:"build"`
|
Commit string `json:"commit"`
|
Name string `json:"name"`
|
Version string `json:"version"`
|
}
|
|
UpdateNotice struct {
|
NoticeUser map[string]int
|
HaveNewVersion int64 //是否有新版本,1有,0没有
|
PkgDownloaded int64 //是否下载完成,1有,0没有
|
LastNoticeTime int64
|
NewVersionProgram []*models.Program
|
NoticeStatus bool
|
}
|
)
|
|
var (
|
updateNotice UpdateNotice
|
updateNoticeLock sync.Mutex
|
LastDownFile []string
|
LastDownLock sync.RWMutex
|
)
|
|
func Init() {
|
backUpPath := GetBackupPath()
|
if _, err := os.Stat(backUpPath); os.IsNotExist(err) {
|
_ = os.MkdirAll(backUpPath, 0777)
|
}
|
preDownPath := GetPreDownPath()
|
if _, err := os.Stat(preDownPath); os.IsNotExist(err) {
|
_ = os.MkdirAll(preDownPath, 0777)
|
}
|
updateNotice.NoticeUser = make(map[string]int)
|
LastDownFile = make([]string, 0)
|
}
|
|
func OnlineUpgrade() ([]*models.Program, error) {
|
|
programMap := make(map[string]*models.Program)
|
|
LastDownLock.Lock()
|
defer LastDownLock.Unlock()
|
//查找预下载升级包
|
preDowns := GetLastDownFile()
|
logger.Info("系统开始升级!")
|
for _, preDown := range preDowns {
|
logger.Info(preDowns)
|
ps, err := UpgradeViaZip(preDown)
|
if err != nil {
|
return []*models.Program{}, err
|
}
|
for _, p := range ps {
|
programMap[p.Name] = p
|
}
|
}
|
logger.Info("系统升级完成!!")
|
|
if len(programMap) > 0 { //使用预下载升级完成
|
programs := make([]*models.Program, 0, len(programMap))
|
for _, v := range programMap {
|
programs = append(programs, v)
|
}
|
return programs, nil
|
}
|
|
info, err := getUpdateInfo()
|
if nil != err {
|
return []*models.Program{}, errors.New("系统没有更新可用")
|
}
|
|
logger.Info("系统升级开始!")
|
//循环下载,解压,覆盖升级包
|
for _, payload := range info.Data {
|
ps, err := HandlerPatchPkg(payload)
|
if err != nil {
|
return []*models.Program{}, err
|
}
|
for _, p := range ps {
|
programMap[p.Name] = p
|
}
|
}
|
logger.Info("系统升级完成!!")
|
|
if len(programMap) > 0 { //
|
programs := make([]*models.Program, 0, len(programMap))
|
for _, v := range programMap {
|
programs = append(programs, v)
|
}
|
return programs, nil
|
}
|
|
return []*models.Program{}, err
|
}
|
|
//循环下载,解压,覆盖升级包
|
func HandlerPatchPkg(payload Payload) ([]*models.Program, error) {
|
if payload.PatchUrl == "" {
|
return []*models.Program{}, errors.New("No dist file get")
|
}
|
|
//u, err := url.Parse("http://" + util.GetShopUrl() + uriDownload)
|
u, err := url.Parse(payload.PatchUrl)
|
if err != nil {
|
logger.Error("parse url failed, url:", payload.PatchUrl, ", err:", err.Error())
|
return []*models.Program{}, err
|
}
|
upgradePath := GetPreDownPath()
|
upfile := upgradePath + "/" + GetMd5(payload.Version) + ".tgz"
|
//tmpFile, err := ioutil.TempFile("", "dist-*.zip")
|
tmpFile, err := os.OpenFile(upfile, os.O_CREATE|os.O_WRONLY, 0666)
|
if nil != err {
|
logger.Error("OnlineUpgrade create temp file failed, err:", err.Error())
|
return []*models.Program{}, err
|
}
|
fmt.Println("OnlineUpgrade tmpFile.Name: ", tmpFile.Name())
|
defer func() {
|
tmpFile.Close()
|
backupPath := GetBackupPath()
|
//文件从upgrade目录移动到backup目录
|
os.Rename(tmpFile.Name(), backupPath+"/"+tmpFile.Name())
|
//os.Remove(tmpFile.Name())
|
}()
|
|
//query := u.Query()
|
//query.Set("filename", info.Data.Archive)
|
//u.RawQuery = query.Encode()
|
resp, err := http.Get(u.String())
|
if err != nil {
|
logger.Error("OnlineUpgrade parse url failed, url:", u.String(), ", err:", err.Error())
|
return []*models.Program{}, err
|
}
|
defer resp.Body.Close()
|
if resp.StatusCode != 200 {
|
logger.Error("OnlineUpgrade incorrect status, url:", u.String(), ", status:", resp.StatusCode)
|
return []*models.Program{}, errors.New("Status code not 200")
|
}
|
|
_, err = io.Copy(tmpFile, resp.Body)
|
if err != nil {
|
logger.Error("OnlineUpgrade save upgrade file failed, url:", u.String(), ", err:", err.Error())
|
return []*models.Program{}, err
|
}
|
|
return UpgradeViaZip(tmpFile.Name())
|
}
|
|
//循环下载升级包
|
func DownloadPatchPkg(payload Payload) (string, error) {
|
if payload.PatchUrl == "" {
|
return "", errors.New("no dist file get")
|
}
|
|
//u, err := url.Parse("http://" + util.GetShopUrl() + uriDownload)
|
u, err := url.Parse(payload.PatchUrl)
|
if err != nil {
|
logger.Error("parse url failed, url:", payload.PatchUrl, ", err:", err.Error())
|
return "", err
|
}
|
|
upgradePath := GetPreDownPath()
|
upfile := upgradePath + "/" + GetMd5(payload.Version) + ".tgz"
|
_, err = os.Stat(upfile)
|
if nil == err {
|
//已下载过
|
logger.Info("PreDownUpgrade predown upgrade file have down:", upfile)
|
return upfile, nil
|
}
|
|
tmpFile, err := os.OpenFile(upfile, os.O_CREATE|os.O_WRONLY, 0666)
|
if nil != err {
|
logger.Error("OnlineUpgrade create temp file failed, err:", err.Error())
|
return "", err
|
}
|
|
fmt.Println("OnlineUpgrade tmpFile.Name: ", tmpFile.Name())
|
defer func() {
|
tmpFile.Close()
|
}()
|
|
resp, err := http.Get(u.String())
|
if err != nil {
|
logger.Error("OnlineUpgrade parse url failed, url:", u.String(), ", err:", err.Error())
|
return "", err
|
}
|
defer resp.Body.Close()
|
|
if resp.StatusCode != 200 {
|
logger.Error("OnlineUpgrade incorrect status, url:", u.String(), ", status:", resp.StatusCode)
|
return "", errors.New("status code not 200")
|
}
|
|
_, err = io.Copy(tmpFile, resp.Body)
|
if err != nil {
|
logger.Error("PreDownUpgrade parse url failed, url:", u.String(), ", err:", err.Error())
|
tmpFile.Close()
|
|
os.Remove(upfile)
|
return "", err
|
}
|
|
return upfile, nil
|
}
|
|
//检查是否需要更新版本
|
func CheckVersion() (string, string, string) {
|
//获取服务端所有程序最新版本信息。
|
info, err := getUpdateInfo()
|
if nil != err {
|
return "", "", ""
|
}
|
|
if len(info.Data) <= 0 {
|
logger.Error("checkVersion no programs get")
|
return "", "", ""
|
}
|
|
//获取需要更新版本的程序列表
|
//programs := needUpgrade(info.Data.Programs)
|
last := len(info.Data) - 1
|
return info.Data[last].PatchUrl, info.Data[last].Version, info.Data[last].Intro
|
}
|
|
func GetCurVersion() string {
|
curEnv, err := GetRunVersionEnv()
|
if err != nil {
|
return ""
|
}
|
return curEnv
|
}
|
|
//获取服务端最新程序及其版本
|
func getUpdateInfo() (*UpdateInfo, error) {
|
//const PrtSize = 32 << uintptr(^uintptr(0)>>63)
|
//wordSize := strconv.Itoa(PrtSize)
|
|
u, err := url.Parse("http://" + util.GetShopUrl() + uriVersion)
|
if err != nil {
|
logger.Error("parse url failed, url:", "http://"+util.GetShopUrl()+uriVersion, ", err:", err.Error())
|
return nil, err
|
}
|
|
query := u.Query()
|
//query.Set("os", runtime.GOOS)
|
query.Set("arch", runtime.GOARCH)
|
query.Set("versionNum", GetCurVersion())
|
//query.Set("wordSize", wordSize)
|
|
u.RawQuery = query.Encode()
|
resp, err := http.Get(u.String())
|
if err != nil {
|
logger.Error("checkVersion parse url failed, url:", u.String(), ", err:", err.Error())
|
return nil, err
|
}
|
|
if resp.StatusCode != 200 {
|
logger.Error("checkVersion incorrect status, url:", u.String(), ", status:", resp.StatusCode)
|
return nil, errors.New("Status code not 200")
|
}
|
|
defer resp.Body.Close()
|
body, err := ioutil.ReadAll(resp.Body)
|
if err != nil {
|
logger.Error("checkVersion read body failed, url:", u.String(), ", err:", err.Error())
|
return nil, err
|
}
|
|
logger.Info("checkVersion dump body:", string(body))
|
var info UpdateInfo
|
err = json.Unmarshal(body, &info)
|
if err != nil {
|
logger.Error("checkVersion json.Unmarshal failed, url:", u.String(), ", err:", err.Error())
|
return nil, err
|
}
|
|
//b, err := json.Marshal(&info)
|
//if err != nil {
|
// logger.Error("checkVersion json.Marshal failed, url:", u.String(), ", err:", err.Error())
|
//} else {
|
// logger.Info("checkVersion get response, url:", u.String(), ", response:", string(b))
|
//}
|
|
return &info, nil
|
}
|
|
//需要升级的程序
|
func needUpgrade(programs []*models.Program) []*models.Program {
|
//获取当前运行版本目录
|
//dir := utils.GetExePath()
|
dir := util.GetVamicroPath()
|
|
newPrograms := []*models.Program{}
|
for _, p := range programs {
|
exe := path.Join(dir, p.Name)
|
if !utils.PathExists(exe) {
|
newPrograms = append(newPrograms, p)
|
continue
|
}
|
|
lVersion, err := dynamicGetVersion(dir, exe)
|
if err != nil {
|
logger.Error("exe:", exe, "get local version failed, err:", err.Error())
|
continue
|
}
|
|
//版本名称转换为版本号
|
rVersion, err := vaversion.VersionName2VaVersion(p.Version)
|
if err != nil {
|
logger.Error("exe:", exe, "get remote version failed:", p.Version, ", err:", err.Error())
|
continue
|
}
|
|
c, err := lVersion.Compare(rVersion)
|
if err != nil {
|
logger.Error("exe:", exe, "version compare failed, remote:", p.Version, ", err:", err.Error())
|
continue
|
}
|
|
if c > 0 {
|
logger.Error("exe:", exe, "local version greater, local:", lVersion, "remote:", p.Version)
|
continue
|
}
|
|
if c < 0 {
|
newPrograms = append(newPrograms, p)
|
}
|
}
|
|
return newPrograms
|
}
|
|
func NoticeTick(c context.Context) {
|
// tick := time.Tick(1 * time.Second)
|
tick := time.Tick(24 * time.Hour)
|
for {
|
select {
|
case <-c.Done():
|
logger.Info("proc close, self update exit")
|
return
|
case <-tick:
|
//logger.Info("NoticeTick !!!")
|
updateNoticeLock.Lock()
|
for key, _ := range updateNotice.NoticeUser {
|
if 0 < updateNotice.NoticeUser[key] {
|
updateNotice.NoticeUser[key]--
|
}
|
}
|
updateNoticeLock.Unlock()
|
}
|
}
|
}
|
|
//升级配置处理
|
func SelfUpdateStart(c context.Context, ms *bhomeclient.MicroNode) {
|
//三十秒检查一次配置并更新
|
// tick := time.Tick(30 * time.Second)
|
tick := time.Tick(24 * time.Hour)
|
|
var setting models.SysSetting
|
for {
|
select {
|
case <-c.Done():
|
logger.Info("proc close, self update exit")
|
return
|
case <-tick:
|
settings, err := setting.GetAllSetting()
|
if nil != err {
|
logger.Error("fetch setting failed")
|
continue
|
}
|
|
for _, set := range settings {
|
data, _ := json.Marshal(set)
|
var nodes []bhome_msg.BHAddress
|
nodes = append(nodes, bhome_msg.BHAddress{})
|
|
go ms.PublishNetTimeout(nodes, SysUpdateConfigTopic, data, 10)
|
|
switch set.Name {
|
case "sys_auto_clean":
|
if "1" == set.Value {
|
err := os.RemoveAll(GetBackupPath())
|
if nil != err {
|
logger.Error("clean update package failed:", err.Error())
|
}
|
_ = os.MkdirAll(GetBackupPath(), 0777)
|
}
|
case "sys_update_notice":
|
{
|
// 判断有新版本, 不再重复检测
|
if updateNotice.HaveNewVersion == 1 {
|
continue
|
}
|
|
// 设备更新提醒
|
updateNoticeLock.Lock()
|
|
//获取需要更新版本的程序列表
|
_, version, _ := CheckVersion()
|
curVersion := GetCurVersion()
|
IsLastUpdate := true
|
if version != curVersion {
|
// 设置更新提醒, 重新下载升级包
|
updateNotice.HaveNewVersion = 1
|
updateNotice.PkgDownloaded = 0
|
IsLastUpdate = true
|
} else {
|
IsLastUpdate = false
|
}
|
|
if !IsLastUpdate { //如果没有更新,设置用户延迟时间为0
|
for key, _ := range updateNotice.NoticeUser {
|
if 0 > updateNotice.NoticeUser[key] {
|
updateNotice.NoticeUser[key] = 0
|
}
|
}
|
}
|
|
if "1" == set.Value {
|
updateNotice.NoticeStatus = true
|
} else {
|
updateNotice.NoticeStatus = false
|
}
|
|
updateNoticeLock.Unlock()
|
}
|
case "sys_auto_update":
|
{
|
if "1" == set.Value && updateNotice.HaveNewVersion > 0 && updateNotice.PkgDownloaded == 0 {
|
err := PreDownUpdateFile()
|
if nil != err {
|
logger.Error("pre download update file failed:", err.Error())
|
} else {
|
updateNotice.PkgDownloaded = 1
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
//检查是否距上次比较有更新
|
func IsLastUpdate(programs []*models.Program, NewVersionProgram []*models.Program) bool {
|
for _, program := range programs {
|
for _, program2 := range NewVersionProgram {
|
if program.Name == program2.Name {
|
if program.Version != program2.Version {
|
return true
|
}
|
}
|
}
|
}
|
return true
|
}
|
|
//获取更新提醒
|
func GetUpdateNotice() UpdateNotice {
|
return updateNotice
|
}
|
|
//延迟提醒
|
func DelayNotice(uid string, second int) UpdateNotice {
|
updateNoticeLock.Lock()
|
updateNotice.NoticeUser[uid] = second
|
updateNoticeLock.Unlock()
|
return updateNotice
|
}
|
|
//获取代码备份位置
|
func GetBackupPath() string {
|
dir := util.GetVamicroPath() + "/backup"
|
_, err := os.Stat(dir)
|
if nil != err {
|
if os.IsNotExist(err) {
|
os.Mkdir(dir, 0744)
|
} else {
|
return "./backup"
|
}
|
}
|
|
return dir
|
}
|
|
//获取解压后的补丁包位置
|
func GetPatchPath() string {
|
dir := util.GetVamicroPath() + "/patch"
|
_, err := os.Stat(dir)
|
if nil != err {
|
if os.IsNotExist(err) {
|
os.Mkdir(dir, 0744)
|
} else {
|
return "./patch"
|
}
|
}
|
|
return dir
|
}
|
|
//获取预下载升级包目录
|
func GetPreDownPath() string {
|
dir := util.GetVamicroPath() + "/upgrade"
|
_, err := os.Stat(dir)
|
if nil != err {
|
if os.IsNotExist(err) {
|
os.Mkdir(dir, 0744)
|
} else {
|
return "./upgrade"
|
}
|
}
|
|
return dir
|
}
|
|
//获取上传升级包目录
|
func GetPreUploadPath() string {
|
dir := util.GetVamicroPath() + "/upgrade_manual"
|
_, err := os.Stat(dir)
|
if nil != err {
|
if os.IsNotExist(err) {
|
os.Mkdir(dir, 0744)
|
} else {
|
return "./upgrade_manual"
|
}
|
}
|
|
return dir
|
}
|
|
func GetMd5(in string) string {
|
data := md5.Sum([]byte(in))
|
return fmt.Sprintf("%x", data)
|
}
|
|
//预下载升级文件
|
func PreDownUpdateFile() error {
|
info, err := getUpdateInfo()
|
if nil != err {
|
return err
|
}
|
|
LastDownLock.Lock()
|
defer LastDownLock.Unlock()
|
|
LastDownFile = make([]string, 0)
|
|
//循环下载升级包
|
for _, payload := range info.Data {
|
logger.Info("正在下载版本补丁【" + payload.Version + "】")
|
upfile, err := DownloadPatchPkg(payload)
|
logger.Info("下载版本补丁完成【" + payload.Version + "】")
|
if err != nil {
|
return err
|
}
|
|
LastDownFile = append(LastDownFile, upfile)
|
}
|
|
return nil
|
}
|
|
//获取预下载升级包
|
func GetLastDownFile() []string {
|
var res = make([]string, 0)
|
if len(LastDownFile) > 0 {
|
for _, file := range LastDownFile {
|
_, err := os.Stat(file)
|
if nil == err {
|
res = append(res, file)
|
}
|
}
|
}
|
return res
|
}
|
|
//回滚版本
|
func Rollback(version string) error {
|
dir := util.GetVamicroPath() + "/" + version
|
_, err := os.Stat(dir)
|
if nil != err {
|
return err
|
}
|
SetRunVersionEnv(version)
|
versionEnv = version
|
return nil
|
}
|
|
type RegUserInfo struct {
|
UserType string `json:"userType"` //个人:personal 公司: company
|
PhoneNum string `json:"phoneNum"` //手机号码
|
Name string `json:"name"` //姓名或公司名称
|
ProvinceId string `json:"provinceId"` //省
|
CityId string `json:"cityId"` //市
|
CountyId string `json:"countyId"` //县
|
Email string `json:"email"` //邮箱
|
}
|
|
//获取授权
|
func Authorization(code string, isManual bool) (authinfo util.AuthorizationInfo, err error) {
|
sn := util.GetVamicroPath() + "/sn.txt"
|
authorization := util.GetVamicroPath() + "/auth.txt"
|
|
activateCode := ""
|
if len(code) == 29 && code[5:6] == "-" { //25位激活码激活
|
activateCode = code
|
}
|
|
if "" != code && len(code) != 29 && code[5:6] != "-" {
|
authinfo, err := util.GetAuthorizationInfo(code)
|
if nil == err {
|
activateCode = authinfo.ActivateCode
|
logger.Debug("code found:" + code)
|
if isManual { //手动操作更新授权文件,则立即返回,不用再次访问商城
|
ioutil.WriteFile(sn, []byte(authinfo.ActivateCode), os.ModePerm)
|
ioutil.WriteFile(authorization, []byte(code), os.ModePerm)
|
return authinfo, nil
|
} else {
|
//否则以商城为准
|
defer func() {
|
if nil != err {
|
//ioutil.WriteFile(sn, []byte(authinfo.ActivateCode), os.ModePerm)
|
//ioutil.WriteFile(authorization, []byte(code), os.ModePerm)
|
}
|
}()
|
}
|
} else {
|
return authinfo, errors.New("非法的授权!!")
|
}
|
}
|
devId := config.Server.AnalyServerId
|
machineCode := licence.GetMachineCode()
|
|
authinfo, authcode, err := postAuthReq(util.GetSn(), activateCode, devId, machineCode, "")
|
if nil != err {
|
logger.Error("Authorization err:", err.Error(), authcode)
|
//ioutil.WriteFile(authorization, []byte(authcode), os.ModePerm) //bug:局域网会把授权清除
|
return authinfo, err
|
}
|
|
if authinfo.MachineCode != machineCode {
|
logger.Error("GetAuthorization machineCode not match, local:", machineCode, " remote:", authinfo.MachineCode)
|
return authinfo, errors.New("授权不匹配")
|
}
|
|
ioutil.WriteFile(sn, []byte(authinfo.ActivateCode), os.ModePerm)
|
ioutil.WriteFile(authorization, []byte(authcode), os.ModePerm)
|
|
return authinfo, nil
|
}
|
|
func postAuthReq(sn string, activateCode string, deviceId string, machineCode string, oldDeviceId string) (authinfo util.AuthorizationInfo, authcode string, err error) {
|
u, err := url.Parse("http://" + util.GetShopUrl() + uriAuth)
|
if err != nil {
|
logger.Error("parse url failed, url:", "http://"+util.GetShopUrl()+uriAuth, ", err:", err.Error())
|
return authinfo, "", err
|
}
|
query := u.Query()
|
query.Set("sn", sn)
|
query.Set("activateCode", activateCode)
|
query.Set("deviceId", deviceId)
|
query.Set("machineCode", machineCode)
|
query.Set("oldDeviceId", oldDeviceId)
|
query.Set("deviceType", config.Server.DeviceType)
|
query.Set("deviceMode", config.Server.DeviceModel)
|
query.Set("vGpu", util.GetVGpu())
|
|
var sysInitApi bhomedbapi.SysInitApi
|
b, rInfo := sysInitApi.GetRegInfo()
|
if b {
|
rbd, e := json.Marshal(rInfo)
|
if e == nil {
|
var sysRI RegUserInfo
|
if e = json.Unmarshal(rbd, &sysRI); e == nil {
|
query.Set("userType", sysRI.UserType)
|
query.Set("name", sysRI.Name)
|
query.Set("phoneNum", sysRI.PhoneNum)
|
query.Set("provinceId", sysRI.ProvinceId)
|
query.Set("cityId", sysRI.CityId)
|
query.Set("countyId", sysRI.CountyId)
|
query.Set("email", sysRI.Email)
|
} else {
|
logger.Error("json.Unmarshal sysRI e:", e)
|
}
|
} else {
|
logger.Error("json.Marshal rInfo e:", e)
|
}
|
}
|
|
u.RawQuery = query.Encode()
|
resp, err := http.Get(u.String())
|
if err != nil {
|
logger.Error("GetAuthorization parse url failed, url:", u.String(), ", err:", err.Error())
|
return authinfo, "", err
|
}
|
|
if resp.StatusCode != 200 {
|
logger.Error("GetAuthorization incorrect status, url:", u.String(), ", status:", resp.StatusCode)
|
return authinfo, "", errors.New("Status code not 200")
|
}
|
|
defer resp.Body.Close()
|
body, err := ioutil.ReadAll(resp.Body)
|
if err != nil {
|
logger.Error("GetAuthorization read body failed, url:", u.String(), ", err:", err.Error())
|
return authinfo, "", err
|
}
|
|
logger.Info("postAuthReq body:", string(body))
|
var info map[string]interface{}
|
err = json.Unmarshal(body, &info)
|
if err != nil {
|
logger.Error("GetAuthorization json.Unmarshal failed, url:", u.String(), ", err:", err.Error())
|
return authinfo, "", err
|
}
|
|
authinfo, err = util.GetAuthorizationInfo(info["data"].(string))
|
if nil == err {
|
logger.Error("err:", err)
|
return authinfo, info["data"].(string), nil
|
}
|
|
if 500 == int(info["code"].(float64)) {
|
logger.Error("ret 500")
|
return authinfo, "", errors.New(info["msg"].(string))
|
}
|
|
if true != info["success"].(bool) {
|
logger.Error("not success")
|
return authinfo, "", errors.New(info["msg"].(string))
|
}
|
|
return authinfo, info["data"].(string), nil
|
}
|
|
func GenQRCode() ([]byte, string, error) {
|
sn := util.GetSn()
|
var authInfo util.AuthorizationInfo
|
authInfo.Sn = sn
|
authInfo.DevId = config.Server.AnalyServerId
|
authInfo.MachineCode = licence.GetMachineCode()
|
authInfo.DeviceType = config.Server.DeviceType
|
authInfo.DeviceMode = config.Server.DeviceModel
|
authInfo.VGpu = util.GetVGpu()
|
|
var sysInitApi bhomedbapi.SysInitApi
|
if bsi, rInfo := sysInitApi.GetRegInfo(); bsi {
|
rbd, e := json.Marshal(rInfo)
|
if e == nil {
|
var sysRI RegUserInfo
|
if e = json.Unmarshal(rbd, &sysRI); e == nil {
|
authInfo.UserType = sysRI.UserType
|
authInfo.Name = sysRI.Name
|
authInfo.PhoneNum = sysRI.PhoneNum
|
authInfo.ProvinceId = sysRI.ProvinceId
|
authInfo.CityId = sysRI.CityId
|
authInfo.CountyId = sysRI.CountyId
|
authInfo.Email = sysRI.Email
|
} else {
|
logger.Error("json.Unmarshal sysRI e:", e)
|
}
|
} else {
|
logger.Error("json.Marshal rInfo e:", e)
|
}
|
}
|
|
hackQ, _ := HackAuthorizationInfo(authInfo)
|
|
url := "http://" + util.GetShopUrl() + uriMobile + "?q=" + hackQ
|
|
logger.Info("qrcode len:", len(url), " content:", url)
|
|
// 生成二维码
|
q, err := qrcode.New(url, qrcode.Highest)
|
if err != nil {
|
return nil, url, err
|
}
|
|
png, err1 := q.PNG(350)
|
|
return png, url, err1
|
}
|
|
//刷新授权到其他进程
|
func AuthorizationUpdate(c context.Context, ms *bhomeclient.MicroNode) {
|
//三十秒检查一次配置并更新
|
// tick := time.Tick(30 * time.Second)
|
tick := time.Tick(24 * time.Hour)
|
|
var authInfo util.AuthorizationInfo
|
var err error
|
for {
|
select {
|
case <-c.Done():
|
logger.Info("proc close, self update exit")
|
return
|
case <-tick:
|
author := util.GetAuthorization()
|
sn := util.GetSn()
|
|
authInfo, err = Authorization(sn, false)
|
if nil != err && !strings.Contains(err.Error(), "成功") {
|
logger.Error("GetAuthorization error:", err.Error())
|
if "" != author {
|
authInfo, err = util.GetAuthorizationInfo(author)
|
}
|
}
|
|
logger.Debug("authInfo:", authInfo)
|
data, _ := json.Marshal(authInfo)
|
var nodes []bhome_msg.BHAddress
|
nodes = append(nodes, bhome_msg.BHAddress{})
|
go ms.PublishNetTimeout(nodes, AuthorizationUpdateTopic, data, 10)
|
}
|
}
|
}
|
|
func HackAuthorizationInfo(authorizationInfo util.AuthorizationInfo) (string, error) {
|
b, err := json.Marshal(authorizationInfo)
|
if nil != err {
|
return "", err
|
}
|
logger.Debug("authorInfo", authorizationInfo)
|
|
info, err := util.RsaEncrypt(b)
|
if nil != err {
|
logger.Error("HackAuthorizationInfo utils.RsaEncrypt failed, err:", err.Error())
|
return "", err
|
}
|
|
return base64.StdEncoding.EncodeToString(info), nil
|
}
|
|
func GetQ() string {
|
sn := util.GetSn()
|
var authinfo util.AuthorizationInfo
|
authinfo.Sn = sn
|
authinfo.DevId = config.Server.AnalyServerId
|
authinfo.MachineCode = licence.GetMachineCode()
|
authinfo.VGpu = util.GetVGpu()
|
q, err := HackAuthorizationInfo(authinfo)
|
if nil == err {
|
return q
|
}
|
return err.Error()
|
}
|
|
func CancelAuthorization(passwd string, q string) (error, string) {
|
uApi := bhomedbapi.UserApi{}
|
ok, _ := uApi.Login("basic", passwd)
|
if !ok {
|
return errors.New("密码不正确!"), ""
|
}
|
//获取请求码里的devId
|
qInfo, err := util.GetAuthorizationInfo(q)
|
if nil != err {
|
return errors.New("请求码格式不正确"), ""
|
}
|
|
curAuthInfo := util.GetAuthorization()
|
|
//获取当前授权码
|
authInfo, err := util.GetAuthorizationInfo(curAuthInfo)
|
if nil != err {
|
return errors.New("当前服务器授权信息不完整"), ""
|
}
|
authInfo.OldDeviceId = authInfo.DevId
|
authInfo.DevId = qInfo.DevId
|
authInfo.VGpu = util.GetVGpu()
|
sn := util.GetVamicroPath() + "/sn.txt"
|
authorization := util.GetVamicroPath() + "/auth.txt"
|
authCode, err := HackAuthorizationInfo(authInfo)
|
if nil != err {
|
return errors.New("产品密钥导出失败"), ""
|
}
|
ioutil.WriteFile(sn, []byte(""), os.ModePerm)
|
time.Sleep(100 * time.Microsecond)
|
ioutil.WriteFile(authorization, []byte(""), os.ModePerm)
|
|
_, _, err = postAuthReq(authInfo.Sn, authInfo.ActivateCode, qInfo.DevId, licence.GetMachineCode(), authInfo.OldDeviceId)
|
|
if nil != err {
|
return err, ""
|
}
|
|
return nil, authCode
|
}
|