26 Commits

Author SHA1 Message Date
xfy
0777fd469a fix(upload): unify image size limit across all formats
上传入口此前对超大图片行为不一致:JPEG/PNG 因 decode limits 失败后
静默存原图,WebP 报"损坏",GIF 完全不查。统一为 header 阶段硬拒绝。

- image.rs: 新增 check_upload_dimensions,按 MIME 只读 header 拿尺寸
  (WebP 走 zenwebp header,JPEG/PNG/GIF 走 image into_dimensions),
  超 MAX_IMAGE_DIMENSION/MAX_IMAGE_PIXELS 返回友好提示
- upload.rs: magic bytes 校验后插入统一尺寸校验,三种格式同路径
- upload.rs: JPEG/PNG 转码 fallback 的 Err(_) 改为 Err(e) 带原因日志
  (超限已在 header 阶段拦截,此处仅剩真损坏兜底)

读取侧 serve_image 不动;webp::decode 内的像素校验保留(读取侧仍需)。
2026-06-24 13:25:23 +08:00
xfy
45d14e2ad9 feat(image): add image dimensions cache with header-only reading 2026-06-22 17:55:16 +08:00
xfy
d1e08ec402 fix(image): write disk cache atomically via temp-file + rename
.dat/.ct 改为先写 .tmp 再 rename,避免并发请求读到内容与 content-type
错配的半成品文件(L5)。写失败或 rename 失败时清理临时文件与目标。
2026-06-18 13:40:48 +08:00
xfy
3723cd03f9 fix(image): add canonicalize prefix check to is_path_safe for defense in depth
子串检查之外,对已存在文件做 canonicalize 前缀校验,确认解析后路径仍在
uploads 目录内,抵御符号链接等绕过(L4)。文件或 uploads 目录不存在时
只靠第一层校验(交由后续读取报 404)。函数改为 async,调用点与测试同步更新。
2026-06-18 13:39:46 +08:00
xfy
7a6e9350fe fix(image): reject undecodable images with 422; cap raw file size at 20MB
- decode 失败(WebP 与其他格式)不再降级返回原始字节,防止构造的畸形文件以
  图片 content-type 返回任意内容(M3)
- 原始分支读前查 metadata,超 20MB 返回 413,避免超大文件撑爆内存
2026-06-18 13:38:03 +08:00
xfy
22e883c6d9 fix(image): add X-Content-Type-Options: nosniff to all image responses
304 与 200 两个分支都附加 nosniff,防止浏览器对 content-type 错配的图片字节
做 MIME sniff(M2)。配合原始文件分支按扩展名决定 content-type 的行为做纵深防御。
2026-06-18 13:36:39 +08:00
xfy
a71da7473d perf(image): remove redundant Vec clone before spawn_blocking 2026-06-18 10:10:44 +08:00
xfy
36554af5f5 perf(image): store cached image data as Bytes to avoid Vec cloning 2026-06-18 10:03:35 +08:00
xfy
abdfd2e3f9 fix: make If-None-Match comparison RFC 7232 compliant 2026-06-17 14:14:37 +08:00
xfy
27ce878771 feat: support If-None-Match 304 for image responses 2026-06-17 14:08:45 +08:00
xfy
21b665f41d feat: add Cache-Control and ETag headers for image responses 2026-06-17 13:59:17 +08:00
xfy
fe6e5bd045 perf: offload image decode/resize/encode to spawn_blocking 2026-06-17 13:52:05 +08:00
xfy
7bad3ce382 fix: make ConnectInfo optional in serve_image to prevent 500 2026-06-17 13:40:17 +08:00
xfy
449a545886 security: fix critical issues from repository review
Some checks failed
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
xfy
26b012c40c docs(api, auth): 补充中文注释 2026-06-12 18:27:24 +08:00
xfy
294d60afab style: format rust code
Some checks failed
CI / build (push) Has been cancelled
CI / check (push) Has been cancelled
2026-06-12 17:14:31 +08:00
xfy
db3379364f fix: limit WebP decode buffer size to prevent malicious allocations 2026-06-09 15:48:34 +08:00
xfy
7c6bab8019 fix: preserve f32 precision for WebP quality 2026-06-09 15:43:16 +08:00
xfy
2e2be7b16d feat: add WebP encoding support with zenwebp
- Replace image crate's WebP with zenwebp for better quality/speed
- Add webp.rs module with configurable quality and method
- Update .env.example with WEBP_QUALITY and WEBP_METHOD
- Add WebP decode support in image serving pipeline
- Add detailed timing logs for WebP conversion
2026-06-09 15:30:06 +08:00
xfy
5ecd8a9b86 feat: add disk-level cache for processed image variants 2026-06-09 13:45:49 +08:00
xfy
3974856f3d fix: resolve image/upload 500 errors and refactor rate limiting
- Separate /uploads and /api/upload routes from Dioxus app to avoid
  IncrementalRenderer intercepting non-page requests
- Remove broken SmartIpKeyExtractor-based general_limit() that failed
  under Dioxus dev server proxy (Unable To Extract Key)
- Move rate limiting into handlers using governor::RateLimiter directly
- Add IMAGE_LIMITER for /uploads/* serving
- Make all rate limits configurable via environment variables
- Add rate limit config to .env.example with sensible defaults
2026-06-09 09:48:51 +08:00
xfy
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
xfy
2c08c6c7fd fix(image): case-insensitive format matching in process_image 2026-06-08 15:29:17 +08:00
xfy
8b1b949bf8 refactor: apply formatting to image.rs 2026-06-08 15:13:18 +08:00
xfy
d584ef6e00 fix(image): improve cache keys, case-insensitive format, strict thumb validation 2026-06-08 15:13:18 +08:00
xfy
1f009f57c8 feat: add image processing handler with resize/thumbnail/rotate/format 2026-06-08 15:13:18 +08:00