package server import ( "log" "net/http" "text/template" "github.com/coreos/dex/storage" ) type connectorInfo struct { DisplayName string URL string } var loginTmpl = template.Must(template.New("login-template").Parse(`<html> <head></head> <body> <p>Login options</p> {{ range $i, $connector := .Connectors }} <a href="{{ $connector.URL }}?state={{ $.State }}">{{ $connector.DisplayName }}</a> {{ end }} </body> </html>`)) func renderLoginOptions(w http.ResponseWriter, connectors []connectorInfo, state string) { data := struct { Connectors []connectorInfo State string }{connectors, state} renderTemplate(w, loginTmpl, data) } var passwordTmpl = template.Must(template.New("password-template").Parse(`<html> <body> <p>Login</p> <form action="{{ .Callback }}" method="POST"> Login: <input type="text" name="login"/><br/> Password: <input type="password" name="password"/><br/> <input type="hidden" name="state" value="{{ .State }}"/> <input type="submit"/> {{ if .Message }} <p>Error: {{ .Message }}</p> {{ end }} </form> </body> </html>`)) func renderPasswordTmpl(w http.ResponseWriter, state, callback, message string) { data := struct { State string Callback string Message string }{state, callback, message} renderTemplate(w, passwordTmpl, data) } var approvalTmpl = template.Must(template.New("approval-template").Parse(`<html> <body> <p>User: {{ .User }}</p> <p>Client: {{ .ClientName }}</p> <form method="post"> <input type="hidden" name="state" value="{{ .State }}"/> <input type="hidden" name="approval" value="approve"> <button type="submit">Approve</button> </form> <form method="post"> <input type="hidden" name="state" value="{{ .State }}"/> <input type="hidden" name="approval" value="reject"> <button type="submit">Reject</button> </form> </body> </html>`)) func renderApprovalTmpl(w http.ResponseWriter, state string, identity storage.Claims, client storage.Client, scopes []string) { data := struct { User string ClientName string State string }{identity.Email, client.Name, state} renderTemplate(w, approvalTmpl, data) } func renderTemplate(w http.ResponseWriter, tmpl *template.Template, data interface{}) { err := tmpl.Execute(w, data) if err == nil { return } switch err := err.(type) { case template.ExecError: // An ExecError guarentees that Execute has not written to the underlying reader. log.Printf("Error rendering template %s: %s", tmpl.Name(), err) // TODO(ericchiang): replace with better internal server error. http.Error(w, "Internal server error", http.StatusInternalServerError) default: // An error with the underlying write, such as the connection being // dropped. Ignore for now. } }