bootstraping page save process
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmKcMkwACgkQO3+8IhRO Y5jVmxAAialwgk9+gDLnZU5tnyPo7I4fSiSXD9OpFSKYnqKsB+iu+YeUuCuKMSmV peEnNN5BKOWgMginG5H0t6x+PsjKAcpbO+YaukOgEqS2RAasnBfw04gNKXRmhz8/ Tf2kUhv+h9X8OpLEfrGXzO+vyRTzjZWe2DgDhDkTwJfdWqGr7ruqdk8vpzgTIXy+ vjd3ZqS/tnvnzsj3riojaFNv75Pnd+szr8/+klr683e9rCRWmDijXDg3/LjqX3s2 1KHjayyZiCl21iTJ4YxG7n9pnddLdfekw/PK3FQCcwHU8SvSR0fWBYJ78nqlsPmt 3OqKqSRn6jQP2Tw1IwmCdgfW0gTuZjPetzWb4DleOfi1iDm9RuGfDLKP6xPKPJRW sjk+icfyVOIIj3FP3dRV4uwTufOHgTQHJuz/B4ajpgukC9R3TRTTzBdKn86hhCbj Tvqwzf120IwS+fEFdaurgZ/ODZ2YAVZMOT6A88fZt12ui664aWG442WWrNKTOeYS z14rOUK/PscgJbj4tyIuItL0TGJqSG9o5gCj8Pr/B7pIHNpTRztRh9sb66c/Oe34 V3S1r9Z0SkRR9OEkPFKIn0vaZGa9jVUFlz4hQzonSN7DHETLJoBSpGlof8wrHus9 cltFwO46NrDRck/skDYiJbJvHfXbkUZ5vHs2hSjqS8yb0/HwQk8= =JyHV -----END PGP SIGNATURE-----
10 files changed,
67 insertions(+),
45 deletions(-)
M
archetype/adapter.go
→
archetype/adapter.go
@@ -1,24 +1,17 @@
package archetype -type EditMode int - -const ( - EditModeLiteralTextArea EditMode = iota - EditModeEscapedContentEditable -) - type Adapter interface { Init(cfg *Config) Name() string - EditMode() EditMode + EditableSlugs() bool GetConfig(key string) (interface{}, error) SetConfig(key string, value interface{}) error ListPages() map[string]string GetPage(string) (Page, error) FormatPage(string) string FormattingHelp() string - CreatePage(page Page) error - EditPage(old Page, new Page) error - DeletePage(page Page) error - Build() string + CreatePage(slug, title, content string) error + SavePage(oldSlug, newSlug, title, content string) error + DeletePage(slug string) error + Build() (bool, string) }
M
archetype/eureka.go
→
archetype/eureka.go
@@ -27,8 +27,8 @@ func (self *EurekaAdapter) Name() string {
return "eureka" } -func (self *EurekaAdapter) EditMode() EditMode { - return EditModeLiteralTextArea +func (self *EurekaAdapter) EditableSlugs() bool { + return false } func (self *EurekaAdapter) GetConfig(key string) (interface{}, error) {@@ -77,6 +77,7 @@ content := string(f[:])
return Page{ Title: title, + Slug: filename, Content: content, Edited: fileInfo.ModTime(), }, nil@@ -90,18 +91,18 @@ func (self *EurekaAdapter) FormattingHelp() string {
return "help!" } -func (self *EurekaAdapter) CreatePage(page Page) error { +func (self *EurekaAdapter) CreatePage(slug, title, content string) error { return nil } -func (self *EurekaAdapter) EditPage(old Page, new Page) error { +func (self *EurekaAdapter) SavePage(oldSlug, newSlug, title, content string) error { return nil } -func (self *EurekaAdapter) DeletePage(page Page) error { +func (self *EurekaAdapter) DeletePage(slug string) error { return nil } -func (self *EurekaAdapter) Build() string { - return "Build successful" +func (self *EurekaAdapter) Build() (bool, string) { + return true, "Build successful" }
M
archetype/page.go
→
archetype/page.go
@@ -6,6 +6,7 @@ )
type Page struct { Title string + Slug string Content string Edited time.Time }
M
go.sum
→
go.sum
@@ -23,3 +23,7 @@ nilfm.cc/git/quartzgun v0.0.0-20220516061509-0e5a81f27b63 h1:HlIWrDDJjOFLrxPQzldzDz78K8Z5NDtTCoYkmmI8/JA=
nilfm.cc/git/quartzgun v0.0.0-20220516061509-0e5a81f27b63/go.mod h1:/DDvt1DtzNuUf3HHaP29WMei/kkdaRW+ySmEzybvVto= nilfm.cc/git/quartzgun v0.1.0 h1:G+f/UnGpm5FAEqaY3Lj5UHvq0eB5sytM5s4FLesLC3E= nilfm.cc/git/quartzgun v0.1.0/go.mod h1:/DDvt1DtzNuUf3HHaP29WMei/kkdaRW+ySmEzybvVto= +nilfm.cc/git/quartzgun v0.1.1 h1:swJg3im4YsD64MnfJHa2Bxm0adGT/ArAMHLAPeEjuS0= +nilfm.cc/git/quartzgun v0.1.1/go.mod h1:/DDvt1DtzNuUf3HHaP29WMei/kkdaRW+ySmEzybvVto= +nilfm.cc/git/quartzgun v0.1.2 h1:B0IN24Y1Bg2IVvKxXXVtTUNFdVL8h3k/r0+LFAyqtMI= +nilfm.cc/git/quartzgun v0.1.2/go.mod h1:/DDvt1DtzNuUf3HHaP29WMei/kkdaRW+ySmEzybvVto=
M
lfo/middleware.go
→
lfo/middleware.go
@@ -2,6 +2,7 @@ package lfo
import ( "context" + "strings" "net/http" core "nilfm.cc/git/nirvash/archetype" )@@ -15,14 +16,21 @@
return http.HandlerFunc(handlerFunc) } -func WithEditModes(next http.Handler) http.Handler { - handlerFunc := func(w http.ResponseWriter, req *http.Request) { - *req = *req.WithContext(context.WithValue(req.Context(), "edit-modes", map[string]core.EditMode{ - "Literal": core.EditModeLiteralTextArea, - "Escaped": core.EditModeEscapedContentEditable, - })) - next.ServeHTTP(w, req) - } - - return http.HandlerFunc(handlerFunc) -} +func EnsurePageData(next http.Handler) http.Handler { + handlerFunc := func(w http.ResponseWriter, req *http.Request) { + pageTitle := req.FormValue("title") + pageContent := req.FormValue("content") + + if pageTitle == "" || pageContent == "" { + newUri := "/edit/" + slug := strings.Join(strings.Split(req.URL.Path, "/")[2:], "/") + newUri += slug + req.Method = http.MethodGet + http.Redirect(w, req, newUri, http.StatusSeeOther) + } else { + next.ServeHTTP(w, req) + } + } + + return http.HandlerFunc(handlerFunc) +}
M
nirvash.go
→
nirvash.go
@@ -33,7 +33,7 @@ "/static": cfg.AssetRoot,
}, } - rtr.Get("/login", renderer.Template( + rtr.Get("/login",renderer.Template( "templates/login.html")) rtr.Post("/login", middleware.Authorize("/", udb, "/login?tryagain=1"))@@ -45,12 +45,20 @@ "templates/cms_list.html",
"templates/header.html", "templates/footer.html"), cfg.Adapter), http.MethodGet, udb, "/login")) - rtr.Get(`/edit/(?P<Slug>\S+)`, middleware.Protected( + rtr.Get(`/edit/(?P<Slug>\S+)`, middleware.Fortify(middleware.Protected( shell.WithAdapter( renderer.Template( "templates/cms_edit.html", "templates/header.html", - "templates/footer.html"), cfg.Adapter), http.MethodGet, udb, "/login")) + "templates/footer.html"), cfg.Adapter), http.MethodGet, udb, "/login"))) + + rtr.Post(`/save/(?P<Slug>\S+)`, middleware.Defend(middleware.Protected( + shell.WithAdapter( + shell.EnsurePageData( + renderer.Template( + "templates/cms_save.html", + "templates/header.html", + "templates/footer.html")), cfg.Adapter), http.MethodGet, udb, "/login"), udb, "/")) http.ListenAndServe(":8080", rtr) }
M
templates/cms_edit.html
→
templates/cms_edit.html
@@ -1,19 +1,18 @@
{{ $slug := ((.Context).Value "params").Slug }} {{ $page := ((.Context).Value "adapter").GetPage $slug }} -{{ $editMode := ((.Context).Value "adapter").EditMode }} -{{ $editModes := (.Context).Value "edit-modes" }} +{{ $editableSlugs := ((.Context).Value "adapter").EditableSlugs }} {{ template "header" . }} - -<form method="POST" action="/save/{{$slug}}"> -<textarea name="title">{{($page).Title}}</textarea> -<span>last edited {{($page).Edited}}</span> -{{ if eq $editMode 0 }} +<a href="/">«</a> +<form method="POST" action="/save/{{($page).Slug}}"> + <input hidden name="oldSlug" value="{{($page).Slug}}"> + {{ if $editableSlugs }} + <input type="text" name="slug" value="{{($page).Slug}}"> + {{ end }} + <textarea name="title">{{($page).Title}}</textarea> + <span>last edited {{($page).Edited}}</span> <textarea name="content">{{($page).Content}}</textarea> -{{ else }} - <div contenteditable>{{($page).Content}}</div> -{{ end }} -<input type="submit" value="Save"/> + <input type="submit" value="Save"/> </form> {{ template "footer" . }}
M
templates/header.html
→
templates/header.html
@@ -8,4 +8,11 @@ <meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Nirvash — CMS</title> </head> <body> + <nav> + <ul> + <li><a href="/">Pages</a></li> + <li><a href="/static-mgr/">Static Files</a></li> + <li><a href="/build/">Build</a></li> + </ul> + </nav> {{end}}