From 0b4cc932b6fa89b2c3f962d1099407061cf5a48c Mon Sep 17 00:00:00 2001 From: Christian Galo Date: Fri, 21 Feb 2025 11:22:45 -0600 Subject: [PATCH] Start implementing middleware for logging and authentication in member-console application --- cmd/start.go | 62 +++++++++++++++++++++++++------ internal/middleware/middleware.go | 17 +++++++++ 2 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 internal/middleware/middleware.go diff --git a/cmd/start.go b/cmd/start.go index 865bf48..e06f651 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -3,7 +3,9 @@ package cmd import ( "log" "net/http" + "time" + "git.coopcloud.tech/wiki-cafe/member-console/internal/middleware" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -12,7 +14,7 @@ var startCmd = &cobra.Command{ Use: "start", Short: "Start serving the member-console web application", Long: `The start command starts an HTTP server that serves the member-console web - application. + application from the components directory in the current directory. The server listens on port 8080 by default, unless a different port is specified using the --port flag.`, Args: cobra.NoArgs, @@ -20,20 +22,27 @@ var startCmd = &cobra.Command{ // Retrieve the port value from Viper port := viper.GetString("port") - // Define the directory containing the static HTML files - dir := http.Dir("./components") - fileServer := http.FileServer(dir) - - // Use a ServeMux to handle requests + // Create a new HTTP request router httpRequestRouter := http.NewServeMux() - httpRequestRouter.Handle("/", fileServer) - // Start the HTTP server - log.Printf("Starting server on :%s...\n", port) - err := http.ListenAndServe(":"+port, httpRequestRouter) - if err != nil { - log.Fatal(err) + // Create a middleware stack + stack := middleware.CreateStack( + loggingMiddleware, + authMiddleware, + ) + + server := http.Server{ + Addr: ":" + port, + Handler: stack(httpRequestRouter), } + + // Register the login page handler + httpRequestRouter.HandleFunc("/login", serveLoginPage) + + // Serve the components directory + httpRequestRouter.Handle("/", http.FileServer(http.Dir("./components"))) + log.Println("Starting server on port", port) + log.Fatal(server.ListenAndServe()) }, } @@ -50,3 +59,32 @@ func init() { // Add the command to the root command rootCmd.AddCommand(startCmd) } + +// authMiddleware is a simple middleware function that checks for a valid session cookie +func authMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Check for the session cookie + cookie, err := r.Cookie("session") + if err != nil || cookie.Value != "authenticated" { + http.Redirect(w, r, "/login", http.StatusSeeOther) + return + } + + // Call the next handler + next.ServeHTTP(w, r) + }) +} + +// loggerMiddleware is a simple middleware function that logs the request method and URL +func loggingMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + next.ServeHTTP(w, r) + log.Println(r.Method, r.URL.Path, time.Since(start)) + }) +} + +// serveLoginPage is a simple handler function that serves the login page +func serveLoginPage(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, "./components/login.html") +} diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go new file mode 100644 index 0000000..2dc4a37 --- /dev/null +++ b/internal/middleware/middleware.go @@ -0,0 +1,17 @@ +package middleware + +import "net/http" + +type Middleware func(http.Handler) http.Handler + +// CreateStack creates a stack of middleware handlers +func CreateStack(middlewares ...Middleware) Middleware { + return func(nextMiddleware http.Handler) http.Handler { + for i := len(middlewares) - 1; i >= 0; i-- { + currentMiddleware := middlewares[i] + nextMiddleware = currentMiddleware(nextMiddleware) + } + + return nextMiddleware + } +}