feat(settings): 公司信息配置与 logo 管理(public 端点供登录页)

- system_settings 单行 CRUD:GET/PUT(AdminUser)+ GET /public(无鉴权,
  SettingPublicOut 白名单仅 company_name/logo_url 两字段,短缓存 300s)
- logo 上传:后缀+magic bytes+2MB 三重校验,固定名覆盖落盘 uploads/logo/
  (不使用上传方文件名,杜绝路径拼接);旧扩展名文件清理;文件流端点
  no-cache,URL 带 update_time 版本参数破缓存
- logo 存目录不存库:图片入 DB 让每次读取与 mysqldump 放大传输且无法
  独立替换;DB 只持一行相对路径
- 新增依赖 python-multipart(FastAPI UploadFile 必备传输层);.gitignore
  增 backend/uploads/ 与 db/backups/
- 集成 11 例:单行语义/白名单字段/三重校验/越权 403/匿名 401/审计留痕

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
liuwenxinandClaude Code committed 2026-10-15 18:22:12 +08:00
1 parent e95dc4b2de
commit efed29647c
9 files changed
+433

No files matched your search

+9
View File
@@ -92,6 +92,15 @@ class Settings(BaseSettings):
auth = f":{self.redis_password}@" if self.redis_password else ""
return f"redis://{auth}{self.redis_host}:{self.redis_port}/{self.redis_db}"
@property
def upload_dir(self) -> Path:
"""上传文件根目录(公司 logo 等):backend/uploads/。
不叫 static/ 是刻意的:静态目录将来可能整体交给前端构建产物,
运行期上传物必须与之隔离;该目录不入版本库(.gitignore)。
"""
return BACKEND_DIR / "uploads"
@lru_cache
def get_settings() -> Settings: