add_ver.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package http
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "net/http"
  6. "regexp"
  7. "time"
  8. "encoding/json"
  9. "go-common/app/admin/main/appstatic/model"
  10. "go-common/library/ecode"
  11. "go-common/library/log"
  12. bm "go-common/library/net/http/blademaster"
  13. )
  14. const nameFmt = `^[a-zA-Z0-9._-]+$`
  15. const fileFmt = "Mod_%d-%s/%s"
  16. func httpCode(c *bm.Context, message string, err error) {
  17. c.JSON(map[string]interface{}{
  18. "message": message,
  19. }, err)
  20. }
  21. // validate required data
  22. func validateRequired(reqInfo *model.RequestVer) (err error) {
  23. reg := regexp.MustCompile(nameFmt)
  24. if res := reg.MatchString(reqInfo.ModName); !res {
  25. err = fmt.Errorf("mod_name %s contains illegal character", reqInfo.ModName)
  26. return
  27. }
  28. if res := reg.MatchString(reqInfo.Department); !res {
  29. err = fmt.Errorf("department %s contains illegal character", reqInfo.Department)
  30. return
  31. }
  32. return
  33. }
  34. // check whether the build range is valid
  35. func checkRange(build *model.Build) (res bool) {
  36. if (build.GE != 0 && build.GT != 0) || (build.LE != 0 && build.LT != 0) { // two values by one side
  37. return false
  38. }
  39. var (
  40. gt = build.GT
  41. lt = build.LT
  42. )
  43. // transform E to T
  44. if build.GE != 0 {
  45. gt = build.GE - 1
  46. }
  47. if build.LE != 0 {
  48. lt = build.LE + 1
  49. }
  50. // range check
  51. if lt != 0 && gt != 0 && lt-gt <= 1 {
  52. return false
  53. }
  54. return true
  55. }
  56. // transform []int to []string
  57. func sliceString(is []int) (ss []string) {
  58. for _, v := range is {
  59. ss = append(ss, fmt.Sprintf("%d", v))
  60. }
  61. return
  62. }
  63. // check limit data and build the Limit Struct, error is json error here
  64. func checkLimit(reqInfo *model.RequestVer) (res *model.Limit, err error) {
  65. getFormat := "GetLimit Param (%s), Value = (%s)"
  66. res = &model.Limit{}
  67. // mobi_app
  68. if len(reqInfo.MobiAPP) != 0 {
  69. res.MobiApp = reqInfo.MobiAPP
  70. }
  71. // device
  72. if len(reqInfo.Device) != 0 {
  73. res.Device = reqInfo.Device
  74. }
  75. // plat
  76. if len(reqInfo.Plat) != 0 {
  77. res.Plat = reqInfo.Plat
  78. }
  79. if reqInfo.IsWifi != 0 {
  80. res.IsWifi = reqInfo.IsWifi
  81. }
  82. // Scale & Arch & Level
  83. if len(reqInfo.Scale) != 0 {
  84. res.Scale = sliceString(reqInfo.Scale)
  85. }
  86. if len(reqInfo.Arch) != 0 {
  87. res.Arch = sliceString(reqInfo.Arch)
  88. }
  89. if reqInfo.Level != 0 {
  90. res.Level = sliceString([]int{reqInfo.Level}) // treat level as others ( []int )
  91. }
  92. // build_range
  93. if buildStr := reqInfo.BuildRange; buildStr != "" {
  94. log.Info(getFormat, "build_range", buildStr)
  95. var build = model.Build{}
  96. if err = json.Unmarshal([]byte(buildStr), &build); err != nil { // json err
  97. log.Error("buildStr (%s) json.Unmarshal error(%v)", buildStr, err)
  98. return
  99. }
  100. if isValid := checkRange(&build); !isValid { // range not valid
  101. err = fmt.Errorf("build range (%s) not valid", buildStr)
  102. log.Error("buildStr CheckRange Error (%v)", err)
  103. return
  104. }
  105. res.Build = &build
  106. }
  107. // sysver
  108. if sysverStr := reqInfo.Sysver; sysverStr != "" {
  109. var build = model.Build{}
  110. if err = json.Unmarshal([]byte(sysverStr), &build); err != nil { // json err
  111. log.Error("buildStr (%s) json.Unmarshal error(%v)", sysverStr, err)
  112. return
  113. }
  114. if isValid := checkRange(&build); !isValid { // range not valid
  115. err = fmt.Errorf("build range (%s) not valid", sysverStr)
  116. log.Error("sysverStr CheckRange Error (%v)", err)
  117. return
  118. }
  119. res.Sysver = &build
  120. }
  121. // time_range
  122. if timeStr := reqInfo.TimeRange; timeStr != "" {
  123. log.Info(getFormat, "time_range", timeStr)
  124. var tr = model.TimeRange{}
  125. if err = json.Unmarshal([]byte(timeStr), &tr); err != nil {
  126. log.Error("timeStr (%s) json.Unmarshal error(%v)", timeStr, err)
  127. return
  128. }
  129. if tr.Stime != 0 && tr.Etime != 0 && tr.Stime > tr.Etime {
  130. err = fmt.Errorf("Stime(%d) is bigger than Etime(%d)", tr.Stime, tr.Etime)
  131. log.Error("Time Range Error(%v)", err)
  132. return
  133. }
  134. res.TimeRange = &tr
  135. }
  136. return
  137. }
  138. // validate the file type, content and upload it to the BFS storage
  139. func validateFile(ctx *bm.Context, req *http.Request, pool *model.ResourcePool) (fInfo *model.FileInfo, err error) {
  140. // get the file
  141. file, header, err := req.FormFile("file")
  142. if err != nil {
  143. return
  144. }
  145. defer file.Close()
  146. // read the file
  147. content, err := ioutil.ReadAll(file)
  148. if err != nil {
  149. log.Error("resource uploadFile.ReadAll error(%v)", err)
  150. return
  151. }
  152. // parse file, get type, size, md5
  153. fInfo, err = apsSvc.ParseFile(content)
  154. if err != nil {
  155. log.Error("[validateFile]-[ParseFile] Error-[%v]", err)
  156. return
  157. }
  158. if !apsSvc.TypeCheck(fInfo.Type) {
  159. log.Error("[validateFile]-[FileType] Error-[%v]", fInfo.Type)
  160. err = fmt.Errorf("请上传指定类型文件")
  161. return
  162. }
  163. // regex checking
  164. reg := regexp.MustCompile(nameFmt)
  165. if res := reg.MatchString(header.Filename); !res {
  166. err = fmt.Errorf("fileName %s contains illegal character", header.Filename)
  167. return
  168. }
  169. // upload file to BFS
  170. fInfo.Name = fmt.Sprintf(fileFmt, pool.ID, fInfo.Md5, header.Filename) // rename with the MD5 and poolID
  171. location, err := apsSvc.Upload(ctx, fInfo.Name, fInfo.Type, time.Now().Unix(), content)
  172. if err != nil {
  173. log.Error("[validateFile]-[UploadBFS] Error-[%v]", err)
  174. return
  175. }
  176. fInfo.URL = location
  177. return
  178. }
  179. // for other systems
  180. func addVer(c *bm.Context) {
  181. var (
  182. pool = model.ResourcePool{}
  183. department = model.Department{}
  184. req = c.Request
  185. limitData *model.Limit
  186. fInfo *model.FileInfo
  187. err error
  188. reqInfo = model.RequestVer{}
  189. respData = &model.RespAdd{}
  190. )
  191. req.ParseMultipartForm(apsSvc.MaxSize)
  192. if err = c.Bind(&reqInfo); err != nil {
  193. return
  194. }
  195. // validate required data
  196. if err = validateRequired(&reqInfo); err != nil {
  197. log.Error("addVer ModName, ResName Error (%v)", err)
  198. c.JSON(nil, err)
  199. return
  200. }
  201. // validate department
  202. if err = apsSvc.DB.Where("`name` = ?", reqInfo.Department).First(&department).Error; err != nil {
  203. log.Error("addVer First department Error (%v)", err)
  204. httpCode(c, fmt.Sprintf("department %s doesn't exist", reqInfo.Department), ecode.RequestErr)
  205. return
  206. }
  207. // validate mod Name
  208. if err = apsSvc.DB.Where("`name` = ? AND `department_id` = ? AND `deleted` = 0 AND `action` = 1", reqInfo.ModName, department.ID).First(&pool).Error; err != nil {
  209. log.Error("addVer First Pool Error (%v)", err)
  210. httpCode(c, fmt.Sprintf("Mod_name %s doesn't exist", reqInfo.ModName), ecode.RequestErr)
  211. return
  212. }
  213. // check limit & config data
  214. if limitData, err = checkLimit(&reqInfo); err != nil {
  215. log.Error("addVer CheckLimit Error (%v)", err)
  216. httpCode(c, fmt.Sprintf("Limit Params JSON Error:(%v)", err), ecode.RequestErr)
  217. return
  218. }
  219. // validate file data
  220. if fInfo, err = validateFile(c, req, &pool); err != nil {
  221. log.Error("addVer ValidateFile Error (%v)", err)
  222. httpCode(c, fmt.Sprintf("File Error:(%v)", err), ecode.RequestErr)
  223. return
  224. }
  225. // DB & storage operation
  226. if respData.ResID, respData.Version, err = apsSvc.GenerateVer(reqInfo.ResName, limitData, fInfo, &pool, reqInfo.DefaultPackage); err != nil {
  227. log.Error("addVer GenerateVer Error (%v)", err)
  228. httpCode(c, fmt.Sprintf("Generate Version Error:(%v)", err), ecode.ServerErr)
  229. return
  230. }
  231. c.JSON(respData, nil)
  232. }