middleware.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package main
  2. import (
  3. "errors"
  4. "net/http"
  5. "sparrow/pkg/models"
  6. "sparrow/pkg/productconfig"
  7. "sparrow/pkg/rpcs"
  8. "sparrow/pkg/server"
  9. "strconv"
  10. "strings"
  11. "github.com/go-martini/martini"
  12. "github.com/martini-contrib/render"
  13. )
  14. func checkAppDomain(domain string, identifier string) error {
  15. domainPieces := strings.Split(domain, "/")
  16. identifierPieces := strings.Split(identifier, "-")
  17. if len(domainPieces) == 0 {
  18. return errors.New("wrong app domain format.")
  19. }
  20. if len(identifierPieces) != 3 {
  21. return errors.New("wrong identifier format.")
  22. }
  23. devvendorid, err := strconv.ParseUint(identifierPieces[0], 16, 64)
  24. if err != nil {
  25. return errors.New("wrong vendor format.")
  26. }
  27. devproductid, err := strconv.ParseUint(identifierPieces[1], 16, 64)
  28. if err != nil {
  29. return errors.New("wrong product format.")
  30. }
  31. if len(domainPieces) == 1 {
  32. if domainPieces[0] != "*" {
  33. return errors.New("wrong app domain " + domainPieces[0])
  34. }
  35. return nil
  36. }
  37. if len(domainPieces) == 2 {
  38. id, err := strconv.ParseUint(domainPieces[1], 10, 64)
  39. if err != nil {
  40. return errors.New("wrong app domain format..")
  41. }
  42. if domainPieces[0] == "vendor" {
  43. if id != devvendorid {
  44. return errors.New("app has no access right on device.")
  45. }
  46. } else if domainPieces[0] == "product" {
  47. if id != devproductid {
  48. return errors.New("app has no access right on device.")
  49. }
  50. } else {
  51. return errors.New("wrong app domain" + domain)
  52. }
  53. }
  54. if len(domainPieces) > 2 {
  55. return errors.New("wrong app domain" + domainPieces[0])
  56. }
  57. return nil
  58. }
  59. // check if app has access right on device of given identifier( in url params )
  60. func ApplicationAuthOnDeviceIdentifer(context martini.Context, params martini.Params, req *http.Request, r render.Render) {
  61. identifier := params["identifier"]
  62. key := req.Header.Get("App-Key")
  63. if identifier == "" || key == "" {
  64. r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, errors.New("missing device identifier or app key.")))
  65. return
  66. }
  67. app := &models.Application{}
  68. err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.ValidateApplication", key, app)
  69. if err != nil {
  70. r.JSON(http.StatusOK, renderError(ErrAccessDenied, err))
  71. return
  72. }
  73. err = checkAppDomain(app.AppDomain, identifier)
  74. if err != nil {
  75. r.JSON(http.StatusOK, renderError(ErrAccessDenied, err))
  76. return
  77. }
  78. }
  79. // check if device is online.
  80. func CheckDeviceOnline(context martini.Context, params martini.Params, req *http.Request, r render.Render) {
  81. identifier := params["identifier"]
  82. device := &models.Device{}
  83. err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindDeviceByIdentifier", identifier, device)
  84. if err != nil {
  85. r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
  86. return
  87. }
  88. onlineargs := rpcs.ArgsGetDeviceOnlineStatus{
  89. Id: device.RecordId,
  90. }
  91. onlinereply := rpcs.ReplyGetDeviceOnlineStatus{}
  92. err = server.RPCCallByName(nil, rpcs.DeviceManagerName, "DeviceManager.GetDeviceOnlineStatus", onlineargs, &onlinereply)
  93. if err != nil {
  94. server.Log.Errorf("get device online status error: %v", err)
  95. r.JSON(http.StatusOK, renderError(ErrDeviceNotOnline, errors.New("get device online status error "+err.Error())))
  96. return
  97. }
  98. context.Map(device)
  99. }
  100. // get device identifier
  101. func CheckDeviceIdentifier(context martini.Context, params martini.Params, req *http.Request, r render.Render) {
  102. identifier := params["identifier"]
  103. device := &models.Device{}
  104. err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindDeviceByIdentifier", identifier, device)
  105. if err != nil {
  106. r.JSON(http.StatusOK, renderError(ErrDeviceNotFound, err))
  107. return
  108. }
  109. context.Map(device)
  110. }
  111. // check if proudct is ok and map a product config to context, must by called after CheckDevice
  112. func CheckProductConfig(context martini.Context, device *models.Device,
  113. params martini.Params, req *http.Request, r render.Render) {
  114. product := &models.Product{}
  115. err := server.RPCCallByName(nil, rpcs.RegistryServerName, "Registry.FindProduct", device.ProductID, product)
  116. if err != nil {
  117. r.JSON(http.StatusOK, renderError(ErrProductNotFound, err))
  118. return
  119. }
  120. c, err := productconfig.New(product.ProductConfig)
  121. if err != nil {
  122. r.JSON(http.StatusOK, renderError(ErrWrongProductConfig, err))
  123. return
  124. }
  125. context.Map(c)
  126. }