console.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "strings"
  8. )
  9. //Handle console command from the console module
  10. func consoleCommandHandler(input string) string {
  11. //chunk := strings.Split(input, " ");
  12. chunk, err := parseCommandLine(input)
  13. if err != nil {
  14. return err.Error()
  15. }
  16. if len(chunk) > 0 && chunk[0] == "auth" {
  17. if matchSubfix(chunk, []string{"auth", "new"}, 4, "auth new {username} {password}") {
  18. return "Creating a new user " + chunk[2] + " with password " + chunk[3]
  19. } else if matchSubfix(chunk, []string{"auth", "dump"}, 4, "auth dump {filename}.csv") {
  20. filename := chunk[2]
  21. fmt.Println("Dumping user list to " + filename + " csv file")
  22. csv := authAgent.ExportUserListAsCSV()
  23. err := ioutil.WriteFile(filename, []byte(csv), 0755)
  24. if err != nil {
  25. return err.Error()
  26. }
  27. return "OK"
  28. }
  29. } else if len(chunk) > 0 && chunk[0] == "permission" {
  30. if matchSubfix(chunk, []string{"permission", "list"}, 2, "") {
  31. fmt.Println("> ", permissionHandler.PermissionGroups)
  32. return "OK"
  33. } else if matchSubfix(chunk, []string{"permission", "user"}, 3, "permission user {username}") {
  34. username := chunk[2]
  35. group, _ := permissionHandler.GetUsersPermissionGroup(username)
  36. for _, thisGroup := range group {
  37. fmt.Println(thisGroup)
  38. }
  39. return "OK"
  40. } else if matchSubfix(chunk, []string{"permission", "group"}, 3, "permission group {groupname}") {
  41. groupname := chunk[2]
  42. groups := permissionHandler.PermissionGroups
  43. for _, thisGroup := range groups {
  44. if thisGroup.Name == groupname {
  45. fmt.Println(thisGroup)
  46. }
  47. }
  48. return "OK"
  49. } else if matchSubfix(chunk, []string{"permission", "getinterface"}, 3, "permission getinterface {username}") {
  50. //Get the list of interface module for this user
  51. userinfo, err := userHandler.GetUserInfoFromUsername(chunk[2])
  52. if err != nil {
  53. return err.Error()
  54. }
  55. return strings.Join(userinfo.GetInterfaceModules(), ",")
  56. }
  57. } else if len(chunk) > 0 && chunk[0] == "quota" {
  58. if matchSubfix(chunk, []string{"quota", "user"}, 3, "quota user {username}") {
  59. userinfo, err := userHandler.GetUserInfoFromUsername(chunk[2])
  60. if err != nil {
  61. return err.Error()
  62. }
  63. fmt.Println("> "+"User Quota: ", userinfo.StorageQuota.UsedStorageQuota, "/", userinfo.StorageQuota.GetUserStorageQuota(), "bytes")
  64. return "OK"
  65. }
  66. } else if len(chunk) > 0 && chunk[0] == "database" {
  67. if matchSubfix(chunk, []string{"database", "dump"}, 3, "database dump {filename}") {
  68. //Dump the database to file
  69. return "WIP"
  70. } else if matchSubfix(chunk, []string{"database", "list", "tables"}, 3, "") {
  71. //List all opened tables
  72. sysdb.Tables.Range(func(k, v interface{}) bool {
  73. fmt.Println(k.(string))
  74. return true
  75. })
  76. return "OK"
  77. } else if matchSubfix(chunk, []string{"database", "view"}, 3, "database list {tablename}") {
  78. //List everything in this table
  79. tableList := []string{}
  80. sysdb.Tables.Range(func(k, v interface{}) bool {
  81. tableList = append(tableList, k.(string))
  82. return true
  83. })
  84. if !inArray(tableList, chunk[2]) {
  85. return "Table not exists"
  86. } else if chunk[2] == "auth" {
  87. return "You cannot view this database table"
  88. }
  89. entries, err := sysdb.ListTable(chunk[2])
  90. if err != nil {
  91. return err.Error()
  92. }
  93. for _, keypairs := range entries {
  94. fmt.Println("> " + string(keypairs[0]) + ":" + string(keypairs[1]))
  95. }
  96. fmt.Println("Total Entry Count: ", len(entries))
  97. return "OK"
  98. }
  99. } else if len(chunk) > 0 && chunk[0] == "user" {
  100. if matchSubfix(chunk, []string{"user", "object", "dump"}, 4, "user object dump {username}") {
  101. //Dump the given user object as json
  102. userinfo, err := userHandler.GetUserInfoFromUsername(chunk[3])
  103. if err != nil {
  104. return err.Error()
  105. }
  106. jsonString, _ := json.Marshal(userinfo)
  107. return string(jsonString)
  108. } else if matchSubfix(chunk, []string{"user", "quota"}, 3, "user quota {username}") {
  109. //List user quota of the given username
  110. userinfo, err := userHandler.GetUserInfoFromUsername(chunk[2])
  111. if err != nil {
  112. return err.Error()
  113. }
  114. fmt.Println(userinfo.StorageQuota.UsedStorageQuota, "/", userinfo.StorageQuota.TotalStorageQuota)
  115. return "OK"
  116. }
  117. } else if len(chunk) > 0 && chunk[0] == "storage" {
  118. if matchSubfix(chunk, []string{"storage", "list", "basepool"}, 3, "") {
  119. //Dump the base storage pool
  120. jsonString, _ := json.Marshal(userHandler.GetStoragePool())
  121. return string(jsonString)
  122. }
  123. } else if len(chunk) > 0 && chunk[0] == "scan" {
  124. if matchSubfix(chunk, []string{"scan", "all"}, 2, "") {
  125. //scan all nearby arozos units
  126. fmt.Println("Scanning (Should take around 10s)")
  127. hosts := MDNS.Scan(10, "")
  128. for _, host := range hosts {
  129. fmt.Println(host)
  130. }
  131. return "OK"
  132. } else if matchSubfix(chunk, []string{"scan", "aroz"}, 2, "") || matchSubfix(chunk, []string{"scan", "arozos"}, 2, "") {
  133. //scan all nearby arozos units
  134. fmt.Println("Scanning nearybe ArozOS Hosts (Should take around 10s)")
  135. hosts := MDNS.Scan(10, "arozos.com")
  136. for _, host := range hosts {
  137. fmt.Println(host)
  138. }
  139. return "OK"
  140. }
  141. } else if len(chunk) > 0 && chunk[0] == "find" {
  142. if matchSubfix(chunk, []string{"find", "module"}, 3, "list module {modulename}") {
  143. //Display all loaded modules
  144. for _, module := range moduleHandler.LoadedModule {
  145. if strings.ToLower(module.Name) == strings.ToLower(chunk[2]) {
  146. jsonString, _ := json.Marshal(module)
  147. return string(jsonString)
  148. }
  149. }
  150. return string("Module not found")
  151. } else if matchSubfix(chunk, []string{"find", "modules"}, 2, "") {
  152. //Display all loaded modules
  153. jsonString, _ := json.Marshal(moduleHandler.LoadedModule)
  154. return string(jsonString)
  155. } else if matchSubfix(chunk, []string{"find", "subservices"}, 2, "") {
  156. //Display all loaded subservices
  157. fmt.Println(ssRouter.RunningSubService)
  158. return "OK"
  159. }
  160. } else if len(chunk) == 1 && chunk[0] == "stop" {
  161. //Stopping the server
  162. fmt.Println("Shutting down aroz online system by terminal request")
  163. executeShutdownSequence()
  164. }
  165. return "Invalid Command. Given: '" + strings.Join(chunk, " ") + "'"
  166. }
  167. //Check if the given line input match the requirement
  168. func matchSubfix(chunk []string, match []string, minlength int, usageExample string) bool {
  169. matching := true
  170. //Check if the chunk contains minmium length of the command request
  171. if len(chunk) >= len(match) {
  172. for i, cchunk := range match {
  173. if chunk[i] != cchunk {
  174. matching = false
  175. }
  176. }
  177. } else {
  178. matching = false
  179. }
  180. if len(chunk)-minlength == -1 && chunk[len(chunk)-1] == match[len(match)-1] {
  181. fmt.Println("Paramter missing. Usage: " + usageExample)
  182. return false
  183. }
  184. return matching
  185. }
  186. func parseCommandLine(command string) ([]string, error) {
  187. var args []string
  188. state := "start"
  189. current := ""
  190. quote := "\""
  191. escapeNext := true
  192. for i := 0; i < len(command); i++ {
  193. c := command[i]
  194. if state == "quotes" {
  195. if string(c) != quote {
  196. current += string(c)
  197. } else {
  198. args = append(args, current)
  199. current = ""
  200. state = "start"
  201. }
  202. continue
  203. }
  204. if escapeNext {
  205. current += string(c)
  206. escapeNext = false
  207. continue
  208. }
  209. if c == '\\' {
  210. escapeNext = true
  211. continue
  212. }
  213. if c == '"' || c == '\'' {
  214. state = "quotes"
  215. quote = string(c)
  216. continue
  217. }
  218. if state == "arg" {
  219. if c == ' ' || c == '\t' {
  220. args = append(args, current)
  221. current = ""
  222. state = "start"
  223. } else {
  224. current += string(c)
  225. }
  226. continue
  227. }
  228. if c != ' ' && c != '\t' {
  229. state = "arg"
  230. current += string(c)
  231. }
  232. }
  233. if state == "quotes" {
  234. return []string{}, errors.New(fmt.Sprintf("Unclosed quote in command line: %s", command))
  235. }
  236. if current != "" {
  237. args = append(args, current)
  238. }
  239. return args, nil
  240. }