diff --git a/misc/handlers.go b/misc/handlers.go index ea96760..629ce07 100644 --- a/misc/handlers.go +++ b/misc/handlers.go @@ -8,6 +8,7 @@ import ( "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" "github.com/bouncepaw/mycorrhiza/l18n" "github.com/bouncepaw/mycorrhiza/shroom" + "github.com/bouncepaw/mycorrhiza/static" "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" @@ -16,10 +17,15 @@ import ( "io" "log" "math/rand" + "mime" "net/http" ) func InitHandlers(rtr *mux.Router) { + rtr.HandleFunc("/robots.txt", handlerRobotsTxt) + rtr.HandleFunc("/static/style.css", handlerStyle) + rtr.PathPrefix("/static/"). + Handler(http.StripPrefix("/static/", http.FileServer(http.FS(static.FS)))) rtr.HandleFunc("/list", handlerList) rtr.HandleFunc("/reindex", handlerReindex) rtr.HandleFunc("/update-header-links", handlerUpdateHeaderLinks) @@ -42,7 +48,7 @@ func handlerReindex(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) if ok := user.CanProceed(rq, "reindex"); !ok { var lc = l18n.FromRequest(rq) - viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights")) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights")) log.Println("Rejected", rq.URL) return } @@ -58,7 +64,7 @@ func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) if ok := user.CanProceed(rq, "update-header-links"); !ok { var lc = l18n.FromRequest(rq) - viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights")) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights")) log.Println("Rejected", rq.URL) return } @@ -75,7 +81,7 @@ func handlerRandom(w http.ResponseWriter, rq *http.Request) { ) if amountOfHyphae == 0 { var lc = l18n.FromRequest(rq) - viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip")) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip")) return } i := rand.Intn(amountOfHyphae) @@ -105,3 +111,34 @@ func handlerAbout(w http.ResponseWriter, rq *http.Request) { log.Println(err) } } + +var stylesheets = []string{"default.css", "custom.css"} + +func handlerStyle(w http.ResponseWriter, rq *http.Request) { + w.Header().Set("Content-Type", mime.TypeByExtension(".css")) + for _, name := range stylesheets { + file, err := static.FS.Open(name) + if err != nil { + continue + } + _, err = io.Copy(w, file) + if err != nil { + log.Println(err) + } + _ = file.Close() + } +} + +func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + + file, err := static.FS.Open("robots.txt") + if err != nil { + return + } + _, err = io.Copy(w, file) + if err != nil { + log.Println() + } + _ = file.Close() +} diff --git a/misc/views.go b/misc/views.go index 79f5242..870d8e3 100644 --- a/misc/views.go +++ b/misc/views.go @@ -37,7 +37,7 @@ type listData struct { } func viewList(meta viewutil.Meta) { - // TODO: make this better, there are too many loops and vars + // TODO: make this more effective, there are too many loops and vars var ( hyphaNames = make(chan string) sortedHypha = hyphae.PathographicSort(hyphaNames) diff --git a/viewutil/err.go b/viewutil/err.go index 200233e..c375842 100644 --- a/viewutil/err.go +++ b/viewutil/err.go @@ -2,14 +2,13 @@ package viewutil import ( "fmt" - "github.com/bouncepaw/mycorrhiza/l18n" "mime" "net/http" ) // HttpErr is used by many handlers to signal errors in a compact way. // TODO: get rid of this abomination -func HttpErr(meta Meta, lc *l18n.Localizer, status int, name, errMsg string) { +func HttpErr(meta Meta, status int, name, errMsg string) { meta.W.(http.ResponseWriter).Header().Set("Content-Type", mime.TypeByExtension(".html")) meta.W.(http.ResponseWriter).WriteHeader(status) fmt.Fprint( @@ -21,7 +20,7 @@ func HttpErr(meta Meta, lc *l18n.Localizer, status int, name, errMsg string) { `

%s. %s

`, errMsg, name, - lc.Get("ui.error_go_back"), + meta.Lc.Get("ui.error_go_back"), ), ), ) diff --git a/web/auth.go b/web/auth.go index 0734c2f..f4ea069 100644 --- a/web/auth.go +++ b/web/auth.go @@ -20,6 +20,7 @@ import ( ) func initAuth(r *mux.Router) { + r.HandleFunc("/user-list", handlerUserList) r.HandleFunc("/lock", handlerLock) // The check below saves a lot of extra checks and lines of codes in other places in this file. if !cfg.UseAuth { @@ -35,6 +36,13 @@ func initAuth(r *mux.Router) { r.HandleFunc("/logout", handlerLogout) } +func handlerUserList(w http.ResponseWriter, rq *http.Request) { + lc := l18n.FromRequest(rq) + w.Header().Set("Content-Type", mime.TypeByExtension(".html")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(views.Base(viewutil.MetaFrom(w, rq), lc.Get("ui.users_title"), views.UserList(lc)))) +} + func handlerLock(w http.ResponseWriter, rq *http.Request) { _, _ = io.WriteString(w, views.Lock(l18n.FromRequest(rq))) } diff --git a/web/stuff.go b/web/help.go similarity index 98% rename from web/stuff.go rename to web/help.go index 71eb1f7..8227b5b 100644 --- a/web/stuff.go +++ b/web/help.go @@ -17,7 +17,7 @@ import ( "github.com/bouncepaw/mycomarkup/v3/mycocontext" ) -func initStuff(r *mux.Router) { +func initHelp(r *mux.Router) { r.PathPrefix("/help").HandlerFunc(handlerHelp) } diff --git a/web/mutators.go b/web/mutators.go index 0737e69..331464d 100644 --- a/web/mutators.go +++ b/web/mutators.go @@ -39,7 +39,7 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if !u.CanProceed("remove-media") { - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no rights") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "no rights") return } if rq.Method == "GET" { @@ -53,11 +53,11 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) { } switch h := h.(type) { case *hyphae.EmptyHypha, *hyphae.TextualHypha: - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "no media to remove") return case *hyphae.MediaHypha: if err := shroom.RemoveMedia(u, h); err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } } @@ -74,7 +74,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { if !u.CanProceed("delete") { log.Printf("%s has no rights to delete ‘%s’\n", u.Name, h.CanonicalName()) - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights") return } @@ -82,7 +82,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { case *hyphae.EmptyHypha: log.Printf("%s tries to delete empty hypha ‘%s’\n", u.Name, h.CanonicalName()) // TODO: localize - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") return } @@ -98,7 +98,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil { log.Println(err) - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } http.Redirect(w, rq, "/hypha/"+h.CanonicalName(), http.StatusSeeOther) @@ -116,13 +116,13 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { switch h.(type) { case *hyphae.EmptyHypha: log.Printf("%s tries to rename empty hypha ‘%s’", u.Name, h.CanonicalName()) - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize return } if !u.CanProceed("rename") { log.Printf("%s has no rights to rename ‘%s’\n", u.Name, h.CanonicalName()) - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights") return } @@ -144,7 +144,7 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil { log.Printf("%s tries to rename ‘%s’: %s", u.Name, oldHypha.CanonicalName(), err.Error()) - viewutil.HttpErr(meta, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize + viewutil.HttpErr(meta, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize return } http.Redirect(w, rq, "/hypha/"+newName, http.StatusSeeOther) @@ -164,8 +164,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if err := shroom.CanEdit(u, h, lc); err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, - err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error()) return } switch h.(type) { @@ -175,8 +174,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { textAreaFill, err = shroom.FetchTextFile(h) if err != nil { log.Println(err) - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, - lc.Get("ui.error_text_fetch")) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, lc.Get("ui.error_text_fetch")) return } } @@ -204,7 +202,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) { if action != "Preview" { if err := shroom.UploadText(h, []byte(textData), message, u); err != nil { - viewutil.HttpErr(meta, lc, http.StatusForbidden, hyphaName, err.Error()) + viewutil.HttpErr(meta, http.StatusForbidden, hyphaName, err.Error()) return } } @@ -242,12 +240,10 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, - err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error()) } if err := shroom.CanAttach(u, h, lc); err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, - err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error()) } // If file is not passed: @@ -265,7 +261,7 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) { ) if err := shroom.UploadBinary(h, mime, file, u); err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error()) return } http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther) diff --git a/web/web.go b/web/web.go index 0686cb2..304aeb0 100644 --- a/web/web.go +++ b/web/web.go @@ -4,54 +4,17 @@ package web import ( "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/misc" - "github.com/bouncepaw/mycorrhiza/viewutil" "io" - "mime" "net/http" "net/url" "github.com/gorilla/mux" "github.com/bouncepaw/mycorrhiza/cfg" - "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/static" "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" - "github.com/bouncepaw/mycorrhiza/views" ) -var stylesheets = []string{"default.css", "custom.css"} - -func handlerStyle(w http.ResponseWriter, rq *http.Request) { - w.Header().Set("Content-Type", mime.TypeByExtension(".css")) - for _, name := range stylesheets { - file, err := static.FS.Open(name) - if err != nil { - continue - } - io.Copy(w, file) - file.Close() - } -} - -func handlerUserList(w http.ResponseWriter, rq *http.Request) { - lc := l18n.FromRequest(rq) - w.Header().Set("Content-Type", mime.TypeByExtension(".html")) - w.WriteHeader(http.StatusOK) - w.Write([]byte(views.Base(viewutil.MetaFrom(w, rq), lc.Get("ui.users_title"), views.UserList(lc)))) -} - -func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) { - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - - file, err := static.FS.Open("robots.txt") - if err != nil { - return - } - io.Copy(w, file) - file.Close() -} - // Handler initializes and returns the HTTP router based on the configuration. func Handler() http.Handler { router := mux.NewRouter() @@ -68,10 +31,6 @@ func Handler() http.Handler { // Public routes. They're always accessible regardless of the user status. initAuth(router) - router.HandleFunc("/robots.txt", handlerRobotsTxt) - router.HandleFunc("/static/style.css", handlerStyle) - router.PathPrefix("/static/"). - Handler(http.StripPrefix("/static/", http.FileServer(http.FS(static.FS)))) // Wiki routes. They may be locked or restricted. wikiRouter := router.PathPrefix("").Subrouter() @@ -87,7 +46,7 @@ func Handler() http.Handler { initReaders(wikiRouter) initMutators(wikiRouter) initHistory(wikiRouter) - initStuff(wikiRouter) + initHelp(wikiRouter) initSearch(wikiRouter) initBacklinks(wikiRouter) categories.InitHandlers(wikiRouter) @@ -100,9 +59,6 @@ func Handler() http.Handler { initAdmin(adminRouter) } - // Miscellaneous - wikiRouter.HandleFunc("/user-list", handlerUserList) - // Index page wikiRouter.HandleFunc("/", func(w http.ResponseWriter, rq *http.Request) { // Let's pray it never fails