91 lines
2.3 KiB
Go
91 lines
2.3 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
"github.com/inou-ai/messaging-center/internal/core"
|
|
"github.com/inou-ai/messaging-center/internal/store"
|
|
)
|
|
|
|
// Server is the HTTP API server.
|
|
type Server struct {
|
|
config *core.Config
|
|
store *store.Store
|
|
oauth *OAuthProvider
|
|
router chi.Router
|
|
}
|
|
|
|
// NewServer creates a new API server.
|
|
func NewServer(cfg *core.Config, s *store.Store) *Server {
|
|
srv := &Server{
|
|
config: cfg,
|
|
store: s,
|
|
oauth: NewOAuthProvider(&cfg.OAuth),
|
|
}
|
|
srv.setupRoutes()
|
|
return srv
|
|
}
|
|
|
|
// ServeHTTP implements http.Handler.
|
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
s.router.ServeHTTP(w, r)
|
|
}
|
|
|
|
func (s *Server) setupRoutes() {
|
|
r := chi.NewRouter()
|
|
|
|
// Middleware
|
|
r.Use(middleware.Logger)
|
|
r.Use(middleware.Recoverer)
|
|
r.Use(middleware.RealIP)
|
|
|
|
// Health endpoints (no auth)
|
|
r.Get("/health", s.handleHealth)
|
|
r.Get("/ready", s.handleReady)
|
|
|
|
// OAuth token endpoint
|
|
r.Post("/oauth/token", s.oauth.HandleToken)
|
|
|
|
// API v1
|
|
r.Route("/api/v1", func(r chi.Router) {
|
|
// Messages
|
|
r.Route("/messages", func(r chi.Router) {
|
|
r.With(s.oauth.RequireAuth("messages:read")).Get("/", s.handleListMessages)
|
|
r.With(s.oauth.RequireAuth("messages:read")).Get("/{id}", s.handleGetMessage)
|
|
r.With(s.oauth.RequireAuth("messages:write")).Post("/", s.handleCreateMessage)
|
|
})
|
|
|
|
// Commands
|
|
r.Route("/commands", func(r chi.Router) {
|
|
r.With(s.oauth.RequireAuth("commands:write")).Post("/", s.handleCreateCommand)
|
|
r.With(s.oauth.RequireAuth("commands:write")).Get("/{id}", s.handleGetCommand)
|
|
})
|
|
|
|
// Channels
|
|
r.Route("/channels", func(r chi.Router) {
|
|
r.With(s.oauth.RequireAuth("admin")).Get("/", s.handleListChannels)
|
|
})
|
|
})
|
|
|
|
s.router = r
|
|
}
|
|
|
|
// handleHealth returns 200 OK if the server is running.
|
|
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
|
|
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
|
}
|
|
|
|
// handleReady returns 200 OK if the server is ready to accept traffic.
|
|
func (s *Server) handleReady(w http.ResponseWriter, r *http.Request) {
|
|
if err := s.store.Ping(); err != nil {
|
|
writeJSON(w, http.StatusServiceUnavailable, map[string]string{
|
|
"status": "not ready",
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]string{"status": "ready"})
|
|
}
|