nquest/main.go

169 lines
3.9 KiB
Go

package main
import (
"context"
"fmt"
"net/http"
"os"
"time"
"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
oapiMiddleware "github.com/oapi-codegen/echo-middleware"
"github.com/wader/gormstore/v2"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gitrepo.ru/neonxp/nquest/api"
appmiddleware "gitrepo.ru/neonxp/nquest/pkg/contextlib"
"gitrepo.ru/neonxp/nquest/pkg/controller"
"gitrepo.ru/neonxp/nquest/pkg/models"
"gitrepo.ru/neonxp/nquest/pkg/service"
)
func main() {
cfg, err := GetConfig()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading config\n: %s", err)
os.Exit(1)
}
db, err := gorm.Open(postgres.Open(cfg.DSN()), &gorm.Config{})
if err != nil {
fmt.Fprintf(os.Stderr, "Error DB connection\n: %s", err)
os.Exit(1)
}
// db.Use(prometheus.New(prometheus.Config{
// DBName: "db1", // use `DBName` as metrics label
// RefreshInterval: 15, // Refresh metrics interval (default 15 seconds)
// MetricsCollector: []prometheus.MetricsCollector{
// &prometheus.MySQL{
// VariableNames: []string{"Threads_running"},
// },
// }, // user defined metrics
// }))
if err := db.AutoMigrate(
&models.User{},
&models.Team{},
&models.TeamMember{},
&models.TeamRequest{},
&models.Game{},
&models.GamePassing{},
&models.Team{},
&models.TeamAtGame{},
&models.Task{},
&models.Solution{},
&models.Code{},
); err != nil {
fmt.Fprintf(os.Stderr, "Error DB migration\n: %s", err)
os.Exit(1)
}
// --[ Services ]--
userService := service.NewUser(db)
teamService := service.NewTeam(db)
gameService := service.NewGame(db)
// --[ HTTP server ]--
e := echo.New()
e.Debug = true
store := gormstore.New(db, []byte(cfg.Secret))
quit := make(chan struct{})
defer func() {
close(quit)
}()
go store.PeriodicCleanup(12*time.Hour, quit)
// userMW := appmiddleware.User(models.RoleUser, userService)
authFunc := func(ctx context.Context, ai *openapi3filter.AuthenticationInput) error {
echoCtx := ctx.Value(oapiMiddleware.EchoContextKey).(echo.Context)
user := appmiddleware.GetUser(echoCtx)
if user != nil {
return nil
}
return echo.ErrForbidden
}
swagger, err := api.GetSwagger()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
os.Exit(1)
}
swagger.Servers = []*openapi3.Server{{URL: "/api", Description: "Needed to match path"}}
e.Use(
middleware.Recover(),
middleware.RequestID(),
session.Middleware(store),
middleware.Logger(),
middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(20)),
middleware.CSRFWithConfig(middleware.CSRFConfig{
TokenLookup: "cookie:_csrf",
CookiePath: "/",
// CookieDomain: "nquest.ru",
// CookieSecure: true,
CookieHTTPOnly: true,
CookieSameSite: http.SameSiteStrictMode,
}),
middleware.Gzip(),
echoprometheus.NewMiddleware("nquest"),
appmiddleware.User(userService),
)
// --[ Router ]--
handler := serverRouter{
Game: &controller.Game{
GameService: gameService,
},
User: &controller.User{
UserService: userService,
},
Team: &controller.Team{
UserService: userService,
TeamService: teamService,
},
Engine: &controller.Engine{
GameService: gameService,
},
}
codegen := e.Group("")
codegen.Use(
oapiMiddleware.OapiRequestValidatorWithOptions(
swagger,
&oapiMiddleware.Options{
Options: openapi3filter.Options{
AuthenticationFunc: authFunc,
},
},
),
)
api.RegisterHandlersWithBaseURL(codegen, handler, "/api")
e.StaticFS("/", distDirFS)
e.FileFS("/*", "index.html", distIndexHtml)
// --[ System ]--
e.GET("/metrics", echoprometheus.NewHandler())
e.Logger.Fatal(e.Start(cfg.Listen))
}
type serverRouter struct {
*controller.Game
*controller.User
*controller.Team
*controller.Engine
}