generated from VLADIMIR/template
199 lines
6.5 KiB
Go
199 lines
6.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"evening_detective_server/internal/app"
|
|
"evening_detective_server/internal/modules/cleaner"
|
|
"evening_detective_server/internal/modules/email_sender"
|
|
"evening_detective_server/internal/modules/file_storage"
|
|
"evening_detective_server/internal/modules/password_generator"
|
|
"evening_detective_server/internal/modules/processor_jwt"
|
|
"evening_detective_server/internal/modules/storytelling"
|
|
"evening_detective_server/internal/repos/actions_repo"
|
|
"evening_detective_server/internal/repos/applications_repo"
|
|
"evening_detective_server/internal/repos/games_repo"
|
|
"evening_detective_server/internal/repos/refresh_tokens_repo"
|
|
"evening_detective_server/internal/repos/scenarios_repo"
|
|
"evening_detective_server/internal/repos/teams_repo"
|
|
"evening_detective_server/internal/repos/users_repo"
|
|
"evening_detective_server/internal/services/file_service"
|
|
"evening_detective_server/internal/services/game_service"
|
|
"evening_detective_server/internal/services/scenarios_service"
|
|
"evening_detective_server/internal/services/ui_service"
|
|
"evening_detective_server/internal/services/users_service"
|
|
proto "evening_detective_server/proto"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
"github.com/joho/godotenv"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
|
|
"github.com/swaggest/swgui/v5emb"
|
|
)
|
|
|
|
//go:embed main.swagger.json
|
|
var swaggerJSON []byte
|
|
|
|
func main() {
|
|
_ = godotenv.Load()
|
|
|
|
// PostgreSQL
|
|
dbpool, err := pgxpool.New(context.Background(), os.Getenv("DATABASE_URL"))
|
|
if err != nil {
|
|
log.Fatalf("Unable to create connection pool: %v\n", err)
|
|
}
|
|
defer dbpool.Close()
|
|
|
|
// Test request to DB
|
|
var greeting string
|
|
if err = dbpool.QueryRow(context.Background(), "select 'Hello, world!'").Scan(&greeting); err != nil {
|
|
log.Fatalf("QueryRow failed: %v\n", err)
|
|
}
|
|
|
|
usersRepo := users_repo.NewUserRepo(dbpool)
|
|
passwordGenerator := password_generator.NewGenerator(8)
|
|
emailSender := email_sender.NewSender(
|
|
os.Getenv("SMTP_HOST"),
|
|
os.Getenv("SMTP_PORT"),
|
|
os.Getenv("SMTP_USER"),
|
|
os.Getenv("SMTP_PASSWORD"),
|
|
)
|
|
processorJWT := processor_jwt.NewProcessor(os.Getenv("JWT_SECRET"))
|
|
refreshTokensRepo := refresh_tokens_repo.NewRefreshTokensRepo(dbpool)
|
|
usersService := users_service.NewUsersService(usersRepo, passwordGenerator, emailSender, processorJWT, refreshTokensRepo)
|
|
uiService := ui_service.NewUiService()
|
|
fileStorage, err := file_storage.NewRustFSStorage(
|
|
os.Getenv("S3_HOST"),
|
|
os.Getenv("S3_USER"),
|
|
os.Getenv("S3_PASSWORD"),
|
|
os.Getenv("S3_BUCKET"),
|
|
)
|
|
if err != nil {
|
|
log.Fatalf("Unable to create connection rustfs: %v\n", err)
|
|
}
|
|
fileService := file_service.NewFileService(fileStorage)
|
|
scenariosRepo := scenarios_repo.NewScenariosRepo(dbpool)
|
|
cleaner := cleaner.NewCleaner()
|
|
scenarioService := scenarios_service.NewScenarioService(
|
|
scenariosRepo,
|
|
cleaner,
|
|
os.Getenv("FILE_PREFIX_DOMAIN"),
|
|
)
|
|
gameRepo := games_repo.NewGamesRepo(dbpool)
|
|
teamRepo := teams_repo.NewTeamsRepo(dbpool)
|
|
storyteller := storytelling.NewStory()
|
|
actionsRepo := actions_repo.NewActionsRepo(dbpool)
|
|
applicationsRepo := applications_repo.NewApplicationsRepo(dbpool)
|
|
gameService := game_service.NewGameService(
|
|
gameRepo,
|
|
teamRepo,
|
|
scenariosRepo,
|
|
scenarioService,
|
|
os.Getenv("FILE_PREFIX_DOMAIN"),
|
|
passwordGenerator,
|
|
storyteller,
|
|
cleaner,
|
|
actionsRepo,
|
|
applicationsRepo,
|
|
)
|
|
|
|
// Create a listener on TCP port
|
|
lis, err := net.Listen("tcp", ":8080")
|
|
if err != nil {
|
|
log.Fatalln("Failed to listen:", err)
|
|
}
|
|
|
|
// Create a gRPC server object
|
|
s := grpc.NewServer(
|
|
grpc.UnaryInterceptor(
|
|
processor_jwt.NewAuthorizationInterceptor(
|
|
map[string]bool{
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/Ping": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/Echo": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/Signup": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/RefreshPassword": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/Login": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/Refresh": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/DownloadFile": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/GetScenario": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/GetScenariosCatalog": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/GetTeamStory": true,
|
|
"/crabs.evening_detective_server.EveningDetectiveServer/AddTeamAction": true,
|
|
},
|
|
processorJWT,
|
|
),
|
|
),
|
|
)
|
|
// Attach the Greeter service to the server
|
|
proto.RegisterEveningDetectiveServerServer(
|
|
s,
|
|
app.NewServer(
|
|
usersService,
|
|
uiService,
|
|
fileService,
|
|
scenarioService,
|
|
gameService,
|
|
),
|
|
)
|
|
|
|
// Serve gRPC server
|
|
log.Println("Serving gRPC on 0.0.0.0:8080")
|
|
go func() {
|
|
log.Fatalln(s.Serve(lis))
|
|
}()
|
|
|
|
// Create a client connection to the gRPC server we just started
|
|
// This is where the gRPC-Gateway proxies the requests
|
|
conn, err := grpc.NewClient(
|
|
"0.0.0.0:8080",
|
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
|
)
|
|
if err != nil {
|
|
log.Fatalln("Failed to dial server:", err)
|
|
}
|
|
|
|
gwmux := runtime.NewServeMux()
|
|
// Register Greeter
|
|
err = proto.RegisterEveningDetectiveServerHandler(context.Background(), gwmux, conn)
|
|
if err != nil {
|
|
log.Fatalln("Failed to register gateway:", err)
|
|
}
|
|
|
|
mainMux := http.NewServeMux()
|
|
|
|
docsHandler := v5emb.New("API", "/swagger/doc.json", "/docs/")
|
|
mainMux.Handle("/docs/", docsHandler)
|
|
mainMux.HandleFunc("/swagger/doc.json", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write(swaggerJSON)
|
|
})
|
|
mainMux.Handle("/api/", gwmux)
|
|
|
|
gwServer := &http.Server{
|
|
Addr: ":8090",
|
|
Handler: cors(mainMux),
|
|
}
|
|
|
|
log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090")
|
|
log.Println("Serving docs on http://0.0.0.0:8090/docs")
|
|
log.Fatalln(gwServer.ListenAndServe())
|
|
}
|
|
|
|
func cors(h http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
|
|
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization, ResponseType, X-Id, X-Password")
|
|
if r.Method == "OPTIONS" {
|
|
return
|
|
}
|
|
h.ServeHTTP(w, r)
|
|
})
|
|
}
|