keeping track of my children's money since 2013
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

handlers.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package allowances
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "strconv"
  8. "strings"
  9. "github.com/gorilla/sessions"
  10. "mcquay.me/allowances/children"
  11. "mcquay.me/fs"
  12. )
  13. func init() {
  14. log.SetFlags(log.Lshortfile | log.Ltime)
  15. }
  16. type failure struct {
  17. Success bool `json:"success"`
  18. Error string `json:"error"`
  19. }
  20. func NewFailure(msg string) *failure {
  21. return &failure{
  22. Success: false,
  23. Error: msg,
  24. }
  25. }
  26. type Allowances struct {
  27. db children.DB
  28. dbfile string
  29. hashes Passes
  30. store *sessions.CookieStore
  31. }
  32. func NewAllowances(sm *http.ServeMux, dbfile, passfile, staticFiles string) (*Allowances, error) {
  33. var err error
  34. tmpls, err = getTemplates()
  35. if err != nil {
  36. return nil, err
  37. }
  38. hashes, exists, err := GetHashes(passfile)
  39. if !exists {
  40. return nil, fmt.Errorf("passes file doesn't exist: %q", passfile)
  41. }
  42. if err != nil {
  43. return nil, err
  44. }
  45. if !fs.Exists(dbfile) {
  46. return nil, fmt.Errorf("child db file doesn't exist: %q", dbfile)
  47. }
  48. db, err := children.Load(dbfile)
  49. if err != nil {
  50. return nil, err
  51. }
  52. r := &Allowances{
  53. db: db,
  54. dbfile: dbfile,
  55. hashes: hashes,
  56. store: sessions.NewCookieStore([]byte("hello world")),
  57. }
  58. addRoutes(sm, r, staticFiles)
  59. return r, nil
  60. }
  61. func (a *Allowances) home(w http.ResponseWriter, req *http.Request, uid string) error {
  62. tmpls["home"].Execute(w, map[string]interface{}{"children": a.db})
  63. return nil
  64. }
  65. func (a *Allowances) login(w http.ResponseWriter, req *http.Request) {
  66. attempt := req.FormValue("passwd")
  67. ok, err := a.hashes.Check(attempt)
  68. if err != nil {
  69. b, _ := json.Marshal(NewFailure(err.Error()))
  70. http.Error(w, string(b), http.StatusBadRequest)
  71. return
  72. }
  73. if ok {
  74. session, _ := a.store.Get(req, sessionName)
  75. session.Values["uuid"] = "me"
  76. session.Save(req, w)
  77. http.Redirect(w, req, "/", http.StatusSeeOther)
  78. return
  79. }
  80. tmpls["login"].Execute(w, map[string]interface{}{})
  81. }
  82. func (a *Allowances) logout(w http.ResponseWriter, req *http.Request, u string) error {
  83. session, err := a.store.Get(req, sessionName)
  84. if err != nil {
  85. return err
  86. }
  87. delete(session.Values, "uuid")
  88. session.Save(req, w)
  89. http.Redirect(w, req, "/", http.StatusSeeOther)
  90. return nil
  91. }
  92. func (a *Allowances) add(w http.ResponseWriter, req *http.Request, uid string) error {
  93. path := req.URL.Path[len(prefix["add"]):]
  94. bits := strings.Split(path, "/")
  95. child := bits[0]
  96. amount, err := strconv.Atoi(bits[1])
  97. if err != nil {
  98. return fmt.Errorf("couldn't parse a dollar amount: %v", err)
  99. }
  100. a.db[child] += amount
  101. a.db.Save(a.dbfile)
  102. w.Header().Set("Content-Type", "application/json")
  103. b, err := json.Marshal(map[string]interface{}{
  104. "amount": dollarize(a.db[child]),
  105. "name": child,
  106. })
  107. if err != nil {
  108. return err
  109. }
  110. w.Write(b)
  111. return nil
  112. }