Add OpenAPI docs, frontend, migrations, and API updates
- OpenAPI: add missing endpoints (add-from-url, subscriptions, public availability) - OpenAPI: CalendarSubscription schema, Subscriptions tag - Frontend app - Migrations: count_for_availability, subscriptions_sync, user_preferences, calendar_settings - Config, rate limit, auth, calendar, booking, ICS, availability, user service updates Made-with: Cursor
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/calendarapi/internal/api/handlers"
|
||||
"github.com/calendarapi/internal/api/openapi"
|
||||
"github.com/calendarapi/internal/config"
|
||||
mw "github.com/calendarapi/internal/middleware"
|
||||
"github.com/go-chi/chi/v5"
|
||||
chimw "github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/go-chi/cors"
|
||||
)
|
||||
|
||||
type Handlers struct {
|
||||
@@ -23,12 +27,26 @@ type Handlers struct {
|
||||
ICS *handlers.ICSHandler
|
||||
}
|
||||
|
||||
func NewRouter(h Handlers, authMW *mw.AuthMiddleware, rateLimiter *mw.RateLimiter) *chi.Mux {
|
||||
func NewRouter(h Handlers, authMW *mw.AuthMiddleware, rateLimiter *mw.RateLimiter, cfg *config.Config) *chi.Mux {
|
||||
r := chi.NewRouter()
|
||||
|
||||
r.Use(chimw.RequestID)
|
||||
r.Use(chimw.Logger)
|
||||
r.Use(chimw.Recoverer)
|
||||
r.Use(chimw.RealIP)
|
||||
r.Use(chimw.Timeout(30 * time.Second))
|
||||
origins := cfg.CORSOrigins
|
||||
if len(origins) == 0 {
|
||||
origins = []string{"http://localhost:5173", "http://127.0.0.1:5173"}
|
||||
}
|
||||
r.Use(cors.Handler(cors.Options{
|
||||
AllowedOrigins: origins,
|
||||
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
||||
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-API-Key"},
|
||||
ExposedHeaders: []string{"Link"},
|
||||
AllowCredentials: true,
|
||||
MaxAge: 300,
|
||||
}))
|
||||
r.Use(rateLimiter.Limit)
|
||||
|
||||
// OpenAPI spec and Swagger UI
|
||||
@@ -45,6 +63,10 @@ func NewRouter(h Handlers, authMW *mw.AuthMiddleware, rateLimiter *mw.RateLimite
|
||||
r.Post("/booking/{token}/reserve", h.Booking.Reserve)
|
||||
|
||||
r.Get("/cal/{token}/feed.ics", h.ICS.PublicFeed)
|
||||
|
||||
// Public availability (no auth) - for external booking tools
|
||||
r.Get("/availability/aggregate", h.Availability.GetAggregate)
|
||||
r.Get("/availability/{token}", h.Availability.GetByToken)
|
||||
})
|
||||
|
||||
// Authenticated routes
|
||||
@@ -71,6 +93,7 @@ func NewRouter(h Handlers, authMW *mw.AuthMiddleware, rateLimiter *mw.RateLimite
|
||||
r.With(mw.RequireScope("calendars", "write")).Post("/", h.Calendar.Create)
|
||||
r.With(mw.RequireScope("calendars", "write")).Post("/import", h.ICS.Import)
|
||||
r.With(mw.RequireScope("calendars", "write")).Post("/import-url", h.ICS.ImportURL)
|
||||
r.With(mw.RequireScope("calendars", "write")).Post("/add-from-url", h.ICS.AddFromURL)
|
||||
|
||||
r.Route("/{id}", func(r chi.Router) {
|
||||
r.With(mw.RequireScope("calendars", "read")).Get("/", h.Calendar.Get)
|
||||
@@ -87,6 +110,12 @@ func NewRouter(h Handlers, authMW *mw.AuthMiddleware, rateLimiter *mw.RateLimite
|
||||
|
||||
// ICS
|
||||
r.With(mw.RequireScope("calendars", "read")).Get("/export.ics", h.ICS.Export)
|
||||
|
||||
// Subscriptions
|
||||
r.With(mw.RequireScope("calendars", "read")).Get("/subscriptions", h.ICS.ListSubscriptions)
|
||||
r.With(mw.RequireScope("calendars", "write")).Post("/subscriptions", h.ICS.AddSubscription)
|
||||
r.With(mw.RequireScope("calendars", "write")).Delete("/subscriptions/{subId}", h.ICS.DeleteSubscription)
|
||||
r.With(mw.RequireScope("calendars", "write")).Post("/subscriptions/{subId}/sync", h.ICS.SyncSubscription)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user