0c811efd4d
feat(assets): 素材注册表数据层
...
- migration 015:assets 元数据注册表 + asset_refs 引用关联表
- upload_image 落盘后登记 assets(失败补偿删文件);尺寸校验复用
upload_dimensions 一次解析同时返回 (w,h)
- sync_asset_refs 镜像 sync_tags:文章 create/update 事务内
解析 content_html + cover_image 的 /uploads/ 路径重建引用
- Asset/AssetDto/AssetFilter/AssetSort 共享模型,id 以 String 承载
(SQL 侧 ::uuid cast,避免 uuid crate 进 WASM 构建)
2026-07-24 16:07:07 +08:00
b34803e57d
fix(search): drop ineffective trgm GIN index; correct misleading comment
...
ILIKE '%...%' 双侧通配符无法命中 trgm GIN(仅前缀模式命中),索引建了等于
白建且误导(L1)。删除以避免误导,搜索暂靠 LIMIT + 限流兜底;tsvector 全文
检索作为后续独立升级。
2026-06-18 13:42:23 +08:00
179897ba6f
fix(migrations): make all migrations idempotent; distinguish applied vs error
...
- 006: ADD COLUMN 补 IF NOT EXISTS
- 002: 5 个索引(status_published/slug_unique/post_tags_post/post_tags_tag/cover)补 IF NOT EXISTS
- migrate.sh: 区分「已应用」与「真出错」,真错误时打印输出并中止,不再静默吞掉(M6)
已验证:第二次运行全部 OK(幂等),不再出现重复对象错误。
2026-06-18 13:34:07 +08:00
82ab190e0d
fix(comments): make duplicate-check atomic with transaction; index content_hash
...
查重 SELECT 与 INSERT 包进同一事务,串行化并发请求缩小重复窗口(M4);
重复时 rollback 空事务。content_hash 加索引(非唯一,避免误杀不同作者
发相同短内容的合法场景)加速 5 分钟窗口查重,原先全表扫。
2026-06-18 13:31:37 +08:00
53bfb1b7c0
feat(session): invalidate all sessions on role/status change via generation
...
users 表加 session_generation 列。get_user_by_token 缓存命中后回查 DB
generation,不匹配则逐出缓存并视为未登录,消除降级/封禁用户的权限残留
窗口(H2)。新增 invalidate_user_sessions 用于 bump generation,当前仓库
无运行时角色变更入口,作为未来用户管理功能的基础设施预留。
- 迁移 012:ADD COLUMN IF NOT EXISTS session_generation INT DEFAULT 0
- User/SessionUser 同步加字段,From<User> 如实传递
- 缓存校验走主键查询,亚毫秒级
2026-06-18 13:26:09 +08:00
c6161764a9
perf(db): add indexes for trash and admin post list queries
...
- idx_posts_deleted_at: 回收站查询 WHERE deleted_at IS NOT NULL ORDER BY deleted_at DESC
- idx_posts_created_at_admin: 管理后台全量列表 WHERE deleted_at IS NULL ORDER BY created_at DESC
2026-06-18 11:02:13 +08:00
468a819951
fix(db): backfill word_count and reading_time for existing posts
2026-06-17 16:24:44 +08:00
a6f08d5d3f
feat(db): add word_count and reading_time columns to posts
2026-06-17 16:06:21 +08:00
48888a9886
feat(migrations): add cleanup migration for duplicate indexes
2026-06-17 13:11:53 +08:00
08895f504e
refactor(migrations): remove duplicate idx_tags_name and idx_post_tags_tag_id
2026-06-17 13:11:53 +08:00
73aa680202
refactor(migrations): remove redundant idx_posts_slug index
2026-06-17 13:11:53 +08:00
449a545886
security: fix critical issues from repository review
...
CI / build (push) Has been cancelled
CI / check (push) Has been cancelled
P0 blockers:
- Fix migration numbering conflict and duplicate indexes
- Change comments.post_id FK to ON DELETE CASCADE
- Restrict public post detail endpoint to published posts only
- Fix rate-limiting IP extraction and fallback to ConnectInfo
- Harden HTML sanitizer: deny unknown URL schemes, restrict data URIs
- Remove session token from login response body
- Enforce image pixel/dimension limits on upload and serving
P1 high-risk:
- Validate uploads by magic bytes and decode GIF/WebP
- Add pagination/rate-limiting to search, tag posts, and comments
- Make first-admin registration and slug uniqueness check atomic
- HTML-escape comment author fields
- Improve HTML minify cache key and skip admin/error responses
- Add mobile navigation menu
P2 accessibility/quality:
- Associate form labels with inputs
- Key PostDetail article by slug to re-init scripts on navigation
- Improve image viewer keyboard accessibility
- Make theme toggle SSR-friendly and add aria-label
- Invalidate slug 404 cache on create and pending count on new comment
- Deduplicate tags case-insensitively
P3 cleanup:
- Remove unused tower-http dependency, expand make clean
- Configure DB pool timeouts and verified recycling
- Run background cleanup tasks immediately on startup
- Use SHA-256 for stable disk cache keys
- Log DB errors with Display instead of Debug
- Update README migration instructions
All tests pass (321), clippy clean, dx check clean.
2026-06-17 10:34:14 +08:00
959cc1fb0e
feat(db): 新增 settings 键值表与回收站默认配置
2026-06-16 12:28:29 +08:00
7244c39a47
feat(db): add toc_html column to posts table
...
- Add migration 005_add_toc_html.sql to store pre-rendered TOC HTML
- Enables caching rendered TOC alongside content_html at write time
2026-06-12 10:35:33 +08:00
ec2f3e313e
refactor(comments): remove consented_at column from migration and model
2026-06-11 13:24:00 +08:00
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
81555d920e
refactor: sessions table stores token hash instead of plaintext
2026-06-11 09:42:32 +08:00
959d813630
feat: pg_trgm full-text search for posts ( #2 )
...
* feat(db): add pg_trgm search index on posts
* feat(api): use pg_trgm similarity search for posts
* fix(api): use ILIKE + word_similarity instead of % operator for search
2026-06-08 18:26:35 +08:00
4d7d7ec383
db: add performance indexes on posts, tags, sessions
2026-06-08 16:39:13 +08:00
ad6c69b0e8
db(migration): merge slug partial unique into 002_posts.sql
2026-06-05 16:29:20 +08:00
488dbc144d
Add migration: partial unique index on posts.slug
2026-06-05 16:19:45 +08:00
b173a5c509
refactor: merge cover_image migration into 002_posts
...
- Add cover_image column directly in CREATE TABLE posts
- Remove standalone 003_post_cover_image.sql migration
2026-06-03 15:41:22 +08:00
cf783d8f6e
feat(migration): add cover_image column to posts table
2026-06-02 18:12:45 +08:00
327738c2e0
refactor: replace post_status ENUM with TEXT + CHECK constraint
2026-06-02 17:33:28 +08:00
973d6f3d57
feat: add posts, tags database schema and API
...
- Add migration 002_posts.sql with posts, tags, post_tags tables
- Add Post/Tag/PostStats models with PostStatus enum
- Add posts API with full CRUD:
- create_post, update_post, delete_post (admin only)
- get_post_by_slug, list_published_posts (public)
- list_posts, get_post_stats (admin)
- list_tags, get_posts_by_tag, search_posts (public)
- Slug auto-generation with uniqueness check
- Server-side markdown rendering with pulldown-cmark
- Auto-summary extraction from markdown
- Soft delete support
2026-06-02 17:33:28 +08:00
6df0a7ee19
US-006: 验证 + 修复编译和运行时问题
...
- 修复 migration: role 从 ENUM 改为 VARCHAR(20) 以兼容 tokio-postgres
- 修复 Cargo.toml: 将 chrono/argon2/uuid/rand 改为非 optional,添加 wasm-bindgen/getrandom js
- 修复 main.rs: Tokio runtime panic,改用 std::thread + Runtime::new
- 修复 db/mod.rs wasm stub: DummyPool 替代 deadpool_postgres
- 修复 login/admin.rs: wasm_bindgen::JsCast 条件编译
- 验证通过: 注册✓ 登录✓ get_current_user✓ 重复注册拒绝✓ 错误密码✓
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:49:43 +08:00
031a7aa0f2
US-001: 数据库配置与建表
...
- 添加依赖: tokio-postgres, deadpool-postgres, argon2, uuid, chrono, regex, dotenvy
- 创建 .env 文件模板 (DATABASE_URL)
- 创建 migrations/001_init.sql: users 表 + sessions 表 + 部分唯一索引
- 创建 src/db/mod.rs 和 src/db/pool.rs: std::sync::LazyLock 全局初始化 deadpool
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:15:47 +08:00