// Package api provides the HTTP API for mosis-portal package api import ( "net/http" "github.com/go-chi/chi/v5" chimw "github.com/go-chi/chi/v5/middleware" "github.com/omixlab/mosis-portal/internal/api/handlers" "github.com/omixlab/mosis-portal/internal/api/middleware" "github.com/omixlab/mosis-portal/internal/auth" "github.com/omixlab/mosis-portal/internal/config" "github.com/omixlab/mosis-portal/internal/database" ) // NewRouter creates and configures the HTTP router func NewRouter(cfg *config.Config, db *database.DB) http.Handler { r := chi.NewRouter() // Middleware r.Use(chimw.Logger) r.Use(chimw.Recoverer) r.Use(chimw.RealIP) r.Use(chimw.RequestID) // Initialize auth components jwtManager := auth.NewJWTManager(cfg.JWTSecret) oauthManager := auth.NewOAuthManager( cfg.BaseURL, cfg.GitHubClientID, cfg.GitHubClientSecret, cfg.GoogleClientID, cfg.GoogleClientSecret, ) authMiddleware := middleware.NewAuthMiddleware(jwtManager, db) authHandler := handlers.NewAuthHandler(oauthManager, jwtManager, db) // Health check r.Get("/health", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("ok")) }) // API v1 r.Route("/v1", func(r chi.Router) { // Auth routes (public) r.Route("/auth", func(r chi.Router) { // OAuth - use GET for initiating (redirect based) r.Get("/oauth/github", authHandler.OAuthStart(auth.ProviderGitHub)) r.Get("/oauth/github/callback", authHandler.OAuthCallback(auth.ProviderGitHub)) r.Get("/oauth/google", authHandler.OAuthStart(auth.ProviderGoogle)) r.Get("/oauth/google/callback", authHandler.OAuthCallback(auth.ProviderGoogle)) // Token management r.Post("/refresh", authHandler.Refresh) r.Post("/logout", authHandler.Logout) // Current user (requires auth) r.With(authMiddleware.RequireAuth).Get("/me", authHandler.Me) }) // Protected developer routes r.Group(func(r chi.Router) { r.Use(authMiddleware.RequireAuth) // Developer apps r.Route("/apps", func(r chi.Router) { r.Get("/", handlers.NotImplemented) r.Post("/", handlers.NotImplemented) r.Get("/{appID}", handlers.NotImplemented) r.Patch("/{appID}", handlers.NotImplemented) r.Delete("/{appID}", handlers.NotImplemented) // Versions r.Route("/{appID}/versions", func(r chi.Router) { r.Get("/", handlers.NotImplemented) r.Post("/", handlers.NotImplemented) r.Get("/{versionID}", handlers.NotImplemented) r.Post("/{versionID}/submit", handlers.NotImplemented) r.Post("/{versionID}/publish", handlers.NotImplemented) }) }) // API Keys r.Route("/api-keys", func(r chi.Router) { r.Get("/", handlers.NotImplemented) r.Post("/", handlers.NotImplemented) r.Delete("/{keyID}", handlers.NotImplemented) }) // Signing Keys r.Route("/signing-keys", func(r chi.Router) { r.Get("/", handlers.NotImplemented) r.Post("/", handlers.NotImplemented) r.Delete("/{keyID}", handlers.NotImplemented) }) }) // Public store endpoints r.Route("/store", func(r chi.Router) { r.Get("/apps", handlers.NotImplemented) r.Get("/apps/{appID}", handlers.NotImplemented) r.Get("/apps/{appID}/download", handlers.NotImplemented) r.Get("/apps/updates", handlers.NotImplemented) }) // Telemetry (API key auth preferred, but can work without for initial setup) r.Route("/telemetry", func(r chi.Router) { r.Post("/events", handlers.NotImplemented) r.Post("/crash", handlers.NotImplemented) }) }) // Admin routes (htmx UI) - requires auth r.Route("/admin", func(r chi.Router) { r.Use(authMiddleware.RequireAuth) r.Get("/", handlers.NotImplemented) r.Get("/review-queue", handlers.NotImplemented) r.Get("/review/{versionID}", handlers.NotImplemented) r.Post("/review/{versionID}/approve", handlers.NotImplemented) r.Post("/review/{versionID}/reject", handlers.NotImplemented) }) return r }