package handlers import ( "hamster-tycoon/middlewares" "hamster-tycoon/service" "hamster-tycoon/storage/dao" "hamster-tycoon/storage/dao/fake" "hamster-tycoon/storage/dao/postgresql" "hamster-tycoon/storage/validators" "net/http" "time" "reflect" "strings" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" "gopkg.in/go-playground/validator.v9" ) type Config struct { Mock bool DBConnectionURI string Port int LogLevel string LogFormat string } type handlersContext struct { db dao.Database validator *validator.Validate userService *service.UserService } func NewRouter(config *Config) *gin.Engine { gin.SetMode(gin.ReleaseMode) router := gin.New() router.HandleMethodNotAllowed = true router.Use(cors.New(cors.Config{ AllowOrigins: []string{"*"}, AllowMethods: []string{"*"}, AllowHeaders: []string{"*"}, ExposeHeaders: []string{"*"}, AllowCredentials: true, MaxAge: 12 * time.Hour, })) router.Use(gin.Recovery()) router.Use(middlewares.GetLoggerMiddleware()) router.Use(middlewares.GetHTTPLoggerMiddleware()) hc := &handlersContext{} if config.Mock { hc.db = fake.NewDatabaseFake() } else { hc.db = postgresql.NewDatabasePostgreSQL(config.DBConnectionURI) } hc.validator = newValidator() hc.userService = service.NewUserService(hc.db) public := router.Group("/") public.Handle(http.MethodGet, "/_health", hc.GetHealth) userRoute := public.Group("/users") userRoute.Handle("LOGIN", "", hc.connectUser) userRoute.Handle(http.MethodPost, "", hc.createUser) securedUserRoute := userRoute.Group("") //TODO add secure auth securedUserRoute.Handle(http.MethodGet, "", hc.getAllUsers) securedUserRoute.Handle(http.MethodGet, "/:userId", hc.getUser) securedUserRoute.Handle(http.MethodPut, "/:userId", hc.updateUser) securedUserRoute.Handle(http.MethodDelete, "/:userId", hc.deleteUser) // end: user routes gameRoute := securedUserRoute.Group("/:userId/games") gameRoute.Handle(http.MethodGet, "", hc.getAllGames) gameRoute.Handle(http.MethodGet, "/:gameId", hc.getAGame) gameRoute.Handle(http.MethodPost, "/:gameId", hc.createAGame) gameRoute.Handle(http.MethodPut, "/:gameId",hc.updateAGame) gameRoute.Handle(http.MethodGet, "/:gameId/hamsters",hc.getHamstersOfGame) gameRoute.Handle(http.MethodDelete, "/:gameId",hc.deleteAGame) cageRoute := gameRoute.Group("/:gameId/cages") cageRoute.Handle(http.MethodGet, "",hc.getAllCages) cageRoute.Handle(http.MethodGet, "/:cageId", hc.getACage) cageRoute.Handle(http.MethodPost, "/:cageId", hc.createACage) cageRoute.Handle(http.MethodPut, "/:cageId", hc.updateACage) cageRoute.Handle(http.MethodDelete, "/:cageId",hc.deleteACage) hamsterRoute := cageRoute.Group("/:cageId/hamsters") hamsterRoute.Handle(http.MethodGet, "",hc.getAllHamsters) hamsterRoute.Handle(http.MethodGet, "/:hamsterId", hc.getAHamster) hamsterRoute.Handle(http.MethodPost, "/:hamsterId", hc.createAHamster) hamsterRoute.Handle(http.MethodPut, "/:hamsterId", hc.updateAHamster) hamsterRoute.Handle(http.MethodDelete, "/:hamsterId", hc.deleteAHamster) return router } func newValidator() *validator.Validate { va := validator.New() va.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2) if len(name) < 1 { return "" } return name[0] }) for k, v := range validators.CustomValidators { if v.Validator != nil { va.RegisterValidationCtx(k, v.Validator) } } return va }