b93e14ae88f05c6e01d25ab41d2ecb7456d769b3 / internal/web/session.go · 2134 bytes · raw
package web
import (
"context"
"net/http"
"strings"
"time"
"git.josie-c.com/josie/simplegit/internal/db"
)
const (
sessionCookieName = "session"
sessionDuration = 30 * 24 * time.Hour
)
type contextKey int
const userKey contextKey = iota
// withUser resolves a valid session cookie into a *db.User on the
// request context. Requests without a session pass through anonymous.
func (s *Server) withUser(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(sessionCookieName)
if err == nil && cookie.Value != "" {
session, err := db.GetSession(s.database, cookie.Value)
if err == nil {
user, err := db.GetUserByID(s.database, session.UserID)
if err == nil {
r = r.WithContext(context.WithValue(r.Context(), userKey, &user))
}
}
}
next.ServeHTTP(w, r)
})
}
// currentUser returns the authenticated user, or nil for anonymous requests.
func currentUser(r *http.Request) *db.User {
user, _ := r.Context().Value(userKey).(*db.User)
return user
}
// sessionCookie builds the session cookie. TLS terminates at the reverse
// proxy, so the Secure flag follows the configured base URL's scheme.
func (s *Server) sessionCookie(value string, maxAge time.Duration) *http.Cookie {
return &http.Cookie{
Name: sessionCookieName,
Value: value,
Path: "/",
MaxAge: int(maxAge.Seconds()),
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
Secure: strings.HasPrefix(s.cfg.BaseURL, "https://"),
}
}
// navData is the model shared by repo pages — who is viewing, which repo,
// which tab. Templates read the promoted fields unchanged.
type navData struct {
Username string
Owner string
RepoName string
Visibility string
Active string
}
// nav builds navData for a repo page from the request and viewer.
func nav(r *http.Request, repo db.Repo, user *db.User, active string) navData {
n := navData{
Owner: r.PathValue("user"),
RepoName: repo.Name,
Visibility: repo.Visibility,
Active: active,
}
if user != nil {
n.Username = user.Username
}
return n
}