mirror of
https://github.com/netbirdio/dex.git
synced 2026-05-22 18:43:53 -07:00
120 lines
3.0 KiB
Go
120 lines
3.0 KiB
Go
|
|
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.
|
||
|
|
}
|
||
|
|
}
|