external.agi.go 5.3 KB

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