123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- package agi
- import (
- "encoding/json"
- "log"
- "net/http"
- "path/filepath"
- "strings"
- uuid "github.com/satori/go.uuid"
- "imuslab.com/arozos/mod/agi/static"
- "imuslab.com/arozos/mod/utils"
- )
- type endpointFormat struct {
- Username string `json:"username"`
- Path string `json:"path"`
- }
- // Handle request from EXTERNAL RESTFUL API
- func (g *Gateway) ExtAPIHandler(w http.ResponseWriter, r *http.Request) {
- // get db
- sysdb := g.Option.UserHandler.GetDatabase()
- if !sysdb.TableExists("external_agi") {
- http.Error(w, "invalid API request", http.StatusBadRequest)
- return
- }
- // get the request URI from the r.URL
- requestURI := filepath.ToSlash(filepath.Clean(r.URL.Path))
- subpathElements := strings.Split(requestURI[1:], "/")
- // check if it contains only two part, [rexec uuid]
- if len(subpathElements) != 3 {
- http.Error(w, "invalid API request", http.StatusBadRequest)
- return
- }
- // check if UUID exists in the database
- // get the info from the database
- data, isExist := g.checkIfExternalEndpointExist(subpathElements[2])
- if !isExist {
- http.Error(w, "malformed request: invalid UUID given", http.StatusBadRequest)
- return
- }
- usernameFromDb := data.Username
- pathFromDb := data.Path
- // get the userinfo and the realPath
- userInfo, err := g.Option.UserHandler.GetUserInfoFromUsername(usernameFromDb)
- if err != nil {
- http.Error(w, "invalid request: API author no longer exists", http.StatusBadRequest)
- return
- }
- fsh, realPath, err := static.VirtualPathToRealPath(pathFromDb, userInfo)
- if err != nil {
- http.Error(w, "invalid request: backend script path cannot be resolved", http.StatusBadRequest)
- return
- }
- //Check if the script file still exists
- if !fsh.FileSystemAbstraction.FileExists(realPath) {
- //Script no longer exists
- log.Println("[Remote AGI] ", pathFromDb, " cannot be found on "+realPath)
- http.Error(w, "invalid request: backend script not exists", http.StatusBadRequest)
- return
- }
- // execute!
- //start := time.Now()
- //g.ExecuteAGIScript(scriptContent, "", "", w, r, userInfo)
- result, err := g.ExecuteAGIScriptAsUser(fsh, realPath, userInfo, w, r)
- //duration := time.Since(start)
- if err != nil {
- log.Println("[Remote AGI] ", pathFromDb, " failed to execute", err.Error())
- utils.SendErrorResponse(w, err.Error())
- return
- }
- w.Write([]byte(result))
- //log.Println("[Remote AGI] IP:", r.RemoteAddr, "executed the script ", pathFromDb, "on behalf of", userInfo.Username, "with total duration:", duration)
- }
- func (g *Gateway) AddExternalEndPoint(w http.ResponseWriter, r *http.Request) {
- userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
- if err != nil {
- utils.SendErrorResponse(w, "User not logged in")
- return
- }
- // get db
- sysdb := g.Option.UserHandler.GetDatabase()
- if !sysdb.TableExists("external_agi") {
- sysdb.NewTable("external_agi")
- }
- var dat endpointFormat
- // uuid: [path, id]
- path, err := utils.GetPara(r, "path")
- if err != nil {
- utils.SendErrorResponse(w, "Invalid path given")
- return
- }
- // put the data in then marshal
- id := uuid.NewV4().String()
- dat.Path = path
- dat.Username = userInfo.Username
- jsonStr, err := json.Marshal(dat)
- if err != nil {
- utils.SendErrorResponse(w, "Invalid JSON string: "+err.Error())
- return
- }
- sysdb.Write("external_agi", id, string(jsonStr))
- // send the uuid to frontend
- utils.SendJSONResponse(w, "\""+id+"\"")
- }
- func (g *Gateway) RemoveExternalEndPoint(w http.ResponseWriter, r *http.Request) {
- userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
- if err != nil {
- utils.SendErrorResponse(w, "User not logged in")
- return
- }
- // get db
- sysdb := g.Option.UserHandler.GetDatabase()
- if !sysdb.TableExists("external_agi") {
- sysdb.NewTable("external_agi")
- }
- // get path
- uuid, err := utils.GetPara(r, "uuid")
- if err != nil {
- utils.SendErrorResponse(w, "Invalid uuid given")
- return
- }
- // check if endpoint is here
- data, isExist := g.checkIfExternalEndpointExist(uuid)
- if !isExist {
- utils.SendErrorResponse(w, "UUID does not exists in the database!")
- return
- }
- // make sure user cant see other's endpoint
- if data.Username != userInfo.Username {
- utils.SendErrorResponse(w, "Permission denied")
- return
- }
- // delete record
- sysdb.Delete("external_agi", uuid)
- utils.SendOK(w)
- }
- func (g *Gateway) ListExternalEndpoint(w http.ResponseWriter, r *http.Request) {
- userInfo, err := g.Option.UserHandler.GetUserInfoFromRequest(w, r)
- if err != nil {
- utils.SendErrorResponse(w, "User not logged in")
- return
- }
- // get db
- sysdb := g.Option.UserHandler.GetDatabase()
- if !sysdb.TableExists("external_agi") {
- sysdb.NewTable("external_agi")
- }
- // declare variable for return
- dataFromDB := make(map[string]endpointFormat)
- // O(n) method to do the lookup
- entries, err := sysdb.ListTable("external_agi")
- if err != nil {
- utils.SendErrorResponse(w, "Invalid table")
- return
- }
- for _, keypairs := range entries {
- //Decode the string
- var dataFromResult endpointFormat
- result := ""
- uuid := string(keypairs[0])
- json.Unmarshal(keypairs[1], &result)
- //fmt.Println(result)
- json.Unmarshal([]byte(result), &dataFromResult)
- if dataFromResult.Username == userInfo.Username {
- dataFromDB[uuid] = dataFromResult
- }
- }
- // marhsal and return
- returnJson, err := json.Marshal(dataFromDB)
- if err != nil {
- utils.SendErrorResponse(w, "Invalid JSON: "+err.Error())
- return
- }
- utils.SendJSONResponse(w, string(returnJson))
- }
- func (g *Gateway) checkIfExternalEndpointExist(uuid string) (endpointFormat, bool) {
- // get db
- sysdb := g.Option.UserHandler.GetDatabase()
- if !sysdb.TableExists("external_agi") {
- sysdb.NewTable("external_agi")
- }
- var dat endpointFormat
- // check if key exist
- if !sysdb.KeyExists("external_agi", uuid) {
- return dat, false
- }
- // if yes then return the value
- jsonData := ""
- sysdb.Read("external_agi", uuid, &jsonData)
- json.Unmarshal([]byte(jsonData), &dat)
- return dat, true
- }
|