diff --git a/.gitignore b/.gitignore index 6da99cc..330e7a1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ test.txt ledger-quicknote *.txt +.htpasswd diff --git a/auth/auth.go b/auth/auth.go index 7f32db0..0233d79 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -29,8 +29,32 @@ func NewHtpasswd(path string) (AuthStore, error) { return s, err } +func (s Htpasswd) Register(user, pass string) (err error) { + if _, ok := s.accounts[user]; ok { + return errors.New("user already exists") + } + s.accounts[user], err = hash(pass) + if err != nil { + return + } + return s.write() +} + +func (s Htpasswd) Authenticate(user, pass string) (err error) { + hashed, ok := s.accounts[user] + if !ok { + return errors.New("user not found") + } + return bcrypt.CompareHashAndPassword([]byte(hashed), []byte(pass)) +} + +func (s Htpasswd) Remove(user string) (err error) { + delete(s.accounts, user) + return s.write() +} + func (s *Htpasswd) read() (err error) { - file, err := os.Open(s.filePath) + file, err := os.OpenFile(s.filePath, os.O_RDONLY|os.O_CREATE, 0600) if err != nil { return err } @@ -66,27 +90,6 @@ func (s *Htpasswd) write() (err error) { return nil } -func (s Htpasswd) Register(user, pass string) (err error) { - s.accounts[user], err = hash(pass) - if err != nil { - return - } - return s.write() -} - -func (s Htpasswd) Authenticate(user, pass string) (err error) { - hashed, ok := s.accounts[user] - if !ok { - return errors.New("user not found") - } - return bcrypt.CompareHashAndPassword([]byte(hashed), []byte(pass)) -} - -func (s Htpasswd) Remove(user string) (err error) { - delete(s.accounts, user) - return s.write() -} - func hash(pass string) (string, error) { output, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) return string(output), err diff --git a/main.go b/main.go index 9d91215..0c0bf9e 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/lancatlin/ledger-quicknote/auth" ) var ledgerTpl *template.Template @@ -23,6 +24,10 @@ var LEDGER_INIT string var WORKING_DIR string var HOST string +var store auth.AuthStore + +const HTPASSWD_FILE = ".htpasswd" + type TxData struct { Action string `form:"action" binding:"required"` Name string `form:"name"` @@ -31,6 +36,11 @@ type TxData struct { Account string `form:"account"` } +type UserLogin struct { + Email string `form:"email" binding:"required"` + Password string `form:"password" binding:"required"` +} + func init() { ledgerTpl = template.Must(template.ParseGlob("tx/*")) flag.StringVar(&LEDGER_FILE, "f", "example.txt", "ledger journal file to write") @@ -38,12 +48,17 @@ func init() { flag.StringVar(&WORKING_DIR, "w", "", "ledger working directory") flag.StringVar(&HOST, "b", "127.0.0.1:8000", "binding address") flag.Parse() + var err error + store, err = auth.NewHtpasswd(HTPASSWD_FILE) + if err != nil { + panic(err) + } } func main() { r := gin.Default() r.HTMLRender = loadTemplates("templates") - r.GET("/", func(c *gin.Context) { + r.GET("/dashboard", func(c *gin.Context) { c.HTML(200, "index.html", struct { Templates []*template.Template Scripts map[string][]string @@ -91,6 +106,24 @@ func main() { } }) + r.GET("/signup", func(c *gin.Context) { + c.HTML(200, "signup.html", nil) + }) + + r.POST("/signup", func(c *gin.Context) { + var user UserLogin + if err := c.ShouldBind(&user); err != nil { + c.HTML(400, "signup.html", err) + return + } + if err := store.Register(user.Email, user.Password); err != nil { + c.HTML(400, "signup.html", err) + return + } + c.Request.SetBasicAuth(user.Email, user.Password) + c.Redirect(303, "/dashboard") + }) + log.Fatal(r.Run(HOST)) } diff --git a/templates/signup.html b/templates/signup.html new file mode 100644 index 0000000..a259881 --- /dev/null +++ b/templates/signup.html @@ -0,0 +1,10 @@ +{{ define "title" }}Sign Up{{ end }} +{{ define "main" }} +

Sign Up

+
+
+
+ {{ with .Error }}

{{ . }}

{{ end }} + +
+{{ end }}