package web import ( "net/http" "strings" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" ) func NewRouter(s *Server) chi.Router { r := chi.NewRouter() r.Use(middleware.RequestID) r.Use(middleware.RealIP) r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Route("/api", func(api chi.Router) { // Public auth endpoints. api.Post("/auth/login", s.handleLogin) api.Post("/auth/logout", s.handleLogout) api.Get("/auth/status", s.handleAuthStatus) // Everything below requires authentication. api.Group(func(protected chi.Router) { protected.Use(s.RequireAuth) protected.Get("/dirty", s.handleListDirty) protected.Post("/apply", s.handleApply) protected.Get("/apply/log", s.handleApplyLog) protected.Get("/system/status", s.handleSystemStatus) protected.Get("/version", s.handleVersion) protected.Put("/auth/password", s.handleChangePassword) protected.Get("/import/status", s.handleImportStatus) protected.Post("/import/samba", s.handleImportSamba) protected.Post("/import/nfs", s.handleImportNFS) protected.Route("/samba/shares", func(shares chi.Router) { shares.Get("/", s.handleListSambaShares) shares.Post("/", s.handleCreateSambaShare) shares.Route("/{id}", func(item chi.Router) { item.Get("/", s.handleGetSambaShare) item.Put("/", s.handleUpdateSambaShare) item.Delete("/", s.handleDeleteSambaShare) }) }) protected.Route("/nfs/exports", func(exports chi.Router) { exports.Get("/", s.handleListNFSExports) exports.Post("/", s.handleCreateNFSExport) exports.Route("/{id}", func(item chi.Router) { item.Get("/", s.handleGetNFSExport) item.Put("/", s.handleUpdateNFSExport) item.Delete("/", s.handleDeleteNFSExport) }) }) protected.Route("/users", func(users chi.Router) { users.Get("/", s.handleListUsers) users.Post("/", s.handleCreateUser) users.Route("/{id}", func(item chi.Router) { item.Get("/", s.handleGetUser) item.Put("/", s.handleUpdateUser) item.Delete("/", s.handleDeleteUser) }) }) }) }) r.NotFound(s.handleStatic) r.MethodNotAllowed(func(w http.ResponseWriter, _ *http.Request) { writeError(w, http.StatusMethodNotAllowed, "method not allowed") }) return r } func (s *Server) handleStatic(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet && r.Method != http.MethodHead { writeError(w, http.StatusMethodNotAllowed, "method not allowed") return } path := strings.TrimPrefix(r.URL.Path, "/") if path == "" { path = "index.html" } data, err := Dist.ReadFile("dist/" + path) if err != nil { if path != "index.html" { data, err = Dist.ReadFile("dist/index.html") } if err != nil { http.NotFound(w, r) return } } if strings.HasSuffix(path, ".html") { w.Header().Set("Content-Type", "text/html; charset=utf-8") } else if strings.HasSuffix(path, ".js") { w.Header().Set("Content-Type", "application/javascript") } else if strings.HasSuffix(path, ".css") { w.Header().Set("Content-Type", "text/css") } w.WriteHeader(http.StatusOK) _, _ = w.Write(data) }