cab-backend/cmd/main.go
2026-03-30 21:00:35 +03:00

165 lines
5.8 KiB
Go

package main
import (
"context"
"database/sql"
"fmt"
"log"
"net"
"os"
"path/filepath"
walletpb "game-admin/gen"
"game-admin/internal/config"
"game-admin/internal/grpcserver"
"game-admin/internal/handlers"
"game-admin/internal/middleware"
"game-admin/internal/migrations"
"game-admin/internal/models"
"game-admin/internal/wallet"
"github.com/gin-gonic/gin"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect/pgdialect"
"github.com/uptrace/bun/driver/pgdriver"
"github.com/uptrace/bun/extra/bundebug"
"google.golang.org/grpc"
)
func main() {
cfg := config.Load()
dsn := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable",
cfg.DBUser, cfg.DBPassword, cfg.DBHost, cfg.DBPort, cfg.DBName)
connector := pgdriver.NewConnector(pgdriver.WithDSN(dsn))
sqldb := sql.OpenDB(connector)
db := bun.NewDB(sqldb, pgdialect.New())
db.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true)))
if err := os.MkdirAll(filepath.Join(cfg.UploadDir, "images"), 0o755); err != nil {
log.Fatal("Upload directory init failed:", err)
}
if err := migrations.Migrate(context.Background(), db, cfg); err != nil {
log.Fatal("Migration failed:", err)
}
authH := handlers.NewAuthHandler(db, cfg)
userH := handlers.NewUserHandler(db, cfg)
gameH := handlers.NewGameHandler(db, cfg)
inviteH := handlers.NewInviteHandler(db, cfg)
languageH := handlers.NewLanguageHandler(db, cfg)
imageH := handlers.NewImageHandler(cfg)
walletService := wallet.NewService(db)
r := gin.Default()
r.Static("/uploads", cfg.UploadDir)
r.Use(func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS")
c.Header("Access-Control-Allow-Headers", "Content-Type,Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
})
api := r.Group("/api")
{
api.POST("/auth/login", authH.Login)
api.POST("/auth/register", authH.Register)
api.GET("/invites/validate/:code", inviteH.Validate)
}
auth := api.Group("", middleware.AuthRequired(cfg))
{
auth.GET("/auth/me", authH.Me)
auth.GET("/games", gameH.List)
auth.GET("/games/:id", gameH.GetByID)
auth.GET("/modules", gameH.ListModules)
auth.GET("/languages", languageH.List)
auth.GET("/languages/:id", languageH.GetByID)
auth.GET("/games/:id/leaderboards", gameH.ListLeaderboards)
auth.GET("/games/:id/leaderboards/:leaderboard_id", gameH.GetLeaderboard)
auth.GET("/leaderboards/:leaderboard_id/groups", gameH.ListLeaderboardGroups)
auth.GET("/leaderboards/:leaderboard_id/rankings", gameH.GetLeaderboardRankings)
auth.GET("/games/:id/notifications", gameH.ListNotifications)
auth.GET("/games/:id/notifications/:notification_id", gameH.GetNotification)
admin := auth.Group("", middleware.RoleRequired(models.RoleAdmin, models.RoleModerator))
{
admin.GET("/users", userH.List)
admin.GET("/users/:id", userH.GetByID)
admin.GET("/games/:id/users", userH.ListByGame)
admin.PATCH("/users/:id/role", userH.UpdateRole)
admin.PATCH("/users/:id/toggle-active", userH.ToggleActive)
admin.POST("/games", gameH.Create)
admin.PUT("/games/:id", gameH.Update)
admin.DELETE("/games/:id", gameH.Delete)
admin.GET("/games/:id/modules", gameH.ListGameModules)
admin.POST("/games/:id/modules", gameH.ConnectModule)
admin.DELETE("/games/:id/modules/:module_key", gameH.DisconnectModule)
admin.POST("/games/:id/leaderboards", gameH.CreateLeaderboard)
admin.PUT("/games/:id/leaderboards/:leaderboard_id", gameH.UpdateLeaderboard)
admin.DELETE("/games/:id/leaderboards/:leaderboard_id", gameH.DeleteLeaderboard)
admin.POST("/leaderboards/:leaderboard_id/groups", gameH.CreateLeaderboardGroup)
admin.PUT("/leaderboard-groups/:group_id", gameH.UpdateLeaderboardGroup)
admin.DELETE("/leaderboard-groups/:group_id", gameH.DeleteLeaderboardGroup)
admin.POST("/leaderboard-groups/:group_id/members", gameH.AddLeaderboardGroupMember)
admin.DELETE("/leaderboard-groups/:group_id/members/:user_id", gameH.DeleteLeaderboardGroupMember)
admin.POST("/leaderboards/:leaderboard_id/scores", gameH.UpsertLeaderboardScore)
admin.POST("/games/:id/notifications", gameH.CreateNotification)
admin.PUT("/games/:id/notifications/:notification_id", gameH.UpdateNotification)
admin.DELETE("/games/:id/notifications/:notification_id", gameH.DeleteNotification)
admin.GET("/games/:id/variables", gameH.ListVariables)
admin.POST("/games/:id/variables", gameH.CreateVariable)
admin.PUT("/games/:id/variables/:var_id", gameH.UpdateVariable)
admin.DELETE("/games/:id/variables/:var_id", gameH.DeleteVariable)
admin.POST("/images", imageH.Upload)
admin.POST("/languages", languageH.Create)
admin.PUT("/languages/:id", languageH.Update)
admin.DELETE("/languages/:id", languageH.Delete)
admin.GET("/users/:id/games", gameH.UserGames)
admin.POST("/users/:id/games", gameH.ConnectGame)
admin.DELETE("/users/:id/games/:game_id", gameH.DisconnectGame)
admin.POST("/user-games/:ug_id/topup", gameH.TopUp)
admin.GET("/user-games/:ug_id/transactions", gameH.Transactions)
admin.POST("/invites", inviteH.Create)
admin.GET("/invites", inviteH.List)
admin.DELETE("/invites/:code", inviteH.Delete)
}
}
grpcListener, err := net.Listen("tcp", ":"+cfg.GRPCPort)
if err != nil {
log.Fatal("gRPC listen error:", err)
}
grpcSrv := grpc.NewServer(
grpc.UnaryInterceptor(grpcserver.HMACUnaryServerInterceptor(cfg.GRPCHMACSecret)),
)
walletpb.RegisterWalletServiceServer(grpcSrv, grpcserver.NewWalletServer(walletService))
go func() {
log.Printf("gRPC server starting on :%s", cfg.GRPCPort)
if err := grpcSrv.Serve(grpcListener); err != nil {
log.Fatal("gRPC serve error:", err)
}
}()
log.Printf("HTTP server starting on :%s", cfg.ServerPort)
if err := r.Run(":" + cfg.ServerPort); err != nil {
log.Fatal(err)
}
}