Commit Graph

7 Commits

Author SHA1 Message Date
97adf54d6d fix: golangci-lint 零告警通过 (57→0) + gofumpt/goimports 全量格式化
## CI 修复 (P0/P1)

P0 — 编译阻塞:
  - interfaces.go: postUseCase ISP 接口移除不用的 Create/Update/Delete

P1 — 必须修复:
  - ST1000: 为 13 个包添加包注释 (common/config/model/service/...)
  - ST1005: redis_store.go 全部错误消息改为小写开头
  - errcheck (19处): defer Close()→闭包忽略, notifier.Create→_=, r.Run→检查error
  - errorlint (9处): switch-on-error→errors.Is 链, ==→errors.Is
  - ST1020/ST1022: 导出符号注释以符号名开头

P2 — 安全评审:
  - gosec (12处): G203/G301/G304/G306 添加 nolint 注释并附理由

P3 — 清理:
  - unused: 移除 hasUnicode/energyStore/current/energyAdminUseCase
  - gofumpt + goimports 全量格式化 (35+ 文件)
2026-06-22 02:27:35 +08:00
a2e8242c21 chore: 全局包名路径从 metalab 更改为 mce 2026-06-21 16:55:46 +08:00
ca21ae7216 fix: 修复头像审核旧图裂开问题 + CSP 配置修复
- 头像提交审核不再删除旧文件,审核通过后才删除旧头像文件
- 头像审核被拒时删除已上传的新头像文件,保留旧头像
- CSP style-src 移除 nonce 以启用 unsafe-inline(JS 动态样式需要)
- CSP script-src 移除 nonce 改用 unsafe-inline + unsafe-eval(Vditor 编辑器和动态样式需要)
2026-06-02 22:26:01 +08:00
4887093c3a feat: 头像上传选区限制 3840×3840 + 客户端裁剪压缩
- 后端:3840×2160 限制改为 3840×3840(方形限制适应方形裁剪),并移到裁剪结果上检查而非原图
- 前端:原图短边超过 3840 时自动抬高最小缩放,确保选区永不超过 3840×3840
- 前端:裁剪确认后用 Canvas 预裁剪 + JPEG 压缩再上传,大幅节省带宽
- 前端:裁剪框标题栏新增实时像素尺寸提示
- 新增 .crop-info 样式
2026-05-31 02:42:27 +08:00
0800ee2f3e feat: 消息通知中心 + 账号安全体系 + Bug修复
## 新增功能

### 消息通知中心 (全新模块)
- 新增 MessageController / NotificationService / NotificationRepo
- SSR 消息页面 (/messages):左侧边栏 + 右侧卡片列表,noindex 元标签
- 通知能力:列表分页、单条标为已读、一键全部标为已读
- 未读数角标 (1/66/99+):侧边栏 + 导航栏铃铛图标
- 导航栏轮询 /api/messages/unread 每 60 秒刷新未读数
- 审核通过/驳回时自动 fire-and-forget 推送通知

### 密码修改
- ChangePassword:验证当前密码 → 新密码强度校验(8位+字母+数字) → 哈希更新
- 修改后递增 token_version 强制所有设备退登

### 账号自助注销
- DeleteAccount:验证密码 → 设置 deleted 状态 → 记录原因 → 吊销 JWT
- 注销后登录二次确认:Login 检测 deleted → 返回 confirm_restore
- ConfirmRestore 恢复账号,重新签发 token
- 注销页文案:"账号将在 7 天后正式注销,期间可随时重新登录恢复"

### IP 审计记录
- 注册时记录 RegIP,登录时记录 LastLoginIP + LastLoginAt
- clientIP() 支持 X-Forwarded-For / X-Real-IP 反向代理

### 安全加固
- Login 防时序攻击:用户不存在时仍执行完整 bcrypt 比对
- FindByEmail 改用 Unscoped() 覆盖软删除用户
- 站长 (owner) 不允许自主注销,避免权限体系死锁

## Bug 修复

1. 注销按钮不触发:JS IIFE 中 profile 代码 return 阻塞了 account 标签页处理器注册
   → 拆分为两层 IIFE,profile 放在内层
2. label 缺少 for 属性导致控制台警告 → 全部补充 for 属性
3. 注销后未自动退登:DeleteAccount 只设状态未吊销 JWT → 末尾加 InvalidateSessions
4. 退登后重定向 500 panic:authenticateToken 中 err||versionMismatch 合并判断
   在 err=nil 但版本不匹配时返回 (nil,nil) → 拆为两个独立判断
   injectUserContext 增加 claims==nil / 类型断言空安全守卫
5. 注销后登录直接提示"登录成功":FindByEmail 默认 scope 排除软删除记录
   → 改用 Unscoped()

## 文件变更
- 新建 17 个文件 (消息/审核/站点设置完整模块)
- 修改 25 个文件 (认证/设置/中间件/前端)
- 统计:+3229 / -161,42 files changed
2026-05-27 13:32:45 +08:00
053ca32a14 fix(avatar): WebP 解码未生效 — image.Decode 不支持 WebP,改用 webp.Decode 2026-05-27 01:10:29 +08:00
c3dec09dae feat(settings): 个人资料编辑 + 头像上传/裁切 + 自定义裁切弹窗
**新增功能:**

用户名编辑:输入框替换静态文本,白名单验证(中文/英文/数字/下划线/连字符),前端计数器(n/16),utf8对齐PG VARCHAR,XSS防控。

个性签名编辑:Textarea,128字符上限,实时计数器。

头像上传管线:校验→解码→裁切→CatmullRom缩放→WebP二分编码≤100KB→原子写入(.tmp→os.Rename)。限制5MB,128-3840px,JPEG/PNG/WebP。输出512x512 WebP。文件名 {uid}_{timestamp}.webp。清理旧头像。

自定义裁切弹窗:浅色主题,固定裁切框+图片平移/缩放(1×-3×滚轮),box-shadow遮罩,三等分网格。坐标映射pan/zoom→原图像素→subImage。

CSP修复:img-src允许data:URI(FileReader预览)。

**文件变更:**
修改: README, docs/{development,structure}.md, go.{mod,sum}, cmd/server/main.go, controller/settings, middleware/security, router, templates/settings/{index.html,css}
新增: internal/service/avatar_service.go, docs/settings.md
2026-05-27 01:03:16 +08:00