external.agi.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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) != 2 {
  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[1])
  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. }
  83. func (g *Gateway) RemoveExternalEndPoint(w http.ResponseWriter, r *http.Request) {
  84. userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
  85. if err != nil {
  86. common.SendErrorResponse(w, "Bad User")
  87. return
  88. }
  89. // get db
  90. sysdb := g.Option.UserHandler.GetDatabase()
  91. if !sysdb.TableExists("external_agi") {
  92. sysdb.NewTable("external_agi")
  93. }
  94. // get path
  95. uuid, _ := common.Mv(r, "uuid", false)
  96. data, isExist := g.checkIfExternalEndpointExist(uuid)
  97. if !isExist {
  98. common.SendErrorResponse(w, "UUID does not exists in the database!")
  99. return
  100. }
  101. if data.Username != userInfo.Username {
  102. common.SendErrorResponse(w, "Bad Request, you have no permission to access this UUID entry!")
  103. return
  104. }
  105. sysdb.Delete("external_agi", uuid)
  106. common.SendOK(w)
  107. }
  108. func (g *Gateway) ListExternalEndpoint(w http.ResponseWriter, r *http.Request) {
  109. userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
  110. if err != nil {
  111. common.SendErrorResponse(w, "Bad User")
  112. return
  113. }
  114. // get db
  115. sysdb := g.Option.UserHandler.GetDatabase()
  116. if !sysdb.TableExists("external_agi") {
  117. sysdb.NewTable("external_agi")
  118. }
  119. // declare variable for return
  120. dataFromDB := make(map[string]endpointFormat)
  121. // O(n) method to do the lookup
  122. entries, _ := sysdb.ListTable("external_agi")
  123. for _, keypairs := range entries {
  124. //Decode the string
  125. var dataFromResult endpointFormat
  126. result := ""
  127. uuid := string(keypairs[0])
  128. json.Unmarshal(keypairs[1], &result)
  129. fmt.Println(result)
  130. json.Unmarshal([]byte(result), &dataFromResult)
  131. if dataFromResult.Username == userInfo.Username {
  132. dataFromDB[uuid] = dataFromResult
  133. }
  134. }
  135. returnJson, _ := json.Marshal(dataFromDB)
  136. sendJSONResponse(w, string(returnJson))
  137. }
  138. func (g *Gateway) checkIfExternalEndpointExist(uuid string) (endpointFormat, bool) {
  139. // get db
  140. sysdb := g.Option.UserHandler.GetDatabase()
  141. if !sysdb.TableExists("external_agi") {
  142. sysdb.NewTable("external_agi")
  143. }
  144. var dat endpointFormat
  145. if !sysdb.KeyExists("external_agi", uuid) {
  146. return dat, false
  147. }
  148. jsonData := ""
  149. sysdb.Read("external_agi", uuid, &jsonData)
  150. json.Unmarshal([]byte(jsonData), &dat)
  151. return dat, true
  152. }