2021-05-09 10:42:12 +00:00
|
|
|
|
package web
|
2020-08-05 15:08:59 +00:00
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"net/http"
|
2020-08-10 19:58:02 +00:00
|
|
|
|
|
2021-10-05 20:10:28 +00:00
|
|
|
|
"github.com/bouncepaw/mycomarkup/v3"
|
|
|
|
|
"github.com/bouncepaw/mycomarkup/v3/mycocontext"
|
2021-08-11 09:20:29 +00:00
|
|
|
|
|
2021-07-15 17:46:35 +00:00
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
|
|
2021-02-17 18:41:35 +00:00
|
|
|
|
"github.com/bouncepaw/mycorrhiza/hyphae"
|
2021-09-06 17:46:34 +00:00
|
|
|
|
"github.com/bouncepaw/mycorrhiza/l18n"
|
2021-02-20 14:03:54 +00:00
|
|
|
|
"github.com/bouncepaw/mycorrhiza/shroom"
|
2020-11-15 12:58:13 +00:00
|
|
|
|
"github.com/bouncepaw/mycorrhiza/user"
|
2020-08-31 17:52:26 +00:00
|
|
|
|
"github.com/bouncepaw/mycorrhiza/util"
|
2021-02-22 17:38:41 +00:00
|
|
|
|
"github.com/bouncepaw/mycorrhiza/views"
|
2020-08-05 15:08:59 +00:00
|
|
|
|
)
|
|
|
|
|
|
2021-07-15 17:46:35 +00:00
|
|
|
|
func initMutators(r *mux.Router) {
|
|
|
|
|
r.PathPrefix("/edit/").HandlerFunc(handlerEdit)
|
2022-02-19 16:42:32 +00:00
|
|
|
|
r.PathPrefix("/rename/").HandlerFunc(handlerRename).Methods("GET", "POST")
|
2022-02-19 21:12:28 +00:00
|
|
|
|
r.PathPrefix("/delete/").HandlerFunc(handlerDelete).Methods("GET", "POST")
|
|
|
|
|
r.PathPrefix("/remove-media/").HandlerFunc(handlerRemoveMedia).Methods("GET", "POST")
|
2021-07-15 17:46:35 +00:00
|
|
|
|
r.PathPrefix("/upload-binary/").HandlerFunc(handlerUploadBinary)
|
|
|
|
|
r.PathPrefix("/upload-text/").HandlerFunc(handlerUploadText)
|
2021-01-19 18:08:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 21:12:28 +00:00
|
|
|
|
/// TODO: this is no longer ridiculous, but is now ugly. Gotta make it at least bearable to look at :-/
|
|
|
|
|
|
|
|
|
|
func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) {
|
|
|
|
|
util.PrepareRq(rq)
|
|
|
|
|
var (
|
|
|
|
|
u = user.FromRequest(rq)
|
|
|
|
|
lc = l18n.FromRequest(rq)
|
|
|
|
|
h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete"))
|
|
|
|
|
)
|
|
|
|
|
if !u.CanProceed("remove-media") {
|
|
|
|
|
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "no rights")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if rq.Method == "GET" {
|
2021-02-17 18:41:35 +00:00
|
|
|
|
util.HTTP200Page(
|
|
|
|
|
w,
|
2021-05-09 10:42:12 +00:00
|
|
|
|
views.BaseHTML(
|
2022-02-19 21:12:28 +00:00
|
|
|
|
fmt.Sprintf(lc.Get("ui.ask_remove_media"), util.BeautifulName(h.CanonicalName())),
|
|
|
|
|
views.RemoveMediaAskHTML(rq, h.CanonicalName()),
|
2021-09-06 17:46:34 +00:00
|
|
|
|
lc,
|
2021-02-17 18:41:35 +00:00
|
|
|
|
u))
|
2022-02-19 21:12:28 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
switch h := h.(type) {
|
|
|
|
|
case *hyphae.EmptyHypha, *hyphae.TextualHypha:
|
|
|
|
|
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove")
|
|
|
|
|
return
|
|
|
|
|
case *hyphae.MediaHypha:
|
2022-02-20 09:27:30 +00:00
|
|
|
|
if err := shroom.RemoveMedia(u, h); err != nil {
|
2022-02-19 21:12:28 +00:00
|
|
|
|
httpErr(w, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
2021-01-19 18:08:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 21:12:28 +00:00
|
|
|
|
func handlerDelete(w http.ResponseWriter, rq *http.Request) {
|
|
|
|
|
util.PrepareRq(rq)
|
|
|
|
|
var (
|
|
|
|
|
u = user.FromRequest(rq)
|
|
|
|
|
lc = l18n.FromRequest(rq)
|
|
|
|
|
h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete"))
|
|
|
|
|
)
|
2020-10-02 15:31:59 +00:00
|
|
|
|
|
2022-02-20 09:27:30 +00:00
|
|
|
|
if !u.CanProceed("delete") {
|
|
|
|
|
log.Printf("%s has no rights to delete ‘%s’\n", u.Name, h.CanonicalName())
|
|
|
|
|
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "No rights")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 21:12:28 +00:00
|
|
|
|
switch h.(type) {
|
|
|
|
|
case *hyphae.EmptyHypha:
|
2022-02-20 09:27:30 +00:00
|
|
|
|
log.Printf("%s tries to delete empty hypha ‘%s’\n", u.Name, h.CanonicalName())
|
2022-02-19 21:12:28 +00:00
|
|
|
|
// TODO: localize
|
|
|
|
|
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha")
|
|
|
|
|
return
|
|
|
|
|
}
|
2020-10-02 15:31:59 +00:00
|
|
|
|
|
2022-02-19 21:12:28 +00:00
|
|
|
|
if rq.Method == "GET" {
|
|
|
|
|
util.HTTP200Page(
|
|
|
|
|
w,
|
|
|
|
|
views.BaseHTML(
|
|
|
|
|
fmt.Sprintf(lc.Get("ui.ask_delete"), util.BeautifulName(h.CanonicalName())),
|
|
|
|
|
views.DeleteAskHTML(rq, h.CanonicalName()),
|
|
|
|
|
lc,
|
|
|
|
|
u))
|
|
|
|
|
return
|
|
|
|
|
}
|
2020-09-29 15:04:22 +00:00
|
|
|
|
|
2022-02-20 09:27:30 +00:00
|
|
|
|
if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil {
|
2022-02-19 21:12:28 +00:00
|
|
|
|
log.Println(err)
|
|
|
|
|
httpErr(w, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error())
|
2022-02-20 09:27:30 +00:00
|
|
|
|
return
|
2022-02-19 21:12:28 +00:00
|
|
|
|
}
|
|
|
|
|
http.Redirect(w, rq, "/hypha/"+h.CanonicalName(), http.StatusSeeOther)
|
|
|
|
|
}
|
2021-02-17 18:41:35 +00:00
|
|
|
|
|
2022-02-19 16:42:32 +00:00
|
|
|
|
func handlerRename(w http.ResponseWriter, rq *http.Request) {
|
2021-08-23 08:17:14 +00:00
|
|
|
|
util.PrepareRq(rq)
|
|
|
|
|
var (
|
2022-02-19 16:42:32 +00:00
|
|
|
|
u = user.FromRequest(rq)
|
|
|
|
|
lc = l18n.FromRequest(rq)
|
2022-02-19 21:12:28 +00:00
|
|
|
|
h = hyphae.ByName(util.HyphaNameFromRq(rq, "rename"))
|
2022-02-19 16:42:32 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
switch h.(type) {
|
|
|
|
|
case *hyphae.EmptyHypha:
|
|
|
|
|
log.Printf("%s tries to rename empty hypha ‘%s’", u.Name, h.CanonicalName())
|
|
|
|
|
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 21:12:28 +00:00
|
|
|
|
if !u.CanProceed("rename") {
|
|
|
|
|
log.Printf("%s has no rights to rename ‘%s’\n", u.Name, h.CanonicalName())
|
|
|
|
|
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "No rights")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 16:42:32 +00:00
|
|
|
|
var (
|
|
|
|
|
oldHypha = h.(hyphae.ExistingHypha)
|
2021-08-23 08:17:14 +00:00
|
|
|
|
newName = util.CanonicalName(rq.PostFormValue("new-name"))
|
|
|
|
|
recursive = rq.PostFormValue("recursive") == "true"
|
|
|
|
|
)
|
2022-02-19 16:42:32 +00:00
|
|
|
|
|
|
|
|
|
if rq.Method == "GET" {
|
|
|
|
|
util.HTTP200Page(
|
|
|
|
|
w,
|
|
|
|
|
views.BaseHTML(
|
|
|
|
|
fmt.Sprintf(lc.Get("ui.ask_rename"), util.BeautifulName(oldHypha.CanonicalName())),
|
|
|
|
|
views.RenameAskHTML(rq, oldHypha.CanonicalName()),
|
|
|
|
|
lc,
|
|
|
|
|
u))
|
2022-02-19 21:12:28 +00:00
|
|
|
|
return
|
2022-02-19 16:42:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil {
|
|
|
|
|
log.Printf("%s tries to rename ‘%s’: %s", u.Name, oldHypha.CanonicalName(), err.Error())
|
|
|
|
|
httpErr(w, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize
|
2021-08-23 08:17:14 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
http.Redirect(w, rq, "/hypha/"+newName, http.StatusSeeOther)
|
|
|
|
|
}
|
2020-08-05 15:08:59 +00:00
|
|
|
|
|
|
|
|
|
// handlerEdit shows the edit form. It doesn't edit anything actually.
|
|
|
|
|
func handlerEdit(w http.ResponseWriter, rq *http.Request) {
|
2021-05-09 10:42:12 +00:00
|
|
|
|
util.PrepareRq(rq)
|
2020-08-05 15:08:59 +00:00
|
|
|
|
var (
|
2021-05-09 10:42:12 +00:00
|
|
|
|
hyphaName = util.HyphaNameFromRq(rq, "edit")
|
2021-02-17 18:41:35 +00:00
|
|
|
|
h = hyphae.ByName(hyphaName)
|
|
|
|
|
warning string
|
|
|
|
|
textAreaFill string
|
|
|
|
|
err error
|
|
|
|
|
u = user.FromRequest(rq)
|
2021-09-06 17:46:34 +00:00
|
|
|
|
lc = l18n.FromRequest(rq)
|
2020-08-05 15:08:59 +00:00
|
|
|
|
)
|
2022-02-19 16:42:32 +00:00
|
|
|
|
if err := shroom.CanEdit(u, h, lc); err != nil {
|
2021-09-06 17:46:34 +00:00
|
|
|
|
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
2021-02-17 18:41:35 +00:00
|
|
|
|
err.Error())
|
2020-11-15 12:58:13 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2022-02-04 14:56:28 +00:00
|
|
|
|
switch h.(type) {
|
|
|
|
|
case *hyphae.EmptyHypha:
|
|
|
|
|
warning = fmt.Sprintf(`<p class="warning warning_new-hypha">%s</p>`, lc.Get("edit.new_hypha"))
|
|
|
|
|
default:
|
2022-02-19 08:26:38 +00:00
|
|
|
|
textAreaFill, err = shroom.FetchTextFile(h)
|
2020-08-05 15:08:59 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
log.Println(err)
|
2021-09-06 17:46:34 +00:00
|
|
|
|
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
|
|
|
|
lc.Get("ui.error_text_fetch"))
|
2020-08-05 15:08:59 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-02-17 18:41:35 +00:00
|
|
|
|
}
|
|
|
|
|
util.HTTP200Page(
|
|
|
|
|
w,
|
2021-05-09 10:42:12 +00:00
|
|
|
|
views.BaseHTML(
|
2021-09-06 17:46:34 +00:00
|
|
|
|
fmt.Sprintf(lc.Get("edit.title"), util.BeautifulName(hyphaName)),
|
2021-02-23 14:25:07 +00:00
|
|
|
|
views.EditHTML(rq, hyphaName, textAreaFill, warning),
|
2021-09-06 17:46:34 +00:00
|
|
|
|
lc,
|
2021-02-17 18:41:35 +00:00
|
|
|
|
u))
|
2020-08-05 15:08:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// handlerUploadText uploads a new text part for the hypha.
|
|
|
|
|
func handlerUploadText(w http.ResponseWriter, rq *http.Request) {
|
2021-05-09 10:42:12 +00:00
|
|
|
|
util.PrepareRq(rq)
|
2020-08-05 15:08:59 +00:00
|
|
|
|
var (
|
2021-05-09 10:42:12 +00:00
|
|
|
|
hyphaName = util.HyphaNameFromRq(rq, "upload-text")
|
2021-02-17 18:41:35 +00:00
|
|
|
|
h = hyphae.ByName(hyphaName)
|
2020-11-18 13:07:53 +00:00
|
|
|
|
textData = rq.PostFormValue("text")
|
2021-01-16 16:42:18 +00:00
|
|
|
|
action = rq.PostFormValue("action")
|
2021-06-14 00:38:43 +00:00
|
|
|
|
message = rq.PostFormValue("message")
|
2021-01-09 20:49:48 +00:00
|
|
|
|
u = user.FromRequest(rq)
|
2021-09-06 17:46:34 +00:00
|
|
|
|
lc = l18n.FromRequest(rq)
|
2020-08-05 15:08:59 +00:00
|
|
|
|
)
|
2021-02-17 18:41:35 +00:00
|
|
|
|
|
|
|
|
|
if action != "Preview" {
|
2022-02-20 09:27:30 +00:00
|
|
|
|
if err := shroom.UploadText(h, []byte(textData), message, u); err != nil {
|
2022-02-19 16:42:32 +00:00
|
|
|
|
httpErr(w, lc, http.StatusForbidden, hyphaName, err.Error())
|
2021-02-20 16:21:10 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2020-08-05 15:08:59 +00:00
|
|
|
|
}
|
2021-02-17 18:41:35 +00:00
|
|
|
|
|
2021-01-16 16:42:18 +00:00
|
|
|
|
if action == "Preview" {
|
2021-05-25 07:11:16 +00:00
|
|
|
|
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, textData)
|
|
|
|
|
|
2021-02-17 18:41:35 +00:00
|
|
|
|
util.HTTP200Page(
|
|
|
|
|
w,
|
2021-05-09 10:42:12 +00:00
|
|
|
|
views.BaseHTML(
|
2021-09-06 17:46:34 +00:00
|
|
|
|
fmt.Sprintf(lc.Get("edit.preview_title"), util.BeautifulName(hyphaName)),
|
2021-02-23 14:25:07 +00:00
|
|
|
|
views.PreviewHTML(
|
2021-02-17 18:41:35 +00:00
|
|
|
|
rq,
|
|
|
|
|
hyphaName,
|
|
|
|
|
textData,
|
2021-06-14 00:38:43 +00:00
|
|
|
|
message,
|
2021-02-17 18:41:35 +00:00
|
|
|
|
"",
|
2021-05-25 07:11:16 +00:00
|
|
|
|
mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx))),
|
2021-09-06 17:46:34 +00:00
|
|
|
|
lc,
|
2021-02-17 18:41:35 +00:00
|
|
|
|
u))
|
2020-08-05 15:08:59 +00:00
|
|
|
|
} else {
|
2021-02-17 18:41:35 +00:00
|
|
|
|
http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
|
2020-08-05 15:08:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-25 13:08:59 +00:00
|
|
|
|
// handlerUploadBinary uploads a new attachment for the hypha.
|
2020-08-05 15:08:59 +00:00
|
|
|
|
func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
|
2021-05-09 10:42:12 +00:00
|
|
|
|
util.PrepareRq(rq)
|
2021-02-17 18:41:35 +00:00
|
|
|
|
rq.ParseMultipartForm(10 << 20) // Set upload limit
|
2020-11-18 13:07:53 +00:00
|
|
|
|
var (
|
2021-05-09 10:42:12 +00:00
|
|
|
|
hyphaName = util.HyphaNameFromRq(rq, "upload-binary")
|
2021-02-17 18:41:35 +00:00
|
|
|
|
h = hyphae.ByName(hyphaName)
|
|
|
|
|
u = user.FromRequest(rq)
|
2021-09-06 17:46:34 +00:00
|
|
|
|
lc = l18n.FromRequest(rq)
|
2021-02-17 18:41:35 +00:00
|
|
|
|
file, handler, err = rq.FormFile("binary")
|
2020-11-18 13:07:53 +00:00
|
|
|
|
)
|
2021-02-20 14:03:54 +00:00
|
|
|
|
if err != nil {
|
2021-09-06 17:46:34 +00:00
|
|
|
|
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
2021-02-20 14:03:54 +00:00
|
|
|
|
err.Error())
|
|
|
|
|
}
|
2022-02-19 16:42:32 +00:00
|
|
|
|
if err := shroom.CanAttach(u, h, lc); err != nil {
|
2021-09-06 17:46:34 +00:00
|
|
|
|
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
2021-02-17 18:41:35 +00:00
|
|
|
|
err.Error())
|
2020-08-05 15:08:59 +00:00
|
|
|
|
}
|
2020-11-18 13:07:53 +00:00
|
|
|
|
|
2020-08-05 15:08:59 +00:00
|
|
|
|
// If file is not passed:
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2020-11-18 13:07:53 +00:00
|
|
|
|
|
2020-08-05 15:08:59 +00:00
|
|
|
|
// If file is passed:
|
2021-02-17 18:41:35 +00:00
|
|
|
|
if file != nil {
|
|
|
|
|
defer file.Close()
|
|
|
|
|
}
|
2022-02-19 16:42:32 +00:00
|
|
|
|
|
2020-08-05 15:08:59 +00:00
|
|
|
|
var (
|
2022-02-19 16:42:32 +00:00
|
|
|
|
mime = handler.Header.Get("Content-Type")
|
2020-08-05 15:08:59 +00:00
|
|
|
|
)
|
|
|
|
|
|
2022-02-20 09:27:30 +00:00
|
|
|
|
if err := shroom.UploadBinary(h, mime, file, u); err != nil {
|
2022-02-19 16:42:32 +00:00
|
|
|
|
httpErr(w, lc, http.StatusInternalServerError, hyphaName, err.Error())
|
2020-11-18 13:07:53 +00:00
|
|
|
|
return
|
2020-08-19 18:54:23 +00:00
|
|
|
|
}
|
2021-02-17 18:41:35 +00:00
|
|
|
|
http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
|
2020-08-05 15:08:59 +00:00
|
|
|
|
}
|