This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Benjamin Admin bfdaf63ba9 fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.

This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).

Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 09:51:32 +01:00

144 lines
3.8 KiB
Go

package main
import (
"log"
"github.com/breakpilot/billing-service/internal/config"
"github.com/breakpilot/billing-service/internal/database"
"github.com/breakpilot/billing-service/internal/handlers"
"github.com/breakpilot/billing-service/internal/middleware"
"github.com/breakpilot/billing-service/internal/services"
"github.com/gin-gonic/gin"
)
func main() {
// Load configuration
cfg, err := config.Load()
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
// Initialize database
db, err := database.Connect(cfg.DatabaseURL)
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
defer db.Close()
// Run migrations
if err := database.Migrate(db); err != nil {
log.Fatalf("Failed to run migrations: %v", err)
}
// Setup Gin router
if cfg.Environment == "production" {
gin.SetMode(gin.ReleaseMode)
}
router := gin.Default()
// Global middleware
router.Use(middleware.CORS())
router.Use(middleware.RequestLogger())
router.Use(middleware.RateLimiter())
// Health check (no auth required)
router.GET("/health", func(c *gin.Context) {
c.JSON(200, gin.H{
"status": "healthy",
"service": "billing-service",
"version": "1.0.0",
})
})
// Initialize services
subscriptionService := services.NewSubscriptionService(db)
// Create Stripe service (mock or real depending on config)
var stripeService *services.StripeService
if cfg.IsMockMode() {
log.Println("Starting in MOCK MODE - Stripe API calls will be simulated")
stripeService = services.NewMockStripeService(
cfg.BillingSuccessURL,
cfg.BillingCancelURL,
cfg.TrialPeriodDays,
subscriptionService,
)
} else {
stripeService = services.NewStripeService(
cfg.StripeSecretKey,
cfg.StripeWebhookSecret,
cfg.BillingSuccessURL,
cfg.BillingCancelURL,
cfg.TrialPeriodDays,
subscriptionService,
)
}
entitlementService := services.NewEntitlementService(db, subscriptionService)
usageService := services.NewUsageService(db, entitlementService)
// Initialize handlers
billingHandler := handlers.NewBillingHandler(
db,
subscriptionService,
stripeService,
entitlementService,
usageService,
)
webhookHandler := handlers.NewWebhookHandler(
db,
cfg.StripeWebhookSecret,
subscriptionService,
entitlementService,
)
// API v1 routes
v1 := router.Group("/api/v1/billing")
{
// Stripe webhook (no auth - uses Stripe signature)
v1.POST("/webhook", webhookHandler.HandleStripeWebhook)
// =============================================
// User Endpoints (require JWT auth)
// =============================================
user := v1.Group("")
user.Use(middleware.AuthMiddleware(cfg.JWTSecret))
{
// Subscription status and management
user.GET("/status", billingHandler.GetBillingStatus)
user.GET("/plans", billingHandler.GetPlans)
user.POST("/trial/start", billingHandler.StartTrial)
user.POST("/change-plan", billingHandler.ChangePlan)
user.POST("/cancel", billingHandler.CancelSubscription)
user.GET("/portal", billingHandler.GetCustomerPortal)
}
// =============================================
// Internal Endpoints (service-to-service)
// =============================================
internal := v1.Group("")
internal.Use(middleware.InternalAPIKeyMiddleware(cfg.InternalAPIKey))
{
// Entitlements
internal.GET("/entitlements/:userId", billingHandler.GetEntitlements)
internal.GET("/entitlements/check/:userId/:feature", billingHandler.CheckEntitlement)
// Usage tracking
internal.POST("/usage/track", billingHandler.TrackUsage)
internal.GET("/usage/check/:userId/:type", billingHandler.CheckUsage)
}
}
// Start server
port := cfg.Port
if port == "" {
port = "8083"
}
log.Printf("Starting Billing Service on port %s", port)
if err := router.Run(":" + port); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}