go first commit

This commit is contained in:
Leon Bösche
2025-12-17 22:57:57 +01:00
parent e5a4de7aab
commit 7749ebfd08
22 changed files with 1044 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
package http
import (
"net/http"
"go.b0esche.cloud/backend/internal/audit"
"go.b0esche.cloud/backend/internal/auth"
"go.b0esche.cloud/backend/internal/config"
"go.b0esche.cloud/backend/internal/database"
"go.b0esche.cloud/backend/internal/middleware"
"go.b0esche.cloud/backend/pkg/jwt"
"github.com/go-chi/chi/v5"
)
func NewRouter(cfg *config.Config, db *database.DB, jwtManager *jwt.Manager, authService *auth.Service, auditLogger *audit.Logger) http.Handler {
r := chi.NewRouter()
// Global middleware
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.RateLimit)
// Health check
r.Get("/health", healthHandler)
// Auth routes (no auth required)
r.Route("/auth", func(r chi.Router) {
r.Get("/login", func(w http.ResponseWriter, req *http.Request) {
authLoginHandler(w, req, authService)
})
r.Get("/callback", func(w http.ResponseWriter, req *http.Request) {
authCallbackHandler(w, req, cfg, authService, jwtManager, auditLogger)
})
})
// Auth middleware for protected routes
r.Use(middleware.Auth(jwtManager, db))
return r
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}
func authLoginHandler(w http.ResponseWriter, r *http.Request, authService *auth.Service) {
state, err := auth.GenerateState()
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
// TODO: Store state securely (e.g., in session or cache)
url := authService.LoginURL(state)
http.Redirect(w, r, url, http.StatusFound)
}
func authCallbackHandler(w http.ResponseWriter, r *http.Request, cfg *config.Config, authService *auth.Service, jwtManager *jwt.Manager, auditLogger *audit.Logger) {
code := r.URL.Query().Get("code")
state := r.URL.Query().Get("state")
// TODO: Validate state
user, session, err := authService.HandleCallback(r.Context(), code, state)
if err != nil {
auditLogger.Log(r.Context(), audit.Entry{
Action: "login",
Success: false,
Metadata: map[string]interface{}{"error": err.Error()},
})
http.Error(w, "Authentication failed", http.StatusUnauthorized)
return
}
token, err := jwtManager.Generate(user.Email, []string{}, session.ID.String()) // Orgs not yet
if err != nil {
http.Error(w, "Token generation failed", http.StatusInternalServerError)
return
}
auditLogger.Log(r.Context(), audit.Entry{
UserID: &user.ID,
Action: "login",
Success: true,
})
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"token": "` + token + `"}`))
}

View File

@@ -0,0 +1,26 @@
package http
import (
"net/http"
"go.b0esche.cloud/backend/internal/audit"
"go.b0esche.cloud/backend/internal/auth"
"go.b0esche.cloud/backend/internal/config"
"go.b0esche.cloud/backend/internal/database"
"go.b0esche.cloud/backend/pkg/jwt"
)
type Server struct {
*http.Server
}
func New(cfg *config.Config, db *database.DB, jwtManager *jwt.Manager, authService *auth.Service, auditLogger *audit.Logger) *Server {
r := NewRouter(cfg, db, jwtManager, authService, auditLogger)
return &Server{
Server: &http.Server{
Addr: cfg.ServerAddr,
Handler: r,
},
}
}