external.agi.go 5.3 KB

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