Files
go_blog/main.go
T
kevinandClaude Fable 5 b474ee009a feat: add article management (list, edit, delete)
- Add admin article list page at /admin/articles with status badges,
  pin marker, publish time, and edit/delete actions
- Share the create/edit form: dynamic action URL, prefilled fields,
  is_top checkbox state, and create-vs-edit heading
- Add ArticleUpdate/ArticleDelete handlers (soft-delete via DeletedAt);
  stamp PublishedAt on first publish
- Add "Manage Articles" entry on the dashboard
- Hide home page sign-in/dashboard buttons
- Add EN/ZH i18n keys for the management UI

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-21 20:13:39 +08:00

84 lines
2.3 KiB
Go

package main
import (
"fmt"
"log"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"go_blog/config"
"go_blog/handlers"
"go_blog/middleware"
"go_blog/models"
)
func main() {
// 1. Load configuration (auto-creates if missing).
cfg := config.LoadConfig()
// 2. Initialize the database (auto-migrates, seeds admin).
db := models.InitDB(cfg)
// 3. Create session store (cookie-based).
store := cookie.NewStore([]byte(cfg.Secret))
store.Options(sessions.Options{
Path: "/",
MaxAge: 86400, // 24 hours
HttpOnly: true, // prevent XSS access
Secure: false, // set true in production with HTTPS
})
// 4. Create Gin router.
router := gin.Default()
// 5. Load HTML templates.
router.LoadHTMLGlob("templates/**/*.html")
// 6. Serve uploaded files (avatars etc.) from the storage path.
router.Static("/uploads", cfg.Path)
// 6. Global session middleware.
router.Use(sessions.Sessions("blog_session", store))
// 7. Global context middleware (sets IsLoggedIn, Username for templates).
router.Use(middleware.SetUserContext(db))
// 8. Register routes.
router.GET("/", handlers.HomePage(db))
router.GET("/login", handlers.LoginPage())
router.POST("/login", handlers.Login(db))
router.POST("/logout", handlers.Logout())
router.GET("/article/:slug", handlers.ArticleDetail(db))
// Protected admin routes.
admin := router.Group("/admin")
admin.Use(middleware.AuthRequired())
{
admin.GET("", handlers.AdminDashboard(db))
admin.GET("/articles", handlers.ArticleListPage(db))
admin.GET("/articles/new", handlers.ArticleCreatePage(db))
admin.POST("/articles/new", handlers.ArticleCreate(db))
admin.GET("/articles/:id/edit", handlers.ArticleEditPage(db))
admin.POST("/articles/:id/edit", handlers.ArticleUpdate(db))
admin.POST("/articles/:id/delete", handlers.ArticleDelete(db))
}
// Protected profile routes.
profile := router.Group("/profile")
profile.Use(middleware.AuthRequired())
{
profile.GET("", handlers.ProfilePage(db))
profile.POST("", handlers.UpdateProfile(db, cfg.Path))
profile.POST("/avatar", handlers.UploadAvatar(db, cfg.Path))
}
// 9. Start the server.
addr := fmt.Sprintf(":%s", cfg.Port)
log.Printf("Go Blog starting on http://localhost%s", addr)
if err := router.Run(addr); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}