146 lines
3.0 KiB
Go
146 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:]
|
|
|
|
// ignore if file wasn't there to begin with
|
|
db, _ := children.Load(dbfile)
|
|
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)
|
|
}
|
|
}
|