From e3bd294b3ba11b92849ae776fb6ef1413ede1b23 Mon Sep 17 00:00:00 2001 From: Peter Sanchez Date: Wed, 14 Aug 2024 06:41:19 -0600 Subject: [PATCH] Adding BaseService for convenience --- accounts/routes.go | 80 +++++++++++++++++++++------------------------- server/service.go | 40 +++++++++++++++++++++++ 2 files changed, 76 insertions(+), 44 deletions(-) create mode 100644 server/service.go diff --git a/accounts/routes.go b/accounts/routes.go index 2f4ff4f..38610c1 100644 --- a/accounts/routes.go +++ b/accounts/routes.go @@ -19,35 +19,29 @@ import ( // Service is the base accounts service struct type Service struct { - name string + server.BaseService fetch gobwebs.UserFetch - eg *echo.Group } // RegisterRoutes ... func (s *Service) RegisterRoutes() { - s.eg.GET("/login", s.Login).Name = s.RouteName("login") - s.eg.POST("/login", s.LoginPOST).Name = s.RouteName("login_post") - s.eg.GET("/logout", s.Logout).Name = s.RouteName("logout") - s.eg.GET("/login/email/:key", s.LoginEmailConf).Name = s.RouteName("login_email") - s.eg.GET("/forgot-password", s.ForgotPassword).Name = s.RouteName("forgot_password") - s.eg.POST("/forgot-password", s.ForgotPasswordPOST).Name = s.RouteName("forgot_password_post") - s.eg.GET("/forgot-password/:key", s.ForgotPasswordConf).Name = s.RouteName("forgot_password_conf") - s.eg.POST("/forgot-password/:key", s.ForgotPasswordConfPOST).Name = s.RouteName("forgot_password_conf_post") - s.eg.GET("/confirm/:key", s.ConfirmEmailConf).Name = s.RouteName("confirm_email") + s.Group.GET("/login", s.Login).Name = s.RouteName("login") + s.Group.POST("/login", s.LoginPOST).Name = s.RouteName("login_post") + s.Group.GET("/logout", s.Logout).Name = s.RouteName("logout") + s.Group.GET("/login/email/:key", s.LoginEmailConf).Name = s.RouteName("login_email") + s.Group.GET("/forgot-password", s.ForgotPassword).Name = s.RouteName("forgot_password") + s.Group.POST("/forgot-password", s.ForgotPasswordPOST).Name = s.RouteName("forgot_password_post") + s.Group.GET("/forgot-password/:key", s.ForgotPasswordConf).Name = s.RouteName("forgot_password_conf") + s.Group.POST("/forgot-password/:key", s.ForgotPasswordConfPOST).Name = s.RouteName("forgot_password_conf_post") + s.Group.GET("/confirm/:key", s.ConfirmEmailConf).Name = s.RouteName("confirm_email") // Login required to use the following - s.eg.Use(auth.AuthRequired()) - s.eg.GET("/change-password", s.ChangePassword).Name = s.RouteName("change_password") - s.eg.POST("/change-password", s.ChangePasswordPOST).Name = s.RouteName("change_password_post") - s.eg.GET("/update-email", s.UpdateEmail).Name = s.RouteName("update_email") - s.eg.POST("/update-email", s.UpdateEmailPOST).Name = s.RouteName("update_email_post") - s.eg.GET("/update-email/:key", s.UpdateEmailConf).Name = s.RouteName("update_email_conf") -} - -// RouteName ... -func (s *Service) RouteName(value string) string { - return fmt.Sprintf("%s:%s", s.name, value) + s.Group.Use(auth.AuthRequired()) + s.Group.GET("/change-password", s.ChangePassword).Name = s.RouteName("change_password") + s.Group.POST("/change-password", s.ChangePasswordPOST).Name = s.RouteName("change_password_post") + s.Group.GET("/update-email", s.UpdateEmail).Name = s.RouteName("update_email") + s.Group.POST("/update-email", s.UpdateEmailPOST).Name = s.RouteName("update_email_post") + s.Group.GET("/update-email/:key", s.UpdateEmailConf).Name = s.RouteName("update_email_conf") } // Logout ... @@ -80,11 +74,10 @@ func (s *Service) Login(c echo.Context) error { // LoginAuth ... func (s *Service) LoginAuth(c echo.Context) error { - gctx := c.(*server.Context) next := c.QueryParam("next") gmap := s.fetch.LoginAuthTemplateVars(c) gmap["next"] = next - return gctx.Render(http.StatusOK, "login.html", gmap) + return s.Render(c, http.StatusOK, "login.html", gmap) } // LoginEmail ... @@ -97,7 +90,7 @@ func (s *Service) LoginEmail(c echo.Context) error { sent := c.QueryParam("sent") gmap := s.fetch.LoginEmailTemplateVars(c) gmap["sent"] = sent - return gctx.Render(http.StatusOK, "login_email.html", gmap) + return s.Render(c, http.StatusOK, "login_email.html", gmap) } // LoginPOST ... @@ -123,7 +116,7 @@ func (s *Service) LoginAuthPOST(c echo.Context) error { case validate.InputErrors: gmap["errors"] = err gmap["form"] = form - return gctx.Render(http.StatusOK, "login.html", gmap) + return s.Render(c, http.StatusOK, "login.html", gmap) default: // Raise ISE if error is unrelated to input validation return err @@ -164,7 +157,7 @@ func (s *Service) LoginEmailPOST(c echo.Context) error { case validate.InputErrors: gmap["errors"] = err gmap["form"] = form - return gctx.Render(http.StatusOK, "login_email.html", gmap) + return s.Render(c, http.StatusOK, "login_email.html", gmap) default: // Raise ISE if error is unrelated to input validation return err @@ -269,9 +262,8 @@ func (s *Service) LoginEmailConf(c echo.Context) error { // ChangePassword changes the password for an authenticated user func (s *Service) ChangePassword(c echo.Context) error { - gctx := c.(*server.Context) gmap := s.fetch.ChangePasswordTemplateVars(c) - return gctx.Render(http.StatusOK, "change_password.html", gmap) + return s.Render(c, http.StatusOK, "change_password.html", gmap) } // ChangePasswordPOST changes the password for an authenticated user @@ -284,7 +276,7 @@ func (s *Service) ChangePasswordPOST(c echo.Context) error { case validate.InputErrors: gmap["errors"] = err gmap["form"] = form - return gctx.Render(http.StatusOK, "change_password.html", gmap) + return s.Render(c, http.StatusOK, "change_password.html", gmap) default: // Raise ISE if error is unrelated to input validation return err @@ -307,7 +299,7 @@ func (s *Service) ChangePasswordPOST(c echo.Context) error { } gmap["form"] = form - return gctx.Render(http.StatusOK, "change_password.html", gmap) + return s.Render(c, http.StatusOK, "change_password.html", gmap) } // ForgotPassword ... @@ -325,7 +317,7 @@ func (s *Service) ForgotPassword(c echo.Context) error { sent := c.QueryParam("sent") gmap := s.fetch.ForgotPasswordTemplateVars(c) gmap["sent"] = sent - return gctx.Render(http.StatusOK, "forgot_password.html", gmap) + return s.Render(c, http.StatusOK, "forgot_password.html", gmap) } // ForgotPasswordPOST ... @@ -342,7 +334,7 @@ func (s *Service) ForgotPasswordPOST(c echo.Context) error { case validate.InputErrors: gmap["errors"] = err gmap["form"] = form - return gctx.Render(http.StatusOK, "forgot_password.html", gmap) + return s.Render(c, http.StatusOK, "forgot_password.html", gmap) default: // Raise ISE if error is unrelated to input validation return err @@ -429,7 +421,6 @@ func (s *Service) ForgotPasswordConf(c echo.Context) error { return echo.NotFoundHandler(c) } - gctx := c.(*server.Context) conf, err := GetConfirmation(c.Request().Context(), key) if err != nil { if err == sql.ErrNoRows { @@ -460,7 +451,7 @@ func (s *Service) ForgotPasswordConf(c echo.Context) error { gmap := s.fetch.ForgotPasswordConfTemplateVars(c) gmap["guser"] = user gmap["key"] = key - return gctx.Render(http.StatusOK, "forgot_password_conf.html", gmap) + return s.Render(c, http.StatusOK, "forgot_password_conf.html", gmap) } // ForgotPasswordConfPOST changes the password for an authenticated user @@ -470,7 +461,6 @@ func (s *Service) ForgotPasswordConfPOST(c echo.Context) error { return echo.NotFoundHandler(c) } - gctx := c.(*server.Context) conf, err := GetConfirmation(c.Request().Context(), key) if err != nil { if err == sql.ErrNoRows { @@ -502,7 +492,7 @@ func (s *Service) ForgotPasswordConfPOST(c echo.Context) error { gmap["form"] = form gmap["guser"] = user gmap["key"] = key - return gctx.Render(http.StatusOK, "forgot_password_conf.html", gobwebs.Map{ + return s.Render(c, http.StatusOK, "forgot_password_conf.html", gobwebs.Map{ "errors": err, "form": form, "guser": user, @@ -533,7 +523,7 @@ func (s *Service) ForgotPasswordConfPOST(c echo.Context) error { return c.Redirect(http.StatusMovedPermanently, next) } - return gctx.Render(http.StatusOK, "forgot_password_conf_done.html", gmap) + return s.Render(c, http.StatusOK, "forgot_password_conf_done.html", gmap) } // ConfirmEmailConf confirms a users email and marks them as verified @@ -607,7 +597,7 @@ func (s *Service) UpdateEmail(c echo.Context) error { sent := c.QueryParam("sent") gmap := s.fetch.UpdateEmailTemplateVars(c) gmap["sent"] = sent - return gctx.Render(http.StatusOK, "update_email.html", gmap) + return s.Render(c, http.StatusOK, "update_email.html", gmap) } // UpdateEmailPOST changes the password for an authenticated user @@ -624,7 +614,7 @@ func (s *Service) UpdateEmailPOST(c echo.Context) error { case validate.InputErrors: gmap["errors"] = err gmap["form"] = form - return gctx.Render(http.StatusOK, "update_email.html", gmap) + return s.Render(c, http.StatusOK, "update_email.html", gmap) default: // Raise ISE if error is unrelated to input validation return err @@ -641,7 +631,7 @@ func (s *Service) UpdateEmailPOST(c echo.Context) error { nerr := fmt.Errorf("This email is currently registered to an existing account") gmap["errors"] = validate.GetInputErrors([]error{nerr}) gmap["form"] = form - return gctx.Render(http.StatusOK, "update_email.html", gmap) + return s.Render(c, http.StatusOK, "update_email.html", gmap) } // Email is not in our system. Verify there is no pending @@ -691,7 +681,7 @@ func (s *Service) UpdateEmailPOST(c echo.Context) error { nerr := fmt.Errorf("This email is currently pending confirmation for another account") gmap["errors"] = validate.GetInputErrors([]error{nerr}) gmap["form"] = form - return gctx.Render(http.StatusOK, "update_email.html", gmap) + return s.Render(c, http.StatusOK, "update_email.html", gmap) } // All looks good. Send confirmation email @@ -794,7 +784,9 @@ func (s *Service) UpdateEmailConf(c echo.Context) error { } // NewService return service -func NewService(eg *echo.Group, name string, fetch gobwebs.UserFetch) *Service { - service := &Service{name: name, fetch: fetch, eg: eg} +func NewService(eg *echo.Group, name string, + fetch gobwebs.UserFetch, render validate.TemplateRenderFunc) *Service { + baseService := server.NewService(eg, name, render) + service := &Service{BaseService: baseService, fetch: fetch} return service } diff --git a/server/service.go b/server/service.go new file mode 100644 index 0000000..3e583fe --- /dev/null +++ b/server/service.go @@ -0,0 +1,40 @@ +package server + +import ( + "fmt" + + "github.com/labstack/echo/v4" + "netlandish.com/x/gobwebs/validate" +) + +// BaseService is can be used as the base for a WebService interface +type BaseService struct { + Name string + Group *echo.Group + + RenderFunc validate.TemplateRenderFunc +} + +func (b *BaseService) RegisterRoutes() { + panic(fmt.Errorf("not implemented")) +} + +func (b *BaseService) RouteName(value string) string { + return fmt.Sprintf("%s:%s", b.Name, value) +} + +func (b *BaseService) Render(c echo.Context, code int, name string, data interface{}) error { + if b.RenderFunc != nil { + return b.RenderFunc(c, code, name, data) + } + gctx := c.(*Context) + return gctx.Render(code, name, data) +} + +func NewService(eg *echo.Group, name string, render validate.TemplateRenderFunc) BaseService { + return BaseService{ + Name: name, + Group: eg, + RenderFunc: render, + } +} -- 2.45.2