1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-03-10 13:38:20 +00:00
mycorrhiza/web/cats.go
Timur Ismagilov a4cc67cd74
Migrate from log to slog #109 (#255)
* Migrate httpd.go

* Migrate history and main

* Migrate hypview

* Migrate interwiki

* Migrate misc

* Migrate utils

* Migrate backlinks

* Migrate categories

* Reformat some imports

* Migrate hyphae

* Migrate migration

* Reformat more imports

* Migrate user

* Migrate shroom

* Migrate viewutil

* Migrate web

* Migrate others

* Migrate main

* Wording concerns
2024-09-07 23:55:39 +03:00

136 lines
4.6 KiB
Go

package web
import (
"io"
"log/slog"
"net/http"
"sort"
"strings"
"github.com/bouncepaw/mycorrhiza/internal/categories"
"github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/web/viewutil"
)
func handlerEditCategory(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
meta := viewutil.MetaFrom(w, rq)
catName := util.CanonicalName(strings.TrimPrefix(strings.TrimPrefix(rq.URL.Path, "/edit-category"), "/"))
if catName == "" {
viewutil.HandlerNotFound(w, rq)
return
}
slog.Info("Editing category", "name", catName)
_ = pageCatEdit.RenderTo(meta, map[string]any{
"Addr": "/edit-category/" + catName,
"CatName": catName,
"Hyphae": categories.HyphaeInCategory(catName),
"GivenPermissionToModify": meta.U.CanProceed("add-to-category"),
})
}
func handlerListCategory(w http.ResponseWriter, rq *http.Request) {
slog.Info("Viewing list of categories")
cats := categories.ListOfCategories()
sort.Strings(cats)
_ = pageCatList.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{
"Addr": "/category",
"Categories": cats,
})
}
func handlerCategory(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
catName := util.CanonicalName(strings.TrimPrefix(strings.TrimPrefix(rq.URL.Path, "/category"), "/"))
if catName == "" {
handlerListCategory(w, rq)
return
}
meta := viewutil.MetaFrom(w, rq)
slog.Info("Viewing category", "name", catName)
_ = pageCatPage.RenderTo(meta, map[string]any{
"Addr": "/category/" + catName,
"CatName": catName,
"Hyphae": categories.HyphaeInCategory(catName),
"GivenPermissionToModify": meta.U.CanProceed("add-to-category"),
})
}
// A request for removal of hyphae can either remove one hypha (used in the card on /hypha) or many hyphae (used in /edit-category). Both approaches are handled by /remove-from-category. This function finds all passed hyphae.
//
// There is one hypha from the hypha field. Then there are n hyphae in fields prefixed by _. It seems like I have to do it myself. Compare with PHP which handles it for you. I hope I am doing this wrong.
func hyphaeFromRequest(rq *http.Request) (canonicalNames []string) {
if err := rq.ParseForm(); err != nil {
slog.Info("Failed to parse form", "err", err)
}
if hyphaName := util.CanonicalName(rq.PostFormValue("hypha")); hyphaName != "" {
canonicalNames = append(canonicalNames, hyphaName)
}
// According to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox,
//
// > If a checkbox is unchecked when its form is submitted, there is no value submitted to the server to represent its unchecked state
//
// It means, that if there is a value, it is checked. And we can ignore values altogether.
for key, _ := range rq.PostForm {
// No prefix or "_":
if !strings.HasPrefix(key, "_") || len(key) == 1 {
continue
}
canonicalNames = append(canonicalNames, util.CanonicalName(key[1:]))
}
return
}
func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
var (
u = user.FromRequest(rq)
hyphaNames = hyphaeFromRequest(rq)
catName = util.CanonicalName(rq.PostFormValue("cat"))
redirectTo = rq.PostFormValue("redirect-to")
)
if !u.CanProceed("remove-from-category") {
w.WriteHeader(http.StatusForbidden)
_, _ = io.WriteString(w, "403 Forbidden")
return
}
if len(hyphaNames) == 0 || catName == "" {
slog.Info("No data for removal of hyphae from category passed",
"username", u.Name, "catName", catName)
http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
return
}
for _, hyphaName := range hyphaNames {
// TODO: Make it more effective.
categories.RemoveHyphaFromCategory(hyphaName, catName)
}
slog.Info("Remove hyphae from category",
"username", u.Name, "catName", catName, "hyphaNames", hyphaNames)
http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
}
func handlerAddToCategory(w http.ResponseWriter, rq *http.Request) {
util.PrepareRq(rq)
var (
hyphaName = util.CanonicalName(rq.PostFormValue("hypha"))
catName = util.CanonicalName(rq.PostFormValue("cat"))
redirectTo = rq.PostFormValue("redirect-to")
)
if !user.FromRequest(rq).CanProceed("add-to-category") {
w.WriteHeader(http.StatusForbidden)
_, _ = io.WriteString(w, "403 Forbidden")
return
}
if hyphaName == "" || catName == "" {
http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
return
}
slog.Info(user.FromRequest(rq).Name, "added", hyphaName, "to", catName)
categories.AddHyphaToCategory(hyphaName, catName)
http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
}