feat: webhooker 1.0 MVP — entity rename, core engine, delivery, management UI #16

Merged
sneak merged 33 commits from feature/mvp-1.0 into main 2026-03-04 01:19:41 +01:00
2 changed files with 27 additions and 7 deletions
Showing only changes of commit 7d13c9da17 - Show all commits

View File

@@ -16,6 +16,7 @@ import (
"sneak.berlin/go/webhooker/internal/config" "sneak.berlin/go/webhooker/internal/config"
"sneak.berlin/go/webhooker/internal/globals" "sneak.berlin/go/webhooker/internal/globals"
"sneak.berlin/go/webhooker/internal/logger" "sneak.berlin/go/webhooker/internal/logger"
"sneak.berlin/go/webhooker/internal/session"
) )
// nolint:revive // MiddlewareParams is a standard fx naming convention // nolint:revive // MiddlewareParams is a standard fx naming convention
@@ -24,17 +25,20 @@ type MiddlewareParams struct {
Logger *logger.Logger Logger *logger.Logger
Globals *globals.Globals Globals *globals.Globals
Config *config.Config Config *config.Config
Session *session.Session
} }
type Middleware struct { type Middleware struct {
log *slog.Logger log *slog.Logger
params *MiddlewareParams params *MiddlewareParams
session *session.Session
} }
func New(lc fx.Lifecycle, params MiddlewareParams) (*Middleware, error) { func New(lc fx.Lifecycle, params MiddlewareParams) (*Middleware, error) {
s := new(Middleware) s := new(Middleware)
s.params = &params s.params = &params
s.log = params.Logger.Get() s.log = params.Logger.Get()
s.session = params.Session
return s, nil return s, nil
} }
@@ -118,11 +122,27 @@ func (s *Middleware) CORS() func(http.Handler) http.Handler {
}) })
} }
func (s *Middleware) Auth() func(http.Handler) http.Handler { // RequireAuth returns middleware that checks for a valid session.
// Unauthenticated users are redirected to the login page.
func (s *Middleware) RequireAuth() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// TODO: implement proper authentication sess, err := s.session.Get(r)
s.log.Debug("AUTH: before request") if err != nil {
s.log.Debug("auth middleware: failed to get session", "error", err)
http.Redirect(w, r, "/pages/login", http.StatusSeeOther)
return
}
if !s.session.IsAuthenticated(sess) {
s.log.Debug("auth middleware: unauthenticated request",
"path", r.URL.Path,
"method", r.Method,
)
http.Redirect(w, r, "/pages/login", http.StatusSeeOther)
return
}
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
}) })
} }

View File

@@ -92,14 +92,14 @@ func (s *Server) SetupRoutes() {
// Webhook management routes (require authentication) // Webhook management routes (require authentication)
s.router.Route("/sources", func(r chi.Router) { s.router.Route("/sources", func(r chi.Router) {
// TODO: Add authentication middleware here r.Use(s.mw.RequireAuth())
r.Get("/", s.h.HandleSourceList()) // List all webhooks r.Get("/", s.h.HandleSourceList()) // List all webhooks
r.Get("/new", s.h.HandleSourceCreate()) // Show create form r.Get("/new", s.h.HandleSourceCreate()) // Show create form
r.Post("/new", s.h.HandleSourceCreateSubmit()) // Handle create submission r.Post("/new", s.h.HandleSourceCreateSubmit()) // Handle create submission
}) })
s.router.Route("/source/{sourceID}", func(r chi.Router) { s.router.Route("/source/{sourceID}", func(r chi.Router) {
// TODO: Add authentication middleware here r.Use(s.mw.RequireAuth())
r.Get("/", s.h.HandleSourceDetail()) // View webhook details r.Get("/", s.h.HandleSourceDetail()) // View webhook details
r.Get("/edit", s.h.HandleSourceEdit()) // Show edit form r.Get("/edit", s.h.HandleSourceEdit()) // Show edit form
r.Post("/edit", s.h.HandleSourceEditSubmit()) // Handle edit submission r.Post("/edit", s.h.HandleSourceEditSubmit()) // Handle edit submission