package main import ( "context" "encoding/json" "fmt" "log" "net/http" "recipe-manager/config" "recipe-manager/data" "recipe-manager/enums/permissions" "recipe-manager/middlewares" "recipe-manager/models" "recipe-manager/routers" "recipe-manager/services/logger" "recipe-manager/services/oauth" "recipe-manager/services/recipe" "recipe-manager/services/sheet" "recipe-manager/services/user" "strings" "github.com/jmoiron/sqlx" "github.com/go-chi/chi/v5" "github.com/go-chi/cors" "go.uber.org/zap" ) type Server struct { server *http.Server data *data.Data database *sqlx.DB cache_db *data.RedisCli cfg *config.ServerConfig oauth oauth.OAuthService taoLogger *logger.TaoLogger } func NewServer(cfg *config.ServerConfig, oauthService oauth.OAuthService) *Server { taoLogger := logger.NewTaoLogger(cfg) taoLogger.Log = taoLogger.Log.Named("Server") redisClient := data.NewRedisClient("redis:6379", "") return &Server{ server: &http.Server{Addr: fmt.Sprintf(":%d", cfg.ServerPort)}, data: data.NewData(taoLogger, redisClient), database: data.NewSqliteDatabase(), cache_db: redisClient, cfg: cfg, oauth: oauth.NewOAuthService(cfg), taoLogger: taoLogger, } } func (s *Server) Run() error { //go cli.CommandLineListener() s.createHandler() // log.Printf("Server running on %s", s.server.Addr) s.taoLogger.Log.Info("Server running", zap.String("addr", s.server.Addr)) defer func(Log *zap.Logger) { err := Log.Sync() if err != nil { log.Fatal(err) } }(s.taoLogger.Log) return s.server.ListenAndServe() } func (s *Server) createHandler() { r := chi.NewRouter() r.Use(cors.Handler(cors.Options{ AllowedOrigins: strings.Split(s.cfg.AllowedOrigins, ","), AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, AllowCredentials: true, ExposedHeaders: []string{"Content-Type"}, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"}, })) // Recipe Service recipeService := recipe.NewRecipeService(s.data, s.taoLogger) // User Service userService := user.NewUserService(s.cfg, s.database, s.taoLogger) // Seed _ = userService.CreateNewUser(context.WithValue(context.Background(), "user", &models.User{Email: "system"}), "kenta420", "poomipat.c@forth.co.th", "", permissions.SuperAdmin) _ = userService.CreateNewUser(context.WithValue(context.Background(), "user", &models.User{Email: "system"}), "phu", "pakin.t@forth.co.th", "", permissions.SuperAdmin) _ = userService.CreateNewUser(context.WithValue(context.Background(), "user", &models.User{Email: "system"}), "wanlop", "wanlop.r@forth.co.th", "", permissions.SuperAdmin) _ = userService.CreateNewUser(context.WithValue(context.Background(), "user", &models.User{Email: "system"}), "dawit", "dawit.o@forth.co.th", "", permissions.SuperAdmin) _ = userService.CreateNewUser(context.WithValue(context.Background(), "user", &models.User{Email: "system"}), "narisara", "narisara.k@tao-bin.com", "", permissions.SuperAdmin) // Auth Router r.Group(func(r chi.Router) { ar := routers.NewAuthRouter(s.cfg, s.oauth, userService, s.taoLogger) ar.Route(r) }) // Initial redis for k, v := range s.data.CurrentRecipe { s.taoLogger.Log.Debug("Caching", zap.Any("Recipe", k)) s.cache_db.SetToKey(k, v) } // Protected Group r.Group(func(r chi.Router) { r.Use(func(next http.Handler) http.Handler { return middlewares.Authorize(s.oauth, userService, next) }) sheetService, err := sheet.NewSheetService(context.Background(), s.cfg) if err != nil { s.taoLogger.Log.Fatal("Error while trying to create sheet service: ", zap.Error(err)) return } // Recipe Router rr := routers.NewRecipeRouter(s.data, recipeService, sheetService, s.taoLogger, s.cache_db) rr.Route(r) // Material Router mr := routers.NewMaterialRouter(s.data, s.taoLogger) mr.Route(r) // User Router ur := routers.NewUserRouter(s.taoLogger, userService) ur.Route(r) // Topping Router tr := routers.NewToppingRouter(s.data, s.taoLogger) tr.Route(r) }) r.NotFound(func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusNotFound) json.NewEncoder(w).Encode(map[string]string{"message": fmt.Sprintf("path %s are not exits", r.RequestURI)}) }) // display all routes [DEBUG] chi.Walk(r, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { fmt.Println(method, " ---> ", route) return nil }) s.server.Handler = r } func (s *Server) Shutdown(ctx context.Context) error { return s.server.Shutdown(ctx) }