console.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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) > 0 && chunk[0] == "access" {
  161. //Handle emergency situation where the user is blocked by himself
  162. if matchSubfix(chunk, []string{"access", "whitelist", "disable"}, 3, "") {
  163. //Disable whitelist
  164. authAgent.WhitelistManager.SetWhitelistEnabled(false)
  165. return "Whitelist Disabled"
  166. } else if matchSubfix(chunk, []string{"access", "whitelist", "enable"}, 3, "") {
  167. //Enable whitelist
  168. authAgent.WhitelistManager.SetWhitelistEnabled(true)
  169. return "Whitelist Enabled"
  170. } else if matchSubfix(chunk, []string{"access", "whitelist", "add"}, 4, "access whitelist add {ip_range}") {
  171. err = authAgent.WhitelistManager.SetWhitelist(chunk[3])
  172. if err != nil {
  173. return err.Error()
  174. }
  175. return "OK"
  176. } else if matchSubfix(chunk, []string{"access", "whitelist", "del"}, 4, "access whitelist del {ip_range}") {
  177. err = authAgent.WhitelistManager.UnsetWhitelist(chunk[3])
  178. if err != nil {
  179. return err.Error()
  180. }
  181. return "OK"
  182. } else if matchSubfix(chunk, []string{"access", "blacklist", "enable"}, 3, "") {
  183. //Enable blacklist
  184. authAgent.WhitelistManager.SetWhitelistEnabled(true)
  185. return "Blacklist Enabled"
  186. } else if matchSubfix(chunk, []string{"access", "blacklist", "disable"}, 3, "") {
  187. //Disable blacklist
  188. authAgent.BlacklistManager.SetBlacklistEnabled(false)
  189. return "Blacklist Disabled"
  190. } else {
  191. return "[Whitelist / Blacklist Console Control API] \nUsage: access {whitelist/blacklist} {action} {data}"
  192. }
  193. } else if len(chunk) == 1 && chunk[0] == "stop" {
  194. //Stopping the server
  195. fmt.Println("Shutting down aroz online system by terminal request")
  196. executeShutdownSequence()
  197. }
  198. return "Invalid Command. Given: '" + strings.Join(chunk, " ") + "'"
  199. }
  200. //Check if the given line input match the requirement
  201. func matchSubfix(chunk []string, match []string, minlength int, usageExample string) bool {
  202. matching := true
  203. //Check if the chunk contains minmium length of the command request
  204. if len(chunk) >= len(match) {
  205. for i, cchunk := range match {
  206. if chunk[i] != cchunk {
  207. matching = false
  208. }
  209. }
  210. } else {
  211. matching = false
  212. }
  213. if len(chunk)-minlength == -1 && chunk[len(chunk)-1] == match[len(match)-1] {
  214. fmt.Println("Paramter missing. Usage: " + usageExample)
  215. return false
  216. }
  217. return matching
  218. }
  219. func parseCommandLine(command string) ([]string, error) {
  220. var args []string
  221. state := "start"
  222. current := ""
  223. quote := "\""
  224. escapeNext := true
  225. for i := 0; i < len(command); i++ {
  226. c := command[i]
  227. if state == "quotes" {
  228. if string(c) != quote {
  229. current += string(c)
  230. } else {
  231. args = append(args, current)
  232. current = ""
  233. state = "start"
  234. }
  235. continue
  236. }
  237. if escapeNext {
  238. current += string(c)
  239. escapeNext = false
  240. continue
  241. }
  242. if c == '\\' {
  243. escapeNext = true
  244. continue
  245. }
  246. if c == '"' || c == '\'' {
  247. state = "quotes"
  248. quote = string(c)
  249. continue
  250. }
  251. if state == "arg" {
  252. if c == ' ' || c == '\t' {
  253. args = append(args, current)
  254. current = ""
  255. state = "start"
  256. } else {
  257. current += string(c)
  258. }
  259. continue
  260. }
  261. if c != ' ' && c != '\t' {
  262. state = "arg"
  263. current += string(c)
  264. }
  265. }
  266. if state == "quotes" {
  267. return []string{}, errors.New(fmt.Sprintf("Unclosed quote in command line: %s", command))
  268. }
  269. if current != "" {
  270. args = append(args, current)
  271. }
  272. return args, nil
  273. }