From 41651f9e9b1367160e374491c81f2050e2cd4ec1 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sun, 20 Feb 2022 00:12:28 +0300 Subject: [PATCH] Break a lot of stuff Starring: * Fix some bugs for /rename/ * Introduce /delete/, /remove-media/ * Introduce some bugs for the methods mentioned above --- shroom/rename.go | 3 + shroom/unattach.go | 18 ++-- user/user.go | 6 -- views/modal.qtpl | 14 +-- views/modal.qtpl.go | 217 ++++++++++++++++++++++---------------------- web/mutators.go | 148 +++++++++++++++--------------- 6 files changed, 198 insertions(+), 208 deletions(-) diff --git a/shroom/rename.go b/shroom/rename.go index e59bb5a..503f497 100644 --- a/shroom/rename.go +++ b/shroom/rename.go @@ -26,6 +26,9 @@ func Rename(oldHypha hyphae.ExistingHypha, newName string, recursive bool, u *us switch targetHypha := hyphae.ByName(newName); targetHypha.(type) { case hyphae.ExistingHypha: + if targetHypha.CanonicalName() == oldHypha.CanonicalName() { + return nil + } rejectRenameLog(oldHypha, u, fmt.Sprintf("name ‘%s’ taken already", newName)) return errors.New("ui.rename_taken_tip") // FIXME: There is a bug related to this. } diff --git a/shroom/unattach.go b/shroom/unattach.go index 14f9af5..ec2ff1c 100644 --- a/shroom/unattach.go +++ b/shroom/unattach.go @@ -9,17 +9,11 @@ import ( "github.com/bouncepaw/mycorrhiza/user" ) -// UnattachHypha unattaches hypha and makes a history record about that. -func UnattachHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) error { - - if err := CanUnattach(u, h, lc); err != nil { - return err - } - H := h.(*hyphae.MediaHypha) - +// RemoveMedia unattaches hypha and makes a history record about that. +func RemoveMedia(u *user.User, h *hyphae.MediaHypha, lc *l18n.Localizer) error { hop := history. Operation(history.TypeUnattachHypha). - WithFilesRemoved(H.MediaFilePath()). + WithFilesRemoved(h.MediaFilePath()). WithMsg(fmt.Sprintf("Unattach ‘%s’", h.CanonicalName())). WithUser(u). Apply() @@ -30,10 +24,10 @@ func UnattachHypha(u *user.User, h hyphae.Hypha, lc *l18n.Localizer) error { return fmt.Errorf("Could not unattach this hypha due to internal server errors: %v", hop.Errs) } - if H.HasTextFile() { - hyphae.Insert(hyphae.ShrinkMediaToTextual(H)) + if h.HasTextFile() { + hyphae.Insert(hyphae.ShrinkMediaToTextual(h)) } else { - hyphae.DeleteHypha(H) + hyphae.DeleteHypha(h) } return nil } diff --git a/user/user.go b/user/user.go index 6020522..886c081 100644 --- a/user/user.go +++ b/user/user.go @@ -35,15 +35,9 @@ var minimalRights = map[string]int{ "upload-binary": 1, "upload-text": 1, "rename": 2, - "rename-ask": 2, - "rename-confirm": 2, "remove-media": 2, - "unattach-ask": 2, - "unattach-confirm": 2, "update-header-links": 3, "delete": 3, - "delete-ask": 3, - "delete-confirm": 3, "reindex": 4, "admin": 4, "admin/shutdown": 4, diff --git a/views/modal.qtpl b/views/modal.qtpl index 8d6adf0..8db2581 100644 --- a/views/modal.qtpl +++ b/views/modal.qtpl @@ -7,7 +7,7 @@ lc := l18n.FromRequest(rq) %} {%= modalBegin( - "delete-confirm", + "delete", hyphaName, "", fmt.Sprintf(lc.Get("ui.ask_delete"), beautifulLink(hyphaName))) %} @@ -16,25 +16,27 @@ {%= modalEnd(hyphaName, true, lc) %} {% endfunc %} -{% func UnattachAskHTML(rq *http.Request, hyphaName string) %} +{% func RemoveMediaAskHTML(rq *http.Request, hyphaName string) %} {% code lc := l18n.FromRequest(rq) %} {%= modalBegin( - "unattach", + "remove-media", hyphaName, "", - fmt.Sprintf(lc.Get("ui.ask_unattach"), beautifulLink(hyphaName))) %} -{%= modalReallyWant(hyphaName, lc.Get("ui.ask_unattach_verb"), lc) %} + fmt.Sprintf(lc.Get("ui.ask_remove_media"), beautifulLink(hyphaName))) %} +{%= modalReallyWant(hyphaName, lc.Get("ui.ask_remove_media_verb"), lc) %} {%= modalEnd(hyphaName, true, lc) %} {% endfunc %} +bloody hell !! + {% func RenameAskHTML(rq *http.Request, hyphaName string) %} {% code lc := l18n.FromRequest(rq) %} {%= modalBegin( - "rename-confirm", + "rename", hyphaName, ` method="post" enctype="multipart/form-data"`, fmt.Sprintf(lc.Get("ui.ask_rename"), beautifulLink(hyphaName))) %} diff --git a/views/modal.qtpl.go b/views/modal.qtpl.go index 10bddfe..09b6eb8 100644 --- a/views/modal.qtpl.go +++ b/views/modal.qtpl.go @@ -39,7 +39,7 @@ func StreamDeleteAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName `) //line views/modal.qtpl:9 streammodalBegin(qw422016, - "delete-confirm", + "delete", hyphaName, "", fmt.Sprintf(lc.Get("ui.ask_delete"), beautifulLink(hyphaName))) @@ -91,7 +91,7 @@ func DeleteAskHTML(rq *http.Request, hyphaName string) string { } //line views/modal.qtpl:19 -func StreamUnattachAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string) { +func StreamRemoveMediaAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string) { //line views/modal.qtpl:19 qw422016.N().S(` `) @@ -103,15 +103,15 @@ func StreamUnattachAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaNam `) //line views/modal.qtpl:23 streammodalBegin(qw422016, - "unattach", + "remove-media", hyphaName, "", - fmt.Sprintf(lc.Get("ui.ask_unattach"), beautifulLink(hyphaName))) + fmt.Sprintf(lc.Get("ui.ask_remove_media"), beautifulLink(hyphaName))) //line views/modal.qtpl:27 qw422016.N().S(` `) //line views/modal.qtpl:28 - streammodalReallyWant(qw422016, hyphaName, lc.Get("ui.ask_unattach_verb"), lc) + streammodalReallyWant(qw422016, hyphaName, lc.Get("ui.ask_remove_media_verb"), lc) //line views/modal.qtpl:28 qw422016.N().S(` `) @@ -124,22 +124,22 @@ func StreamUnattachAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaNam } //line views/modal.qtpl:30 -func WriteUnattachAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string) { +func WriteRemoveMediaAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string) { //line views/modal.qtpl:30 qw422016 := qt422016.AcquireWriter(qq422016) //line views/modal.qtpl:30 - StreamUnattachAskHTML(qw422016, rq, hyphaName) + StreamRemoveMediaAskHTML(qw422016, rq, hyphaName) //line views/modal.qtpl:30 qt422016.ReleaseWriter(qw422016) //line views/modal.qtpl:30 } //line views/modal.qtpl:30 -func UnattachAskHTML(rq *http.Request, hyphaName string) string { +func RemoveMediaAskHTML(rq *http.Request, hyphaName string) string { //line views/modal.qtpl:30 qb422016 := qt422016.AcquireByteBuffer() //line views/modal.qtpl:30 - WriteUnattachAskHTML(qb422016, rq, hyphaName) + WriteRemoveMediaAskHTML(qb422016, rq, hyphaName) //line views/modal.qtpl:30 qs422016 := string(qb422016.B) //line views/modal.qtpl:30 @@ -149,233 +149,236 @@ func UnattachAskHTML(rq *http.Request, hyphaName string) string { //line views/modal.qtpl:30 } -//line views/modal.qtpl:32 -func StreamRenameAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string) { -//line views/modal.qtpl:32 - qw422016.N().S(` -`) -//line views/modal.qtpl:34 - lc := l18n.FromRequest(rq) +// bloody hell !! +// -//line views/modal.qtpl:35 +//line views/modal.qtpl:34 +func StreamRenameAskHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName string) { +//line views/modal.qtpl:34 qw422016.N().S(` `) //line views/modal.qtpl:36 + lc := l18n.FromRequest(rq) + +//line views/modal.qtpl:37 + qw422016.N().S(` +`) +//line views/modal.qtpl:38 streammodalBegin(qw422016, - "rename-confirm", + "rename", hyphaName, ` method="post" enctype="multipart/form-data"`, fmt.Sprintf(lc.Get("ui.ask_rename"), beautifulLink(hyphaName))) -//line views/modal.qtpl:40 +//line views/modal.qtpl:42 qw422016.N().S(`

`) -//line views/modal.qtpl:47 +//line views/modal.qtpl:49 qw422016.E().S(lc.Get("ui.rename_tip")) -//line views/modal.qtpl:47 +//line views/modal.qtpl:49 qw422016.N().S(`

`) -//line views/modal.qtpl:48 +//line views/modal.qtpl:50 streammodalEnd(qw422016, hyphaName, false, lc) -//line views/modal.qtpl:48 +//line views/modal.qtpl:50 qw422016.N().S(` `) -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 } -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 func WriteRenameAskHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName string) { -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 StreamRenameAskHTML(qw422016, rq, hyphaName) -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 qt422016.ReleaseWriter(qw422016) -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 } -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 func RenameAskHTML(rq *http.Request, hyphaName string) string { -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 qb422016 := qt422016.AcquireByteBuffer() -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 WriteRenameAskHTML(qb422016, rq, hyphaName) -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 qs422016 := string(qb422016.B) -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 qt422016.ReleaseByteBuffer(qb422016) -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 return qs422016 -//line views/modal.qtpl:49 +//line views/modal.qtpl:51 } -//line views/modal.qtpl:51 +//line views/modal.qtpl:53 func streammodalReallyWant(qw422016 *qt422016.Writer, hyphaName, verb string, lc *l18n.Localizer) { -//line views/modal.qtpl:51 +//line views/modal.qtpl:53 qw422016.N().S(` `) -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 } -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 func writemodalReallyWant(qq422016 qtio422016.Writer, hyphaName, verb string, lc *l18n.Localizer) { -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 streammodalReallyWant(qw422016, hyphaName, verb, lc) -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 qt422016.ReleaseWriter(qw422016) -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 } -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 func modalReallyWant(hyphaName, verb string, lc *l18n.Localizer) string { -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 qb422016 := qt422016.AcquireByteBuffer() -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 writemodalReallyWant(qb422016, hyphaName, verb, lc) -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 qs422016 := string(qb422016.B) -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 qt422016.ReleaseByteBuffer(qb422016) -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 return qs422016 -//line views/modal.qtpl:53 +//line views/modal.qtpl:55 } -//line views/modal.qtpl:55 +//line views/modal.qtpl:57 func streammodalBegin(qw422016 *qt422016.Writer, path, hyphaName, formAttrs, legend string) { -//line views/modal.qtpl:55 +//line views/modal.qtpl:57 qw422016.N().S(`
`) -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 } -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 func writemodalEnd(qq422016 qtio422016.Writer, hyphaName string, shouldFocusOnConfirm bool, lc *l18n.Localizer) { -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 streammodalEnd(qw422016, hyphaName, shouldFocusOnConfirm, lc) -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 qt422016.ReleaseWriter(qw422016) -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 } -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 func modalEnd(hyphaName string, shouldFocusOnConfirm bool, lc *l18n.Localizer) string { -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 qb422016 := qt422016.AcquireByteBuffer() -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 writemodalEnd(qb422016, hyphaName, shouldFocusOnConfirm, lc) -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 qs422016 := string(qb422016.B) -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 qt422016.ReleaseByteBuffer(qb422016) -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 return qs422016 -//line views/modal.qtpl:70 +//line views/modal.qtpl:72 } diff --git a/web/mutators.go b/web/mutators.go index 268e5f8..d963f02 100644 --- a/web/mutators.go +++ b/web/mutators.go @@ -19,108 +19,95 @@ import ( ) func initMutators(r *mux.Router) { - // Those that do not actually mutate anything: r.PathPrefix("/edit/").HandlerFunc(handlerEdit) r.PathPrefix("/rename/").HandlerFunc(handlerRename).Methods("GET", "POST") - r.PathPrefix("/delete-ask/").HandlerFunc(handlerDeleteAsk) - r.PathPrefix("/unattach-ask/").HandlerFunc(handlerUnattachAsk) - // And those that do mutate something: + r.PathPrefix("/delete/").HandlerFunc(handlerDelete).Methods("GET", "POST") + r.PathPrefix("/remove-media/").HandlerFunc(handlerRemoveMedia).Methods("GET", "POST") r.PathPrefix("/upload-binary/").HandlerFunc(handlerUploadBinary) r.PathPrefix("/upload-text/").HandlerFunc(handlerUploadText) - r.PathPrefix("/delete-confirm/").HandlerFunc(handlerDeleteConfirm) - r.PathPrefix("/unattach-confirm/").HandlerFunc(handlerUnattachConfirm) } -/// TODO: this is ridiculous, refactor heavily: +/// TODO: this is no longer ridiculous, but is now ugly. Gotta make it at least bearable to look at :-/ -func factoryHandlerAsker( - actionPath string, - asker func(*user.User, hyphae.Hypha, *l18n.Localizer) error, - succTitleKey string, - succPageTemplate func(*http.Request, string) string, -) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, rq *http.Request) { - util.PrepareRq(rq) - var ( - hyphaName = util.HyphaNameFromRq(rq, actionPath) - h = hyphae.ByName(hyphaName) - u = user.FromRequest(rq) - lc = l18n.FromRequest(rq) - ) - if err := asker(u, h, lc); err != nil { - httpErr( - w, - lc, - http.StatusInternalServerError, - hyphaName, - err.Error()) - return - } +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" { util.HTTP200Page( w, views.BaseHTML( - fmt.Sprintf(lc.Get(succTitleKey), util.BeautifulName(hyphaName)), - succPageTemplate(rq, hyphaName), + fmt.Sprintf(lc.Get("ui.ask_remove_media"), util.BeautifulName(h.CanonicalName())), + views.RemoveMediaAskHTML(rq, h.CanonicalName()), lc, u)) + return } -} - -var handlerUnattachAsk = factoryHandlerAsker( - "unattach-ask", - shroom.CanUnattach, - "ui.ask_unattach", - views.UnattachAskHTML, -) - -var handlerDeleteAsk = factoryHandlerAsker( - "delete-ask", - shroom.CanDelete, - "ui.ask_delete", - views.DeleteAskHTML, -) - -func factoryHandlerConfirmer( - actionPath string, - confirmer func(hyphae.Hypha, *user.User, *http.Request) error, -) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, rq *http.Request) { - util.PrepareRq(rq) - var ( - hyphaName = util.HyphaNameFromRq(rq, actionPath) - h = hyphae.ByName(hyphaName) - u = user.FromRequest(rq) - lc = l18n.FromRequest(rq) - ) - if err := confirmer(h, u, rq); err != nil { - httpErr(w, lc, http.StatusInternalServerError, hyphaName, - err.Error()) + switch h := h.(type) { + case *hyphae.EmptyHypha, *hyphae.TextualHypha: + httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove") + return + case *hyphae.MediaHypha: + if err := shroom.RemoveMedia(u, h, lc); err != nil { + httpErr(w, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } - http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther) } } -var handlerUnattachConfirm = factoryHandlerConfirmer( - "unattach-confirm", - func(h hyphae.Hypha, u *user.User, rq *http.Request) error { - return shroom.UnattachHypha(u, h, l18n.FromRequest(rq)) - }, -) +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")) + ) -var handlerDeleteConfirm = factoryHandlerConfirmer( - "delete-confirm", - func(h hyphae.Hypha, u *user.User, rq *http.Request) error { - return shroom.DeleteHypha(u, h, l18n.FromRequest(rq)) - }, -) + switch h.(type) { + case *hyphae.EmptyHypha: + log.Printf("%s tries to delete empty hypha ‘%s’", u.Name, h.CanonicalName()) + // TODO: localize + httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") + return + } + + 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 + } + + 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 + } + + if err := shroom.DeleteHypha(u, h, lc); err != nil { + log.Println(err) + httpErr(w, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + } + http.Redirect(w, rq, "/hypha/"+h.CanonicalName(), http.StatusSeeOther) +} func handlerRename(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) var ( u = user.FromRequest(rq) lc = l18n.FromRequest(rq) - h = hyphae.ByName(util.HyphaNameFromRq(rq, "rename-confirm")) + h = hyphae.ByName(util.HyphaNameFromRq(rq, "rename")) ) switch h.(type) { @@ -130,6 +117,12 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { return } + 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 + } + var ( oldHypha = h.(hyphae.ExistingHypha) newName = util.CanonicalName(rq.PostFormValue("new-name")) @@ -144,6 +137,7 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { views.RenameAskHTML(rq, oldHypha.CanonicalName()), lc, u)) + return } if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil {