show logged in user in web ui
This commit is contained in:
parent
4ebe6c7752
commit
3c59c31689
4 changed files with 102 additions and 5 deletions
|
@ -8,9 +8,9 @@ This template is intended for use with [gonew](https://go.dev/blog/gonew), but c
|
||||||
|
|
||||||
After you run gonew or update the package name manually, you will also want to:
|
After you run gonew or update the package name manually, you will also want to:
|
||||||
|
|
||||||
* search for the string `go-project-template` and replace it with the name of your project.
|
* search for the string `go-project-template` and replace it with the name of your project, as that string appears in a few places other than the package name itself.
|
||||||
* Rename the sample config file in the root from `go-project-template.sample.json`
|
* Rename the sample config file in the root from `go-project-template.sample.json`
|
||||||
* You might want to put a human-readable project name in the `<title>` element in `httpserver/templates/base.html`
|
* You might want to put a human-readable project name in `httpserver/templates/base.html`, where `go-project-template` appears multiple times.
|
||||||
* Rewrite this README
|
* Rewrite this README
|
||||||
|
|
||||||
## Project Usage
|
## Project Usage
|
||||||
|
|
|
@ -16,7 +16,37 @@ html, body {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: solid black 1px;
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
color: #aaa;
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
font-size: 8pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-login {
|
||||||
|
background-color: #aaa;
|
||||||
|
border: solid #555 1px;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
padding-top: 0.25em;
|
||||||
|
padding-bottom: 0.25em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
|
@ -2,13 +2,18 @@ package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
|
||||||
"git.janky.solutions/finn/go-project-template/config"
|
"git.janky.solutions/finn/go-project-template/config"
|
||||||
|
"git.janky.solutions/finn/go-project-template/db"
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
|
pgx "github.com/jackc/pgx/v5"
|
||||||
echo "github.com/labstack/echo/v4"
|
echo "github.com/labstack/echo/v4"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -50,11 +55,62 @@ func init() {
|
||||||
type Template struct {
|
type Template struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
type templateData struct {
|
||||||
|
Authenticated bool
|
||||||
|
User db.User
|
||||||
|
Version string
|
||||||
|
Data any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateData) dataFromContext(c echo.Context) error {
|
||||||
|
sessionInterface := c.Get(contextKeySession)
|
||||||
|
if sessionInterface == nil {
|
||||||
|
return nil // no session, no data to populate
|
||||||
|
}
|
||||||
|
|
||||||
|
session := sessionInterface.(*sessions.Session)
|
||||||
|
|
||||||
|
userIDInterface, ok := session.Values[sessionValueAuthUser]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, ok := userIDInterface.(int32)
|
||||||
|
if !ok {
|
||||||
|
logrus.WithField("userID", userIDInterface).Warn("unexpected session error: user ID is not an int32")
|
||||||
|
return errors.New("user ID is not an in32")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := c.Request().Context()
|
||||||
|
queries, conn, err := db.Get(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close(ctx)
|
||||||
|
|
||||||
|
user, err := queries.GetUser(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Authenticated = true
|
||||||
|
t.User = user
|
||||||
|
t.Version = fmt.Sprintf("%s %s", config.BuildInfo.Main.Path, config.Version)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Template) Render(w io.Writer, name string, data any, c echo.Context) error {
|
||||||
|
td := templateData{Data: data}
|
||||||
|
td.dataFromContext(c)
|
||||||
|
|
||||||
// Why does it work like this? because go's templating system doesn't handle multiple templates extending from a common base well
|
// Why does it work like this? because go's templating system doesn't handle multiple templates extending from a common base well
|
||||||
// just doing it normally causes every template to render the same (the import form, at time of writing, probably the last template alphabetically)
|
// just doing it normally causes every template to render the same (the import form, at time of writing, probably the last template alphabetically)
|
||||||
// https://stackoverflow.com/a/69244593/21894038
|
// https://stackoverflow.com/a/69244593/21894038
|
||||||
tmpl := template.Must(allTemplates.Clone())
|
tmpl := template.Must(allTemplates.Clone())
|
||||||
tmpl = template.Must(tmpl.ParseFS(templatesSubFS, name))
|
tmpl = template.Must(tmpl.ParseFS(templatesSubFS, name))
|
||||||
return tmpl.ExecuteTemplate(w, name, data)
|
return tmpl.ExecuteTemplate(w, name, td)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,22 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
|
<header>
|
||||||
|
<span class="brand">go-project-template</span>
|
||||||
|
<span class="right">
|
||||||
|
{{ if .Authenticated }}
|
||||||
|
Signed in as <span class="username">{{ .User.Username }}</span>
|
||||||
|
{{ else }}
|
||||||
|
<a href="/auth/begin" class="btn-login">login</a>
|
||||||
|
{{ end }}
|
||||||
|
</span>
|
||||||
|
</header>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
{{ block "body" .}}{{ end }}
|
{{ block "body" .}}{{ end }}
|
||||||
</div>
|
</div>
|
||||||
<footer>
|
<footer>
|
||||||
<code>{{ version }}</code>
|
<span></span>
|
||||||
|
<span class="version">{{ .Version }}</span>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in a new issue