external.agi.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package agi
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "path/filepath"
  9. "strings"
  10. "time"
  11. "github.com/google/uuid"
  12. "imuslab.com/arozos/mod/common"
  13. )
  14. type endpointFormat struct {
  15. Username string `json:"username"`
  16. Path string `json:"path"`
  17. }
  18. //Handle request from EXTERNAL RESTFUL API
  19. func (g *Gateway) ExtAPIHandler(w http.ResponseWriter, r *http.Request) {
  20. // get db
  21. sysdb := g.Option.UserHandler.GetDatabase()
  22. if !sysdb.TableExists("external_agi") {
  23. common.SendErrorResponse(w, "Bad Request, invaild database")
  24. return
  25. }
  26. // get the request URI from the r.URL
  27. requestURI := filepath.ToSlash(filepath.Clean(r.URL.Path))
  28. subpathElements := strings.Split(requestURI[1:], "/")
  29. // check if it contains only two part, [rexec uuid]
  30. if len(subpathElements) != 3 {
  31. common.SendErrorResponse(w, "Bad Request, invaild request sent")
  32. return
  33. }
  34. // check if UUID exists in the database
  35. // get the info from the database
  36. data, isExist := g.checkIfExternalEndpointExist(subpathElements[2])
  37. if !isExist {
  38. common.SendErrorResponse(w, "Bad Request, invaild UUID entered")
  39. return
  40. }
  41. usernameFromDb := data.Username
  42. pathFromDb := data.Path
  43. // get the userinfo and the realPath
  44. userInfo, err := g.Option.UserHandler.GetUserInfoFromUsername(usernameFromDb)
  45. if err != nil {
  46. common.SendErrorResponse(w, "Bad username")
  47. return
  48. }
  49. _, realPath, err := virtualPathToRealPath(pathFromDb, userInfo)
  50. if err != nil {
  51. common.SendErrorResponse(w, "Bad filepath")
  52. return
  53. }
  54. // read the file and store it into scriptContent
  55. scriptContentByte, err := ioutil.ReadFile(realPath)
  56. if err != nil {
  57. common.SendErrorResponse(w, "Bad file I/O")
  58. return
  59. }
  60. scriptContent := string(scriptContentByte)
  61. // execute!
  62. start := time.Now()
  63. g.ExecuteAGIScript(scriptContent, "", "", w, r, userInfo)
  64. duration := time.Since(start)
  65. log.Println("[Remote AGI] IP:", r.RemoteAddr, " executed the script ", pathFromDb, "(", realPath, ")", " on behalf of", userInfo.Username, "with total duration: ", duration)
  66. }
  67. func (g *Gateway) AddExternalEndPoint(w http.ResponseWriter, r *http.Request) {
  68. userInfo, _ := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
  69. // get db
  70. sysdb := g.Option.UserHandler.GetDatabase()
  71. if !sysdb.TableExists("external_agi") {
  72. sysdb.NewTable("external_agi")
  73. }
  74. var dat endpointFormat
  75. // uuid: [path, id]
  76. path, _ := common.Mv(r, "path", false)
  77. id := uuid.New().String()
  78. dat.Path = path
  79. dat.Username = userInfo.Username
  80. jsonStr, _ := json.Marshal(dat)
  81. sysdb.Write("external_agi", id, string(jsonStr))
  82. sendOK(w)
  83. }
  84. func (g *Gateway) RemoveExternalEndPoint(w http.ResponseWriter, r *http.Request) {
  85. userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
  86. if err != nil {
  87. common.SendErrorResponse(w, "Bad User")
  88. return
  89. }
  90. // get db
  91. sysdb := g.Option.UserHandler.GetDatabase()
  92. if !sysdb.TableExists("external_agi") {
  93. sysdb.NewTable("external_agi")
  94. }
  95. // get path
  96. uuid, _ := common.Mv(r, "uuid", false)
  97. data, isExist := g.checkIfExternalEndpointExist(uuid)
  98. if !isExist {
  99. common.SendErrorResponse(w, "UUID does not exists in the database!")
  100. return
  101. }
  102. if data.Username != userInfo.Username {
  103. common.SendErrorResponse(w, "Bad Request, you have no permission to access this UUID entry!")
  104. return
  105. }
  106. sysdb.Delete("external_agi", uuid)
  107. common.SendOK(w)
  108. }
  109. func (g *Gateway) ListExternalEndpoint(w http.ResponseWriter, r *http.Request) {
  110. userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
  111. if err != nil {
  112. common.SendErrorResponse(w, "Bad User")
  113. return
  114. }
  115. // get db
  116. sysdb := g.Option.UserHandler.GetDatabase()
  117. if !sysdb.TableExists("external_agi") {
  118. sysdb.NewTable("external_agi")
  119. }
  120. // declare variable for return
  121. dataFromDB := make(map[string]endpointFormat)
  122. // O(n) method to do the lookup
  123. entries, _ := sysdb.ListTable("external_agi")
  124. for _, keypairs := range entries {
  125. //Decode the string
  126. var dataFromResult endpointFormat
  127. result := ""
  128. uuid := string(keypairs[0])
  129. json.Unmarshal(keypairs[1], &result)
  130. fmt.Println(result)
  131. json.Unmarshal([]byte(result), &dataFromResult)
  132. if dataFromResult.Username == userInfo.Username {
  133. dataFromDB[uuid] = dataFromResult
  134. }
  135. }
  136. returnJson, _ := json.Marshal(dataFromDB)
  137. sendJSONResponse(w, string(returnJson))
  138. }
  139. func (g *Gateway) checkIfExternalEndpointExist(uuid string) (endpointFormat, bool) {
  140. // get db
  141. sysdb := g.Option.UserHandler.GetDatabase()
  142. if !sysdb.TableExists("external_agi") {
  143. sysdb.NewTable("external_agi")
  144. }
  145. var dat endpointFormat
  146. if !sysdb.KeyExists("external_agi", uuid) {
  147. return dat, false
  148. }
  149. jsonData := ""
  150. sysdb.Read("external_agi", uuid, &jsonData)
  151. json.Unmarshal([]byte(jsonData), &dat)
  152. return dat, true
  153. }