package admin import ( "fmt" "net/http" "os" "path/filepath" "arimelody-web/admin/account" "arimelody-web/admin/auth" "arimelody-web/admin/core" "arimelody-web/admin/logs" "arimelody-web/admin/music" "arimelody-web/admin/templates" "arimelody-web/controller" "arimelody-web/model" ) func Handler(app *model.AppState) http.Handler { mux := http.NewServeMux() mux.Handle("/register", auth.RegisterAccountHandler(app)) mux.Handle("/login", auth.LoginHandler(app)) mux.Handle("/totp", auth.LoginTOTPHandler(app)) mux.Handle("/logout", core.RequireAccount(auth.LogoutHandler(app))) mux.Handle("/music/", core.RequireAccount(http.StripPrefix("/music", music.Handler(app)))) mux.Handle("/logs", core.RequireAccount(logs.Handler(app))) mux.Handle("/account/", core.RequireAccount(http.StripPrefix("/account", account.Handler(app)))) mux.Handle("/static/", http.StripPrefix("/static", staticHandler())) mux.Handle("/", core.RequireAccount(AdminIndexHandler(app))) // response wrapper to make sure a session cookie exists return core.EnforceSession(app, mux) } func AdminIndexHandler(app *model.AppState) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } session := r.Context().Value("session").(*model.Session) latestRelease, err := controller.GetLatestRelease(app.DB) if err != nil { fmt.Fprintf(os.Stderr, "WARN: Failed to pull latest release: %s\n", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } type IndexData struct { Session *model.Session LatestRelease *model.Release } err = templates.IndexTemplate.Execute(w, IndexData{ Session: session, LatestRelease: latestRelease, }) if err != nil { fmt.Fprintf(os.Stderr, "WARN: Failed to render admin index: %s\n", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } }) } func staticHandler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { info, err := os.Stat(filepath.Join("admin", "static", filepath.Clean(r.URL.Path))) // does the file exist? if err != nil { if os.IsNotExist(err) { http.NotFound(w, r) return } } // is thjs a directory? (forbidden) if info.IsDir() { http.NotFound(w, r) return } http.FileServer(http.Dir(filepath.Join("admin", "static"))).ServeHTTP(w, r) }) }