diff options
| author | AKP <tom@tdpain.net> | 2022-04-01 21:54:24 +0100 |
|---|---|---|
| committer | AKP <tom@tdpain.net> | 2022-04-01 21:54:24 +0100 |
| commit | b9d32fc0488fa6a16c1c15cf92f905f4e54bca09 (patch) | |
| tree | fd0b46dfb143635bf871a48f9e1a32a27f340e64 /walrss | |
| parent | 5b1336c229ffbb26eb17b611fab3ccfe17e2d3c6 (diff) | |
god knows what all of this is
Signed-off-by: AKP <tom@tdpain.net>
Diffstat (limited to 'walrss')
| -rw-r--r-- | walrss/internal/core/users.go | 18 | ||||
| -rw-r--r-- | walrss/internal/http/auth.go | 100 | ||||
| -rw-r--r-- | walrss/internal/http/http.go | 24 | ||||
| -rw-r--r-- | walrss/internal/http/views/layoutComponents.qtpl.html | 9 | ||||
| -rw-r--r-- | walrss/internal/http/views/layoutComponents.qtpl.html.go | 43 | ||||
| -rw-r--r-- | walrss/internal/http/views/page.qtpl.html | 59 | ||||
| -rw-r--r-- | walrss/internal/http/views/page.qtpl.html.go | 237 | ||||
| -rw-r--r-- | walrss/internal/http/views/register.qtpl.html | 37 | ||||
| -rw-r--r-- | walrss/internal/http/views/register.qtpl.html.go | 96 | ||||
| -rw-r--r-- | walrss/internal/http/views/signin.qtpl.html | 33 | ||||
| -rw-r--r-- | walrss/internal/http/views/signin.qtpl.html.go | 92 | ||||
| -rw-r--r-- | walrss/internal/http/views/views.go | 19 |
12 files changed, 746 insertions, 21 deletions
diff --git a/walrss/internal/core/users.go b/walrss/internal/core/users.go index dfc3635..2343de7 100644 --- a/walrss/internal/core/users.go +++ b/walrss/internal/core/users.go @@ -42,11 +42,8 @@ func RegisterUser(st *state.State, email, password string) (*db.User, error) { } func AreUserCredentialsCorrect(st *state.State, email, password string) (bool, error) { - user := new(db.User) - if err := st.Data.FindOne(user, bh.Where("Email").Eq(email)); err != nil { - if errors.Is(err, bh.ErrNotFound) { - return false, ErrNotFound - } + user, err := GetUserByEmail(st, email) + if err != nil { return false, err } @@ -59,3 +56,14 @@ func AreUserCredentialsCorrect(st *state.State, email, password string) (bool, e return true, nil } + +func GetUserByEmail(st *state.State, userID string) (*db.User, error) { + user := new(db.User) + if err := st.Data.FindOne(user, bh.Where("Email").Eq(userID)); err != nil { + if errors.Is(err, bh.ErrNotFound) { + return nil, ErrNotFound + } + return nil, err + } + return user, nil +} diff --git a/walrss/internal/http/auth.go b/walrss/internal/http/auth.go index 7be4078..eff478d 100644 --- a/walrss/internal/http/auth.go +++ b/walrss/internal/http/auth.go @@ -1,29 +1,99 @@ package http import ( + "errors" "github.com/codemicro/walrss/walrss/internal/core" + "github.com/codemicro/walrss/walrss/internal/http/views" + "github.com/codemicro/walrss/walrss/internal/urls" "github.com/gofiber/fiber/v2" "time" ) func (s *Server) authRegister(ctx *fiber.Ctx) error { - user, err := core.RegisterUser(s.state, - ctx.FormValue("email"), - ctx.FormValue("password"), - ) - if err != nil { - return err + page := new(views.RegisterPage) + + if ctx.Method() == fiber.MethodPost { + password := ctx.FormValue("password") + passwordConfirmation := ctx.FormValue("passwordConfirmation") + if password != passwordConfirmation { + page.Problem = "Passwords do not match" + goto exit + } + + user, err := core.RegisterUser( + s.state, + ctx.FormValue("email"), + password, + ) + if err != nil { + if core.IsUserError(err) { + ctx.Status(core.GetUserErrorStatus(err)) + page.Problem = "Could not register account: " + err.Error() + goto exit + } + return err + } + + token := core.GenerateSessionToken(user.ID) + + ctx.Cookie(&fiber.Cookie{ + Name: sessionCookieKey, + Value: token, + Expires: time.Now().UTC().Add(sessionDuration), + Secure: !s.state.Config.Debug, + HTTPOnly: true, + }) + + return ctx.Redirect(urls.Index) } - token := core.GenerateSessionToken(user.ID) +exit: + return views.SendPage(ctx, page) +} + +func (s *Server) authSignIn(ctx *fiber.Ctx) error { + page := &views.SignInPage{} + + if ctx.Method() == fiber.MethodPost { + email := ctx.FormValue("email") + + ok, err := core.AreUserCredentialsCorrect( + s.state, + email, + ctx.FormValue("password"), + ) + if err != nil { + if errors.Is(err, core.ErrNotFound) { + goto incorrectUsernameOrPassword + } + return err + } + + if !ok { + goto incorrectUsernameOrPassword + } + + user, err := core.GetUserByEmail(s.state, email) + if err != nil { + return err + } + + token := core.GenerateSessionToken(user.ID) + + ctx.Cookie(&fiber.Cookie{ + Name: sessionCookieKey, + Value: token, + Expires: time.Now().UTC().Add(sessionDuration), + Secure: !s.state.Config.Debug, + HTTPOnly: true, + }) + + return ctx.Redirect(urls.Index) + } - ctx.Cookie(&fiber.Cookie{ - Name: sessionCookieKey, - Value: token, - Expires: time.Now().UTC().Add(sessionDuration), - Secure: !s.state.Config.Debug, - HTTPOnly: true, - }) + return views.SendPage(ctx, page) - return ctx.SendString("ok!") +incorrectUsernameOrPassword: + ctx.Status(fiber.StatusUnauthorized) + return views.SendPage(ctx, &views.SignInPage{Problem: "Incorrect username or password"}) } diff --git a/walrss/internal/http/http.go b/walrss/internal/http/http.go index 5af260e..92829f7 100644 --- a/walrss/internal/http/http.go +++ b/walrss/internal/http/http.go @@ -5,6 +5,7 @@ import ( "github.com/codemicro/walrss/walrss/internal/state" "github.com/codemicro/walrss/walrss/internal/urls" "github.com/gofiber/fiber/v2" + "github.com/rs/zerolog/log" "time" ) @@ -22,8 +23,25 @@ func New(st *state.State) (*Server, error) { app := fiber.New(fiber.Config{ DisableStartupMessage: !st.Config.Debug, AppName: "Walrss", + ErrorHandler: func(ctx *fiber.Ctx, err error) error { + code := fiber.StatusInternalServerError + msg := "Internal Server Error" + + switch e := err.(type) { + case *fiber.Error: + code = e.Code + msg = err.Error() + case *core.UserError: + code = e.Status + msg = err.Error() + default: + log.Error().Err(err).Str("location", "http").Str("url", ctx.OriginalURL()).Send() + } + + ctx.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8) + return ctx.Status(code).SendString(msg) + }, }) - // TODO: Add error handler with UserError support s := &Server{ state: st, @@ -36,7 +54,11 @@ func New(st *state.State) (*Server, error) { } func (s *Server) registerHandlers() { + s.app.Get(urls.AuthRegister, s.authRegister) s.app.Post(urls.AuthRegister, s.authRegister) + + s.app.Get(urls.AuthSignIn, s.authSignIn) + s.app.Post(urls.AuthSignIn, s.authSignIn) } func (s *Server) Run() error { diff --git a/walrss/internal/http/views/layoutComponents.qtpl.html b/walrss/internal/http/views/layoutComponents.qtpl.html new file mode 100644 index 0000000..bc3ef1c --- /dev/null +++ b/walrss/internal/http/views/layoutComponents.qtpl.html @@ -0,0 +1,9 @@ +{% import "github.com/codemicro/walrss/walrss/internal/urls" %} + +{% func navbar() %} +<nav class="navbar navbar-light bg-light mb-3"> + <div class="container-fluid"> + <a class="navbar-brand" href="{%s= urls.Index %}">Walrss</a> + </div> +</nav> +{% endfunc %}
\ No newline at end of file diff --git a/walrss/internal/http/views/layoutComponents.qtpl.html.go b/walrss/internal/http/views/layoutComponents.qtpl.html.go new file mode 100644 index 0000000..28af874 --- /dev/null +++ b/walrss/internal/http/views/layoutComponents.qtpl.html.go @@ -0,0 +1,43 @@ +// Code generated by qtc from "layoutComponents.qtpl.html". DO NOT EDIT. +// See https://github.com/valyala/quicktemplate for details. + +package views + +import "github.com/codemicro/walrss/walrss/internal/urls" + +import ( + qtio422016 "io" + + qt422016 "github.com/valyala/quicktemplate" +) + +var ( + _ = qtio422016.Copy + _ = qt422016.AcquireByteBuffer +) + +func streamnavbar(qw422016 *qt422016.Writer) { + qw422016.N().S(` +<nav class="navbar navbar-light bg-light mb-3"> + <div class="container-fluid"> + <a class="navbar-brand" href="`) + qw422016.N().S(urls.Index) + qw422016.N().S(`">Walrss</a> + </div> +</nav> +`) +} + +func writenavbar(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + streamnavbar(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func navbar() string { + qb422016 := qt422016.AcquireByteBuffer() + writenavbar(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} diff --git a/walrss/internal/http/views/page.qtpl.html b/walrss/internal/http/views/page.qtpl.html new file mode 100644 index 0000000..968ea7d --- /dev/null +++ b/walrss/internal/http/views/page.qtpl.html @@ -0,0 +1,59 @@ +{% interface +Page { + Title() + Body() + HeadContent() +} +%} + +Page prints a page implementing Page interface. +{% func RenderPage(p Page) %} +<!DOCTYPE html> +<html> +<head> + <title>{%s= makePageTitle(p) %}</title> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> + {%= p.HeadContent() %} +</head> +<body> +{%= p.Body() %} +</body> +</html> +{% endfunc %} + +{% code type BasePage struct {} %} +{% func (p *BasePage) Title() %}{% endfunc %} +{% func (p *BasePage) HeadContent() %}{% endfunc %} + +{% func ProblemBox(p string) %} +<div class="alert alert-danger" role="alert"> + {%s= p %} +</div> +{% endfunc %} + +{% func SuccessBox(p string) %} +<div class="alert alert-success" role="alert"> + {%s= p %} +</div> +{% endfunc %} + +{% func WarningBox(p string) %} +<div class="alert alert-warning" role="alert"> + {%s= p %} +</div> +{% endfunc %} + +PolyPage is used to create a basic page dynamically using Daz. +{% code +type PolyPage struct { + BasePage + TitleString string + BodyContent string + ExtraHeadContent string +} +%} + +{% func (p *PolyPage) Title() %}{%s= p.TitleString %}{% endfunc %} +{% func (p *PolyPage) Body() %}{%s= p.BodyContent %}{% endfunc %} +{% func (p *PolyPage) HeadContent() %}{%s= p.ExtraHeadContent %}{% endfunc %}
\ No newline at end of file diff --git a/walrss/internal/http/views/page.qtpl.html.go b/walrss/internal/http/views/page.qtpl.html.go new file mode 100644 index 0000000..125a3b0 --- /dev/null +++ b/walrss/internal/http/views/page.qtpl.html.go @@ -0,0 +1,237 @@ +// Code generated by qtc from "page.qtpl.html". DO NOT EDIT. +// See https://github.com/valyala/quicktemplate for details. + +package views + +import ( + qtio422016 "io" + + qt422016 "github.com/valyala/quicktemplate" +) + +var ( + _ = qtio422016.Copy + _ = qt422016.AcquireByteBuffer +) + +type Page interface { + Title() string + StreamTitle(qw422016 *qt422016.Writer) + WriteTitle(qq422016 qtio422016.Writer) + Body() string + StreamBody(qw422016 *qt422016.Writer) + WriteBody(qq422016 qtio422016.Writer) + HeadContent() string + StreamHeadContent(qw422016 *qt422016.Writer) + WriteHeadContent(qq422016 qtio422016.Writer) +} + +// Page prints a page implementing Page interface. + +func StreamRenderPage(qw422016 *qt422016.Writer, p Page) { + qw422016.N().S(` +<!DOCTYPE html> +<html> +<head> + <title>`) + qw422016.N().S(makePageTitle(p)) + qw422016.N().S(`</title> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> + `) + p.StreamHeadContent(qw422016) + qw422016.N().S(` +</head> +<body> +`) + p.StreamBody(qw422016) + qw422016.N().S(` +</body> +</html> +`) +} + +func WriteRenderPage(qq422016 qtio422016.Writer, p Page) { + qw422016 := qt422016.AcquireWriter(qq422016) + StreamRenderPage(qw422016, p) + qt422016.ReleaseWriter(qw422016) +} + +func RenderPage(p Page) string { + qb422016 := qt422016.AcquireByteBuffer() + WriteRenderPage(qb422016, p) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +type BasePage struct{} + +func (p *BasePage) StreamTitle(qw422016 *qt422016.Writer) { +} + +func (p *BasePage) WriteTitle(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamTitle(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *BasePage) Title() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteTitle(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +func (p *BasePage) StreamHeadContent(qw422016 *qt422016.Writer) { +} + +func (p *BasePage) WriteHeadContent(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamHeadContent(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *BasePage) HeadContent() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteHeadContent(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +func StreamProblemBox(qw422016 *qt422016.Writer, p string) { + qw422016.N().S(` +<div class="alert alert-danger" role="alert"> + `) + qw422016.N().S(p) + qw422016.N().S(` +</div> +`) +} + +func WriteProblemBox(qq422016 qtio422016.Writer, p string) { + qw422016 := qt422016.AcquireWriter(qq422016) + StreamProblemBox(qw422016, p) + qt422016.ReleaseWriter(qw422016) +} + +func ProblemBox(p string) string { + qb422016 := qt422016.AcquireByteBuffer() + WriteProblemBox(qb422016, p) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +func StreamSuccessBox(qw422016 *qt422016.Writer, p string) { + qw422016.N().S(` +<div class="alert alert-success" role="alert"> + `) + qw422016.N().S(p) + qw422016.N().S(` +</div> +`) +} + +func WriteSuccessBox(qq422016 qtio422016.Writer, p string) { + qw422016 := qt422016.AcquireWriter(qq422016) + StreamSuccessBox(qw422016, p) + qt422016.ReleaseWriter(qw422016) +} + +func SuccessBox(p string) string { + qb422016 := qt422016.AcquireByteBuffer() + WriteSuccessBox(qb422016, p) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +func StreamWarningBox(qw422016 *qt422016.Writer, p string) { + qw422016.N().S(` +<div class="alert alert-warning" role="alert"> + `) + qw422016.N().S(p) + qw422016.N().S(` +</div> +`) +} + +func WriteWarningBox(qq422016 qtio422016.Writer, p string) { + qw422016 := qt422016.AcquireWriter(qq422016) + StreamWarningBox(qw422016, p) + qt422016.ReleaseWriter(qw422016) +} + +func WarningBox(p string) string { + qb422016 := qt422016.AcquireByteBuffer() + WriteWarningBox(qb422016, p) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +// PolyPage is used to create a basic page dynamically using Daz. + +type PolyPage struct { + BasePage + TitleString string + BodyContent string + ExtraHeadContent string +} + +func (p *PolyPage) StreamTitle(qw422016 *qt422016.Writer) { + qw422016.N().S(p.TitleString) +} + +func (p *PolyPage) WriteTitle(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamTitle(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *PolyPage) Title() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteTitle(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +func (p *PolyPage) StreamBody(qw422016 *qt422016.Writer) { + qw422016.N().S(p.BodyContent) +} + +func (p *PolyPage) WriteBody(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamBody(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *PolyPage) Body() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteBody(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +func (p *PolyPage) StreamHeadContent(qw422016 *qt422016.Writer) { + qw422016.N().S(p.ExtraHeadContent) +} + +func (p *PolyPage) WriteHeadContent(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamHeadContent(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *PolyPage) HeadContent() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteHeadContent(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} diff --git a/walrss/internal/http/views/register.qtpl.html b/walrss/internal/http/views/register.qtpl.html new file mode 100644 index 0000000..812a671 --- /dev/null +++ b/walrss/internal/http/views/register.qtpl.html @@ -0,0 +1,37 @@ +{% import "github.com/codemicro/walrss/walrss/internal/urls" %} + +{% code type RegisterPage struct { + BasePage + Problem string +} %} + +{% func (p *RegisterPage) Title() %}Register{% endfunc %} +{% func (p *RegisterPage) Body() %} +{%= navbar() %} + +<div class="container"> + <h1>Register</h1> + + {% if p.Problem != "" %} + {%= ProblemBox(p.Problem) %} + {% endif %} + + <form action="" method="post"> + <div class="mb-3"> + <label for="emailInput" class="form-label">Email address</label> + <input type="email" class="form-control" id="emailInput" name="email"> + </div> + <div class="mb-3"> + <label for="passwordInput" class="form-label">Password</label> + <input type="password" class="form-control" id="passwordInput" name="password"> + </div> + <div class="mb-3"> + <label for="passwordConfirmation" class="form-label">Retype password</label> + <input type="password" class="form-control" id="passwordConfirmation" name="passwordConfirmation"> + </div> + <button type="submit" class="btn btn-primary">Submit</button> + </form> + <br> + <a href="{%s= urls.AuthSignIn %}">Already got an account? Click here to sign in</a> +</div> +{% endfunc %}
\ No newline at end of file diff --git a/walrss/internal/http/views/register.qtpl.html.go b/walrss/internal/http/views/register.qtpl.html.go new file mode 100644 index 0000000..d25fdfb --- /dev/null +++ b/walrss/internal/http/views/register.qtpl.html.go @@ -0,0 +1,96 @@ +// Code generated by qtc from "register.qtpl.html". DO NOT EDIT. +// See https://github.com/valyala/quicktemplate for details. + +package views + +import "github.com/codemicro/walrss/walrss/internal/urls" + +import ( + qtio422016 "io" + + qt422016 "github.com/valyala/quicktemplate" +) + +var ( + _ = qtio422016.Copy + _ = qt422016.AcquireByteBuffer +) + +type RegisterPage struct { + BasePage + Problem string +} + +func (p *RegisterPage) StreamTitle(qw422016 *qt422016.Writer) { + qw422016.N().S(`Register`) +} + +func (p *RegisterPage) WriteTitle(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamTitle(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *RegisterPage) Title() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteTitle(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +func (p *RegisterPage) StreamBody(qw422016 *qt422016.Writer) { + qw422016.N().S(` +`) + streamnavbar(qw422016) + qw422016.N().S(` + +<div class="container"> + <h1>Register</h1> + + `) + if p.Problem != "" { + qw422016.N().S(` + `) + StreamProblemBox(qw422016, p.Problem) + qw422016.N().S(` + `) + } + qw422016.N().S(` + + <form action="" method="post"> + <div class="mb-3"> + <label for="emailInput" class="form-label">Email address</label> + <input type="email" class="form-control" id="emailInput" name="email"> + </div> + <div class="mb-3"> + <label for="passwordInput" class="form-label">Password</label> + <input type="password" class="form-control" id="passwordInput" name="password"> + </div> + <div class="mb-3"> + <label for="passwordConfirmation" class="form-label">Retype password</label> + <input type="password" class="form-control" id="passwordConfirmation" name="passwordConfirmation"> + </div> + <button type="submit" class="btn btn-primary">Submit</button> + </form> + <br> + <a href="`) + qw422016.N().S(urls.AuthSignIn) + qw422016.N().S(`">Already got an account? Click here to sign in</a> +</div> +`) +} + +func (p *RegisterPage) WriteBody(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamBody(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *RegisterPage) Body() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteBody(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} diff --git a/walrss/internal/http/views/signin.qtpl.html b/walrss/internal/http/views/signin.qtpl.html new file mode 100644 index 0000000..3022f7f --- /dev/null +++ b/walrss/internal/http/views/signin.qtpl.html @@ -0,0 +1,33 @@ +{% import "github.com/codemicro/walrss/walrss/internal/urls" %} + +{% code type SignInPage struct { + BasePage + Problem string +} %} + +{% func (p *SignInPage) Title() %}Sign in{% endfunc %} +{% func (p *SignInPage) Body() %} +{%= navbar() %} + +<div class="container"> + <h1>Sign in</h1> + + {% if p.Problem != "" %} + {%= ProblemBox(p.Problem) %} + {% endif %} + + <form action="" method="post"> + <div class="mb-3"> + <label for="emailInput" class="form-label">Email address</label> + <input type="email" class="form-control" id="emailInput" name="email"> + </div> + <div class="mb-3"> + <label for="passwordInput" class="form-label">Password</label> + <input type="password" class="form-control" id="passwordInput" name="password"> + </div> + <button type="submit" class="btn btn-primary">Submit</button> + </form> + <br> + <a href="{%s= urls.AuthRegister %}">No account? Click here to register</a> +</div> +{% endfunc %}
\ No newline at end of file diff --git a/walrss/internal/http/views/signin.qtpl.html.go b/walrss/internal/http/views/signin.qtpl.html.go new file mode 100644 index 0000000..ba433dd --- /dev/null +++ b/walrss/internal/http/views/signin.qtpl.html.go @@ -0,0 +1,92 @@ +// Code generated by qtc from "signin.qtpl.html". DO NOT EDIT. +// See https://github.com/valyala/quicktemplate for details. + +package views + +import "github.com/codemicro/walrss/walrss/internal/urls" + +import ( + qtio422016 "io" + + qt422016 "github.com/valyala/quicktemplate" +) + +var ( + _ = qtio422016.Copy + _ = qt422016.AcquireByteBuffer +) + +type SignInPage struct { + BasePage + Problem string +} + +func (p *SignInPage) StreamTitle(qw422016 *qt422016.Writer) { + qw422016.N().S(`Sign in`) +} + +func (p *SignInPage) WriteTitle(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamTitle(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *SignInPage) Title() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteTitle(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} + +func (p *SignInPage) StreamBody(qw422016 *qt422016.Writer) { + qw422016.N().S(` +`) + streamnavbar(qw422016) + qw422016.N().S(` + +<div class="container"> + <h1>Sign in</h1> + + `) + if p.Problem != "" { + qw422016.N().S(` + `) + StreamProblemBox(qw422016, p.Problem) + qw422016.N().S(` + `) + } + qw422016.N().S(` + + <form action="" method="post"> + <div class="mb-3"> + <label for="emailInput" class="form-label">Email address</label> + <input type="email" class="form-control" id="emailInput" name="email"> + </div> + <div class="mb-3"> + <label for="passwordInput" class="form-label">Password</label> + <input type="password" class="form-control" id="passwordInput" name="password"> + </div> + <button type="submit" class="btn btn-primary">Submit</button> + </form> + <br> + <a href="`) + qw422016.N().S(urls.AuthRegister) + qw422016.N().S(`">No account? Click here to register</a> +</div> +`) +} + +func (p *SignInPage) WriteBody(qq422016 qtio422016.Writer) { + qw422016 := qt422016.AcquireWriter(qq422016) + p.StreamBody(qw422016) + qt422016.ReleaseWriter(qw422016) +} + +func (p *SignInPage) Body() string { + qb422016 := qt422016.AcquireByteBuffer() + p.WriteBody(qb422016) + qs422016 := string(qb422016.B) + qt422016.ReleaseByteBuffer(qb422016) + return qs422016 +} diff --git a/walrss/internal/http/views/views.go b/walrss/internal/http/views/views.go new file mode 100644 index 0000000..2c11f09 --- /dev/null +++ b/walrss/internal/http/views/views.go @@ -0,0 +1,19 @@ +package views + +import "github.com/gofiber/fiber/v2" + +//go:generate go install github.com/valyala/quicktemplate/qtc@latest +//go:generate qtc -skipLineComments -ext qtpl.html + +func SendPage(ctx *fiber.Ctx, page Page) error { + ctx.Set(fiber.HeaderContentType, "html") + return ctx.SendString(RenderPage(page)) +} + +func makePageTitle(p Page) string { + t := p.Title() + if t == "" { + return "Walrss" + } + return t + " | Walrss" +} |
