package server import ( "fmt" "io/fs" "net/http" "github.com/mstarongithub/passkey" "github.com/rs/zerolog/log" "gitlab.com/mstarongitlab/goutils/other" "gitlab.com/mstarongitlab/linstrom/storage" ) type Server struct { store *storage.Storage router http.Handler server *http.Server } func NewServer( store *storage.Storage, pkey *passkey.Passkey, reactiveFS, staticFS fs.FS, placeholderFile *string, ) *Server { handler := buildRootHandler(pkey, reactiveFS, staticFS, placeholderFile) handler = ChainMiddlewares(handler, LoggingMiddleware, ContextValsMiddleware(map[any]any{ ContextKeyStorage: store, })) server := http.Server{ Handler: handler, } return &Server{ store: store, router: handler, server: &server, } } func buildRootHandler( pkey *passkey.Passkey, reactiveFS, staticFS fs.FS, placeholderFile *string, ) http.Handler { mux := http.NewServeMux() mux.Handle( "/webauthn/", http.StripPrefix( "/webauthn", forceCorrectPasskeyAuthFlowMiddleware(buildPasskeyAuthRouter(pkey)), ), ) mux.Handle("/", setupFrontendRouter(reactiveFS, staticFS)) mux.Handle("/pk/", http.StripPrefix("/pk", http.FileServer(http.Dir("pk-auth")))) mux.HandleFunc("/alive", isAliveHandler) mux.Handle("/api/", http.StripPrefix("/api", checkSessionMiddleware(setupApiRouter()))) mux.Handle( "/profiling/", http.StripPrefix("/profiling", profilingAuthenticationMiddleware(setupProfilingHandler())), ) // temporary until proper route structure exists mux.Handle( "/authonly/", pkey.Auth( ContextKeyPasskeyUsername, nil, func(w http.ResponseWriter, r *http.Request) { other.HttpErr( w, HttpErrIdNotAuthenticated, "Not authenticated", http.StatusUnauthorized, ) }, )(ChainMiddlewares(setupTestEndpoints(), passkeyIdToAccountIdTransformerMiddleware)), ) mux.HandleFunc("/placeholder-file", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, *placeholderFile) }) return mux } func buildPasskeyAuthRouter(pkey *passkey.Passkey) http.Handler { router := http.NewServeMux() pkey.MountRoutes(router, "/") return router } func (s *Server) Start(addr string) error { log.Info().Str("addr", addr).Msg("Starting server") s.server.Addr = addr return s.server.ListenAndServe() }