fix: fix routing and dependency injection

This commit is contained in:
Mark Bailey 2024-11-25 14:48:26 -05:00
parent 7b6f4f39c2
commit ae26700e59
11 changed files with 71 additions and 55 deletions

View File

@ -1,12 +1,12 @@
package controller package controller
import ( import (
"git.markbailey.dev/cerbervs/ptpp/app/session"
"git.markbailey.dev/cerbervs/ptpp/lib/logger"
"net/http" "net/http"
"git.markbailey.dev/cerbervs/ptpp/app/session"
"git.markbailey.dev/cerbervs/ptpp/lib/logger"
"git.markbailey.dev/cerbervs/ptpp/lib/database" "git.markbailey.dev/cerbervs/ptpp/lib/database"
werror "git.markbailey.dev/cerbervs/ptpp/lib/error"
) )
type IController interface { type IController interface {
@ -19,7 +19,7 @@ type IController interface {
Post(w http.ResponseWriter, r *http.Request) error Post(w http.ResponseWriter, r *http.Request) error
Patch(w http.ResponseWriter, r *http.Request) error Patch(w http.ResponseWriter, r *http.Request) error
Connect(w http.ResponseWriter, r *http.Request) error Connect(w http.ResponseWriter, r *http.Request) error
Init(session.IManager, database.IDB, logger.ILogger) error Init(session.IManager, database.IDB, logger.ILogger) IController
} }
type Controller struct { type Controller struct {
@ -28,8 +28,8 @@ type Controller struct {
Logger logger.ILogger Logger logger.ILogger
} }
func (c Controller) Init(s session.IManager, d database.IDB, l logger.ILogger) error { func (c Controller) Init(s session.IManager, d database.IDB, l logger.ILogger) IController {
return werror.Wrap(nil, "You must implement the init method in your extended controller") return nil
} }
func (c Controller) Get(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Get(w http.ResponseWriter, _ *http.Request) (_ error) {
@ -39,6 +39,7 @@ func (c Controller) Get(w http.ResponseWriter, _ *http.Request) (_ error) {
} }
return nil return nil
} }
func (c Controller) Head(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Head(w http.ResponseWriter, _ *http.Request) (_ error) {
if _, err := w.Write([]byte("not implemented")); err != nil { if _, err := w.Write([]byte("not implemented")); err != nil {
c.Logger.Error(c.Logger.Wrap(err, "Error writing response")) c.Logger.Error(c.Logger.Wrap(err, "Error writing response"))
@ -46,6 +47,7 @@ func (c Controller) Head(w http.ResponseWriter, _ *http.Request) (_ error) {
} }
return nil return nil
} }
func (c Controller) Options(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Options(w http.ResponseWriter, _ *http.Request) (_ error) {
if _, err := w.Write([]byte("not implemented")); err != nil { if _, err := w.Write([]byte("not implemented")); err != nil {
c.Logger.Error(c.Logger.Wrap(err, "Error writing response")) c.Logger.Error(c.Logger.Wrap(err, "Error writing response"))
@ -53,6 +55,7 @@ func (c Controller) Options(w http.ResponseWriter, _ *http.Request) (_ error) {
} }
return nil return nil
} }
func (c Controller) Trace(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Trace(w http.ResponseWriter, _ *http.Request) (_ error) {
if _, err := w.Write([]byte("not implemented")); err != nil { if _, err := w.Write([]byte("not implemented")); err != nil {
c.Logger.Error(c.Logger.Wrap(err, "Error writing response")) c.Logger.Error(c.Logger.Wrap(err, "Error writing response"))
@ -60,6 +63,7 @@ func (c Controller) Trace(w http.ResponseWriter, _ *http.Request) (_ error) {
} }
return nil return nil
} }
func (c Controller) Put(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Put(w http.ResponseWriter, _ *http.Request) (_ error) {
if _, err := w.Write([]byte("not implemented")); err != nil { if _, err := w.Write([]byte("not implemented")); err != nil {
c.Logger.Error(c.Logger.Wrap(err, "Error writing response")) c.Logger.Error(c.Logger.Wrap(err, "Error writing response"))
@ -67,6 +71,7 @@ func (c Controller) Put(w http.ResponseWriter, _ *http.Request) (_ error) {
} }
return nil return nil
} }
func (c Controller) Delete(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Delete(w http.ResponseWriter, _ *http.Request) (_ error) {
if _, err := w.Write([]byte("not implemented")); err != nil { if _, err := w.Write([]byte("not implemented")); err != nil {
c.Logger.Error(c.Logger.Wrap(err, "Error writing response")) c.Logger.Error(c.Logger.Wrap(err, "Error writing response"))
@ -74,6 +79,7 @@ func (c Controller) Delete(w http.ResponseWriter, _ *http.Request) (_ error) {
} }
return nil return nil
} }
func (c Controller) Post(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Post(w http.ResponseWriter, _ *http.Request) (_ error) {
if _, err := w.Write([]byte("not implemented")); err != nil { if _, err := w.Write([]byte("not implemented")); err != nil {
c.Logger.Error(c.Logger.Wrap(err, "Error writing response")) c.Logger.Error(c.Logger.Wrap(err, "Error writing response"))
@ -81,6 +87,7 @@ func (c Controller) Post(w http.ResponseWriter, _ *http.Request) (_ error) {
} }
return nil return nil
} }
func (c Controller) Patch(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Patch(w http.ResponseWriter, _ *http.Request) (_ error) {
if _, err := w.Write([]byte("not implemented")); err != nil { if _, err := w.Write([]byte("not implemented")); err != nil {
c.Logger.Error(c.Logger.Wrap(err, "Error writing response")) c.Logger.Error(c.Logger.Wrap(err, "Error writing response"))
@ -88,6 +95,7 @@ func (c Controller) Patch(w http.ResponseWriter, _ *http.Request) (_ error) {
} }
return nil return nil
} }
func (c Controller) Connect(w http.ResponseWriter, _ *http.Request) (_ error) { func (c Controller) Connect(w http.ResponseWriter, _ *http.Request) (_ error) {
if _, err := w.Write([]byte("not implemented")); err != nil { if _, err := w.Write([]byte("not implemented")); err != nil {
c.Logger.Error(c.Logger.Wrap(err, "Error writing response")) c.Logger.Error(c.Logger.Wrap(err, "Error writing response"))

View File

@ -1,10 +1,12 @@
package handler package handler
import "net/http" import (
"net/http"
)
type Handler func(http.ResponseWriter, *http.Request) error type HandlerFunc func(http.ResponseWriter, *http.Request) error
func (fn Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (fn HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil { if err := fn(w, r); err != nil {
w.Header().Set("HX-Retarget", "#layout_content") w.Header().Set("HX-Retarget", "#layout_content")
w.Header().Set("HX-Reswap", "innerHTML") w.Header().Set("HX-Reswap", "innerHTML")

View File

@ -1,6 +1,8 @@
package routing package routing
import ( import (
"net/http"
"git.markbailey.dev/cerbervs/ptpp/app/controller" "git.markbailey.dev/cerbervs/ptpp/app/controller"
"git.markbailey.dev/cerbervs/ptpp/app/handler" "git.markbailey.dev/cerbervs/ptpp/app/handler"
"git.markbailey.dev/cerbervs/ptpp/app/session" "git.markbailey.dev/cerbervs/ptpp/app/session"
@ -9,7 +11,6 @@ import (
"git.markbailey.dev/cerbervs/ptpp/lib/logger" "git.markbailey.dev/cerbervs/ptpp/lib/logger"
"git.markbailey.dev/cerbervs/ptpp/lib/middleware" "git.markbailey.dev/cerbervs/ptpp/lib/middleware"
"git.markbailey.dev/cerbervs/ptpp/util" "git.markbailey.dev/cerbervs/ptpp/util"
"net/http"
) )
var sess session.IManager var sess session.IManager
@ -26,21 +27,22 @@ type Route struct {
type Router struct { type Router struct {
Mux *http.ServeMux Mux *http.ServeMux
BasePath string
Routes []Route
SubRouters *[]Router SubRouters *[]Router
Middleware *[]middleware.Func Middleware *[]middleware.Func
BasePath string
Routes []Route
} }
func (r Router) HandleAllRequestMethods(route Route) { func (r Router) HandleAllRequestMethods(route Route) {
r.Mux.Handle("GET "+r.BasePath+route.Path, handler.Handler(route.Controller.Get)) c := route.Controller.Init(sess, database.ChooseDB(), logger.NewCompositeLogger())
r.Mux.Handle("OPTIONS "+r.BasePath+route.Path, handler.Handler(route.Controller.Options)) r.Mux.Handle("GET "+r.BasePath+route.Path, handler.HandlerFunc(c.Get))
r.Mux.Handle("TRACE "+r.BasePath+route.Path, handler.Handler(route.Controller.Trace)) r.Mux.Handle("OPTIONS "+r.BasePath+route.Path, handler.HandlerFunc(c.Options))
r.Mux.Handle("PUT "+r.BasePath+route.Path, handler.Handler(route.Controller.Put)) r.Mux.Handle("TRACE "+r.BasePath+route.Path, handler.HandlerFunc(c.Trace))
r.Mux.Handle("DELETE "+r.BasePath+route.Path, handler.Handler(route.Controller.Delete)) r.Mux.Handle("PUT "+r.BasePath+route.Path, handler.HandlerFunc(c.Put))
r.Mux.Handle("POST "+r.BasePath+route.Path, handler.Handler(route.Controller.Post)) r.Mux.Handle("DELETE "+r.BasePath+route.Path, handler.HandlerFunc(c.Delete))
r.Mux.Handle("PATCH "+r.BasePath+route.Path, handler.Handler(route.Controller.Patch)) r.Mux.Handle("POST "+r.BasePath+route.Path, handler.HandlerFunc(c.Post))
r.Mux.Handle("CONNECT "+r.BasePath+route.Path, handler.Handler(route.Controller.Connect)) r.Mux.Handle("PATCH "+r.BasePath+route.Path, handler.HandlerFunc(c.Patch))
r.Mux.Handle("CONNECT "+r.BasePath+route.Path, handler.HandlerFunc(c.Connect))
} }
func (r Router) RegisterRoutes() http.Handler { func (r Router) RegisterRoutes() http.Handler {
@ -49,10 +51,6 @@ func (r Router) RegisterRoutes() http.Handler {
} }
for _, route := range r.Routes { for _, route := range r.Routes {
if err := route.Controller.Init(sess, database.ChooseDB(), logger.NewCompositeLogger()); err != nil {
panic(err)
}
r.HandleAllRequestMethods(route) r.HandleAllRequestMethods(route)
} }
@ -108,6 +106,7 @@ func (r Router) GetRouteByName(name string) (string, error) {
return "", werror.Wrap(nil, "Route not found") return "", werror.Wrap(nil, "Route not found")
} }
func init() { func init() {
var err error var err error

View File

@ -11,7 +11,7 @@ var AppRouter = Router{
Mux: http.NewServeMux(), Mux: http.NewServeMux(),
BasePath: "/", BasePath: "/",
Routes: []Route{ Routes: []Route{
{Controller: &shared.HomePageHandler{}, Path: "", Name: "app.index"}, {Controller: &shared.HomePageController{}, Path: "", Name: "app.index"},
{Controller: &shared.SignUpHandler{}, Path: "sign-up", Name: "app.user.sign_up"}, {Controller: &shared.SignUpHandler{}, Path: "sign-up", Name: "app.user.sign_up"},
{Controller: &shared.SignInHandler{}, Path: "sign-in", Name: "app.user.sign_in"}, {Controller: &shared.SignInHandler{}, Path: "sign-in", Name: "app.user.sign_in"},
{Controller: &shared.SignOutHandler{}, Path: "sign-out", Name: "app.user.sign_out"}, {Controller: &shared.SignOutHandler{}, Path: "sign-out", Name: "app.user.sign_out"},

2
go.mod
View File

@ -1,6 +1,6 @@
module git.markbailey.dev/cerbervs/ptpp module git.markbailey.dev/cerbervs/ptpp
go 1.23.2 go 1.23
require ( require (
github.com/a-h/templ v0.2.793 github.com/a-h/templ v0.2.793

View File

@ -17,12 +17,12 @@ type IndexHandler struct {
controller.Controller controller.Controller
} }
func (h IndexHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) error { func (h IndexHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) controller.IController {
h.Logger = l h.Logger = l
h.Db = d h.Db = d
h.Session = s h.Session = s
return nil return h
} }
func (h IndexHandler) Get(w http.ResponseWriter, r *http.Request) error { func (h IndexHandler) Get(w http.ResponseWriter, r *http.Request) error {

View File

@ -13,19 +13,19 @@ import (
"git.markbailey.dev/cerbervs/ptpp/view/homepage" "git.markbailey.dev/cerbervs/ptpp/view/homepage"
) )
type HomePageHandler struct { type HomePageController struct {
controller.Controller controller.Controller
} }
func (h HomePageHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) error { func (c HomePageController) Init(s session.IManager, d database.IDB, l logger.ILogger) controller.IController {
h.Logger = l c.Logger = l
h.Db = d c.Db = d
h.Session = s c.Session = s
return nil return c
} }
func (h HomePageHandler) Get(w http.ResponseWriter, r *http.Request) error { func (h HomePageController) Get(w http.ResponseWriter, r *http.Request) error {
if r.URL.Path != "/" { if r.URL.Path != "/" {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
err := layout.NotFound().Render(context.Background(), w) err := layout.NotFound().Render(context.Background(), w)

View File

@ -3,14 +3,15 @@ package shared
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"net/http"
"time"
"git.markbailey.dev/cerbervs/ptpp/app/controller" "git.markbailey.dev/cerbervs/ptpp/app/controller"
"git.markbailey.dev/cerbervs/ptpp/app/session" "git.markbailey.dev/cerbervs/ptpp/app/session"
"git.markbailey.dev/cerbervs/ptpp/lib/database" "git.markbailey.dev/cerbervs/ptpp/lib/database"
"git.markbailey.dev/cerbervs/ptpp/lib/database/dto" "git.markbailey.dev/cerbervs/ptpp/lib/database/dto"
"git.markbailey.dev/cerbervs/ptpp/lib/logger" "git.markbailey.dev/cerbervs/ptpp/lib/logger"
"git.markbailey.dev/cerbervs/ptpp/util" "git.markbailey.dev/cerbervs/ptpp/util"
"net/http"
"time"
"git.markbailey.dev/cerbervs/ptpp/view/user" "git.markbailey.dev/cerbervs/ptpp/view/user"
) )
@ -19,48 +20,48 @@ type SignUpHandler struct {
controller.Controller controller.Controller
} }
func (c SignUpHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) error { func (c SignUpHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) controller.IController {
c.Logger = l c.Logger = l
c.Db = d c.Db = d
c.Session = s c.Session = s
return nil return c
} }
type SignInHandler struct { type SignInHandler struct {
controller.Controller controller.Controller
} }
func (c SignInHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) error { func (c SignInHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) controller.IController {
c.Logger = l c.Logger = l
c.Db = d c.Db = d
c.Session = s c.Session = s
return nil return c
} }
type PopulateHandler struct { type PopulateHandler struct {
controller.Controller controller.Controller
} }
func (c PopulateHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) error { func (c PopulateHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) controller.IController {
c.Logger = l c.Logger = l
c.Db = d c.Db = d
c.Session = s c.Session = s
return nil return c
} }
type SignOutHandler struct { type SignOutHandler struct {
controller.Controller controller.Controller
} }
func (c SignOutHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) error { func (c SignOutHandler) Init(s session.IManager, d database.IDB, l logger.ILogger) controller.IController {
c.Logger = l c.Logger = l
c.Db = d c.Db = d
c.Session = s c.Session = s
return nil return c
} }
func (c PopulateHandler) Get(w http.ResponseWriter, r *http.Request) error { func (c PopulateHandler) Get(w http.ResponseWriter, r *http.Request) error {
@ -144,7 +145,7 @@ func (c SignInHandler) Post(w http.ResponseWriter, r *http.Request) error {
foundUser, err := c.Db.Repo().FindUserByUsername(fd.Username) foundUser, err := c.Db.Repo().FindUserByUsername(fd.Username)
if foundUser == nil || err != nil { if foundUser == nil || err != nil {
return util.Redirect(w, r, "/sign-in", http.StatusSeeOther, false) return util.Redirect(w, r, "/sign-in", http.StatusPermanentRedirect, false)
} }
authenticated, err := util.CheckPassword(fd.Password, foundUser.Password) authenticated, err := util.CheckPassword(fd.Password, foundUser.Password)
@ -250,6 +251,10 @@ func (c SignUpHandler) Post(w http.ResponseWriter, r *http.Request) error {
} }
foundUser, err := c.Db.Repo().FindUserByUsername(fd.Username) foundUser, err := c.Db.Repo().FindUserByUsername(fd.Username)
if err != nil {
c.Db.Error(err)
return err
}
if foundUser != nil { if foundUser != nil {
if _, err := w.Write([]byte("Invalid username. Please try another")); err != nil { if _, err := w.Write([]byte("Invalid username. Please try another")); err != nil {

View File

@ -75,15 +75,15 @@ func WithAuth(next http.Handler) http.Handler {
} }
if cookie, err = r.Cookie("token"); err != nil { if cookie, err = r.Cookie("token"); err != nil {
_ = util.Redirect(w, r, "/signin", http.StatusSeeOther, true) _ = util.Redirect(w, r, "/sign-in", http.StatusPermanentRedirect, true)
return return
} }
if token = cookie.Value; token == "" { if token = cookie.Value; token == "" {
_ = util.Redirect(w, r, "/signin", http.StatusSeeOther, true) _ = util.Redirect(w, r, "/sign-in", http.StatusPermanentRedirect, true)
return return
} }
if claims, err = util.ParseToken(token, os.Getenv("TOKEN_SECRET")); err != nil { if claims, err = util.ParseToken(token, os.Getenv("TOKEN_SECRET")); err != nil {
_ = util.Redirect(w, r, "/signin", http.StatusSeeOther, true) _ = util.Redirect(w, r, "/sign-in", http.StatusPermanentRedirect, true)
return return
} }
@ -136,5 +136,9 @@ func WithUsername(next http.Handler) http.Handler {
} }
func init() { func init() {
sess, _ = session.NewManager("memory", "ptpp", 3600) var err error
sess, err = session.NewManager("memory", "ptpp", 3600)
if err != nil {
panic(err)
}
} }

View File

@ -15,9 +15,7 @@ templ SignIn(err string) {
</h1> </h1>
<form <form
class="space-y-4 md:space-y-6" class="space-y-4 md:space-y-6"
action="/sign-in" hx-post="/sign-in"
method="post"
hx-post="/signin"
hx-swap="outerHTML" hx-swap="outerHTML"
hx-target="#section" hx-target="#section"
> >

View File

@ -43,7 +43,7 @@ func SignIn(err string) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<section class=\"bg-gray-50 dark:bg-gray-900\" id=\"section\"><div class=\"flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0\"><div class=\"w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700\"><div class=\"p-6 space-y-4 md:space-y-6 sm:p-8\"><h1 class=\"text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white\">Create an account</h1><form class=\"space-y-4 md:space-y-6\" action=\"/sign-in\" method=\"post\" hx-post=\"/signin\" hx-swap=\"outerHTML\" hx-target=\"#section\"><div><label for=\"username\" class=\"block mb-2 text-sm font-medium text-gray-900 dark:text-white\">Username</label> <input type=\"text\" name=\"username\" id=\"username\" placeholder=\"Username\" class=\"bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\" required=\"true\"></div><div><label for=\"password\" class=\"block mb-2 text-sm font-medium text-gray-900 dark:text-white\">Password</label> <input type=\"password\" name=\"password\" id=\"password\" placeholder=\"••••••••\" class=\"bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\" required=\"true\"></div>") _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<section class=\"bg-gray-50 dark:bg-gray-900\" id=\"section\"><div class=\"flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0\"><div class=\"w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700\"><div class=\"p-6 space-y-4 md:space-y-6 sm:p-8\"><h1 class=\"text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white\">Create an account</h1><form class=\"space-y-4 md:space-y-6\" hx-post=\"/sign-in\" hx-swap=\"outerHTML\" hx-target=\"#section\"><div><label for=\"username\" class=\"block mb-2 text-sm font-medium text-gray-900 dark:text-white\">Username</label> <input type=\"text\" name=\"username\" id=\"username\" placeholder=\"Username\" class=\"bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\" required=\"true\"></div><div><label for=\"password\" class=\"block mb-2 text-sm font-medium text-gray-900 dark:text-white\">Password</label> <input type=\"password\" name=\"password\" id=\"password\" placeholder=\"••••••••\" class=\"bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500\" required=\"true\"></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -55,7 +55,7 @@ func SignIn(err string) templ.Component {
var templ_7745c5c3_Var3 string var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(err) templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(err)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/signin.templ`, Line: 54, Col: 14} return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/user/signin.templ`, Line: 52, Col: 14}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {