userFunc.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. package agi
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "path/filepath"
  9. "github.com/robertkrimen/otto"
  10. "imuslab.com/arozos/mod/filesystem"
  11. user "imuslab.com/arozos/mod/user"
  12. )
  13. //Define path translation function
  14. func virtualPathToRealPath(vpath string, u *user.User) (*filesystem.FileSystemHandler, string, error) {
  15. fsh, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
  16. if err != nil {
  17. return nil, "", err
  18. }
  19. rpath, err := fsh.FileSystemAbstraction.VirtualPathToRealPath(vpath, u.Username)
  20. if err != nil {
  21. return nil, "", err
  22. }
  23. return fsh, rpath, nil
  24. }
  25. func realpathToVirtualpath(fsh *filesystem.FileSystemHandler, path string, u *user.User) (string, error) {
  26. return fsh.FileSystemAbstraction.RealPathToVirtualPath(path, u.Username)
  27. }
  28. //Inject user based functions into the virtual machine
  29. func (g *Gateway) injectUserFunctions(vm *otto.Otto, scriptFile string, scriptScope string, u *user.User, w http.ResponseWriter, r *http.Request) {
  30. username := u.Username
  31. vm.Set("USERNAME", username)
  32. vm.Set("USERICON", u.GetUserIcon())
  33. vm.Set("USERQUOTA_TOTAL", u.StorageQuota.TotalStorageQuota)
  34. vm.Set("USERQUOTA_USED", u.StorageQuota.UsedStorageQuota)
  35. vm.Set("USER_VROOTS", u.GetAllAccessibleFileSystemHandler())
  36. vm.Set("USER_MODULES", u.GetUserAccessibleModules())
  37. //File system and path related
  38. vm.Set("decodeVirtualPath", func(call otto.FunctionCall) otto.Value {
  39. log.Println("Call to deprecated function decodeVirtualPath")
  40. return otto.FalseValue()
  41. })
  42. vm.Set("decodeAbsoluteVirtualPath", func(call otto.FunctionCall) otto.Value {
  43. log.Println("Call to deprecated function decodeAbsoluteVirtualPath")
  44. return otto.FalseValue()
  45. })
  46. vm.Set("encodeRealPath", func(call otto.FunctionCall) otto.Value {
  47. log.Println("Call to deprecated function encodeRealPath")
  48. return otto.FalseValue()
  49. })
  50. //Check if a given virtual path is readonly
  51. vm.Set("pathCanWrite", func(call otto.FunctionCall) otto.Value {
  52. vpath, _ := call.Argument(0).ToString()
  53. if u.CanWrite(vpath) {
  54. return otto.TrueValue()
  55. } else {
  56. return otto.FalseValue()
  57. }
  58. })
  59. //Permission related
  60. vm.Set("getUserPermissionGroup", func(call otto.FunctionCall) otto.Value {
  61. groupinfo := u.GetUserPermissionGroup()
  62. jsonString, _ := json.Marshal(groupinfo)
  63. reply, _ := vm.ToValue(string(jsonString))
  64. return reply
  65. })
  66. vm.Set("userIsAdmin", func(call otto.FunctionCall) otto.Value {
  67. reply, _ := vm.ToValue(u.IsAdmin())
  68. return reply
  69. })
  70. //User Account Related
  71. /*
  72. userExists(username);
  73. */
  74. vm.Set("userExists", func(call otto.FunctionCall) otto.Value {
  75. if u.IsAdmin() {
  76. //Get username from function paramter
  77. username, err := call.Argument(0).ToString()
  78. if err != nil || username == "undefined" {
  79. g.raiseError(errors.New("username is undefined"))
  80. reply, _ := vm.ToValue(nil)
  81. return reply
  82. }
  83. //Check if user exists
  84. userExists := u.Parent().GetAuthAgent().UserExists(username)
  85. if userExists {
  86. return otto.TrueValue()
  87. } else {
  88. return otto.FalseValue()
  89. }
  90. } else {
  91. g.raiseError(errors.New("Permission Denied: userExists require admin permission"))
  92. return otto.FalseValue()
  93. }
  94. })
  95. /*
  96. createUser(username, password, defaultGroup);
  97. */
  98. vm.Set("createUser", func(call otto.FunctionCall) otto.Value {
  99. if u.IsAdmin() {
  100. //Ok. Create user base on given information
  101. username, err := call.Argument(0).ToString()
  102. if err != nil || username == "undefined" {
  103. g.raiseError(errors.New("username is undefined"))
  104. reply, _ := vm.ToValue(false)
  105. return reply
  106. }
  107. password, err := call.Argument(1).ToString()
  108. if err != nil || password == "undefined" {
  109. g.raiseError(errors.New("password is undefined"))
  110. reply, _ := vm.ToValue(false)
  111. return reply
  112. }
  113. defaultGroup, err := call.Argument(2).ToString()
  114. if err != nil || defaultGroup == "undefined" {
  115. g.raiseError(errors.New("defaultGroup is undefined"))
  116. reply, _ := vm.ToValue(false)
  117. return reply
  118. }
  119. //Check if username already used
  120. userExists := u.Parent().GetAuthAgent().UserExists(username)
  121. if userExists {
  122. g.raiseError(errors.New("Username already exists"))
  123. reply, _ := vm.ToValue(false)
  124. return reply
  125. }
  126. //Check if the given permission group exists
  127. groupExists := u.Parent().GetPermissionHandler().GroupExists(defaultGroup)
  128. if !groupExists {
  129. g.raiseError(errors.New(defaultGroup + " user-group not exists"))
  130. reply, _ := vm.ToValue(false)
  131. return reply
  132. }
  133. //Create the user
  134. err = u.Parent().GetAuthAgent().CreateUserAccount(username, password, []string{defaultGroup})
  135. if err != nil {
  136. g.raiseError(errors.New("User creation failed: " + err.Error()))
  137. reply, _ := vm.ToValue(false)
  138. return reply
  139. }
  140. return otto.TrueValue()
  141. } else {
  142. g.raiseError(errors.New("Permission Denied: createUser require admin permission"))
  143. return otto.FalseValue()
  144. }
  145. })
  146. vm.Set("editUser", func(call otto.FunctionCall) otto.Value {
  147. if u.IsAdmin() {
  148. } else {
  149. g.raiseError(errors.New("Permission Denied: editUser require admin permission"))
  150. return otto.FalseValue()
  151. }
  152. //libname, err := call.Argument(0).ToString()
  153. return otto.FalseValue()
  154. })
  155. /*
  156. removeUser(username)
  157. */
  158. vm.Set("removeUser", func(call otto.FunctionCall) otto.Value {
  159. if u.IsAdmin() {
  160. //Get username from function paramters
  161. username, err := call.Argument(0).ToString()
  162. if err != nil || username == "undefined" {
  163. g.raiseError(errors.New("username is undefined"))
  164. reply, _ := vm.ToValue(false)
  165. return reply
  166. }
  167. //Check if the user exists
  168. userExists := u.Parent().GetAuthAgent().UserExists(username)
  169. if !userExists {
  170. g.raiseError(errors.New(username + " not exists"))
  171. reply, _ := vm.ToValue(false)
  172. return reply
  173. }
  174. //User exists. Remove it from the system
  175. err = u.Parent().GetAuthAgent().UnregisterUser(username)
  176. if err != nil {
  177. g.raiseError(errors.New("User removal failed: " + err.Error()))
  178. reply, _ := vm.ToValue(false)
  179. return reply
  180. }
  181. return otto.TrueValue()
  182. } else {
  183. g.raiseError(errors.New("Permission Denied: removeUser require admin permission"))
  184. return otto.FalseValue()
  185. }
  186. })
  187. vm.Set("getUserInfoByName", func(call otto.FunctionCall) otto.Value {
  188. //libname, err := call.Argument(0).ToString()
  189. if u.IsAdmin() {
  190. } else {
  191. g.raiseError(errors.New("Permission Denied: getUserInfoByName require admin permission"))
  192. return otto.FalseValue()
  193. }
  194. return otto.TrueValue()
  195. })
  196. //Allow real time library includsion into the virtual machine
  197. vm.Set("requirelib", func(call otto.FunctionCall) otto.Value {
  198. libname, err := call.Argument(0).ToString()
  199. if err != nil {
  200. g.raiseError(err)
  201. reply, _ := vm.ToValue(nil)
  202. return reply
  203. }
  204. //Handle special case on high level libraries
  205. if libname == "websocket" && w != nil && r != nil {
  206. g.injectWebSocketFunctions(vm, u, w, r)
  207. return otto.TrueValue()
  208. } else {
  209. //Check if the library name exists. If yes, run the initiation script on the vm
  210. if entryPoint, ok := g.LoadedAGILibrary[libname]; ok {
  211. entryPoint(vm, u)
  212. return otto.TrueValue()
  213. } else {
  214. //Lib not exists
  215. log.Println("Lib not found: " + libname)
  216. return otto.FalseValue()
  217. }
  218. }
  219. //Unknown status
  220. return otto.FalseValue()
  221. })
  222. //Execd (Execute & detach) run another script and detach the execution
  223. vm.Set("execd", func(call otto.FunctionCall) otto.Value {
  224. //Check if the pkg is already registered
  225. scriptName, err := call.Argument(0).ToString()
  226. if err != nil {
  227. g.raiseError(err)
  228. return otto.FalseValue()
  229. }
  230. //Carry the payload to the forked process if there are any
  231. payload, _ := call.Argument(1).ToString()
  232. //Check if the script file exists
  233. targetScriptPath := filepath.ToSlash(filepath.Join(filepath.Dir(scriptFile), scriptName))
  234. if !fileExists(targetScriptPath) {
  235. g.raiseError(errors.New("*AGI* Target path not exists!"))
  236. return otto.FalseValue()
  237. }
  238. //Run the script
  239. scriptContent, _ := ioutil.ReadFile(targetScriptPath)
  240. go func() {
  241. //Create a new VM to execute the script (also for isolation)
  242. vm := otto.New()
  243. //Inject standard libs into the vm
  244. g.injectStandardLibs(vm, scriptFile, scriptScope)
  245. g.injectUserFunctions(vm, scriptFile, scriptScope, u, w, r)
  246. vm.Set("PARENT_DETACHED", true)
  247. vm.Set("PARENT_PAYLOAD", payload)
  248. _, err = vm.Run(string(scriptContent))
  249. if err != nil {
  250. //Script execution failed
  251. log.Println("Script Execution Failed: ", err.Error())
  252. g.raiseError(err)
  253. }
  254. }()
  255. return otto.TrueValue()
  256. })
  257. }