diff options
author | sanine-a <sanine.not@pm.me> | 2023-05-10 14:15:30 -0500 |
---|---|---|
committer | sanine-a <sanine.not@pm.me> | 2023-05-10 14:15:30 -0500 |
commit | c4dbe6328640f8ac43518a642e77dec061bfdd03 (patch) | |
tree | d432f0c0522d946e9b42f39c8960a3b37f4af37d | |
parent | fd994ce631ce7244157f81678574e6bc420d0fcc (diff) |
add hacky command parser
-rw-r--r-- | conf/create.go | 81 | ||||
-rw-r--r-- | conf/endpoint.go.bak (renamed from conf/endpoint.go) | 0 | ||||
-rw-r--r-- | conf/list.go | 68 | ||||
-rw-r--r-- | conf/main.go | 204 | ||||
-rw-r--r-- | conf/user.go.bak (renamed from conf/user.go) | 0 | ||||
-rw-r--r-- | db/db.go | 2 |
6 files changed, 207 insertions, 148 deletions
diff --git a/conf/create.go b/conf/create.go new file mode 100644 index 0000000..ec732d2 --- /dev/null +++ b/conf/create.go @@ -0,0 +1,81 @@ +package main + + +import ( + "fmt" + "log" + "strings" + "syscall" + "golang.org/x/term" +) + + +func hiddenPrompt(prompt string) (string, error) { + fmt.Print(prompt) + bytes, err := term.ReadPassword(int(syscall.Stdin)) + if err != nil { + return "", err + } + + return strings.TrimSpace(string(bytes)), nil +} + + +var createUser = &Command{ + Name: "user", + Execute: func(args []string) { + if len(args) < 1 { + fmt.Println("error: no username provided") + return; + } + username := args[0] + var password string + if len(args) == 1 { + password, err := hiddenPrompt("Enter password: ") + if err != nil { log.Fatal(err) } + confirm, err := hiddenPrompt("Confirm password: ") + if err != nil { log.Fatal(err) } + if password != confirm { + fmt.Println("passwords do not match!") + return + } + } else { + password = args[1] + } + + _, err := p.CreateUser(username, password) + if err != nil { log.Fatal(err) } + fmt.Printf("created user %v\n", username) + }, +} + + +var createEndpoint = &Command{ + Name: "endpoint", + Execute: func(args []string) { + if len(args) < 3 { + fmt.Println("error: name, URI, and address must be specified!") + return + } + + name := args[0] + path := args[1] + addr := args[2] + + _, err := p.CreateEndpoint(name, path, addr) + if err != nil { log.Fatal(err) } + fmt.Printf("created endpoint %v\n", name) + }, +} + + +func CreateInit(parser *Command) { + create := &Command{ + Name: "create", + Branch: true, + } + + create.AddCommand(createUser) + create.AddCommand(createEndpoint) + parser.AddCommand(create) +} diff --git a/conf/endpoint.go b/conf/endpoint.go.bak index 1f8fa11..1f8fa11 100644 --- a/conf/endpoint.go +++ b/conf/endpoint.go.bak diff --git a/conf/list.go b/conf/list.go new file mode 100644 index 0000000..bf3fd80 --- /dev/null +++ b/conf/list.go @@ -0,0 +1,68 @@ +package main + +import( + "fmt" + "log" + "time" +) + + +var listUsers = Command{ + Name: "users", + Execute: func([]string) { + users, err := p.AllUsers() + if err != nil { + log.Fatal(err) + } + fmt.Printf("id\tname\n========================================\n") + for _, user := range users { + fmt.Printf("%v\t%v\n", user.Id, user.Name) + } + }, +} + + +var listSessions = Command{ + Name: "sessions", + Execute: func([]string) { + sessions, err := p.AllSessions() + if err != nil { + log.Fatal(err) + } + fmt.Printf("id\tuser\tcreated\tmodified\n========================================\n") + for _, session := range sessions { + user, err := p.GetById(session.UserId) + if err != nil { + log.Fatal(err) + } + fmt.Printf("%v\t%v\n", session.Id, user.Name, session.Created.Format(time.RFC3339), session.Modified.Format(time.RFC3339)) + } + }, +} + + +var listEndpoints = Command{ + Name: "endpoints", + Execute: func([]string) { + endpoints, err := p.AllEndpoints() + if err != nil { log.Fatal(err) } + + fmt.Printf("name\tpath\taddress\n========================================\n") + for _, endpoint := range endpoints { + fmt.Printf("%v\t%v\t%v\n", endpoint.Name, endpoint.Path, endpoint.Address) + } + }, +} + + +func ListInit(parser *Command) { + list := &Command{ + Name: "list", + Branch: true, + } + + list.AddCommand(&listUsers) + list.AddCommand(&listSessions) + list.AddCommand(&listEndpoints) + parser.AddCommand(list) +} diff --git a/conf/main.go b/conf/main.go index d0785f8..a768bac 100644 --- a/conf/main.go +++ b/conf/main.go @@ -5,181 +5,91 @@ import ( "fmt" "log" "flag" - "strings" - "bufio" +// "strings" +// "bufio" db "sanine.net/git/phlox/db" ) -var p *db.Phlox - - -type Params struct { - DbFilename string +var Params struct { + InitDb string + Db string } -var params Params -type Command struct { - Set bool - Value int - Flag string - Usage string - Invoke func() -} - - -func RegisterCommand(val int, cmd *Command) { - cmd.Value = val - flag.BoolVar(&(*cmd).Set, cmd.Flag, false, cmd.Usage) -} - +var p *db.Phlox -func OpenDb() { - err := p.Open(params.DbFilename) - if err != nil { log.Fatal(err) } +type Command struct { + Name string + Help string + subcommands map[string]*Command + Branch bool + Execute func([]string) } - -func ReadLine(prompt string) string { - reader := bufio.NewReader(os.Stdin) - - fmt.Print(prompt) - line, err := reader.ReadString('\n') - if err != nil { - log.Fatal(err) +func (c *Command) errNoSubCommand() { + fmt.Println("error: a subcommand was required but not provided.") + fmt.Println("available options are:\n") + for name := range c.subcommands { + fmt.Printf("\t* %v\n", name) } - - return strings.TrimSpace(line) + fmt.Println() } - -func main() { - p = &db.Phlox{} - - cmds := map[int]*Command{ - 1: Create(), - 2: SchemaVersion(), - - 3: CreateUser(), - 4: DeleteUser(), - 5: UpdatePassword(), - 6: ListUsers(), - - 7: CreateEndpoint(), - 8: DeleteEndpoint(), - 9: SetPath(), - 10: SetAddress(), - 11: ListEndpoints(), - - 12: SetHost(), - 13: GetHost(), - 14: SetLogin(), - 15: GetLogin(), - } - - for val, cmd := range cmds { - RegisterCommand(val, cmd) - } - - flag.StringVar(¶ms.DbFilename, "db", "phlox.conf", "select the db file to operate on") - flag.Parse() - - for _, cmd := range cmds { - if cmd.Set { cmd.Invoke(); os.Exit(0); } +func (c *Command) Parse(args []string) { + if !c.Branch { + c.Execute(args) + } else { + if len(args) > 0 { + cn, ok := c.subcommands[args[0]] + if ok { + cn.Parse(args[1:]) + } else { + c.errNoSubCommand() + } + } else { + c.errNoSubCommand() + } } - - log.Fatal("no command specified!") } -func Create() *Command { - return &Command{ - Flag: "create", - Usage: "create a new database", - Invoke: func() { - err := p.Create(params.DbFilename) - if err != nil { - log.Fatal(err) - } - fmt.Printf("created database %v\n", params.DbFilename) - }, +func (c *Command) AddCommand(cn *Command) { + if c.subcommands == nil { + c.subcommands = make(map[string]*Command) } + c.subcommands[cn.Name] = cn } -func SchemaVersion() *Command { - return &Command{ - Flag: "schema-version", - Usage: "get the schema version", - Invoke: func() { - err := p.Open(params.DbFilename) - if err != nil { log.Fatal(err) } - version, err := p.GetSchemaVersion() - if err != nil { log.Fatal(err) } - fmt.Printf("schema version: %v\n", version) - }, - } -} +var parser *Command -func SetHost() *Command { - return &Command{ - Flag: "set-host-address", - Usage: "set the address to serve the reverse proxy on", - Invoke: func() { - OpenDb() - defer p.Close() - address := ReadLine("Address: ") - err := p.SetHostAddress(address) - if err != nil { log.Fatal(err) } - fmt.Printf("set host address to %v\n", address) - }, - } -} +func main() { + p = &db.Phlox{} + flag.StringVar(&Params.InitDb, "init", "", "initialize a new database at the given path") + flag.StringVar(&Params.Db, "db", "/etc/phlox/phlox.conf", "open the database at the given path for processing") + flag.Parse() -func GetHost() *Command { - return &Command{ - Flag: "get-host-address", - Usage: "get the address to serve the reverse proxy on", - Invoke: func() { - OpenDb() - defer p.Close() - address, err := p.GetHostAddress() - if err != nil { log.Fatal(err) } - fmt.Printf("host address is %v\n", address) - }, + if Params.InitDb != "" { + // initialize a new db + err := p.Create(Params.InitDb) + if err != nil { log.Fatal(err) } + fmt.Printf("created new database at %v\n", Params.InitDb) + p.Close() + os.Exit(0) } -} - -func SetLogin() *Command { - return &Command{ - Flag: "set-login-page", - Usage: "set the file to serve as the login page", - Invoke: func() { - OpenDb() - defer p.Close() - path := ReadLine("File Path (blank for internal default): ") - err := p.SetLoginPage(path) - if err != nil { log.Fatal(err) } - fmt.Printf("set login page to %v\n", path) - }, + err := p.Open(Params.Db) + if err != nil { + log.Fatal(err) } -} + defer p.Close() + parser = &Command{Branch: true} + ListInit(parser) + CreateInit(parser) -func GetLogin() *Command { - return &Command{ - Flag: "get-login-page", - Usage: "get the file to serve the reverse proxy on", - Invoke: func() { - OpenDb() - defer p.Close() - path, err := p.GetLoginPage() - if err != nil { log.Fatal(err) } - fmt.Printf("login page is at %v\n", path) - }, - } + parser.Parse(flag.Args()) } diff --git a/conf/user.go b/conf/user.go.bak index 5ceaefb..5ceaefb 100644 --- a/conf/user.go +++ b/conf/user.go.bak @@ -119,7 +119,7 @@ func (p *Phlox) Create(filename string) error { insert into config values("hostaddress", "localhost:3333"); insert into config values("loginpage", ""); - create table users (userid integer not null primary key, username string, passwordhash string, salt string); + create table users (userid integer not null primary key, username string unique, passwordhash string, salt string); create table sessions (sessionid string not null primary key, userid integer, created string, modified string, foreign key(userid) references users(userid)); create table endpoints (endpointid integer not null primary key, name string, path string, address string); `) |