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:
@@ -0,0 +1,31 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// CommentConfig holds the singleton (id=1) global comment policy.
|
||||
type CommentConfig struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
Enabled bool `gorm:"default:true" json:"enabled"` // master switch for the comment system
|
||||
AllowGuest bool `gorm:"default:true" json:"allow_guest"` // whether anonymous (non-logged-in) comments are allowed
|
||||
GuestRequireApproval bool `gorm:"default:false" json:"guest_require_approval"` // hold guest comments in the moderation queue
|
||||
UseGravatar bool `gorm:"default:true" json:"use_gravatar"` // when false, avatars render as a text-initial placeholder
|
||||
UpdatedBy uint `gorm:"index" json:"updated_by"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// TableName overrides the default GORM table name.
|
||||
func (CommentConfig) TableName() string {
|
||||
return "comment_configs"
|
||||
}
|
||||
|
||||
// defaultCommentConfig returns the in-memory fallback used before the DB row is
|
||||
// seeded, matching the seed defaults.
|
||||
func defaultCommentConfig() *CommentConfig {
|
||||
return &CommentConfig{
|
||||
ID: 1,
|
||||
Enabled: true,
|
||||
AllowGuest: true,
|
||||
GuestRequireApproval: false,
|
||||
UseGravatar: true,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user