Hi… I am well aware that this diff view is very suboptimal. It will be fixed when the refactored server comes along!
Show logged in username
{{ template "head.html" }}
<main>
<h1>sinwon</h1>
<p>Welcome, {{ .Me.Username }}!</p>
<form method="post"> <a href="/user/new"><button type="button">Create user</button></a>
	<a href="/user/{{ .Me }}"><button type="button">Edit user</button></a>
	<a href="/user/{{ .Me.ID }}"><button type="button">Edit user</button></a>
	<button type="submit" formaction="/client/new">Register new client</button>
	<button type="submit" formaction="/logout">Logout</button>
</form>
{{ with .Clients }}
	<p>{{ . | len }} clients registered:</p>
	<ul>
		{{ range . }}
			<li><code>{{ .ClientID }}</code></li>
		{{ end }}
	</ul>
{{ else }}
	<p>No client registered yet.</p>
{{ end }}
</main>
{{ template "foot.html" }}
package main
import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"github.com/go-chi/chi/v5"
)
func index(w http.ResponseWriter, req *http.Request) {
	ctx := req.Context()
	db := dbFromContext(ctx)
	tpl := templateFromContext(ctx)
	loginToken := loginTokenFromContext(ctx)
	if loginToken == nil {
		http.Redirect(w, req, "/login", http.StatusFound)
		return
	}
	me, err := db.FetchUser(ctx, loginToken.User)
	if err != nil {
		httpError(w, err)
		return
	}
	clients, err := db.ListClients(ctx, loginToken.User)
	if err != nil {
		httpError(w, err)
		return
	}
	data := struct {
		Clients []Client
Me ID[*User]
Me *User
	}{
		Clients: clients,
Me: loginToken.User,
Me: me,
	}
	if err := tpl.ExecuteTemplate(w, "index.html", &data); err != nil {
		panic(err)
	}
}
func login(w http.ResponseWriter, req *http.Request) {
	ctx := req.Context()
	db := dbFromContext(ctx)
	tpl := templateFromContext(ctx)
	q := req.URL.Query()
	rawRedirectURI := q.Get("redirect_uri")
	if rawRedirectURI == "" {
		rawRedirectURI = "/"
	}
	redirectURI, err := url.Parse(rawRedirectURI)
	if err != nil || redirectURI.Scheme != "" || redirectURI.Opaque != "" || redirectURI.User != nil || redirectURI.Host != "" {
		http.Error(w, "Invalid redirect URI", http.StatusBadRequest)
		return
	}
	if loginTokenFromContext(ctx) != nil {
		http.Redirect(w, req, redirectURI.String(), http.StatusFound)
		return
	}
	username := req.PostFormValue("username")
	password := req.PostFormValue("password")
	if username == "" {
		if err := tpl.ExecuteTemplate(w, "login.html", nil); err != nil {
			panic(err)
		}
		return
	}
	user, err := db.FetchUserByUsername(ctx, username)
	if err != nil && err != errNoDBRows {
		httpError(w, fmt.Errorf("failed to fetch user: %v", err))
		return
	}
	if err == nil {
		err = user.VerifyPassword(password)
	}
	if err != nil {
		log.Printf("login failed for user %q: %v", username, err)
		// TODO: show error message
		if err := tpl.ExecuteTemplate(w, "login.html", nil); err != nil {
			panic(err)
		}
		return
	}
	token := AccessToken{
		User:  user.ID,
		Scope: internalTokenScope,
	}
	secret, err := token.Generate()
	if err != nil {
		httpError(w, fmt.Errorf("failed to generate access token: %v", err))
		return
	}
	if err := db.CreateAccessToken(ctx, &token); err != nil {
		httpError(w, fmt.Errorf("failed to create access token: %v", err))
		return
	}
	setLoginTokenCookie(w, req, &token, secret)
	http.Redirect(w, req, redirectURI.String(), http.StatusFound)
}
func logout(w http.ResponseWriter, req *http.Request) {
	unsetLoginTokenCookie(w, req)
	http.Redirect(w, req, "/login", http.StatusFound)
}
func updateUser(w http.ResponseWriter, req *http.Request) {
	ctx := req.Context()
	db := dbFromContext(ctx)
	tpl := templateFromContext(ctx)
	user := new(User)
	if idStr := chi.URLParam(req, "id"); idStr != "" {
		id, err := ParseID[*User](idStr)
		if err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		user, err = db.FetchUser(ctx, id)
		if err != nil {
			httpError(w, err)
			return
		}
	}
	loginToken := loginTokenFromContext(ctx)
	if loginToken == nil {
		http.Redirect(w, req, "/login", http.StatusFound)
		return
	}
	if user.ID != 0 && loginToken.User != user.ID {
		http.Error(w, "Access denied", http.StatusForbidden)
		return
	}
	username := req.PostFormValue("username")
	password := req.PostFormValue("password")
	if username == "" {
		if err := tpl.ExecuteTemplate(w, "update-user.html", user); err != nil {
			panic(err)
		}
		return
	}
	user.Username = username
	if password != "" {
		if err := user.SetPassword(password); err != nil {
			httpError(w, err)
			return
		}
	}
	if err := db.StoreUser(ctx, user); err != nil {
		httpError(w, err)
		return
	}
	http.Redirect(w, req, "/", http.StatusFound)
}