feat: add article comment system with moderation
- Comment model with nested replies (ParentID), dual authorship (logged-in UserID / anonymous GuestToken cookie), email hash for Gravatar, private flag, and moderation status - CommentConfig singleton (enabled / allow guest / guest-require-approval / use Gravatar) cached like the other platform config - Markdown comments with built-in emoji picker, preview, and markdown help; rendered client-side via marked + DOMPurify, with server-side HTML/dangerous-scheme stripping as a first XSS defense - Private comments visible only to admin and the author; pending comments visible only to admin and the author - Admin moderation list (pending/approved/rejected/all tabs) with approve/reject/delete and a pending-count badge - Comment settings page with the four toggles - One-time session flash notice (auto-dismissed after 4s) so the "comment posted" banner no longer persists across refreshes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,7 @@ func main() {
|
||||
router.POST("/login", handlers.Login(db))
|
||||
router.POST("/logout", handlers.Logout())
|
||||
router.GET("/article/:slug", handlers.ArticleDetail(db))
|
||||
router.POST("/article/:slug/comments", handlers.PostComment(db))
|
||||
|
||||
// Protected admin routes.
|
||||
admin := router.Group("/admin")
|
||||
@@ -66,6 +67,11 @@ func main() {
|
||||
admin.GET("/articles/:id/edit", handlers.ArticleEditPage(db))
|
||||
admin.POST("/articles/:id/edit", handlers.ArticleUpdate(db))
|
||||
admin.POST("/articles/:id/delete", handlers.ArticleDelete(db))
|
||||
|
||||
admin.GET("/comments", handlers.CommentListPage(db))
|
||||
admin.POST("/comments/:id/approve", handlers.CommentApprove(db))
|
||||
admin.POST("/comments/:id/reject", handlers.CommentReject(db))
|
||||
admin.POST("/comments/:id/delete", handlers.CommentDelete(db))
|
||||
}
|
||||
|
||||
// Protected article attachment routes (AJAX uploads / management).
|
||||
@@ -87,6 +93,8 @@ func main() {
|
||||
settings.POST("/upload", handlers.UploadSettingsSave(db))
|
||||
settings.GET("/download", handlers.DownloadSettingsPage(db))
|
||||
settings.POST("/download", handlers.DownloadSettingsSave(db))
|
||||
settings.GET("/comments", handlers.CommentSettingsPage(db))
|
||||
settings.POST("/comments", handlers.CommentSettingsSave(db))
|
||||
}
|
||||
|
||||
// Protected profile routes.
|
||||
|
||||
Reference in New Issue
Block a user