243 lines
6.8 KiB
Go
243 lines
6.8 KiB
Go
|
package http
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"regexp"
|
||
|
"time"
|
||
|
|
||
|
"encoding/json"
|
||
|
"go-common/app/admin/main/appstatic/model"
|
||
|
"go-common/library/ecode"
|
||
|
"go-common/library/log"
|
||
|
bm "go-common/library/net/http/blademaster"
|
||
|
)
|
||
|
|
||
|
const nameFmt = `^[a-zA-Z0-9._-]+$`
|
||
|
const fileFmt = "Mod_%d-%s/%s"
|
||
|
|
||
|
func httpCode(c *bm.Context, message string, err error) {
|
||
|
c.JSON(map[string]interface{}{
|
||
|
"message": message,
|
||
|
}, err)
|
||
|
}
|
||
|
|
||
|
// validate required data
|
||
|
func validateRequired(reqInfo *model.RequestVer) (err error) {
|
||
|
reg := regexp.MustCompile(nameFmt)
|
||
|
if res := reg.MatchString(reqInfo.ModName); !res {
|
||
|
err = fmt.Errorf("mod_name %s contains illegal character", reqInfo.ModName)
|
||
|
return
|
||
|
}
|
||
|
if res := reg.MatchString(reqInfo.Department); !res {
|
||
|
err = fmt.Errorf("department %s contains illegal character", reqInfo.Department)
|
||
|
return
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// check whether the build range is valid
|
||
|
func checkRange(build *model.Build) (res bool) {
|
||
|
if (build.GE != 0 && build.GT != 0) || (build.LE != 0 && build.LT != 0) { // two values by one side
|
||
|
return false
|
||
|
}
|
||
|
var (
|
||
|
gt = build.GT
|
||
|
lt = build.LT
|
||
|
)
|
||
|
// transform E to T
|
||
|
if build.GE != 0 {
|
||
|
gt = build.GE - 1
|
||
|
}
|
||
|
if build.LE != 0 {
|
||
|
lt = build.LE + 1
|
||
|
}
|
||
|
// range check
|
||
|
if lt != 0 && gt != 0 && lt-gt <= 1 {
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// transform []int to []string
|
||
|
func sliceString(is []int) (ss []string) {
|
||
|
for _, v := range is {
|
||
|
ss = append(ss, fmt.Sprintf("%d", v))
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// check limit data and build the Limit Struct, error is json error here
|
||
|
func checkLimit(reqInfo *model.RequestVer) (res *model.Limit, err error) {
|
||
|
getFormat := "GetLimit Param (%s), Value = (%s)"
|
||
|
res = &model.Limit{}
|
||
|
// mobi_app
|
||
|
if len(reqInfo.MobiAPP) != 0 {
|
||
|
res.MobiApp = reqInfo.MobiAPP
|
||
|
}
|
||
|
// device
|
||
|
if len(reqInfo.Device) != 0 {
|
||
|
res.Device = reqInfo.Device
|
||
|
}
|
||
|
// plat
|
||
|
if len(reqInfo.Plat) != 0 {
|
||
|
res.Plat = reqInfo.Plat
|
||
|
}
|
||
|
if reqInfo.IsWifi != 0 {
|
||
|
res.IsWifi = reqInfo.IsWifi
|
||
|
}
|
||
|
// Scale & Arch & Level
|
||
|
if len(reqInfo.Scale) != 0 {
|
||
|
res.Scale = sliceString(reqInfo.Scale)
|
||
|
}
|
||
|
if len(reqInfo.Arch) != 0 {
|
||
|
res.Arch = sliceString(reqInfo.Arch)
|
||
|
}
|
||
|
if reqInfo.Level != 0 {
|
||
|
res.Level = sliceString([]int{reqInfo.Level}) // treat level as others ( []int )
|
||
|
}
|
||
|
// build_range
|
||
|
if buildStr := reqInfo.BuildRange; buildStr != "" {
|
||
|
log.Info(getFormat, "build_range", buildStr)
|
||
|
var build = model.Build{}
|
||
|
if err = json.Unmarshal([]byte(buildStr), &build); err != nil { // json err
|
||
|
log.Error("buildStr (%s) json.Unmarshal error(%v)", buildStr, err)
|
||
|
return
|
||
|
}
|
||
|
if isValid := checkRange(&build); !isValid { // range not valid
|
||
|
err = fmt.Errorf("build range (%s) not valid", buildStr)
|
||
|
log.Error("buildStr CheckRange Error (%v)", err)
|
||
|
return
|
||
|
}
|
||
|
res.Build = &build
|
||
|
}
|
||
|
// sysver
|
||
|
if sysverStr := reqInfo.Sysver; sysverStr != "" {
|
||
|
var build = model.Build{}
|
||
|
if err = json.Unmarshal([]byte(sysverStr), &build); err != nil { // json err
|
||
|
log.Error("buildStr (%s) json.Unmarshal error(%v)", sysverStr, err)
|
||
|
return
|
||
|
}
|
||
|
if isValid := checkRange(&build); !isValid { // range not valid
|
||
|
err = fmt.Errorf("build range (%s) not valid", sysverStr)
|
||
|
log.Error("sysverStr CheckRange Error (%v)", err)
|
||
|
return
|
||
|
}
|
||
|
res.Sysver = &build
|
||
|
}
|
||
|
// time_range
|
||
|
if timeStr := reqInfo.TimeRange; timeStr != "" {
|
||
|
log.Info(getFormat, "time_range", timeStr)
|
||
|
var tr = model.TimeRange{}
|
||
|
if err = json.Unmarshal([]byte(timeStr), &tr); err != nil {
|
||
|
log.Error("timeStr (%s) json.Unmarshal error(%v)", timeStr, err)
|
||
|
return
|
||
|
}
|
||
|
if tr.Stime != 0 && tr.Etime != 0 && tr.Stime > tr.Etime {
|
||
|
err = fmt.Errorf("Stime(%d) is bigger than Etime(%d)", tr.Stime, tr.Etime)
|
||
|
log.Error("Time Range Error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
res.TimeRange = &tr
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// validate the file type, content and upload it to the BFS storage
|
||
|
func validateFile(ctx *bm.Context, req *http.Request, pool *model.ResourcePool) (fInfo *model.FileInfo, err error) {
|
||
|
// get the file
|
||
|
file, header, err := req.FormFile("file")
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
defer file.Close()
|
||
|
// read the file
|
||
|
content, err := ioutil.ReadAll(file)
|
||
|
if err != nil {
|
||
|
log.Error("resource uploadFile.ReadAll error(%v)", err)
|
||
|
return
|
||
|
}
|
||
|
// parse file, get type, size, md5
|
||
|
fInfo, err = apsSvc.ParseFile(content)
|
||
|
if err != nil {
|
||
|
log.Error("[validateFile]-[ParseFile] Error-[%v]", err)
|
||
|
return
|
||
|
}
|
||
|
if !apsSvc.TypeCheck(fInfo.Type) {
|
||
|
log.Error("[validateFile]-[FileType] Error-[%v]", fInfo.Type)
|
||
|
err = fmt.Errorf("请上传指定类型文件")
|
||
|
return
|
||
|
}
|
||
|
// regex checking
|
||
|
reg := regexp.MustCompile(nameFmt)
|
||
|
if res := reg.MatchString(header.Filename); !res {
|
||
|
err = fmt.Errorf("fileName %s contains illegal character", header.Filename)
|
||
|
return
|
||
|
}
|
||
|
// upload file to BFS
|
||
|
fInfo.Name = fmt.Sprintf(fileFmt, pool.ID, fInfo.Md5, header.Filename) // rename with the MD5 and poolID
|
||
|
location, err := apsSvc.Upload(ctx, fInfo.Name, fInfo.Type, time.Now().Unix(), content)
|
||
|
if err != nil {
|
||
|
log.Error("[validateFile]-[UploadBFS] Error-[%v]", err)
|
||
|
return
|
||
|
}
|
||
|
fInfo.URL = location
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// for other systems
|
||
|
func addVer(c *bm.Context) {
|
||
|
var (
|
||
|
pool = model.ResourcePool{}
|
||
|
department = model.Department{}
|
||
|
req = c.Request
|
||
|
limitData *model.Limit
|
||
|
fInfo *model.FileInfo
|
||
|
err error
|
||
|
reqInfo = model.RequestVer{}
|
||
|
respData = &model.RespAdd{}
|
||
|
)
|
||
|
req.ParseMultipartForm(apsSvc.MaxSize)
|
||
|
if err = c.Bind(&reqInfo); err != nil {
|
||
|
return
|
||
|
}
|
||
|
// validate required data
|
||
|
if err = validateRequired(&reqInfo); err != nil {
|
||
|
log.Error("addVer ModName, ResName Error (%v)", err)
|
||
|
c.JSON(nil, err)
|
||
|
return
|
||
|
}
|
||
|
// validate department
|
||
|
if err = apsSvc.DB.Where("`name` = ?", reqInfo.Department).First(&department).Error; err != nil {
|
||
|
log.Error("addVer First department Error (%v)", err)
|
||
|
httpCode(c, fmt.Sprintf("department %s doesn't exist", reqInfo.Department), ecode.RequestErr)
|
||
|
return
|
||
|
}
|
||
|
// validate mod Name
|
||
|
if err = apsSvc.DB.Where("`name` = ? AND `department_id` = ? AND `deleted` = 0 AND `action` = 1", reqInfo.ModName, department.ID).First(&pool).Error; err != nil {
|
||
|
log.Error("addVer First Pool Error (%v)", err)
|
||
|
httpCode(c, fmt.Sprintf("Mod_name %s doesn't exist", reqInfo.ModName), ecode.RequestErr)
|
||
|
return
|
||
|
}
|
||
|
// check limit & config data
|
||
|
if limitData, err = checkLimit(&reqInfo); err != nil {
|
||
|
log.Error("addVer CheckLimit Error (%v)", err)
|
||
|
httpCode(c, fmt.Sprintf("Limit Params JSON Error:(%v)", err), ecode.RequestErr)
|
||
|
return
|
||
|
}
|
||
|
// validate file data
|
||
|
if fInfo, err = validateFile(c, req, &pool); err != nil {
|
||
|
log.Error("addVer ValidateFile Error (%v)", err)
|
||
|
httpCode(c, fmt.Sprintf("File Error:(%v)", err), ecode.RequestErr)
|
||
|
return
|
||
|
}
|
||
|
// DB & storage operation
|
||
|
if respData.ResID, respData.Version, err = apsSvc.GenerateVer(reqInfo.ResName, limitData, fInfo, &pool, reqInfo.DefaultPackage); err != nil {
|
||
|
log.Error("addVer GenerateVer Error (%v)", err)
|
||
|
httpCode(c, fmt.Sprintf("Generate Version Error:(%v)", err), ecode.ServerErr)
|
||
|
return
|
||
|
}
|
||
|
c.JSON(respData, nil)
|
||
|
}
|