Add passwd command, fix template rendering, update deployment docs
- Add `passwd` CLI command to reset user passwords - Fix web UI templates: parse each page template with layout so blocks render correctly (was outputting empty pages) - Add login error logging for debugging auth failures - Update README with deploy workflow and container management commands - Update RUNBOOK for Docker-on-deimos deployment (replaces systemd refs) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ func (ws *WebServer) handleLoginSubmit(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
userID, err := auth.AuthenticateUser(ws.db, username, password)
|
||||
if err != nil {
|
||||
slog.Error("login failed", "username", username, "error", err)
|
||||
ws.render(w, "login.html", map[string]string{"Error": "Invalid credentials"})
|
||||
return
|
||||
}
|
||||
@@ -254,8 +255,14 @@ func (ws *WebServer) authMiddleware(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
func (ws *WebServer) render(w http.ResponseWriter, name string, data any) {
|
||||
t, ok := ws.tmpls[name]
|
||||
if !ok {
|
||||
http.Error(w, "Template not found", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
if err := ws.tmpl.ExecuteTemplate(w, name, data); err != nil {
|
||||
if err := t.ExecuteTemplate(w, "layout.html", data); err != nil {
|
||||
slog.Error("render template", "name", name, "error", err)
|
||||
http.Error(w, "Template error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ type Config struct {
|
||||
type WebServer struct {
|
||||
db *sql.DB
|
||||
baseURL string
|
||||
tmpl *template.Template
|
||||
tmpls map[string]*template.Template
|
||||
webauthn *webauthn.WebAuthn
|
||||
mu sync.Mutex
|
||||
sessions map[string]*webauthn.SessionData
|
||||
@@ -43,15 +43,32 @@ func Start(cfg Config) (*http.Server, error) {
|
||||
return nil, fmt.Errorf("template fs: %w", err)
|
||||
}
|
||||
|
||||
tmpl, err := template.ParseFS(templateFS, "*.html")
|
||||
layoutData, err := fs.ReadFile(templateFS, "layout.html")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse templates: %w", err)
|
||||
return nil, fmt.Errorf("read layout: %w", err)
|
||||
}
|
||||
|
||||
pages := []string{"login.html", "notebooks.html", "notebook.html", "page.html", "keys.html"}
|
||||
tmpls := make(map[string]*template.Template, len(pages))
|
||||
for _, page := range pages {
|
||||
t, err := template.New("layout.html").Parse(string(layoutData))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse layout: %w", err)
|
||||
}
|
||||
pageData, err := fs.ReadFile(templateFS, page)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %s: %w", page, err)
|
||||
}
|
||||
if _, err := t.Parse(string(pageData)); err != nil {
|
||||
return nil, fmt.Errorf("parse %s: %w", page, err)
|
||||
}
|
||||
tmpls[page] = t
|
||||
}
|
||||
|
||||
ws := &WebServer{
|
||||
db: cfg.DB,
|
||||
baseURL: cfg.BaseURL,
|
||||
tmpl: tmpl,
|
||||
tmpls: tmpls,
|
||||
sessions: make(map[string]*webauthn.SessionData),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user