Login / Logout button

This commit is contained in:
soup 2024-11-15 15:04:55 -05:00
parent c18537e82f
commit e8d775d96d
13 changed files with 5292 additions and 31 deletions

View file

@ -26,6 +26,10 @@ func BadRequest(w http.ResponseWriter) {
w.WriteHeader(http.StatusBadRequest)
}
func OK(w http.ResponseWriter) {
w.WriteHeader(http.StatusOK)
}
func InternalServerError(w http.ResponseWriter, err error) {
log.Printf("Internal server error: %v", err)

7
backend/httpx/hx.go Normal file
View file

@ -0,0 +1,7 @@
package httpx
import "net/http"
func HxRefresh(w http.ResponseWriter) {
w.Header().Add("HX-Refresh", "true")
}

View file

@ -56,7 +56,7 @@ func sessionInfo(db *sql.DB, r *http.Request) (auth.SessionInfo, error) {
type Ctx struct {
DB *sql.DB
Session auth.SessionInfo
SessionInfo auth.SessionInfo
NeedsOwnerSetup bool
}
@ -80,7 +80,7 @@ func WithCtx(db *sql.DB, next http.Handler) http.Handler {
}
ctx = context.WithValue(ctx, "__ctx", Ctx{
DB: db,
Session: session,
SessionInfo: session,
NeedsOwnerSetup: needsOwnerSetup,
})
r = r.WithContext(ctx)

View file

@ -1,7 +1,20 @@
package routes
import "net/http"
import (
"net/http"
"shelves/backend/httpx"
"shelves/backend/templates"
)
type homeTemplate struct {
templates.Page
}
func HomeGet(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("Hello, world"))
ctx := httpx.GetCtx(req)
tmpl := homeTemplate{
Page: templates.Page{SessionInfo: ctx.SessionInfo},
}
html(w, templates.Tmpls.HTML("home.tmpl.html", tmpl))
}

View file

@ -40,7 +40,7 @@ func loginRenderView(f loginForm, e loginFormErrors) template.HTML {
},
}
return templates.PageBase{Title: "Login", Body: body.HTML()}.HTML()
return templates.Page{Title: "Login", Body: body.HTML()}.HTML()
}
func getRedirectTo(r *http.Request) string {
@ -61,7 +61,7 @@ func LoginGet(w http.ResponseWriter, r *http.Request) {
ctx := httpx.GetCtx(r)
redirectTo := getRedirectTo(r)
if ctx.Session.IsAdmin {
if ctx.SessionInfo.IsAdmin {
httpx.SeeOther(w, redirectTo)
return
}
@ -88,7 +88,7 @@ func LoginPost(w http.ResponseWriter, r *http.Request) {
return
}
if ctx.Session.IsAdmin {
if ctx.SessionInfo.IsAdmin {
httpx.SeeOther(w, form.redirectTo)
return
}
@ -118,12 +118,14 @@ func LoginPost(w http.ResponseWriter, r *http.Request) {
func LoginDelete(w http.ResponseWriter, r *http.Request) {
ctx := httpx.GetCtx(r)
if !ctx.Session.IsAdmin {
httpx.SeeOther(w, "/")
httpx.HxRefresh(w)
if !ctx.SessionInfo.IsAdmin {
httpx.OK(w)
return
}
sessionId := ctx.Session.SessionId
sessionId := ctx.SessionInfo.SessionId
err := auth.SessionDelete(ctx.DB, sessionId)
if err != nil {
httpx.InternalServerError(w, err)
@ -137,5 +139,5 @@ func LoginDelete(w http.ResponseWriter, r *http.Request) {
cookie.MaxAge = -1
http.SetCookie(w, &cookie)
httpx.SeeOther(w, "/")
httpx.OK(w)
}

View file

@ -55,7 +55,7 @@ func queryGetOwnerSettings(db *sql.DB) (settingsForm, error) {
func SettingsGet(w http.ResponseWriter, r *http.Request) {
ctx := httpx.GetCtx(r)
if !ctx.Session.IsAdmin && !ctx.NeedsOwnerSetup {
if !ctx.SessionInfo.IsAdmin && !ctx.NeedsOwnerSetup {
httpx.LoginRedirect(w, *r.URL)
return
}
@ -115,7 +115,7 @@ func updateOwnerSettings(db *sql.DB, f settingsForm) error {
func SettingsPost(w http.ResponseWriter, r *http.Request) {
ctx := httpx.GetCtx(r)
if !ctx.Session.IsAdmin && !ctx.NeedsOwnerSetup {
if !ctx.SessionInfo.IsAdmin && !ctx.NeedsOwnerSetup {
httpx.Unauthorized(w)
return
}

View file

@ -37,5 +37,5 @@ func (f Form) HTML() template.HTML {
f.Fields[i].init()
}
return tmpls.renderHtml("form.tmpl.html", f)
return Tmpls.HTML("form.tmpl.html", f)
}

View file

@ -1,6 +1,9 @@
package templates
import "html/template"
import (
"html/template"
"shelves/backend/auth"
)
type PageBase struct {
Title string
@ -11,5 +14,19 @@ type PageBase struct {
}
func (pb PageBase) HTML() template.HTML {
return tmpls.renderHtml("page_base.tmpl.html", pb)
return Tmpls.HTML("page_base.tmpl.html", pb)
}
type Page struct {
SessionInfo auth.SessionInfo
Title string
Head template.HTML
Body template.HTML
BodyBefore template.HTML
BodyAfter template.HTML
}
func (p Page) HTML() template.HTML {
return Tmpls.HTML("page.tmpl.html", p)
}

View file

@ -14,9 +14,9 @@ type Template struct {
*template.Template
}
var tmpls = Template{template.Must(template.ParseFS(files, "tmpls/*"))}
var Tmpls = Template{template.Must(template.ParseFS(files, "tmpls/*"))}
func (tmpl Template) renderHtml(name string, data any) template.HTML {
func (tmpl Template) HTML(name string, data any) template.HTML {
writer := &strings.Builder{}
err := tmpl.ExecuteTemplate(writer, name, data)

View file

@ -0,0 +1,3 @@
{{define "Title"}}Home{{end}}
{{template "page.tmpl.html" .}}

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>{{block "Title" .Title}}{{end}} - Shelves</title>
<link rel="stylesheet" href="/static/css/mu.css" />
<script module src="/static/js/vendor/htmx-2.0.3.js"></script>
{{block "Head" .Head}}{{end}}
</head>
<body>
<nav>
<ul>
<li>
{{if eq .SessionInfo.SessionId ""}}
<a href="/login">Login</a>
{{else}}
<button hx-delete="/login">Log out</button>
{{end}}
</li>
</ul>
</nav>
{{block "BodyBefore" .BodyBefore}}{{end}}
{{block "Body" .Body}}{{.}}{{end}}
{{block "BodyAfter" .BodyAfter}}{{end}}
</body>
</html>

View file

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}} - Shelves</title>
<link rel="stylesheet" href="/static/css/mu.css" />
{{.Head}}
</head>
<body>
{{.BodyBefore}}
{{.Body}}
{{.BodyAfter}}
</body>
</html>

5203
frontend/js/vendor/htmx-2.0.3.js vendored Normal file

File diff suppressed because it is too large Load diff