package main import ( "context" "encoding/json" "fmt" "log" "net/http" "net/url" "os" "os/exec" "path/filepath" "recipe-manager/config" "recipe-manager/data" "recipe-manager/routers" "strings" "github.com/go-chi/chi/v5" "github.com/go-chi/cors" "github.com/spf13/viper" ) func loadConfig(path string) (*config.ServerConfig, error) { viper.AddConfigPath(path) viper.SetConfigName("app") viper.SetConfigType("env") viper.AutomaticEnv() var config config.ServerConfig err := viper.ReadInConfig() if err != nil { return nil, err } err = viper.Unmarshal(&config) if err != nil { return nil, err } return &config, nil } type Server struct { server *http.Server data *data.Data cfg *config.ServerConfig } func NewServer() *Server { serverCfg, err := loadConfig(".") if err != nil { log.Fatal(err) } log.Println(serverCfg) return &Server{ server: &http.Server{Addr: fmt.Sprintf(":%d", serverCfg.ServerPort)}, data: data.NewData(), cfg: serverCfg, } } func (s *Server) Run() error { s.createHandler() log.Printf("Server running on %s", s.server.Addr) 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"}, })) database := data.NewData() // Auth Router r.Group(func(r chi.Router) { ar := routers.NewAuthRouter(s.cfg) ar.Route(r) }) // Protect Group r.Group(func(r chi.Router) { r.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("access_token") if err != nil { w.WriteHeader(http.StatusUnauthorized) return } // verify token by request to google api res, err := http.Get("https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=" + url.QueryEscape(cookie.Value)) if err != nil { w.WriteHeader(http.StatusUnauthorized) return } defer res.Body.Close() var tokenInfo map[string]interface{} json.NewDecoder(res.Body).Decode(&tokenInfo) log.Println(tokenInfo) next.ServeHTTP(w, r) }) }) r.Post("/merge", func(w http.ResponseWriter, r *http.Request) { var targetMap map[string]interface{} err := json.NewDecoder(r.Body).Decode(&targetMap) if err != nil { w.WriteHeader(http.StatusBadRequest) log.Fatalln("Merge request failed: ", err) return } repo_path := "cofffeemachineConfig/coffeethai02_" master_version := targetMap["master"].(string) dev_version := targetMap["dev"].(string) output_path := targetMap["output"].(string) changelog_path := targetMap["changelog"].(string) // find target file in the cofffeemachineConfig if _, err := os.Stat(repo_path + master_version + ".json"); err != nil { w.WriteHeader(http.StatusBadRequest) log.Fatalln("Merge request failed. Master file not found: ", err) return } if _, err := os.Stat(repo_path + dev_version + ".json"); err != nil { w.WriteHeader(http.StatusBadRequest) log.Fatalln("Merge request failed. Dev file not found: ", err) return } master_path := repo_path + master_version + ".json" dev_path := repo_path + dev_version + ".json" // // output path // output_path := "" // // changelog path // changelog_path := "" // TODO: Call merge api if found // lookup for python exec py_exec, err := exec.LookPath("python") if err != nil { log.Fatalln("Python error: ", err) } else { py_exec, err = filepath.Abs(py_exec) } log.Println("Found python exec: ", py_exec) // target api file merge_api, api_err := os.Open("./python_api/merge_recipe.py") if api_err != nil { log.Fatalln("Merge request failed. Python api error: ", api_err) } log.Println("Locate python api", merge_api.Name()) cmd := exec.Command(py_exec, merge_api.Name(), "merge", master_path, dev_path, output_path, changelog_path, "debug") log.Println("Run merge command", cmd) err = cmd.Run() if err != nil { log.Fatalln("Merge request failed. Python merge failed: ", err) } w.Header().Add("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(map[string]string{"message": "Merge success"}) }) r.Get("/dllog", func(w http.ResponseWriter, r *http.Request) { }) // Recipe Router rr := routers.NewRecipeRouter(database) rr.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)}) }) s.server.Handler = r } func (s *Server) Shutdown(ctx context.Context) error { return s.server.Shutdown(ctx) }