Files
Crussell/backend/main.go
T
2025-10-15 21:25:45 +01:00

126 lines
3.3 KiB
Go

package main
import (
"crussell/auth"
"crussell/internal/dav"
"fmt"
"log"
"net/http"
"os"
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"crussell/db"
"crussell/mw"
authHandlers "crussell/handlers/auth"
"crussell/handlers/scheduling"
"crussell/handlers/user"
)
func init() {
// 1. Read the environment variable
jwtSecret := os.Getenv("JWT_SECRET_KEY")
// 2. Add a check to ensure the secret is set
if jwtSecret == "" {
log.Fatal("FATAL: JWT_SECRET_KEY environment variable not set. Application cannot start.")
}
// 3. Use the environment variable for initialization
auth.InitJWT(jwtSecret)
}
func initDB() {
if err := db.Connect(); err != nil {
log.Fatal("Failed to connect to DB:", err)
}
fmt.Println("Connected to DB successfully")
}
func initDav() {
if dav.Service == nil {
log.Fatal("Failed to initialize DAV service")
}
fmt.Println("DAV Service connected successfully")
}
func main() {
initDB()
initDav()
r := chi.NewRouter()
// --- Middleware ---
r.Use(middleware.RequestID) // Add X-Request-ID header
r.Use(middleware.RealIP) // Get real IP from headers
r.Use(middleware.Logger) // Basic logging
r.Use(middleware.Recoverer) // Panic recovery
r.Use(middleware.Timeout(15 * time.Second)) // Request timeout
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("X-XSS-Protection", "1; mode=block")
next.ServeHTTP(w, r)
})
})
// --- Public auth routes ---
r.Post("/api/register", authHandlers.RegisterHandler)
r.Post("/api/login", authHandlers.LoginHandler)
// --- Protected routes - any authenticated user ---
r.Group(func(r chi.Router) {
r.Use(mw.RequireAuth)
// User profile
r.Get("/api/user/profile", user.GetProfileHandler)
r.Put("/api/user/profile", user.UpdateProfileHandler)
r.Delete("/api/user/account", user.DeleteAccountHandler)
// Loyalty
r.Get("/api/user/loyalty", user.GetLoyaltyHandler)
})
// --- Scheduling routes ---
r.Route("/api/scheduling", func(r chi.Router) {
// Default hours
r.Get("/default-hours", scheduling.GetDefaultHours)
r.Group(func(r chi.Router) {
r.Use(mw.RequireAuth)
r.Use(mw.RequireAdmin)
r.Put("/default-hours", scheduling.UpdateDefaultHours)
})
// Exceptional groups
r.Get("/exceptional-groups", scheduling.ListExceptionalGroups)
r.Group(func(r chi.Router) {
r.Use(mw.RequireAuth)
r.Use(mw.RequireAdmin)
r.Post("/exceptional-groups", scheduling.CreateExceptionalGroup)
})
// Exceptional applications (assign groups to weeks)
r.Get("/exceptional-applications", scheduling.ListExceptionalApplications)
r.Group(func(r chi.Router) {
r.Use(mw.RequireAuth)
r.Use(mw.RequireAdmin)
r.Post("/exceptional-applications", scheduling.CreateExceptionalApplication)
})
// Merged working hours (default + exceptional)
r.Get("/working-hours", scheduling.GetWorkingHours)
// Fully calculated available hours (default + exceptional + bookings + lunch breaks)
r.Get("/available-hours", scheduling.GetAvailableHours)
})
fmt.Println("Server is listening on :8080")
http.ListenAndServe(":8080", r)
}