04737300e6
feat(comments): add complete comment system with guest commenting, moderation, and admin UI
...
Implements a fully self-built comment system for the blog:
Data layer:
- comments table with BIGSERIAL PK, parent_id self-reference (ON DELETE SET NULL),
depth tracking (max 20), status workflow (pending/approved/spam/trash),
content hashing for dedup, GDPR consent tracking, IP/UA storage with auto-purge
- 5 partial indexes optimized for read patterns
- updated_at auto-trigger
API (9 Dioxus server functions):
- Public: get_comments, get_comment_count, create_comment
- Admin: get_pending_comments, get_pending_count, get_all_comments,
approve_comment (with ancestor auto-approval), spam_comment, trash_comment,
batch_update_comment_status
Security:
- Function-level rate limiting (1/sec, burst 5) via FullstackContext IP extraction
- Input validation (name, email, URL scheme, content length, consent)
- Parent chain validation (must be approved, same post)
- Strict comment Markdown renderer (headings→strong, no img/id/data URIs, nofollow links)
- Honeypot anti-spam field
- 5-minute dedup window via SHA-256 content hash
Frontend:
- CommentSection with SuspenseBoundary isolation
- Flat-list rendering with depth-based CSS indentation (responsive)
- Gravatar via cravatar.cn (server-computed, email never exposed)
- Inline reply forms (one-at-a-time via Signal)
- Admin action buttons (approve/spam/delete) visible per-comment
- CommentForm with privacy consent, Markdown hint, loading states
Admin:
- /admin/comments page with status tabs, batch operations, pagination
- Pending count badge on admin dashboard
Infrastructure:
- Shared get_current_admin_user moved from posts/helpers to auth module
- COMMENT_LIMITER rate limiter tier
- Moka caches (60s TTL for comments, 10s for pending count)
- IP/UA purge background task (daily, 90-day retention)
2026-06-11 12:34:26 +08:00
ccd564312b
feat: hash session tokens and enforce configurable session limit per user
2026-06-11 09:45:56 +08:00
bf401e4916
fix(api): correct AppError variant semantics for transaction/query errors
...
- client.transaction() failures: db_conn -> tx (logs correct category)
- auth session INSERT: db_conn -> query
- delete_post UPDATE: tx -> query (no transaction context)
2026-06-10 13:19:57 +08:00
a3fa602df2
refactor(api): unify error handling with AppError enum
...
Replace scattered ServerFnError::new("...") inline calls and utils.rs
helper functions with a single AppError enum that provides:
- Automatic tracing::error logging for system errors
- Safe generic messages to frontend (no SQL/connection detail leaks)
- Typed error variants (Unauthorized, Forbidden, NotFound, etc.)
- 5 unit tests for message passthrough and detail hiding
Removes src/api/utils.rs entirely; all error creation now goes through
src/api/error.rs.
2026-06-10 13:16:06 +08:00
4f368e6fb8
test: add 122 unit tests across 12 modules
...
Cover utils/text, api/slug, auth/password, auth/session,
models/post, models/user, api/auth validation, api/markdown,
api/image, highlight, api/rate_limit. Add make test target.
2026-06-09 09:25:44 +08:00
e74b9f3c39
feat: apply rate limiting to Register, Login, and upload endpoints
...
- Remove unused tags.rs and related re-exports
- Convert strict_limit/upload_limit from Layer to manual check functions
- Add IP-based rate limiting checks to Register, Login, and upload_image
- Keep general_limit as global middleware for all other routes
2026-06-08 17:30:26 +08:00
e5d37aa034
refactor(api): extract error helper functions, DRY up db/query/tx error handling
2026-06-08 16:17:03 +08:00
675349a5b4
fix: add #[cfg(feature = server)] to server-only imports for WASM compatibility
2026-06-04 16:40:42 +08:00
28707d3c3a
refactor: reuse session validation in get_current_admin_user via get_user_by_token
2026-06-04 16:02:47 +08:00
d3be04bcec
refactor: extract session parsing to auth/session.rs and db error helpers to api/utils.rs
2026-06-04 15:16:40 +08:00
593666135c
feat: add DB connection retry logic with get_conn() helper
2026-06-04 10:03:56 +08:00
f5413e00cc
fix(auth): prevent password_hash from reaching the frontend
...
Introduce PublicUser struct without password_hash field. The
get_current_user server function now returns PublicUser via
CurrentUserResponse, so Argon2 hashes are never serialized to WASM.
Internal server-side functions (get_current_admin_user) continue
using the full User struct.
2026-06-03 10:32:15 +08:00
9c5b09a278
chore: code cleanup - formatting, EOF newlines, model helper, and UI tweaks
2026-06-02 17:33:28 +08:00
32e8407ed7
fix: use Debug format {:?} for database errors
...
tokio-postgres Display only shows 'db error', use {:?} for full error chain
2026-06-02 17:33:28 +08:00
5695b1c62b
feat: add explicit error logging and startup validation
...
- Add DATABASE_URL validation on server startup (exit early with clear error)
- Add tracing::error! to all server functions in api/auth.rs
- Bulk add tracing::error! to all database error handlers in api/posts.rs
- Server 500 errors now log detailed context to terminal
2026-06-02 17:33:28 +08:00
0be0719fdb
将 session cookie 改为后端 HttpOnly 设置
...
- login 通过 Set-Cookie 响应头设置 HttpOnly cookie
- get_current_user 从请求 Cookie header 读取 token,匹配具体 session
- logout 通过 Set-Cookie 清除 cookie,并删除对应 session
- 移除前端 document.cookie 操作代码
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 23:54:58 +08:00
91d9c04a3d
支持使用邮箱登录
...
- 登录查询同时匹配 username 或 email
- 更新登录页标签和 placeholder
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 16:16:40 +08:00
c4dfd1f445
Fix additional clippy warnings and update progress
...
- Add #[allow(dead_code)] to temporarily unused functions
- Remove unused is_expired() and UserRole::as_str()
- Fix unused variable warnings (token, theme)
- Update progress.txt: mark all stories complete
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 17:02:14 +08:00
14b92c3a89
US-005: 后台页面与路由整合
...
- src/router.rs: Dioxus 路由定义 (/login, /register, /admin, /)
- src/main.rs: 整合所有模块 + server block 启动 dotenvy + session 清理任务
- src/tasks/session_cleanup.rs: 每小时清理过期 session
- 修复编译错误: chrono serde, tokio-postgres chrono, argon2 OsRng
- 移除 server_context 依赖,简化 get_current_user 查询
- Tailwind CSS CDN + darkMode class 配置
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:29:50 +08:00
b2a1e13c79
US-003: 认证 API (Server Functions)
...
- src/api/auth.rs: register, login, logout, get_current_user
- register(): 输入验证 + 首个用户 admin + 后续关闭注册
- login(): argon2 验证 + session 创建 + token 返回
- logout(): session 清理
- get_current_user(): 从 cookie 读取 token,返回 Option<User>
- 使用 server_context().request_parts() 读取请求 cookie
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:21:11 +08:00