Files
ntfywui/internal/app/handlers_auth.go
2026-01-12 13:51:52 +01:00

89 lines
2.2 KiB
Go

package app
import (
"net/http"
"strings"
"github.com/yourorg/ntfywui/internal/security"
"github.com/yourorg/ntfywui/internal/store"
)
func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
next := r.URL.Query().Get("next")
if next == "" {
next = "/users"
}
csrf, _ := s.csrfEnsure(w, r)
flash := s.popFlash(w, r)
s.renderer.Render(w, "login.html", PageData{
Title: "Login",
CSRF: csrf,
Flash: flash,
Next: next,
})
case http.MethodPost:
_ = r.ParseForm()
user := cleanUser(r.Form.Get("username"))
pass := r.Form.Get("password")
totp := strings.TrimSpace(r.Form.Get("totp"))
next := r.Form.Get("next")
if next == "" {
next = "/users"
}
// CSRF checked by middleware in routes (we add it by calling s.csrf wrapper above in routes)
a, ok := s.admins.Authenticate(user, pass, totp)
if !ok {
s.audit.Append(store.AuditEvent{
Actor: user,
IP: security.RealIP(r, security.RealIPConfig{TrustedProxies: s.cfg.TrustedProxies}),
UA: r.UserAgent(),
Action: "login_failed",
})
s.setFlash(w, r, "Login fehlgeschlagen")
http.Redirect(w, r, s.abs("/login"), http.StatusFound)
return
}
sess, _ := s.sessions.Get(r)
if sess == nil {
sess = &security.Session{}
}
sess.User = a.Username
sess.Role = string(a.Role)
if sess.CSRF == "" {
tok, _ := security.NewCSRFToken()
sess.CSRF = tok
}
s.sessions.Save(w, sess)
s.auditEvent(r, "login_ok", a.Username, map[string]string{"role": string(a.Role)})
http.Redirect(w, r, s.abs(next), http.StatusFound)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) {
s.auditEvent(r, "logout", "", nil)
s.sessions.Clear(w)
http.Redirect(w, r, s.abs("/login"), http.StatusFound)
}
func (s *Server) csrfEnsure(w http.ResponseWriter, r *http.Request) (string, error) {
sess, ok := s.sessions.Get(r)
if !ok {
sess = &security.Session{}
}
if sess.CSRF == "" {
tok, err := security.NewCSRFToken()
if err != nil {
return "", err
}
sess.CSRF = tok
_ = s.sessions.Save(w, sess)
}
return sess.CSRF, nil
}