package site import ( "encoding/json" "fmt" "html/template" "net/http" "path" "strconv" "strings" "github.com/angelbeltran/templater" "ruben/inventory2/internal/domains/accounts" "ruben/inventory2/internal/domains/authentication" etsy_platform "ruben/inventory2/internal/domains/platforms/etsy" "ruben/inventory2/internal/domains/raw_events" ) type Server struct { mux *http.ServeMux contentDir string templater *templater.Templater rawEvents *raw_events.Store accts *accounts.Store etsy *etsy_platform.Platform auth *authentication.Authenticator } func NewServer( contentDir string, rawEvents *raw_events.Store, accts *accounts.Store, etsy *etsy_platform.Platform, auth *authentication.Authenticator, ) *Server { s := &Server{ mux: http.NewServeMux(), contentDir: contentDir, templater: templater.NewTemplater( contentDir+"/templates", func() template.FuncMap { return template.FuncMap{ "buildSitePath": func(parts ...any) string { strParts := make([]string, len(parts)) for i, p := range parts { strParts[i] = fmt.Sprint(p) } // TODO: make "/site" dynamic somehow //return path.Join(append([]string{"/site"}, strParts...)...) return path.Join(strParts...) }, "splitPath": func(p string) []string { if p == "" { return nil } return strings.Split(strings.TrimSuffix(strings.TrimPrefix(p, "/"), "/"), "/") }, "prettyPrintJSON": func(j json.RawMessage) string { b, err := json.MarshalIndent(j, " ", "") if err != nil { return string(j) } return string(b) }, "parseInt64": func(s string) (int64, error) { return strconv.ParseInt(s, 10, 64) }, "addInt": func(a, b int) int { return a + b }, "subInt": func(a, b int) int { return a - b }, "multInt": func(a, b int) int { return a * b }, } }, ), rawEvents: rawEvents, accts: accts, etsy: etsy, auth: auth, } // api routes s.mux.HandleFunc("GET /login", s.loginPage) s.mux.HandleFunc("GET /login/callback", s.loginCallback) s.mux.HandleFunc("GET /logout", s.logoutPage) s.mux.Handle("POST /accounts", s.authenticate(http.HandlerFunc(s.createAccount))) // TODO: eliminate once no longer used. s.mux.HandleFunc("POST /login", s.login) // TODO: get rid of this, once we're confident this isn't needed... s.mux.Handle("GET /test-auth", s.authenticate(http.HandlerFunc(s.testAuthEndpoint))) // webpage content scfs := http.FileServer(http.Dir(contentDir + "/scripts")) s.mux.Handle("GET /scripts/", http.StripPrefix("/scripts", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/javascript") if path.Ext(r.URL.Path) == ".gz" { w.Header().Set("Content-Encoding", "gzip") } scfs.ServeHTTP(w, r) }))) s.mux.Handle("GET /styles/", http.StripPrefix("/styles", http.FileServer(http.Dir(contentDir+"/styles")))) // TODO: put auth on individual templates, somehow... s.mux.HandleFunc("GET /", s.serveTemplates) return s } // http.Handler implementation func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { s.mux.ServeHTTP(w, r) }