From 5957437dedb29f81bf7823a54eb4871dfe17c5ae Mon Sep 17 00:00:00 2001 From: stephen mcquay Date: Sun, 9 Aug 2015 15:38:35 -0700 Subject: [PATCH] plumbed through child add/delete subcommands --- children/db.go | 43 +++++++++++++++++++++++++++++++++++++++ cmd/allowances/main.go | 46 ++++++++++++++++++++++++++++++++++++++++-- db.go | 35 +++++--------------------------- fs.go | 12 ----------- handlers.go | 24 +++++++++++++--------- 5 files changed, 107 insertions(+), 53 deletions(-) create mode 100644 children/db.go delete mode 100644 fs.go diff --git a/children/db.go b/children/db.go new file mode 100644 index 0000000..71ce80b --- /dev/null +++ b/children/db.go @@ -0,0 +1,43 @@ +package children + +import ( + "encoding/json" + "errors" + "os" + "sync" + + "mcquay.me/fs" +) + +var mut sync.Mutex + +type DB map[string]int + +func Load(filename string) (children DB, err error) { + db := DB{} + if !fs.Exists(filename) { + return db, errors.New("db file doesn't exist") + } + f, err := os.Open(filename) + if err != nil { + return nil, err + } + if err := json.NewDecoder(f).Decode(&db); err != nil { + return nil, err + } + return db, nil +} + +func (db DB) Save(filename string) error { + mut.Lock() + defer mut.Unlock() + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + if err := json.NewEncoder(f).Encode(db); err != nil { + return err + } + return nil +} diff --git a/cmd/allowances/main.go b/cmd/allowances/main.go index 8e5ab7e..6462412 100644 --- a/cmd/allowances/main.go +++ b/cmd/allowances/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "log" "net/http" "os" "strconv" @@ -10,12 +9,14 @@ import ( "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 ` @@ -26,6 +27,13 @@ subcommands: test ` +const childUsage = `allowances child + +subcommands: + add ... + delete ... +` + func main() { if len(os.Args) < 2 { fmt.Fprintf(os.Stderr, usage) @@ -74,6 +82,41 @@ func main() { 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") @@ -93,7 +136,6 @@ func main() { port = p } addr := fmt.Sprintf(":%d", port) - log.Printf("%+v", addr) err = http.ListenAndServe(addr, sm) if err != nil { panic(err) diff --git a/db.go b/db.go index 5109e55..685219c 100644 --- a/db.go +++ b/db.go @@ -2,18 +2,20 @@ package allowances import ( "encoding/json" - "io/ioutil" - "log" "os" "sync" "golang.org/x/crypto/bcrypt" + + "mcquay.me/fs" ) +var dbMutex sync.RWMutex + func GetHashes(filename string) (Passes, bool, error) { r := []string{} exists := false - if !Exists(filename) { + if !fs.Exists(filename) { return r, exists, nil } exists = true @@ -59,30 +61,3 @@ func (p Passes) Check(attempt string) (bool, error) { } return false, nil } - -var dbMutex = sync.RWMutex{} - -func loadChildren(filename string) (children map[string]int) { - dbMutex.RLock() - defer dbMutex.RUnlock() - b, err := ioutil.ReadFile(filename) - if err != nil { - log.Fatal(err) - } - err = json.Unmarshal(b, &children) - if err != nil { - log.Fatal(err) - } - return -} - -func dumpChildren(filename string, children map[string]int) { - dbMutex.Lock() - defer dbMutex.Unlock() - b, err := json.Marshal(children) - err = ioutil.WriteFile(filename, b, 0644) - if err != nil { - log.Fatal("serious issue writing children db file", err) - } - return -} diff --git a/fs.go b/fs.go deleted file mode 100644 index 027f1eb..0000000 --- a/fs.go +++ /dev/null @@ -1,12 +0,0 @@ -package allowances - -import "os" - -func Exists(path string) bool { - if _, err := os.Stat(path); err != nil { - return false - } else if os.IsNotExist(err) { - return false - } - return true -} diff --git a/handlers.go b/handlers.go index c43cc52..513e809 100644 --- a/handlers.go +++ b/handlers.go @@ -9,6 +9,8 @@ import ( "strings" "github.com/gorilla/sessions" + "mcquay.me/allowances/children" + "mcquay.me/fs" ) func init() { @@ -28,7 +30,8 @@ func NewFailure(msg string) *failure { } type Allowances struct { - db string + db children.DB + dbfile string hashes Passes store *sessions.CookieStore } @@ -47,11 +50,16 @@ func NewAllowances(sm *http.ServeMux, dbfile, passfile, staticFiles string) (*Al return nil, err } - if !Exists(dbfile) { + if !fs.Exists(dbfile) { return nil, fmt.Errorf("child db file doesn't exist: %q", dbfile) } + db, err := children.Load(dbfile) + if err != nil { + return nil, err + } r := &Allowances{ - db: dbfile, + db: db, + dbfile: dbfile, hashes: hashes, store: sessions.NewCookieStore([]byte("hello world")), } @@ -60,8 +68,7 @@ func NewAllowances(sm *http.ServeMux, dbfile, passfile, staticFiles string) (*Al } func (a *Allowances) home(w http.ResponseWriter, req *http.Request, uid string) error { - children := loadChildren(a.db) - tmpls["home"].Execute(w, map[string]interface{}{"children": children}) + tmpls["home"].Execute(w, map[string]interface{}{"children": a.db}) return nil } @@ -102,12 +109,11 @@ func (a *Allowances) add(w http.ResponseWriter, req *http.Request, uid string) e if err != nil { return fmt.Errorf("couldn't parse a dollar amount: %v", err) } - children := loadChildren(a.db) - children[child] += amount - defer dumpChildren(a.db, children) + a.db[child] += amount + a.db.Save(a.dbfile) w.Header().Set("Content-Type", "application/json") b, err := json.Marshal(map[string]interface{}{ - "amount": dollarize(children[child]), + "amount": dollarize(a.db[child]), "name": child, }) if err != nil {