Files

120 lines
3.0 KiB
Go
Raw Permalink Normal View History

package server
import (
"embed"
"html/template"
"io/fs"
"log"
"net/http"
"github.com/dexidp/dex/examples/example-app/session"
)
//go:embed templates/*.html
var templatesFS embed.FS
//go:embed static/*
var staticFS embed.FS
const dexLogoDataURI = "/static/dex-glyph-color.svg"
// staticHandler serves embedded static assets.
var staticHandler http.Handler
func init() {
staticSubFS, err := fs.Sub(staticFS, "static")
if err != nil {
log.Fatalf("failed to create static sub filesystem: %v", err)
}
staticHandler = http.FileServer(http.FS(staticSubFS))
}
// LoginPageData holds data for the login page template.
type LoginPageData struct {
ScopesSupported []string
LogoURI string
User *session.UserClaims
NotLoggedIn bool
LogoutURL string
}
// TokenPageData holds data for the token display template.
type TokenPageData struct {
IDToken string
IDTokenJWTLink string
AccessToken string
AccessTokenJWTLink string
RefreshToken string
RedirectURL string
Claims string
PublicKeyPEM string
}
// DevicePageData holds data for the device flow template.
type DevicePageData struct {
SessionID string
DeviceCode string
UserCode string
VerificationURI string
PollInterval int
LogoURI string
}
// Renderer renders HTML pages for the application.
type Renderer interface {
RenderLoginPage(w http.ResponseWriter, data LoginPageData)
RenderTokenPage(w http.ResponseWriter, data TokenPageData)
RenderDevicePage(w http.ResponseWriter, data DevicePageData)
}
// templateRenderer implements Renderer using Go html/template.
type templateRenderer struct {
index *template.Template
token *template.Template
device *template.Template
}
// newTemplateRenderer parses embedded templates and returns a Renderer.
func newTemplateRenderer() Renderer {
parse := func(name string) *template.Template {
t, err := template.ParseFS(templatesFS, name)
if err != nil {
log.Fatalf("failed to parse template %s: %v", name, err)
}
return t
}
return &templateRenderer{
index: parse("templates/index.html"),
token: parse("templates/token.html"),
device: parse("templates/device.html"),
}
}
func (r *templateRenderer) RenderLoginPage(w http.ResponseWriter, data LoginPageData) {
renderTemplate(w, r.index, data)
}
func (r *templateRenderer) RenderTokenPage(w http.ResponseWriter, data TokenPageData) {
renderTemplate(w, r.token, data)
}
func (r *templateRenderer) RenderDevicePage(w http.ResponseWriter, data DevicePageData) {
renderTemplate(w, r.device, data)
}
func renderTemplate(w http.ResponseWriter, tmpl *template.Template, data any) {
err := tmpl.Execute(w, data)
if err == nil {
return
}
switch err := err.(type) {
case *template.Error:
log.Printf("Error rendering template %s: %s", tmpl.Name(), err)
http.Error(w, "Internal server error", http.StatusInternalServerError)
default:
// An error with the underlying writer (e.g. connection dropped). Ignore.
}
}