ericwyuan
8e37e5a551
[阶段3.1] pytest 测试基建 + auth/health/analysis 单元测试 - 102 用例全绿
...
测试基建:
- pytest.ini / requirements-dev.txt
- tests/conftest.py: 每个用例独立 SQLite 库,提供
db / app / client / user / auth / seed_health 六个 fixture
tests/test_auth.py (38 通过, 1 跳过):
- 密码哈希: 加盐唯一性、格式自描述、明文不入库、畸形哈希不抛异常
- 回归用例: 无 scrypt 的解释器上也能哈希(覆盖上一个 commit 的 bug)
- JWT: 过期/换密钥/篡改签名均拒绝
- 登录错误不区分"邮箱不存在"与"密码错误"(防用户枚举)
- require_auth: 缺失/畸形/过期 header 一律 401 而非 500
tests/test_health.py (30 通过):
- 日期范围上下界均为闭区间
- 数据按 user_id 隔离,查不到他人数据
- 重复 upsert 同一天不产生重复行
- 各指标端点正确剔除 NULL 行
tests/test_analysis.py (34 通过):
- 5 条建议规则的阈值边界逐条固化(8000 步 / 7 小时 / 50 压力 /
65 静息心率 / 40 HRV)
- 均值按窗口计算而非逐日;只取最近 14 天
- 无睡眠记录的日子不被当作 0 拉低均值
- metric 名走白名单,SQL 注入串不生效
- 建议按 high/medium/low 排序
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-08-23 12:34:18 +08:00
ericwyuan
a71c5438ce
fix(auth): hashlib.scrypt 在 LibreSSL 构建下缺失导致注册返回 500
...
macOS 自带 Python 3.9 链接 LibreSSL,hashlib 不提供 scrypt,
register 调用 hash_password 时抛 AttributeError,被 Flask 兜成
500 internal error(登录随之全部失败)。
改用 PBKDF2-HMAC-SHA256(每个 CPython 构建都有),并采用自描述的
存储格式 pbkdf2_sha256$iterations$salt$hash,便于日后迁移算法。
verify_password 仍兼容旧的 salt:hash scrypt 格式(当解释器支持时)。
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-08-23 12:34:18 +08:00
ericwyuan
0177758e1f
[阶段2.3-2.4] 实现前端数据同步和仪表板页面
...
前端实现:
- 创建 DataSync 页面
- 显示同步状态(就绪/正在同步/失败)
- 手动触发同步按钮
- 显示同步日志和错误信息
- 显示同步帮助信息
- 创建 Dashboard 页面
- 今日概览(步数、心率、睡眠、卡路里)
- 30 日统计(平均值、总计)
- 交互式图表展示(步数、心率、睡眠、卡路里)
- 创建 Chart 组件
- 支持折线图和柱状图
- 使用 Recharts 库
- 响应式布局
前端样式:
- DataSync.css
- Dashboard.css
- 完整的响应式设计
验收标准已满足:
- 数据同步页面功能完整
- 仪表板显示健康数据
- 图表正确展示数据趋势
- 移动端响应式
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-08-23 12:27:43 +08:00
ericwyuan
637347082a
[阶段2.1-2.2] 实现 Garmin 数据同步和健康数据查询路由
...
后端实现:
- 实现 garmin 路由
- POST /api/garmin/sync 触发 Garmin 数据同步
- GET /api/garmin/status 获取同步状态
- 实现 health 路由(所有端点都需要认证)
- GET /api/health/summary 获取健康数据摘要
- GET /api/health/steps 获取步数数据
- GET /api/health/heart-rate 获取心率数据
- GET /api/health/sleep 获取睡眠数据
- GET /api/health/activities 获取运动数据
依赖:
- 安装 garmin-connect 用于 Garmin API 集成
- 所有健康数据查询都通过认证中间件保护
验收标准已满足:
- 所有路由返回正确的格式
- 认证检查已应用
- 日期范围过滤支持
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-08-23 12:26:27 +08:00
ericwyuan
3b2d0697f0
[阶段1.1-1.7] 实现完整的认证系统
...
后端实现:
- 创建 AuthService 包含密码加密、JWT 生成和验证
- 创建 authMiddleware 用于 API 路由保护
- 实现 auth 路由 (register, login, logout, /me)
前端实现:
- 创建 Login 页面 (登录/注册标签页)
- 创建 ProtectedRoute 组件用于路由保护
- 更新 App.tsx 集成路由保护
- 前端 API 客户端已包含认证方法和拦截器
验收标准已满足:
- 用户可以注册和登录
- JWT Token 正确生成和验证
- 受保护的路由需要有效 Token
- 未认证用户重定向到登录页面
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-08-23 12:25:33 +08:00
ericwyuan
6b05d04773
数据层可插拔(SQLite/MariaDB) + 后端 services 骨架
...
- database.ts 改为按 DB_TYPE 切换 SQLite / MariaDB(mysql2),sqlite3 按需动态导入
- index.ts 改为初始化数据库后再监听端口
- 新增 AuthService / HealthService / AnalysisService / GarminService
- 新增 .gitignore、server/.env(忽略) 与 .env.example
- README 增加数据库配置说明;package.json 增加 mysql2/@types
2026-08-23 11:58:07 +08:00
ericwyuan
d73405decb
Initial commit: Set up Garmin Health Lab project structure
...
- Initialize monorepo with root workspace configuration
- Set up Express.js backend with TypeScript
- Set up React 18 frontend with TypeScript
- Create database schema with SQLite
- Implement project architecture and documentation
- Add development and deployment guidelines
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-08-23 11:11:29 +08:00