allowances/cmd/allowances/main.go

148 lines
3.0 KiB
Go

package main
import (
"fmt"
"net/http"
"os"
"strconv"
"github.com/bgentry/speakeasy"
"mcquay.me/allowances"
"mcquay.me/allowances/children"
)
const usage = `allowances app
subcommands:
pw -- manage password file
child -- manage children
serve -- serve webapp
`
const pwUsage = `allowances pw
subcommands:
add <passes.json>
test <passes.json>
`
const childUsage = `allowances child
subcommands:
add <children.json> <child name> <child name> ...
delete <children.json> <child name> <child name> ...
`
func main() {
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, usage)
os.Exit(1)
}
subcommand := os.Args[1]
switch subcommand {
case "pw":
pwCmd := os.Args[2:]
if len(pwCmd) != 2 {
fmt.Fprintf(os.Stderr, "%s\n", pwUsage)
os.Exit(1)
}
switch pwCmd[0] {
case "add":
pw, err := speakeasy.Ask("new pass: ")
if err != nil {
fmt.Fprintf(os.Stderr, "failure to get password: %v", err)
os.Exit(1)
}
if err := allowances.AddPassword(pwCmd[1], pw); err != nil {
fmt.Fprintf(os.Stderr, "problem adding password: %v", err)
os.Exit(1)
}
case "test":
passes, _, err := allowances.GetHashes(pwCmd[1])
if err != nil {
fmt.Fprintf(os.Stderr, "problem opening passes file: %v", err)
os.Exit(1)
}
pw, err := speakeasy.Ask("check password: ")
if err != nil {
panic(err)
}
ok, err := passes.Check(pw)
if err != nil {
panic(err)
}
if !ok {
fmt.Fprintf(os.Stderr, "bad password")
os.Exit(1)
}
default:
fmt.Fprintf(os.Stderr, "%s\n", pwUsage)
os.Exit(1)
}
case "child":
childCmd := os.Args[2:]
if len(childCmd) < 3 {
fmt.Fprintf(os.Stderr, "%s\n", childUsage)
os.Exit(1)
}
switch childCmd[0] {
case "add":
dbfile := os.Args[3]
names := os.Args[4:]
db, err := children.Load(dbfile)
if err != nil {
fmt.Fprintf(os.Stderr, "problem loading children db: %s\n", pwUsage)
os.Exit(1)
}
for _, name := range names {
db[name] = 0
}
db.Save(dbfile)
case "delete", "del":
dbfile := os.Args[3]
names := os.Args[4:]
db, err := children.Load(dbfile)
if err != nil {
fmt.Fprintf(os.Stderr, "problem loading children db: %s\n", pwUsage)
os.Exit(1)
}
for _, name := range names {
delete(db, name)
}
db.Save(dbfile)
default:
fmt.Fprintf(os.Stderr, "%s\n", pwUsage)
os.Exit(1)
}
case "serve":
sm := http.NewServeMux()
dbfile := os.Getenv("DB")
passfile := os.Getenv("PASSES")
_, err := allowances.NewAllowances(sm, dbfile, passfile, os.Getenv("STATIC"))
if err != nil {
fmt.Fprintf(os.Stderr, "unable to initialize web server: %v\n", err)
os.Exit(1)
}
port := 8000
if os.Getenv("PORT") != "" {
p, err := strconv.Atoi(os.Getenv("PORT"))
if err != nil {
fmt.Fprintf(os.Stderr, "problem parsing port from env: %v\n", err)
os.Exit(1)
}
port = p
}
addr := fmt.Sprintf(":%d", port)
err = http.ListenAndServe(addr, sm)
if err != nil {
panic(err)
}
default:
fmt.Fprintf(os.Stderr, "unknown subcommand %s\n\n%s\n", subcommand, usage)
os.Exit(1)
}
}