diff --git a/http/http.go b/http/http.go index 8699c8e..9697949 100644 --- a/http/http.go +++ b/http/http.go @@ -1,155 +1,162 @@ -package http - -import ( - "net/http" - "time" - - "git.javil.eu/jacob1123/budgeteer" - - "gopkg.in/gin-gonic/gin.v1" -) - -// Handler handles incoming requests -type Handler struct { - Service budgeteer.ModelService - TokenVerifier budgeteer.TokenVerifier - CredentialsVerifier budgeteer.CredentialVerifier -} - -const ( - expiration = 72 - authCookie = "authentication" -) - -// Serve starts the HTTP Server -func (h *Handler) Serve() { - router := gin.Default() - - router.LoadHTMLGlob("./templates/*") - router.Static("/static", "./static") - - router.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "index", nil) }) - router.GET("/login", h.login) - router.GET("/register", h.register) - router.GET("/dashboard", h.dashboard) - api := router.Group("/api/v1") - { - api.GET("/logout", logout) - api.GET("/login", func(c *gin.Context) { c.Redirect(http.StatusPermanentRedirect, "/login") }) - api.POST("/login", h.loginPost) - api.POST("/register", h.registerPost) - } - - router.Run(":1323") -} - -func (h *Handler) dashboard(c *gin.Context) { - token, err := h.verifyLogin(c) - if err != nil { - c.Redirect(http.StatusTemporaryRedirect, "/login") - return - } - - d := TemplateData{ - Token: token, - budgetService: h.Service, - } - c.HTML(http.StatusOK, "dashboard", d) -} - -func (h *Handler) verifyLogin(c *gin.Context) (budgeteer.Token, error) { - tokenString, err := c.Cookie(authCookie) - if err != nil { - return nil, err - } - - token, err := h.TokenVerifier.VerifyToken(tokenString) - if err != nil { - c.SetCookie(authCookie, "", -1, "", "", false, false) - return nil, err - } - - return token, nil -} - -func (h *Handler) login(c *gin.Context) { - if _, err := h.verifyLogin(c); err == nil { - c.Redirect(http.StatusTemporaryRedirect, "/dashboard") - return - } - - c.HTML(http.StatusOK, "login", nil) -} - -func (h *Handler) register(c *gin.Context) { - if _, err := h.verifyLogin(c); err == nil { - c.Redirect(http.StatusTemporaryRedirect, "/dashboard") - return - } - - c.HTML(http.StatusOK, "register", nil) -} - -func logout(c *gin.Context) { - clearLogin(c) -} - -func clearLogin(c *gin.Context) { - c.SetCookie(authCookie, "", -1, "", "", false, true) -} - -func (h *Handler) loginPost(c *gin.Context) { - username, _ := c.GetPostForm("username") - password, _ := c.GetPostForm("password") - - user, err := h.Service.UserByUsername(username) - if err != nil { - c.AbortWithError(http.StatusUnauthorized, err) - return - } - - if err = h.CredentialsVerifier.Verify(password, user.Password); err != nil { - c.AbortWithError(http.StatusUnauthorized, err) - return - } - - t, err := h.TokenVerifier.CreateToken(user) - if err != nil { - c.AbortWithError(http.StatusUnauthorized, err) - } - - maxAge := (int)((expiration * time.Hour).Seconds()) - c.SetCookie(authCookie, t, maxAge, "", "", false, true) - - c.JSON(http.StatusOK, map[string]string{ - "token": t, - }) -} - -func (h *Handler) registerPost(c *gin.Context) { - email, _ := c.GetPostForm("email") - password, _ := c.GetPostForm("password") - name, _ := c.GetPostForm("name") - - user, err := h.Service.UserByUsername(email) - if err == nil { - c.AbortWithStatus(http.StatusUnauthorized) - return - } - - hash, err := h.CredentialsVerifier.Hash(password) - if err != nil { - c.AbortWithError(http.StatusUnauthorized, err) - return - } - - user = &budgeteer.User{ - Name: name, - Password: hash, - Email: email, - } - err = h.Service.CreateUser(user) - if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) - } -} +package http + +import ( + "net/http" + "time" + + "git.javil.eu/jacob1123/budgeteer" + + "gopkg.in/gin-gonic/gin.v1" +) + +// Handler handles incoming requests +type Handler struct { + Service budgeteer.ModelService + TokenVerifier budgeteer.TokenVerifier + CredentialsVerifier budgeteer.CredentialVerifier +} + +const ( + expiration = 72 + authCookie = "authentication" +) + +// Serve starts the HTTP Server +func (h *Handler) Serve() { + router := gin.Default() + + router.LoadHTMLGlob("./templates/*") + router.Static("/static", "./static") + + router.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "index", nil) }) + router.GET("/login", h.login) + router.GET("/register", h.register) + router.GET("/dashboard", h.dashboard) + api := router.Group("/api/v1") + { + user := api.Group("/user") + { + user.GET("/logout", logout) + user.GET("/login", func(c *gin.Context) { c.Redirect(http.StatusPermanentRedirect, "/login") }) + user.POST("/login", h.loginPost) + user.POST("/register", h.registerPost) + } + budget := api.Group("budget") + { + budget.POST("") + } + } + + router.Run(":1323") +} + +func (h *Handler) dashboard(c *gin.Context) { + token, err := h.verifyLogin(c) + if err != nil { + c.Redirect(http.StatusTemporaryRedirect, "/login") + return + } + + d := TemplateData{ + Token: token, + budgetService: h.Service, + } + c.HTML(http.StatusOK, "dashboard", d) +} + +func (h *Handler) verifyLogin(c *gin.Context) (budgeteer.Token, error) { + tokenString, err := c.Cookie(authCookie) + if err != nil { + return nil, err + } + + token, err := h.TokenVerifier.VerifyToken(tokenString) + if err != nil { + c.SetCookie(authCookie, "", -1, "", "", false, false) + return nil, err + } + + return token, nil +} + +func (h *Handler) login(c *gin.Context) { + if _, err := h.verifyLogin(c); err == nil { + c.Redirect(http.StatusTemporaryRedirect, "/dashboard") + return + } + + c.HTML(http.StatusOK, "login", nil) +} + +func (h *Handler) register(c *gin.Context) { + if _, err := h.verifyLogin(c); err == nil { + c.Redirect(http.StatusTemporaryRedirect, "/dashboard") + return + } + + c.HTML(http.StatusOK, "register", nil) +} + +func logout(c *gin.Context) { + clearLogin(c) +} + +func clearLogin(c *gin.Context) { + c.SetCookie(authCookie, "", -1, "", "", false, true) +} + +func (h *Handler) loginPost(c *gin.Context) { + username, _ := c.GetPostForm("username") + password, _ := c.GetPostForm("password") + + user, err := h.Service.UserByUsername(username) + if err != nil { + c.AbortWithError(http.StatusUnauthorized, err) + return + } + + if err = h.CredentialsVerifier.Verify(password, user.Password); err != nil { + c.AbortWithError(http.StatusUnauthorized, err) + return + } + + t, err := h.TokenVerifier.CreateToken(user) + if err != nil { + c.AbortWithError(http.StatusUnauthorized, err) + } + + maxAge := (int)((expiration * time.Hour).Seconds()) + c.SetCookie(authCookie, t, maxAge, "", "", false, true) + + c.JSON(http.StatusOK, map[string]string{ + "token": t, + }) +} + +func (h *Handler) registerPost(c *gin.Context) { + email, _ := c.GetPostForm("email") + password, _ := c.GetPostForm("password") + name, _ := c.GetPostForm("name") + + user, err := h.Service.UserByUsername(email) + if err == nil { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + + hash, err := h.CredentialsVerifier.Hash(password) + if err != nil { + c.AbortWithError(http.StatusUnauthorized, err) + return + } + + user = &budgeteer.User{ + Name: name, + Password: hash, + Email: email, + } + err = h.Service.CreateUser(user) + if err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + } +} diff --git a/templates/login.html b/templates/login.html index bed3743..9bc9609 100644 --- a/templates/login.html +++ b/templates/login.html @@ -11,7 +11,7 @@ $('#invalidCredentials').hide(); $('#loginForm').ajaxForm({ success: function() { - window.location.href = "/api/v1/restricted"; + window.location.href = "/dashboard"; }, error: function() { $('#invalidCredentials').show(); @@ -25,7 +25,7 @@ Budgeteer