externalReqHandler.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package agi
  2. import (
  3. "encoding/json"
  4. "log"
  5. "net/http"
  6. "path/filepath"
  7. "strings"
  8. "time"
  9. uuid "github.com/satori/go.uuid"
  10. "imuslab.com/arozos/mod/agi/static"
  11. "imuslab.com/arozos/mod/utils"
  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. utils.SendErrorResponse(w, "Invalid Request")
  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. utils.SendErrorResponse(w, "Invalid Request")
  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. utils.SendErrorResponse(w, "Malform Request, invaild UUID given")
  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. utils.SendErrorResponse(w, "Invalid username")
  46. return
  47. }
  48. fsh, realPath, err := static.VirtualPathToRealPath(pathFromDb, userInfo)
  49. if err != nil {
  50. utils.SendErrorResponse(w, "Invalid filepath")
  51. return
  52. }
  53. // execute!
  54. start := time.Now()
  55. //g.ExecuteAGIScript(scriptContent, "", "", w, r, userInfo)
  56. result, err := g.ExecuteAGIScriptAsUser(fsh, realPath, userInfo, w, r)
  57. duration := time.Since(start)
  58. if err != nil {
  59. utils.SendErrorResponse(w, err.Error())
  60. return
  61. }
  62. w.Write([]byte(result))
  63. log.Println("[Remote AGI] IP:", r.RemoteAddr, " executed the script ", pathFromDb, "(", realPath, ")", " on behalf of", userInfo.Username, "with total duration: ", duration)
  64. }
  65. func (g *Gateway) AddExternalEndPoint(w http.ResponseWriter, r *http.Request) {
  66. userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
  67. if err != nil {
  68. utils.SendErrorResponse(w, "User not logged in")
  69. return
  70. }
  71. // get db
  72. sysdb := g.Option.UserHandler.GetDatabase()
  73. if !sysdb.TableExists("external_agi") {
  74. sysdb.NewTable("external_agi")
  75. }
  76. var dat endpointFormat
  77. // uuid: [path, id]
  78. path, err := utils.GetPara(r, "path")
  79. if err != nil {
  80. utils.SendErrorResponse(w, "Invalid path given")
  81. return
  82. }
  83. // put the data in then marshal
  84. id := uuid.NewV4().String()
  85. dat.Path = path
  86. dat.Username = userInfo.Username
  87. jsonStr, err := json.Marshal(dat)
  88. if err != nil {
  89. utils.SendErrorResponse(w, "Invalid JSON string: "+err.Error())
  90. return
  91. }
  92. sysdb.Write("external_agi", id, string(jsonStr))
  93. // send the uuid to frontend
  94. utils.SendJSONResponse(w, "\""+id+"\"")
  95. }
  96. func (g *Gateway) RemoveExternalEndPoint(w http.ResponseWriter, r *http.Request) {
  97. userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
  98. if err != nil {
  99. utils.SendErrorResponse(w, "User not logged in")
  100. return
  101. }
  102. // get db
  103. sysdb := g.Option.UserHandler.GetDatabase()
  104. if !sysdb.TableExists("external_agi") {
  105. sysdb.NewTable("external_agi")
  106. }
  107. // get path
  108. uuid, err := utils.GetPara(r, "uuid")
  109. if err != nil {
  110. utils.SendErrorResponse(w, "Invalid uuid given")
  111. return
  112. }
  113. // check if endpoint is here
  114. data, isExist := g.checkIfExternalEndpointExist(uuid)
  115. if !isExist {
  116. utils.SendErrorResponse(w, "UUID does not exists in the database!")
  117. return
  118. }
  119. // make sure user cant see other's endpoint
  120. if data.Username != userInfo.Username {
  121. utils.SendErrorResponse(w, "Permission denied")
  122. return
  123. }
  124. // delete record
  125. sysdb.Delete("external_agi", uuid)
  126. utils.SendOK(w)
  127. }
  128. func (g *Gateway) ListExternalEndpoint(w http.ResponseWriter, r *http.Request) {
  129. userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
  130. if err != nil {
  131. utils.SendErrorResponse(w, "User not logged in")
  132. return
  133. }
  134. // get db
  135. sysdb := g.Option.UserHandler.GetDatabase()
  136. if !sysdb.TableExists("external_agi") {
  137. sysdb.NewTable("external_agi")
  138. }
  139. // declare variable for return
  140. dataFromDB := make(map[string]endpointFormat)
  141. // O(n) method to do the lookup
  142. entries, err := sysdb.ListTable("external_agi")
  143. if err != nil {
  144. utils.SendErrorResponse(w, "Invalid table")
  145. return
  146. }
  147. for _, keypairs := range entries {
  148. //Decode the string
  149. var dataFromResult endpointFormat
  150. result := ""
  151. uuid := string(keypairs[0])
  152. json.Unmarshal(keypairs[1], &result)
  153. //fmt.Println(result)
  154. json.Unmarshal([]byte(result), &dataFromResult)
  155. if dataFromResult.Username == userInfo.Username {
  156. dataFromDB[uuid] = dataFromResult
  157. }
  158. }
  159. // marhsal and return
  160. returnJson, err := json.Marshal(dataFromDB)
  161. if err != nil {
  162. utils.SendErrorResponse(w, "Invalid JSON: "+err.Error())
  163. return
  164. }
  165. utils.SendJSONResponse(w, string(returnJson))
  166. }
  167. func (g *Gateway) checkIfExternalEndpointExist(uuid string) (endpointFormat, bool) {
  168. // get db
  169. sysdb := g.Option.UserHandler.GetDatabase()
  170. if !sysdb.TableExists("external_agi") {
  171. sysdb.NewTable("external_agi")
  172. }
  173. var dat endpointFormat
  174. // check if key exist
  175. if !sysdb.KeyExists("external_agi", uuid) {
  176. return dat, false
  177. }
  178. // if yes then return the value
  179. jsonData := ""
  180. sysdb.Read("external_agi", uuid, &jsonData)
  181. json.Unmarshal([]byte(jsonData), &dat)
  182. return dat, true
  183. }