mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Update locales (ru, tt, en) to use 'Turash' and 'Turash AI' - Update metadata, index.html, and pixel-art README - Replace example credentials/emails from @tuganyak.dev -> @turash.dev - Update admin defaults and migration seed to use new admin@turash.dev - Update docs mentioning the old name
540 lines
24 KiB
Go
540 lines
24 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
|
|
"bugulma/backend/internal/analysis/regulatory"
|
|
"bugulma/backend/internal/analysis/risk"
|
|
"bugulma/backend/internal/analysis/transport"
|
|
"bugulma/backend/internal/domain"
|
|
"bugulma/backend/internal/financial"
|
|
"bugulma/backend/internal/geospatial"
|
|
"bugulma/backend/internal/graph"
|
|
"bugulma/backend/internal/handler"
|
|
"bugulma/backend/internal/matching"
|
|
"bugulma/backend/internal/middleware"
|
|
"bugulma/backend/internal/repository"
|
|
"bugulma/backend/internal/routes"
|
|
"bugulma/backend/internal/service"
|
|
"bugulma/backend/pkg/config"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/joho/godotenv"
|
|
"github.com/neo4j/neo4j-go-driver/v5/neo4j"
|
|
"gorm.io/driver/postgres"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// StartServer initializes and starts the Bugulma backend server
|
|
func StartServer(port string) error {
|
|
// Load .env file
|
|
if err := godotenv.Load(); err != nil {
|
|
log.Printf("Warning: .env file not found, using environment variables")
|
|
}
|
|
|
|
// Load configuration
|
|
cfg := config.Load()
|
|
|
|
// Override port if provided
|
|
if port != "" {
|
|
cfg.ServerPort = port
|
|
}
|
|
|
|
// Initialize database
|
|
db, err := initializeDatabase(cfg)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to initialize database: %w", err)
|
|
}
|
|
|
|
// Initialize repositories
|
|
userRepo, orgRepo, siteRepo, _, resourceFlowRepo, matchRepo, negotiationHistoryRepo, sharedAssetRepo, proposalRepo, geoFeatureRepo, productRepo, serviceRepo, communityListingRepo, publicTransportRepo := initializeRepositories(db)
|
|
|
|
// Seed default data
|
|
if err := seedDefaultData(userRepo); err != nil {
|
|
log.Printf("Warning: Failed to seed default data: %v", err)
|
|
}
|
|
|
|
// (Public transport seeding will occur after services are initialized)
|
|
|
|
// Initialize graph database (optional)
|
|
graphSyncService, graphHandler, graphTraversalHandler, orgGraphRepo, siteGraphRepo, addressGraphRepo, flowGraphRepo, matchGraphRepo, sharedAssetGraphRepo := initializeGraphDatabase(cfg)
|
|
|
|
// Initialize services
|
|
orgService, siteService, resourceFlowService, geospatialService, sharedAssetService, analyticsService, authService, matchingSvc, cacheService, websocketService, aiService, proposalService, spatialMatcher, environmentalSvc, facilityOptimizer, economicService, userService, adminService, i18nService, subscriptionService, verificationService, productRepo, serviceRepo, communityListingRepo, publicTransportService := initializeServices(
|
|
cfg, userRepo, orgRepo, siteRepo, resourceFlowRepo, matchRepo, negotiationHistoryRepo, sharedAssetRepo, proposalRepo, geoFeatureRepo,
|
|
orgGraphRepo, siteGraphRepo, addressGraphRepo, flowGraphRepo, matchGraphRepo, sharedAssetGraphRepo, db,
|
|
productRepo, serviceRepo, communityListingRepo,
|
|
)
|
|
|
|
// Store geographical services for future API endpoints
|
|
_ = spatialMatcher // Will be used in future API handlers
|
|
_ = environmentalSvc // Will be used in future API handlers
|
|
_ = facilityOptimizer // Will be used in future API handlers
|
|
|
|
// Seed public transport data (if repository and imported files present)
|
|
if publicTransportRepo != nil && publicTransportService != nil {
|
|
if err := service.ImportPublicTransportData(context.Background(), publicTransportService, publicTransportRepo); err != nil {
|
|
log.Printf("Warning: failed to import public transport data: %v", err)
|
|
}
|
|
}
|
|
|
|
// Set graph repositories on services that need them
|
|
if orgGraphRepo != nil {
|
|
orgService.SetGraphRepository(orgGraphRepo)
|
|
}
|
|
|
|
// Initialize GTFS repository and schedule service
|
|
gtfsRepo := repository.NewPublicTransportGTFSRepository(db)
|
|
scheduleService := service.NewScheduleService(gtfsRepo, publicTransportRepo)
|
|
|
|
// Initialize handlers (orgHandler is created inside initializeHandlers)
|
|
orgHandler, siteHandler, resourceFlowHandler, proposalHandler, matchingHandler, authHandler, sharedAssetHandler, geospatialHandler, analyticsHandler, aiHandler, heritageHandler, userHandler, orgAdminHandler, i18nHandler, contentHandler, adminHandler, subscriptionHandler, discoveryHandler, publicTransportHandler := initializeHandlers(
|
|
cfg, orgService, siteService, resourceFlowService, matchingSvc, authService, sharedAssetService, proposalService,
|
|
geospatialService, analyticsService, aiService, cacheService, db, userService, adminService, i18nService, subscriptionService, verificationService, publicTransportService, scheduleService,
|
|
)
|
|
|
|
// Setup router
|
|
router := setupRouter(authService)
|
|
|
|
// Initialize event-driven matching service with proper dependencies
|
|
// Note: eventBus is created in initializeServices, but we need to recreate it here for event-driven service
|
|
eventBus, err := service.NewRedisEventBus("redis://localhost:6379")
|
|
if err != nil {
|
|
log.Printf("Warning: Failed to create Redis event bus for event-driven matching: %v", err)
|
|
eventBus = nil
|
|
}
|
|
|
|
eventDrivenMatchingService := service.NewEventDrivenMatchingService(
|
|
eventBus, matchingSvc, resourceFlowRepo, matchRepo, websocketService.GetHub(), economicService,
|
|
)
|
|
if eventBus != nil {
|
|
if err := eventDrivenMatchingService.StartEventProcessing(context.Background()); err != nil {
|
|
log.Printf("Warning: Failed to start event-driven matching: %v", err)
|
|
}
|
|
}
|
|
|
|
// Setup routes
|
|
setupRoutes(router, orgHandler, siteHandler, resourceFlowHandler, proposalHandler, matchingHandler, authHandler,
|
|
sharedAssetHandler, geospatialHandler, analyticsHandler, aiHandler, heritageHandler, graphHandler,
|
|
graphTraversalHandler, websocketService, orgService, siteService, geospatialService, graphSyncService,
|
|
userHandler, orgAdminHandler, i18nHandler, contentHandler, adminHandler, subscriptionHandler, authService, discoveryHandler, publicTransportHandler)
|
|
|
|
// Start server
|
|
log.Printf("Server starting on port %s", cfg.ServerPort)
|
|
if err := router.Run(fmt.Sprintf(":%s", cfg.ServerPort)); err != nil {
|
|
return fmt.Errorf("failed to start server: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// initializeDatabase sets up the database connection and runs migrations
|
|
func initializeDatabase(cfg *config.Config) (*gorm.DB, error) {
|
|
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s",
|
|
cfg.PostgresHost,
|
|
cfg.PostgresPort,
|
|
cfg.PostgresUser,
|
|
cfg.PostgresPassword,
|
|
cfg.PostgresDB,
|
|
cfg.PostgresSSLMode,
|
|
)
|
|
|
|
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to connect to PostgreSQL: %w", err)
|
|
}
|
|
|
|
log.Println("Successfully connected to PostgreSQL database")
|
|
|
|
// Run PostGIS-specific migrations FIRST (before AutoMigrate)
|
|
if err := domain.RunPostGISMigrations(db); err != nil {
|
|
log.Printf("Warning: Failed to run PostGIS migrations: %v", err)
|
|
log.Println("Continuing without PostGIS spatial features")
|
|
} else {
|
|
log.Println("PostGIS migrations completed successfully")
|
|
}
|
|
|
|
// Run search migrations (pg_trgm extension and indexes)
|
|
if err := domain.RunSearchMigrations(db); err != nil {
|
|
log.Printf("Warning: Failed to run search migrations: %v", err)
|
|
log.Println("Continuing without fuzzy search features")
|
|
} else {
|
|
log.Println("Search migrations completed successfully")
|
|
}
|
|
|
|
// Auto-migrate database schema
|
|
if err := domain.AutoMigrate(db); err != nil {
|
|
return nil, fmt.Errorf("failed to migrate database: %w", err)
|
|
}
|
|
|
|
// Create additional indexes after AutoMigrate
|
|
if err := domain.CreateIndexes(db); err != nil {
|
|
log.Printf("Warning: Failed to create indexes: %v", err)
|
|
} else {
|
|
log.Println("Indexes created successfully")
|
|
}
|
|
|
|
log.Println("Database migration completed successfully")
|
|
|
|
return db, nil
|
|
}
|
|
|
|
// initializeRepositories creates all repository instances
|
|
func initializeRepositories(db *gorm.DB) (domain.UserRepository, domain.OrganizationRepository, domain.SiteRepository, domain.AddressRepository, domain.ResourceFlowRepository, domain.MatchRepository, domain.NegotiationHistoryRepository, domain.SharedAssetRepository, domain.ProposalRepository, domain.GeographicalFeatureRepository, domain.ProductRepository, domain.ServiceRepository, domain.CommunityListingRepository, domain.PublicTransportRepository) {
|
|
orgRepo := repository.NewOrganizationRepository(db)
|
|
siteRepo := repository.NewSiteRepository(db)
|
|
addressRepo := repository.NewAddressRepository(db)
|
|
resourceFlowRepo := repository.NewResourceFlowRepository(db)
|
|
matchRepo := repository.NewMatchRepository(db)
|
|
negotiationHistoryRepo := repository.NewNegotiationHistoryRepository(db)
|
|
sharedAssetRepo := repository.NewSharedAssetRepository(db)
|
|
proposalRepo := repository.NewProposalRepository(db)
|
|
userRepo := repository.NewUserRepository(db)
|
|
geoFeatureRepo := repository.NewGeographicalFeatureRepository(db)
|
|
productRepo := repository.NewProductRepository(db)
|
|
serviceRepo := repository.NewServiceRepository(db)
|
|
communityListingRepo := repository.NewCommunityListingRepository(db)
|
|
publicTransportRepo := repository.NewPublicTransportRepository(db)
|
|
|
|
_ = repository.NewResourceFlowVersionRepository(db)
|
|
|
|
return userRepo, orgRepo, siteRepo, addressRepo, resourceFlowRepo, matchRepo, negotiationHistoryRepo, sharedAssetRepo, proposalRepo, geoFeatureRepo, productRepo, serviceRepo, communityListingRepo, publicTransportRepo
|
|
}
|
|
|
|
// seedDefaultData seeds initial data like admin user
|
|
func seedDefaultData(userRepo domain.UserRepository) error {
|
|
_, err := userRepo.GetByEmail(context.Background(), "admin@turash.dev")
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
adminUser := &domain.User{
|
|
ID: "admin-1",
|
|
Email: "admin@turash.dev",
|
|
Name: "Admin User",
|
|
Password: "$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi", // "password" hashed with bcrypt
|
|
Role: domain.UserRoleAdmin,
|
|
}
|
|
|
|
return userRepo.Create(context.Background(), adminUser)
|
|
}
|
|
|
|
// initializeGraphDatabase initializes Neo4j graph database if enabled
|
|
func initializeGraphDatabase(cfg *config.Config) (*service.GraphSyncService, *handler.GraphHandler, *handler.GraphTraversalHandler, *repository.GraphOrganizationRepository, *repository.GraphSiteRepository, *repository.GraphAddressRepository, *repository.GraphResourceFlowRepository, *repository.GraphMatchRepository, *repository.GraphSharedAssetRepository) {
|
|
if !cfg.Neo4jEnabled {
|
|
return nil, nil, nil, nil, nil, nil, nil, nil, nil
|
|
}
|
|
|
|
neo4jURI := cfg.Neo4jURI
|
|
if neo4jURI == "" {
|
|
log.Println("Warning: Neo4j URI not configured, graph database disabled")
|
|
return nil, nil, nil, nil, nil, nil, nil, nil, nil
|
|
}
|
|
|
|
auth := neo4j.BasicAuth(cfg.Neo4jUsername, cfg.Neo4jPassword, "")
|
|
driver, err := neo4j.NewDriverWithContext(neo4jURI, auth)
|
|
if err != nil {
|
|
log.Printf("Warning: Failed to create Neo4j driver: %v", err)
|
|
log.Println("Continuing without graph database features")
|
|
return nil, nil, nil, nil, nil, nil, nil, nil, nil
|
|
}
|
|
|
|
// Verify connectivity
|
|
ctx := context.Background()
|
|
if err := driver.VerifyConnectivity(ctx); err != nil {
|
|
log.Printf("Warning: Failed to connect to Neo4j: %v", err)
|
|
log.Println("Continuing without graph database features")
|
|
return nil, nil, nil, nil, nil, nil, nil, nil, nil
|
|
}
|
|
|
|
log.Println("Successfully connected to Neo4j graph database")
|
|
|
|
// Initialize graph repositories
|
|
orgGraphRepo := repository.NewGraphOrganizationRepository(driver, cfg.Neo4jDatabase)
|
|
siteGraphRepo := repository.NewGraphSiteRepository(driver, cfg.Neo4jDatabase)
|
|
addressGraphRepo := repository.NewGraphAddressRepository(driver, cfg.Neo4jDatabase)
|
|
flowGraphRepo := repository.NewGraphResourceFlowRepository(driver, cfg.Neo4jDatabase)
|
|
matchGraphRepo := repository.NewGraphMatchRepository(driver, cfg.Neo4jDatabase)
|
|
sharedAssetGraphRepo := repository.NewGraphSharedAssetRepository(driver, cfg.Neo4jDatabase)
|
|
productGraphRepo := repository.NewGraphProductRepository(driver, cfg.Neo4jDatabase)
|
|
serviceGraphRepo := repository.NewGraphServiceRepository(driver, cfg.Neo4jDatabase)
|
|
|
|
// Initialize graph sync service
|
|
graphSyncService := service.NewGraphSyncService(
|
|
orgGraphRepo, siteGraphRepo, addressGraphRepo, flowGraphRepo,
|
|
matchGraphRepo, sharedAssetGraphRepo, productGraphRepo, serviceGraphRepo,
|
|
)
|
|
|
|
// Initialize graph calculator for traversal service
|
|
graphCalculator := graph.NewCalculatorWithDefaults(driver, cfg.Neo4jDatabase)
|
|
|
|
// Initialize services
|
|
graphTraversalService := service.NewGraphTraversalService(graphCalculator)
|
|
|
|
// Initialize handlers
|
|
graphHandler := handler.NewGraphHandler(driver, cfg.Neo4jDatabase, graphSyncService)
|
|
graphTraversalHandler := handler.NewGraphTraversalHandler(graphTraversalService)
|
|
|
|
return graphSyncService, graphHandler, graphTraversalHandler, orgGraphRepo, siteGraphRepo, addressGraphRepo, flowGraphRepo, matchGraphRepo, sharedAssetGraphRepo
|
|
}
|
|
|
|
// initializeServices creates all service instances
|
|
func initializeServices(
|
|
cfg *config.Config,
|
|
userRepo domain.UserRepository,
|
|
orgRepo domain.OrganizationRepository,
|
|
siteRepo domain.SiteRepository,
|
|
resourceFlowRepo domain.ResourceFlowRepository,
|
|
matchRepo domain.MatchRepository,
|
|
negotiationHistoryRepo domain.NegotiationHistoryRepository,
|
|
sharedAssetRepo domain.SharedAssetRepository,
|
|
proposalRepo domain.ProposalRepository,
|
|
geoFeatureRepo domain.GeographicalFeatureRepository,
|
|
orgGraphRepo *repository.GraphOrganizationRepository,
|
|
siteGraphRepo *repository.GraphSiteRepository,
|
|
addressGraphRepo *repository.GraphAddressRepository,
|
|
flowGraphRepo *repository.GraphResourceFlowRepository,
|
|
matchGraphRepo *repository.GraphMatchRepository,
|
|
sharedAssetGraphRepo *repository.GraphSharedAssetRepository,
|
|
db *gorm.DB,
|
|
productRepo domain.ProductRepository,
|
|
serviceRepo domain.ServiceRepository,
|
|
communityListingRepo domain.CommunityListingRepository,
|
|
) (*service.OrganizationService, *service.SiteService, *service.ResourceFlowService, *service.GeospatialService, *service.SharedAssetService, *service.AnalyticsService, *service.AuthService, *matching.Service, service.CacheService, *service.WebSocketService, *service.AIService, *service.ProposalService, *service.SpatialResourceMatcher, *service.EnvironmentalImpactService, *service.FacilityLocationOptimizer, *service.EconomicService, *service.UserService, *service.AdminService, *service.I18nService, *service.SubscriptionService, *service.VerificationService, domain.ProductRepository, domain.ServiceRepository, domain.CommunityListingRepository, *service.PublicTransportService) {
|
|
|
|
// Create event bus first
|
|
eventBus, err := service.NewRedisEventBus("redis://localhost:6379")
|
|
if err != nil {
|
|
log.Printf("Warning: Failed to create Redis event bus, using in-memory: %v", err)
|
|
eventBus = nil
|
|
}
|
|
|
|
// Create services
|
|
orgService := service.NewOrganizationService(orgRepo, nil) // Graph repo set later if available
|
|
siteService := service.NewSiteService(siteRepo)
|
|
resourceFlowService := service.NewResourceFlowService(resourceFlowRepo, eventBus)
|
|
authService := service.NewAuthService(userRepo, cfg.JWTSecret)
|
|
sharedAssetService := service.NewSharedAssetService(sharedAssetRepo)
|
|
geospatialService := service.NewGeospatialService(db, geoFeatureRepo)
|
|
analyticsService := service.NewAnalyticsService(db, orgRepo, siteRepo, resourceFlowRepo, matchRepo, sharedAssetRepo)
|
|
proposalService := service.NewProposalService(proposalRepo)
|
|
|
|
// Initialize geospatial calculator
|
|
geoCalc := geospatial.NewCalculatorWithDefaults()
|
|
|
|
// Initialize geographical transportation service
|
|
geoTransportSvc := service.NewTransportationService(geoCalc)
|
|
|
|
// Initialize geographical services
|
|
spatialMatcher := service.NewSpatialResourceMatcher(geoFeatureRepo, siteRepo, resourceFlowRepo, geospatialService, geoTransportSvc, geoCalc)
|
|
environmentalSvc := service.NewEnvironmentalImpactService(geoFeatureRepo, siteRepo, geospatialService, geoCalc)
|
|
facilityOptimizer := service.NewFacilityLocationOptimizer(geoFeatureRepo, siteRepo, geospatialService, spatialMatcher, environmentalSvc, geoTransportSvc)
|
|
|
|
// Create cache and websocket services
|
|
var cacheService service.CacheService
|
|
redisCache, err := service.NewRedisCacheService(cfg.RedisURL)
|
|
if err != nil {
|
|
log.Printf("Warning: Failed to initialize Redis cache, using in-memory cache: %v", err)
|
|
cacheService = service.NewMemoryCacheService()
|
|
} else {
|
|
log.Println("Successfully initialized Redis cache service")
|
|
cacheService = redisCache
|
|
}
|
|
|
|
websocketService := service.NewWebSocketService()
|
|
|
|
// Create analysis services for matching
|
|
riskSvc := risk.NewService()
|
|
transportSvc := transport.NewService()
|
|
regulatorySvc := regulatory.NewService()
|
|
|
|
// Create matching service
|
|
matchingSvc := matching.NewService(
|
|
matchRepo, negotiationHistoryRepo, resourceFlowRepo, siteRepo, orgRepo,
|
|
productRepo, serviceRepo, communityListingRepo,
|
|
riskSvc, transportSvc, regulatorySvc, eventBus,
|
|
)
|
|
|
|
// Create financial calculator and economic service
|
|
financialConfig := financial.DefaultConfig()
|
|
financialCalculator := financial.NewCalculator(financialConfig)
|
|
economicService := service.NewEconomicService(financialCalculator)
|
|
|
|
aiService := service.NewAIService()
|
|
|
|
// Create additional services needed by handlers
|
|
userService := service.NewUserService(userRepo)
|
|
|
|
// Create trust service
|
|
trustRepo := repository.NewTrustMetricsRepository(db)
|
|
verifiedRepo := repository.NewVerifiedDataRepository(db)
|
|
historicalRepo := repository.NewHistoricalSuccessRepository(db)
|
|
trustService := service.NewTrustService(trustRepo, verifiedRepo, historicalRepo)
|
|
|
|
// Create i18n service - simplified initialization
|
|
locRepo := repository.NewLocalizationRepository(db)
|
|
i18nService := service.NewI18nService(nil, locRepo, nil, nil) // Simplified - can be enhanced later
|
|
|
|
// Create subscription service
|
|
subscriptionRepo := repository.NewSubscriptionRepository(db)
|
|
// UsageTrackingRepository can be nil for now - create if needed later
|
|
subscriptionService := service.NewSubscriptionService(subscriptionRepo, nil, userRepo)
|
|
|
|
// Create verification service
|
|
verificationService := service.NewVerificationService(trustService, orgService)
|
|
|
|
// Create admin service
|
|
adminService := service.NewAdminService(orgService, userService, verificationService, i18nService)
|
|
|
|
// Initialize public transport service (reads data/bugulma_public_transport_enriched.json if available)
|
|
publicTransportService, err := service.NewPublicTransportService("data")
|
|
if err != nil {
|
|
log.Printf("Warning: failed to initialize public transport service: %v", err)
|
|
publicTransportService = nil
|
|
}
|
|
|
|
return orgService, siteService, resourceFlowService, geospatialService, sharedAssetService, analyticsService, authService, matchingSvc, cacheService, websocketService, aiService, proposalService, spatialMatcher, environmentalSvc, facilityOptimizer, economicService, userService, adminService, i18nService, subscriptionService, verificationService, productRepo, serviceRepo, communityListingRepo, publicTransportService
|
|
}
|
|
|
|
// initializeHandlers creates all HTTP handler instances
|
|
func initializeHandlers(
|
|
cfg *config.Config,
|
|
orgService *service.OrganizationService,
|
|
siteService *service.SiteService,
|
|
resourceFlowService *service.ResourceFlowService,
|
|
matchingSvc *matching.Service,
|
|
authService *service.AuthService,
|
|
sharedAssetService *service.SharedAssetService,
|
|
proposalService *service.ProposalService,
|
|
geospatialService *service.GeospatialService,
|
|
analyticsService *service.AnalyticsService,
|
|
aiService *service.AIService,
|
|
cacheService service.CacheService,
|
|
db *gorm.DB,
|
|
userService *service.UserService,
|
|
adminService *service.AdminService,
|
|
i18nService *service.I18nService,
|
|
subscriptionService *service.SubscriptionService,
|
|
verificationService *service.VerificationService,
|
|
publicTransportService *service.PublicTransportService,
|
|
scheduleService *service.ScheduleService,
|
|
) (*handler.OrganizationHandler, *handler.SiteHandler, *handler.ResourceFlowHandler, *handler.ProposalHandler, *handler.MatchingHandler, *handler.AuthHandler, *handler.SharedAssetHandler, *handler.GeospatialHandler, *handler.AnalyticsHandler, *handler.AIHandler, *handler.HeritageHandler, *handler.UserHandler, *handler.OrganizationAdminHandler, *handler.I18nHandler, *handler.ContentHandler, *handler.AdminHandler, *handler.SubscriptionHandler, *handler.DiscoveryHandler, *handler.PublicTransportHandler) {
|
|
|
|
imageService := service.NewImageService(cfg)
|
|
orgHandler := handler.NewOrganizationHandler(orgService, imageService, resourceFlowService, matchingSvc, proposalService)
|
|
siteHandler := handler.NewSiteHandler(siteService)
|
|
resourceFlowHandler := handler.NewResourceFlowHandler(resourceFlowService)
|
|
proposalHandler := handler.NewProposalHandler(proposalService)
|
|
matchingHandler := handler.NewMatchingHandler(matchingSvc, nil)
|
|
authHandler := handler.NewAuthHandler(authService)
|
|
sharedAssetHandler := handler.NewSharedAssetHandler(sharedAssetService)
|
|
geospatialHandler := handler.NewGeospatialHandler(geospatialService)
|
|
analyticsHandler := handler.NewAnalyticsHandler(analyticsService)
|
|
aiHandler := handler.NewAIHandler(aiService)
|
|
heritageHandler := handler.NewHeritageHandler(repository.NewHeritageRepository(db))
|
|
|
|
// Additional handlers
|
|
userHandler := handler.NewUserHandler(userService)
|
|
orgAdminHandler := handler.NewOrganizationAdminHandler(orgHandler, verificationService)
|
|
i18nHandler := handler.NewI18nHandler(i18nService)
|
|
contentHandler := handler.NewContentHandler(service.NewContentService(
|
|
repository.NewStaticPageRepository(db),
|
|
repository.NewAnnouncementRepository(db),
|
|
repository.NewMediaAssetRepository(db),
|
|
))
|
|
adminHandler := handler.NewAdminHandler(adminService)
|
|
subscriptionHandler := handler.NewSubscriptionHandler(subscriptionService)
|
|
discoveryHandler := handler.NewDiscoveryHandler(matchingSvc)
|
|
publicTransportHandler := handler.NewPublicTransportHandler(publicTransportService, scheduleService)
|
|
|
|
return orgHandler, siteHandler, resourceFlowHandler, proposalHandler, matchingHandler, authHandler, sharedAssetHandler, geospatialHandler, analyticsHandler, aiHandler, heritageHandler, userHandler, orgAdminHandler, i18nHandler, contentHandler, adminHandler, subscriptionHandler, discoveryHandler, publicTransportHandler
|
|
}
|
|
|
|
// setupRouter configures the Gin router with middleware
|
|
func setupRouter(authService *service.AuthService) *gin.Engine {
|
|
router := gin.Default()
|
|
|
|
// Serve static files
|
|
router.Static("/static", "./static")
|
|
|
|
// CORS middleware
|
|
router.Use(func(c *gin.Context) {
|
|
c.Header("Access-Control-Allow-Origin", "*")
|
|
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
|
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
|
|
|
if c.Request.Method == "OPTIONS" {
|
|
c.AbortWithStatus(204)
|
|
return
|
|
}
|
|
|
|
c.Next()
|
|
})
|
|
|
|
// Context middleware for extracting user/org info from JWT or headers
|
|
router.Use(middleware.ContextMiddleware(authService))
|
|
|
|
return router
|
|
}
|
|
|
|
// setupRoutes configures all API routes using the organized routes package
|
|
func setupRoutes(
|
|
router *gin.Engine,
|
|
orgHandler *handler.OrganizationHandler,
|
|
siteHandler *handler.SiteHandler,
|
|
resourceHandler *handler.ResourceFlowHandler,
|
|
proposalHandler *handler.ProposalHandler,
|
|
matchingHandler *handler.MatchingHandler,
|
|
authHandler *handler.AuthHandler,
|
|
sharedAssetHandler *handler.SharedAssetHandler,
|
|
geospatialHandler *handler.GeospatialHandler,
|
|
analyticsHandler *handler.AnalyticsHandler,
|
|
aiHandler *handler.AIHandler,
|
|
heritageHandler *handler.HeritageHandler,
|
|
graphHandler *handler.GraphHandler,
|
|
graphTraversalHandler *handler.GraphTraversalHandler,
|
|
websocketService *service.WebSocketService,
|
|
orgService *service.OrganizationService,
|
|
siteService *service.SiteService,
|
|
geospatialService *service.GeospatialService,
|
|
graphSyncService *service.GraphSyncService,
|
|
userHandler *handler.UserHandler,
|
|
orgAdminHandler *handler.OrganizationAdminHandler,
|
|
i18nHandler *handler.I18nHandler,
|
|
contentHandler *handler.ContentHandler,
|
|
adminHandler *handler.AdminHandler,
|
|
subscriptionHandler *handler.SubscriptionHandler,
|
|
authService *service.AuthService,
|
|
discoveryHandler *handler.DiscoveryHandler,
|
|
publicTransportHandler *handler.PublicTransportHandler,
|
|
) {
|
|
routes.RegisterAllRoutes(
|
|
router,
|
|
orgHandler,
|
|
siteHandler,
|
|
resourceHandler,
|
|
proposalHandler,
|
|
matchingHandler,
|
|
authHandler,
|
|
sharedAssetHandler,
|
|
geospatialHandler,
|
|
analyticsHandler,
|
|
aiHandler,
|
|
heritageHandler,
|
|
graphHandler,
|
|
graphTraversalHandler,
|
|
websocketService,
|
|
userHandler,
|
|
orgAdminHandler,
|
|
i18nHandler,
|
|
contentHandler,
|
|
adminHandler,
|
|
subscriptionHandler,
|
|
authService,
|
|
discoveryHandler,
|
|
publicTransportHandler,
|
|
)
|
|
}
|