123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- 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)
- }
|