123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- package main
- import (
- "encoding/json"
- "errors"
- "fmt"
- "os"
- "strings"
- "imuslab.com/arozos/mod/utils"
- )
- // Handle console command from the console module
- func consoleCommandHandler(input string) string {
- //chunk := strings.Split(input, " ");
- chunk, err := parseCommandLine(input)
- if err != nil {
- return err.Error()
- }
- if len(chunk) > 0 && chunk[0] == "auth" {
- if matchSubfix(chunk, []string{"auth", "new"}, 4, "auth new {username} {password}") {
- return "Creating a new user " + chunk[2] + " with password " + chunk[3]
- } else if matchSubfix(chunk, []string{"auth", "dump"}, 4, "auth dump {filename}.csv") {
- filename := chunk[2]
- fmt.Println("Dumping user list to " + filename + " csv file")
- csv := authAgent.ExportUserListAsCSV()
- err := os.WriteFile(filename, []byte(csv), 0755)
- if err != nil {
- return err.Error()
- }
- return "OK"
- }
- } else if len(chunk) > 0 && chunk[0] == "permission" {
- if matchSubfix(chunk, []string{"permission", "list"}, 2, "") {
- fmt.Println("> ", permissionHandler.PermissionGroups)
- return "OK"
- } else if matchSubfix(chunk, []string{"permission", "user"}, 3, "permission user {username}") {
- username := chunk[2]
- group, _ := permissionHandler.GetUsersPermissionGroup(username)
- for _, thisGroup := range group {
- fmt.Println(thisGroup)
- }
- return "OK"
- } else if matchSubfix(chunk, []string{"permission", "group"}, 3, "permission group {groupname}") {
- groupname := chunk[2]
- groups := permissionHandler.PermissionGroups
- for _, thisGroup := range groups {
- if thisGroup.Name == groupname {
- fmt.Println(thisGroup)
- }
- }
- return "OK"
- } else if matchSubfix(chunk, []string{"permission", "getinterface"}, 3, "permission getinterface {username}") {
- //Get the list of interface module for this user
- userinfo, err := userHandler.GetUserInfoFromUsername(chunk[2])
- if err != nil {
- return err.Error()
- }
- return strings.Join(userinfo.GetInterfaceModules(), ",")
- }
- } else if len(chunk) > 0 && chunk[0] == "quota" {
- if matchSubfix(chunk, []string{"quota", "user"}, 3, "quota user {username}") {
- userinfo, err := userHandler.GetUserInfoFromUsername(chunk[2])
- if err != nil {
- return err.Error()
- }
- fmt.Println("> "+"User Quota: ", userinfo.StorageQuota.UsedStorageQuota, "/", userinfo.StorageQuota.GetUserStorageQuota(), "bytes")
- return "OK"
- }
- } else if len(chunk) > 0 && chunk[0] == "database" {
- if matchSubfix(chunk, []string{"database", "dump"}, 3, "database dump {filename}") {
- //Dump the database to file
- return "WIP"
- } else if matchSubfix(chunk, []string{"database", "list", "tables"}, 3, "") {
- //List all opened tables
- sysdb.Tables.Range(func(k, v interface{}) bool {
- fmt.Println(k.(string))
- return true
- })
- return "OK"
- } else if matchSubfix(chunk, []string{"database", "view"}, 3, "database list {tablename}") {
- //List everything in this table
- tableList := []string{}
- sysdb.Tables.Range(func(k, v interface{}) bool {
- tableList = append(tableList, k.(string))
- return true
- })
- if !utils.StringInArray(tableList, chunk[2]) {
- return "Table not exists"
- } else if chunk[2] == "auth" {
- return "You cannot view this database table"
- }
- entries, err := sysdb.ListTable(chunk[2])
- if err != nil {
- return err.Error()
- }
- for _, keypairs := range entries {
- fmt.Println("> " + string(keypairs[0]) + ":" + string(keypairs[1]))
- }
- fmt.Println("Total Entry Count: ", len(entries))
- return "OK"
- }
- } else if len(chunk) > 0 && chunk[0] == "user" {
- if matchSubfix(chunk, []string{"user", "object", "dump"}, 4, "user object dump {username}") {
- //Dump the given user object as json
- userinfo, err := userHandler.GetUserInfoFromUsername(chunk[3])
- if err != nil {
- return err.Error()
- }
- jsonString, _ := json.Marshal(userinfo)
- return string(jsonString)
- } else if matchSubfix(chunk, []string{"user", "quota"}, 3, "user quota {username}") {
- //List user quota of the given username
- userinfo, err := userHandler.GetUserInfoFromUsername(chunk[2])
- if err != nil {
- return err.Error()
- }
- fmt.Println(userinfo.StorageQuota.UsedStorageQuota, "/", userinfo.StorageQuota.TotalStorageQuota)
- return "OK"
- }
- } else if len(chunk) > 0 && chunk[0] == "storage" {
- if matchSubfix(chunk, []string{"storage", "list", "basepool"}, 3, "") {
- //Dump the base storage pool
- jsonString, _ := json.Marshal(userHandler.GetStoragePool())
- return string(jsonString)
- }
- } else if len(chunk) > 0 && chunk[0] == "scan" {
- if matchSubfix(chunk, []string{"scan", "all"}, 2, "") {
- //scan all nearby arozos units
- fmt.Println("Scanning (Should take around 10s)")
- hosts := MDNS.Scan(10, "")
- for _, host := range hosts {
- fmt.Println(host)
- }
- return "OK"
- } else if matchSubfix(chunk, []string{"scan", "aroz"}, 2, "") || matchSubfix(chunk, []string{"scan", "arozos"}, 2, "") {
- //scan all nearby arozos units
- fmt.Println("Scanning nearybe ArozOS Hosts (Should take around 10s)")
- hosts := MDNS.Scan(10, "arozos.com")
- for _, host := range hosts {
- fmt.Println(host)
- }
- return "OK"
- }
- } else if len(chunk) > 0 && chunk[0] == "find" {
- if matchSubfix(chunk, []string{"find", "module"}, 3, "list module {modulename}") {
- //Display all loaded modules
- for _, module := range moduleHandler.LoadedModule {
- if strings.ToLower(module.Name) == strings.ToLower(chunk[2]) {
- jsonString, _ := json.Marshal(module)
- return string(jsonString)
- }
- }
- return string("Module not found")
- } else if matchSubfix(chunk, []string{"find", "modules"}, 2, "") {
- //Display all loaded modules
- jsonString, _ := json.Marshal(moduleHandler.LoadedModule)
- return string(jsonString)
- } else if matchSubfix(chunk, []string{"find", "subservices"}, 2, "") {
- //Display all loaded subservices
- fmt.Println(ssRouter.RunningSubService)
- return "OK"
- }
- } else if len(chunk) > 0 && chunk[0] == "access" {
- //Handle emergency situation where the user is blocked by himself
- if matchSubfix(chunk, []string{"access", "whitelist", "disable"}, 3, "") {
- //Disable whitelist
- authAgent.WhitelistManager.SetWhitelistEnabled(false)
- return "Whitelist Disabled"
- } else if matchSubfix(chunk, []string{"access", "whitelist", "enable"}, 3, "") {
- //Enable whitelist
- authAgent.WhitelistManager.SetWhitelistEnabled(true)
- return "Whitelist Enabled"
- } else if matchSubfix(chunk, []string{"access", "whitelist", "add"}, 4, "access whitelist add {ip_range}") {
- err = authAgent.WhitelistManager.SetWhitelist(chunk[3])
- if err != nil {
- return err.Error()
- }
- return "OK"
- } else if matchSubfix(chunk, []string{"access", "whitelist", "del"}, 4, "access whitelist del {ip_range}") {
- err = authAgent.WhitelistManager.UnsetWhitelist(chunk[3])
- if err != nil {
- return err.Error()
- }
- return "OK"
- } else if matchSubfix(chunk, []string{"access", "blacklist", "enable"}, 3, "") {
- //Enable blacklist
- authAgent.WhitelistManager.SetWhitelistEnabled(true)
- return "Blacklist Enabled"
- } else if matchSubfix(chunk, []string{"access", "blacklist", "disable"}, 3, "") {
- //Disable blacklist
- authAgent.BlacklistManager.SetBlacklistEnabled(false)
- return "Blacklist Disabled"
- } else {
- return "[Whitelist / Blacklist Console Control API] \nUsage: access {whitelist/blacklist} {action} {data}"
- }
- } else if len(chunk) == 1 && chunk[0] == "stop" {
- //Stopping the server
- fmt.Println("Shutting down aroz online system by terminal request")
- executeShutdownSequence()
- }
- return "Invalid Command. Given: '" + strings.Join(chunk, " ") + "'"
- }
- // Check if the given line input match the requirement
- func matchSubfix(chunk []string, match []string, minlength int, usageExample string) bool {
- matching := true
- //Check if the chunk contains minmium length of the command request
- if len(chunk) >= len(match) {
- for i, cchunk := range match {
- if chunk[i] != cchunk {
- matching = false
- }
- }
- } else {
- matching = false
- }
- if len(chunk)-minlength == -1 && chunk[len(chunk)-1] == match[len(match)-1] {
- fmt.Println("Paramter missing. Usage: " + usageExample)
- return false
- }
- return matching
- }
- func parseCommandLine(command string) ([]string, error) {
- var args []string
- state := "start"
- current := ""
- quote := "\""
- escapeNext := true
- for i := 0; i < len(command); i++ {
- c := command[i]
- if state == "quotes" {
- if string(c) != quote {
- current += string(c)
- } else {
- args = append(args, current)
- current = ""
- state = "start"
- }
- continue
- }
- if escapeNext {
- current += string(c)
- escapeNext = false
- continue
- }
- if c == '\\' {
- escapeNext = true
- continue
- }
- if c == '"' || c == '\'' {
- state = "quotes"
- quote = string(c)
- continue
- }
- if state == "arg" {
- if c == ' ' || c == '\t' {
- args = append(args, current)
- current = ""
- state = "start"
- } else {
- current += string(c)
- }
- continue
- }
- if c != ' ' && c != '\t' {
- state = "arg"
- current += string(c)
- }
- }
- if state == "quotes" {
- return []string{}, errors.New(fmt.Sprintf("Unclosed quote in command line: %s", command))
- }
- if current != "" {
- args = append(args, current)
- }
- return args, nil
- }
|