go-common/app/admin/main/appstatic/http/add_ver.go

243 lines
6.8 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
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)
}