Migrate web

This commit is contained in:
Timur Ismagilov 2024-09-07 23:29:59 +03:00
parent 132882c37c
commit 7a33272c59
6 changed files with 68 additions and 55 deletions

View File

@ -2,7 +2,7 @@ package web
import ( import (
"fmt" "fmt"
"log" "log/slog"
"mime" "mime"
"net/http" "net/http"
"os" "os"
@ -115,7 +115,7 @@ func handlerAdmin(w http.ResponseWriter, rq *http.Request) {
// handlerAdminShutdown kills the wiki. // handlerAdminShutdown kills the wiki.
func handlerAdminShutdown(w http.ResponseWriter, rq *http.Request) { func handlerAdminShutdown(w http.ResponseWriter, rq *http.Request) {
if user.CanProceed(rq, "admin/shutdown") { if user.CanProceed(rq, "admin/shutdown") {
log.Println("An admin commanded the wiki to shutdown") slog.Info("An admin commanded the wiki to shutdown")
os.Exit(0) os.Exit(0)
} }
} }
@ -162,7 +162,7 @@ func handlerAdminUserEdit(w http.ResponseWriter, rq *http.Request) {
u.Group = newGroup u.Group = newGroup
if err := user.SaveUserDatabase(); err != nil { if err := user.SaveUserDatabase(); err != nil {
u.Group = oldGroup u.Group = oldGroup
log.Println(err) slog.Info("Failed to save user database", "err", err)
f = f.WithError(err) f = f.WithError(err)
} else { } else {
http.Redirect(w, rq, "/admin/users/", http.StatusSeeOther) http.Redirect(w, rq, "/admin/users/", http.StatusSeeOther)
@ -241,7 +241,7 @@ func handlerAdminUserDelete(w http.ResponseWriter, rq *http.Request) {
if !f.HasError() { if !f.HasError() {
http.Redirect(w, rq, "/admin/users/", http.StatusSeeOther) http.Redirect(w, rq, "/admin/users/", http.StatusSeeOther)
} else { } else {
log.Println(f.Error()) slog.Info("Failed to delete user", "err", f.Error())
} }
} }

View File

@ -1,14 +1,13 @@
package web package web
import ( import (
"github.com/bouncepaw/mycorrhiza/internal/categories"
"io" "io"
"log"
"log/slog" "log/slog"
"net/http" "net/http"
"sort" "sort"
"strings" "strings"
"github.com/bouncepaw/mycorrhiza/internal/categories"
"github.com/bouncepaw/mycorrhiza/internal/user" "github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/web/viewutil" "github.com/bouncepaw/mycorrhiza/web/viewutil"
@ -66,7 +65,7 @@ func handlerCategory(w http.ResponseWriter, rq *http.Request) {
// 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. // 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) { func hyphaeFromRequest(rq *http.Request) (canonicalNames []string) {
if err := rq.ParseForm(); err != nil { if err := rq.ParseForm(); err != nil {
log.Println(err) slog.Info("Failed to parse form", "err", err)
} }
if hyphaName := util.CanonicalName(rq.PostFormValue("hypha")); hyphaName != "" { if hyphaName := util.CanonicalName(rq.PostFormValue("hypha")); hyphaName != "" {
canonicalNames = append(canonicalNames, hyphaName) canonicalNames = append(canonicalNames, hyphaName)
@ -100,7 +99,8 @@ func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) {
return return
} }
if len(hyphaNames) == 0 || catName == "" { if len(hyphaNames) == 0 || catName == "" {
log.Printf("%s passed no data for removal of hyphae from a category\n", u.Name) slog.Info("No data for removal of hyphae from category passed",
"username", u.Name, "catName", catName)
http.Redirect(w, rq, redirectTo, http.StatusSeeOther) http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
return return
} }
@ -108,7 +108,8 @@ func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) {
// TODO: Make it more effective. // TODO: Make it more effective.
categories.RemoveHyphaFromCategory(hyphaName, catName) categories.RemoveHyphaFromCategory(hyphaName, catName)
} }
log.Printf("%s removed %q from category %s\n", u.Name, hyphaNames, catName) slog.Info("Remove hyphae from category",
"username", u.Name, "catName", catName, "hyphaNames", hyphaNames)
http.Redirect(w, rq, redirectTo, http.StatusSeeOther) http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
} }

View File

@ -1,23 +1,22 @@
package web package web
import ( import (
"git.sr.ht/~bouncepaw/mycomarkup/v5" "html/template"
"log/slog"
"net/http"
"github.com/bouncepaw/mycorrhiza/hypview"
"github.com/bouncepaw/mycorrhiza/internal/hyphae" "github.com/bouncepaw/mycorrhiza/internal/hyphae"
"github.com/bouncepaw/mycorrhiza/internal/shroom" "github.com/bouncepaw/mycorrhiza/internal/shroom"
"github.com/bouncepaw/mycorrhiza/internal/user" "github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/web/viewutil"
"html/template"
"log"
"net/http"
"git.sr.ht/~bouncepaw/mycomarkup/v5/mycocontext"
"github.com/bouncepaw/mycorrhiza/hypview"
"github.com/bouncepaw/mycorrhiza/mycoopts"
"github.com/gorilla/mux"
"github.com/bouncepaw/mycorrhiza/l18n" "github.com/bouncepaw/mycorrhiza/l18n"
"github.com/bouncepaw/mycorrhiza/mycoopts"
"github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/web/viewutil"
"git.sr.ht/~bouncepaw/mycomarkup/v5"
"git.sr.ht/~bouncepaw/mycomarkup/v5/mycocontext"
"github.com/gorilla/mux"
) )
func initMutators(r *mux.Router) { func initMutators(r *mux.Router) {
@ -64,14 +63,16 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) {
) )
if !u.CanProceed("delete") { if !u.CanProceed("delete") {
log.Printf("%s has no rights to delete %s\n", u.Name, h.CanonicalName()) slog.Info("No rights to delete hypha",
"username", u.Name, "hyphaName", h.CanonicalName())
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights") viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights")
return return
} }
switch h.(type) { switch h.(type) {
case *hyphae.EmptyHypha: case *hyphae.EmptyHypha:
log.Printf("%s tries to delete empty hypha %s\n", u.Name, h.CanonicalName()) slog.Info("Trying to delete empty hyphae",
"username", u.Name, "hyphaName", h.CanonicalName())
// TODO: localize // TODO: localize
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha")
return return
@ -87,7 +88,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) {
} }
if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil { if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil {
log.Println(err) slog.Error("Failed to delete hypha", "err", err)
viewutil.HttpErr(meta, http.StatusInternalServerError, h.CanonicalName(), err.Error()) viewutil.HttpErr(meta, http.StatusInternalServerError, h.CanonicalName(), err.Error())
return return
} }
@ -105,13 +106,15 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) {
switch h.(type) { switch h.(type) {
case *hyphae.EmptyHypha: case *hyphae.EmptyHypha:
log.Printf("%s tries to rename empty hypha %s", u.Name, h.CanonicalName()) slog.Info("Trying to rename empty hypha",
"username", u.Name, "hyphaName", h.CanonicalName())
viewutil.HttpErr(meta, 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 return
} }
if !u.CanProceed("rename") { if !u.CanProceed("rename") {
log.Printf("%s has no rights to rename %s\n", u.Name, h.CanonicalName()) slog.Info("No rights to rename hypha",
"username", u.Name, "hyphaName", h.CanonicalName())
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights") viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights")
return return
} }
@ -129,7 +132,8 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) {
} }
if err := shroom.Rename(oldHypha, newName, recursive, leaveRedirections, u); err != nil { if err := shroom.Rename(oldHypha, newName, recursive, leaveRedirections, u); err != nil {
log.Printf("%s tries to rename %s: %s", u.Name, oldHypha.CanonicalName(), err.Error()) slog.Error("Failed to rename hypha",
"err", err, "username", u.Name, "hyphaName", oldHypha.CanonicalName())
viewutil.HttpErr(meta, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize viewutil.HttpErr(meta, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize
return return
} }
@ -163,7 +167,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
default: default:
content, err = hyphae.FetchMycomarkupFile(h) content, err = hyphae.FetchMycomarkupFile(h)
if err != nil { if err != nil {
log.Println(err) slog.Error("Failed to fetch Mycomarkup file", "err", err)
viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, lc.Get("ui.error_text_fetch")) viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, lc.Get("ui.error_text_fetch"))
return return
} }

View File

@ -2,6 +2,7 @@ package web
import ( import (
"embed" "embed"
"github.com/bouncepaw/mycorrhiza/web/newtmpl" "github.com/bouncepaw/mycorrhiza/web/newtmpl"
"github.com/bouncepaw/mycorrhiza/web/viewutil" "github.com/bouncepaw/mycorrhiza/web/viewutil"
) )

View File

@ -2,12 +2,13 @@ package web
import ( import (
"fmt" "fmt"
"github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/web/viewutil"
"mime" "mime"
"net/http" "net/http"
"reflect" "reflect"
"github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/web/viewutil"
) )
func handlerUserChangePassword(w http.ResponseWriter, rq *http.Request) { func handlerUserChangePassword(w http.ResponseWriter, rq *http.Request) {

View File

@ -2,7 +2,17 @@ package web
import ( import (
"fmt" "fmt"
"git.sr.ht/~bouncepaw/mycomarkup/v5" "html/template"
"io"
"log/slog"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/hypview" "github.com/bouncepaw/mycorrhiza/hypview"
"github.com/bouncepaw/mycorrhiza/internal/backlinks" "github.com/bouncepaw/mycorrhiza/internal/backlinks"
"github.com/bouncepaw/mycorrhiza/internal/categories" "github.com/bouncepaw/mycorrhiza/internal/categories"
@ -12,26 +22,15 @@ import (
"github.com/bouncepaw/mycorrhiza/internal/mimetype" "github.com/bouncepaw/mycorrhiza/internal/mimetype"
"github.com/bouncepaw/mycorrhiza/internal/tree" "github.com/bouncepaw/mycorrhiza/internal/tree"
"github.com/bouncepaw/mycorrhiza/internal/user" "github.com/bouncepaw/mycorrhiza/internal/user"
"github.com/bouncepaw/mycorrhiza/l18n"
"github.com/bouncepaw/mycorrhiza/mycoopts" "github.com/bouncepaw/mycorrhiza/mycoopts"
"github.com/bouncepaw/mycorrhiza/util"
"github.com/bouncepaw/mycorrhiza/web/viewutil" "github.com/bouncepaw/mycorrhiza/web/viewutil"
"html/template"
"io"
"log"
"log/slog"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/gorilla/mux"
"git.sr.ht/~bouncepaw/mycomarkup/v5"
"git.sr.ht/~bouncepaw/mycomarkup/v5/mycocontext" "git.sr.ht/~bouncepaw/mycomarkup/v5/mycocontext"
"git.sr.ht/~bouncepaw/mycomarkup/v5/tools" "git.sr.ht/~bouncepaw/mycomarkup/v5/tools"
"github.com/bouncepaw/mycorrhiza/history" "github.com/gorilla/mux"
"github.com/bouncepaw/mycorrhiza/l18n"
"github.com/bouncepaw/mycorrhiza/util"
) )
func initReaders(r *mux.Router) { func initReaders(r *mux.Router) {
@ -109,6 +108,7 @@ func handlerRevisionText(w http.ResponseWriter, rq *http.Request) {
h = hyphae.ByName(hyphaName) h = hyphae.ByName(hyphaName)
) )
w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Content-Type", "text/plain; charset=utf-8")
switch h := h.(type) { switch h := h.(type) {
case *hyphae.EmptyHypha: case *hyphae.EmptyHypha:
var mycoFilePath = filepath.Join(files.HyphaeDir(), h.CanonicalName()+".myco") var mycoFilePath = filepath.Join(files.HyphaeDir(), h.CanonicalName()+".myco")
@ -116,27 +116,32 @@ func handlerRevisionText(w http.ResponseWriter, rq *http.Request) {
if err != nil { if err != nil {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
log.Printf("While serving text of %s at revision %s: %s\n", hyphaName, revHash, err.Error()) slog.Error("Failed to serve text part",
"err", err, "hyphaName", hyphaName, "revHash", revHash)
_, _ = io.WriteString(w, "Error: "+err.Error()) _, _ = io.WriteString(w, "Error: "+err.Error())
return return
} }
log.Printf("Serving text of %s from %s at revision %s\n", hyphaName, mycoFilePath, revHash) slog.Info("Serving text part",
"hyphaName", hyphaName, "revHash", revHash, "mycoFilePath", mycoFilePath)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
_, _ = io.WriteString(w, textContents) _, _ = io.WriteString(w, textContents)
case hyphae.ExistingHypha: case hyphae.ExistingHypha:
if !h.HasTextFile() { if !h.HasTextFile() {
log.Printf(`Media hypha %s has no text`) slog.Info("Media hypha has no text part; cannot serve it",
"hyphaName", h.CanonicalName())
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
} }
var textContents, err = history.FileAtRevision(h.TextFilePath(), revHash) var textContents, err = history.FileAtRevision(h.TextFilePath(), revHash)
if err != nil { if err != nil {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
log.Printf("While serving text of %s at revision %s: %s\n", hyphaName, revHash, err.Error()) slog.Error("Failed to serve text part",
"err", err, "hyphaName", h.CanonicalName(), "revHash", revHash)
_, _ = io.WriteString(w, "Error: "+err.Error()) _, _ = io.WriteString(w, "Error: "+err.Error())
return return
} }
log.Printf("Serving text of %s from %s at revision %s\n", hyphaName, h.TextFilePath(), revHash) slog.Info("Serving text part", "hyphaName", h.CanonicalName(), "revHash", revHash)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
_, _ = io.WriteString(w, textContents) _, _ = io.WriteString(w, textContents)
} }
@ -188,7 +193,7 @@ func handlerText(w http.ResponseWriter, rq *http.Request) {
hyphaName := util.HyphaNameFromRq(rq, "text") hyphaName := util.HyphaNameFromRq(rq, "text")
switch h := hyphae.ByName(hyphaName).(type) { switch h := hyphae.ByName(hyphaName).(type) {
case hyphae.ExistingHypha: case hyphae.ExistingHypha:
log.Println("Serving", h.TextFilePath()) slog.Info("Serving text part", "path", h.TextFilePath())
w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Content-Type", "text/plain; charset=utf-8")
http.ServeFile(w, rq, h.TextFilePath()) http.ServeFile(w, rq, h.TextFilePath())
} }
@ -201,9 +206,10 @@ func handlerBinary(w http.ResponseWriter, rq *http.Request) {
switch h := hyphae.ByName(hyphaName).(type) { switch h := hyphae.ByName(hyphaName).(type) {
case *hyphae.EmptyHypha, *hyphae.TextualHypha: case *hyphae.EmptyHypha, *hyphae.TextualHypha:
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
log.Printf("Textual hypha %s has no media, cannot serve\n", h.CanonicalName()) slog.Info("Textual hypha has no media file; cannot serve it",
"hyphaName", h.CanonicalName())
case *hyphae.MediaHypha: case *hyphae.MediaHypha:
log.Println("Serving", h.MediaFilePath()) slog.Info("Serving media file", "path", h.MediaFilePath())
w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(h.MediaFilePath()))) w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(h.MediaFilePath())))
http.ServeFile(w, rq, h.MediaFilePath()) http.ServeFile(w, rq, h.MediaFilePath())
} }