summaryrefslogtreecommitdiffstats
path: root/internal
diff options
context:
space:
mode:
authorivar <i@oiee.no>2026-04-03 14:22:23 +0200
committerivar <i@oiee.no>2026-04-03 14:22:23 +0200
commit33310be68544d3381ac6e9899790f4a106e17e8f (patch)
tree385102a7216ffba17d054f11032dae4447371d52 /internal
parenta8914a8f18c345e934bce93b37845a9dfe0ad73e (diff)
downloadnebbet.no-33310be68544d3381ac6e9899790f4a106e17e8f.tar.xz
nebbet.no-33310be68544d3381ac6e9899790f4a106e17e8f.zip
refactor: convert admin handlers to Gin context-based signatures
- Remove old ServeHTTP method (no longer needed with Gin routing) - Update all 6 handler methods to use *gin.Context instead of http.ResponseWriter, *http.Request - Convert handler signatures: handleList, handleNew, handleNewPost, handleEdit, handleDelete - Remove render() helper (use c.HTML() directly) - Update renderError() to accept gin.Context instead of http.ResponseWriter - Update postFromForm() to extract form data from gin.Context using c.PostForm() - Update main.go to use adminSrv.NewServer() and adminSrv.Engine() - All handlers now use Gin methods: c.HTML(), c.PostForm(), c.Param(), c.Redirect() - Path parameters now extracted via c.Param("slug") instead of function arguments - HTTP status codes and error handling fully migrated to Gin patterns Build verified: go build ./cmd/nebbet succeeds Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/admin/auth/auth.go (renamed from internal/auth/auth.go)0
-rw-r--r--internal/admin/server.go137
-rw-r--r--internal/db/meta.go2
-rw-r--r--internal/db/search.go2
4 files changed, 75 insertions, 66 deletions
diff --git a/internal/auth/auth.go b/internal/admin/auth/auth.go
index b0de7d9..b0de7d9 100644
--- a/internal/auth/auth.go
+++ b/internal/admin/auth/auth.go
diff --git a/internal/admin/server.go b/internal/admin/server.go
index 410560f..33413ee 100644
--- a/internal/admin/server.go
+++ b/internal/admin/server.go
@@ -122,37 +122,37 @@ func (s *Server) authMiddleware() gin.HandlerFunc {
// ── Handlers ─────────────────────────────────────────────────────────────────
-func (s *Server) handleList(w http.ResponseWriter, r *http.Request) {
+func (s *Server) handleList(c *gin.Context) {
posts, err := s.listPosts()
if err != nil {
- http.Error(w, "Failed to list posts: "+err.Error(), http.StatusInternalServerError)
+ c.HTML(http.StatusInternalServerError, "base", gin.H{
+ "Title": "Error",
+ "ContentTemplate": "error-content",
+ "Message": "Failed to list posts: " + err.Error(),
+ })
return
}
- s.render(w, "base", map[string]any{
- "Title": "Posts",
- "ContentTemplate": "list-content",
- "Posts": posts,
+ c.HTML(http.StatusOK, "base", gin.H{
+ "Title": "Posts",
+ "ContentTemplate": "list-content",
+ "Posts": posts,
})
}
-func (s *Server) handleNew(w http.ResponseWriter, r *http.Request) {
- if r.Method == http.MethodPost {
- s.handleNewPost(w, r)
- return
- }
- s.render(w, "base", map[string]any{
- "Title": "New Post",
- "ContentTemplate": "form-content",
- "Action": "/admin/new",
- "Post": Post{Date: time.Now().Format("2006-01-02")},
- "IsNew": true,
+func (s *Server) handleNew(c *gin.Context) {
+ c.HTML(http.StatusOK, "base", gin.H{
+ "Title": "New Post",
+ "ContentTemplate": "form-content",
+ "Action": "/admin/new",
+ "Post": Post{Date: time.Now().Format("2006-01-02")},
+ "IsNew": true,
})
}
-func (s *Server) handleNewPost(w http.ResponseWriter, r *http.Request) {
- p := postFromForm(r)
+func (s *Server) handleNewPost(c *gin.Context) {
+ p := postFromForm(c)
if p.Title == "" {
- s.renderError(w, "Title is required")
+ s.renderError(c, "Title is required")
return
}
if p.Slug == "" {
@@ -161,67 +161,86 @@ func (s *Server) handleNewPost(w http.ResponseWriter, r *http.Request) {
mdPath := filepath.Join(s.PostsDir, p.Slug+".md")
if err := os.MkdirAll(s.PostsDir, 0755); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ c.HTML(http.StatusInternalServerError, "base", gin.H{
+ "Title": "Error",
+ "ContentTemplate": "error-content",
+ "Message": err.Error(),
+ })
return
}
if _, err := os.Stat(mdPath); err == nil {
- s.renderError(w, fmt.Sprintf("Post %q already exists", p.Slug))
+ s.renderError(c, fmt.Sprintf("Post %q already exists", p.Slug))
return
}
if err := writePostFile(mdPath, p); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ c.HTML(http.StatusInternalServerError, "base", gin.H{
+ "Title": "Error",
+ "ContentTemplate": "error-content",
+ "Message": err.Error(),
+ })
return
}
s.rebuild(mdPath)
- http.Redirect(w, r, "/admin/", http.StatusSeeOther)
+ c.Redirect(http.StatusSeeOther, "/admin/")
}
-func (s *Server) handleEdit(w http.ResponseWriter, r *http.Request, slug string) {
+func (s *Server) handleEdit(c *gin.Context) {
+ slug := c.Param("slug")
mdPath := filepath.Join(s.PostsDir, slug+".md")
p, err := readPostFile(mdPath, slug)
if err != nil {
- http.NotFound(w, r)
+ c.HTML(http.StatusNotFound, "base", gin.H{
+ "Title": "Not Found",
+ "ContentTemplate": "error-content",
+ "Message": "Post not found",
+ })
return
}
- if r.Method == http.MethodPost {
- updated := postFromForm(r)
+
+ if c.Request.Method == http.MethodPost {
+ updated := postFromForm(c)
updated.Slug = slug // slug is immutable after creation
if updated.Title == "" {
- s.renderError(w, "Title is required")
+ s.renderError(c, "Title is required")
return
}
if err := writePostFile(mdPath, updated); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ c.HTML(http.StatusInternalServerError, "base", gin.H{
+ "Title": "Error",
+ "ContentTemplate": "error-content",
+ "Message": err.Error(),
+ })
return
}
s.rebuild(mdPath)
- http.Redirect(w, r, "/admin/", http.StatusSeeOther)
+ c.Redirect(http.StatusSeeOther, "/admin/")
return
}
- s.render(w, "base", map[string]any{
- "Title": "Edit Post",
- "ContentTemplate": "form-content",
- "Action": "/admin/" + slug + "/edit",
- "Post": p,
- "IsNew": false,
+ c.HTML(http.StatusOK, "base", gin.H{
+ "Title": "Edit Post",
+ "ContentTemplate": "form-content",
+ "Action": "/admin/" + slug,
+ "Post": p,
+ "IsNew": false,
})
}
-func (s *Server) handleDelete(w http.ResponseWriter, r *http.Request, slug string) {
- if r.Method != http.MethodPost {
- http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
- return
- }
+func (s *Server) handleDelete(c *gin.Context) {
+ slug := c.Param("slug")
mdPath := filepath.Join(s.PostsDir, slug+".md")
if err := os.Remove(mdPath); err != nil && !os.IsNotExist(err) {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ c.HTML(http.StatusInternalServerError, "base", gin.H{
+ "Title": "Error",
+ "ContentTemplate": "error-content",
+ "Message": err.Error(),
+ })
return
}
if s.Builder != nil {
_ = s.Builder.RemovePage(mdPath)
}
- http.Redirect(w, r, "/admin/", http.StatusSeeOther)
+ c.Redirect(http.StatusSeeOther, "/admin/")
}
func (s *Server) rebuild(mdPath string) {
@@ -254,31 +273,21 @@ func (s *Server) listPosts() ([]Post, error) {
return posts, nil
}
-func (s *Server) render(w http.ResponseWriter, name string, data map[string]any) {
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- if err := s.tmpl.ExecuteTemplate(w, name, data); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
-}
-
-func (s *Server) renderError(w http.ResponseWriter, msg string) {
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- w.WriteHeader(http.StatusBadRequest)
- _ = s.tmpl.ExecuteTemplate(w, "base", map[string]any{
- "Title": "Error",
- "ContentTemplate": "error-content",
- "Message": msg,
+func (s *Server) renderError(c *gin.Context, msg string) {
+ c.HTML(http.StatusBadRequest, "base", gin.H{
+ "Title": "Error",
+ "ContentTemplate": "error-content",
+ "Message": msg,
})
}
// postFromForm reads a post from an HTTP form submission.
-func postFromForm(r *http.Request) Post {
- _ = r.ParseForm()
+func postFromForm(c *gin.Context) Post {
return Post{
- Title: strings.TrimSpace(r.FormValue("title")),
- Date: strings.TrimSpace(r.FormValue("date")),
- Tags: strings.TrimSpace(r.FormValue("tags")),
- Content: r.FormValue("content"),
+ Title: strings.TrimSpace(c.PostForm("title")),
+ Date: strings.TrimSpace(c.PostForm("date")),
+ Tags: strings.TrimSpace(c.PostForm("tags")),
+ Content: c.PostForm("content"),
}
}
diff --git a/internal/db/meta.go b/internal/db/meta.go
index 33e0da3..dd05764 100644
--- a/internal/db/meta.go
+++ b/internal/db/meta.go
@@ -23,7 +23,7 @@ type PageMeta struct {
}
func OpenMeta(path string) (*MetaDB, error) {
- db, err := sql.Open("sqlite3", path)
+ db, err := sql.Open("sqlite", path)
if err != nil {
return nil, err
}
diff --git a/internal/db/search.go b/internal/db/search.go
index 545645e..b9990a5 100644
--- a/internal/db/search.go
+++ b/internal/db/search.go
@@ -23,7 +23,7 @@ type SearchResult struct {
}
func OpenSearch(path string) (*SearchDB, error) {
- db, err := sql.Open("sqlite3", path)
+ db, err := sql.Open("sqlite", path)
if err != nil {
return nil, err
}