package http import ( "net/http" "time" "git.javil.eu/jacob1123/budgeteer" "gopkg.in/gin-gonic/gin.v1" ) // Handler handles incoming requests type Handler struct { UserService budgeteer.UserService 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) 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) // Unauthenticated routes api.GET("/check", func(c *gin.Context) { c.String(http.StatusOK, "Accessible") }) api.GET("/hello", func(c *gin.Context) { c.String(http.StatusOK, "Hello, World!") }) // Restricted group r := api.Group("/restricted") { //r.Use(middleware.JWT([]byte(secret))) r.GET("", h.restricted) } } router.Run(":1323") } func (h *Handler) restricted(c *gin.Context) { token, err := h.verifyLogin(c) if err != nil { c.Redirect(http.StatusTemporaryRedirect, "/login") return } name := token.GetName() c.String(http.StatusOK, "Welcome "+name+"!") } 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, "/api/v1/hello") 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, "/api/v1/hello") 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.UserService.UserByUsername(username) if err != nil { c.AbortWithStatus(http.StatusUnauthorized) return } if err = h.CredentialsVerifier.Verify(password, user.Password); err != nil { c.AbortWithStatus(http.StatusUnauthorized) return } t, err := h.TokenVerifier.CreateToken(user) if err != nil { c.AbortWithStatus(http.StatusUnauthorized) } maxAge := (int)((expiration * time.Hour).Seconds()) c.SetCookie(authCookie, t, maxAge, "", "", false, true) c.JSON(http.StatusOK, map[string]string{ "token": t, }) }