summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine-a <sanine.not@pm.me>2023-05-10 14:15:30 -0500
committersanine-a <sanine.not@pm.me>2023-05-10 14:15:30 -0500
commitc4dbe6328640f8ac43518a642e77dec061bfdd03 (patch)
treed432f0c0522d946e9b42f39c8960a3b37f4af37d
parentfd994ce631ce7244157f81678574e6bc420d0fcc (diff)
add hacky command parser
-rw-r--r--conf/create.go81
-rw-r--r--conf/endpoint.go.bak (renamed from conf/endpoint.go)0
-rw-r--r--conf/list.go68
-rw-r--r--conf/main.go204
-rw-r--r--conf/user.go.bak (renamed from conf/user.go)0
-rw-r--r--db/db.go2
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(&params.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
diff --git a/db/db.go b/db/db.go
index c58f6ad..55ef81b 100644
--- a/db/db.go
+++ b/db/db.go
@@ -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);
`)