Commit Graph

17 Commits

Author SHA1 Message Date
f0bf450725 feat: 管理首页帖子总数统计(总数/已发布/待审核)
- PostRepo 新增 CountPostsByStatus 和 CountPending 方法
- Service 层定义 postAdminStatStore 接口 (ISP)
- AdminService 注入 postRepo,新增 PostStats 结构体和 GetPostStats 方法
- AdminController.Dashboard 调用 GetPostStats 并传参到模板
- Dashboard 帖子卡片显示总数 + 已发布 + 待审核(橙色徽章)
- DI 层将 AdminController 创建从 buildDepsCore 移至 buildDeps,以便注入 postRepo
2026-05-31 12:46:06 +08:00
12de8be0cf feat: 管理首页新增会话存储后端状态展示
- 仪表盘新增「会话存储后端」卡片,显示 Redis/内存 模式
- 降级时显示「已降级」标签 + 降级说明
- 内存模式下显示活跃会话数
- 新增 stat-red / stat-desc / stat-badge / badge-warn CSS 样式
2026-05-31 11:38:31 +08:00
55c408d86c fix: 审计问题全量修复 + RateLimiter 原子化重构 + CDN 本地化收紧
- 安全:移除 CSP 中 esm.sh/cdnjs.cloudflare.com,highlight.js 主题已本地化 73 个文件
- 安全:StatusBanned 分支补 dummy hash 防时序攻击
- 安全:手写 constantTimeEq 替换为 crypto/subtle.ConstantTimeCompare
- Bug:锁定操作消息已删除→已锁定
- YAGNI:删除 12 个空预留模板目录
- KISS:删除 common.CheckPassword 薄封装,统一用 bcrypt 调用
- KISS:删除 tokenCtrl 别名字段,api.go 统一用 authCtrl
- RateLimiter:check()+recordFail 闭包模式重构为 try() 原子操作,消除竞态
- RateLimiter:新增 ClearIP() 方法,注册成功时清除 IP 计数
- 文档:修正 audit_service.go 注释编号跳跃(3→5→4)
- 文档:修正 deps_core.go 过清理→过期清理
2026-05-31 11:13:32 +08:00
8bb87cd685 fix: 去掉独立修订表格,消除帖子重复显示
- 移除管理后台独立的"修订待审核"表格区域
- 修订标识和按钮已在主列表中内联展示,无需额外表格
- PostsPage 不再额外查询 Revisions 列表
2026-05-30 20:31:19 +08:00
eabc1e7d3d feat: 已发布帖子编辑后进修订审核,通过前保持展示旧内容
- Post 模型新增 PendingTitle/PendingBody 字段,分离已发布内容与待审修订
- Update: approved 帖子编辑写入 Pending 字段,不覆盖正文,不改变发布状态
- Approve: 有 PendingBody 时复制到正式字段后清空,无 PendingBody 走首次审核
- Reject: 有 PendingBody 时仅清空待审修订(保持已发布),无 PendingBody 走普通退回
- 新增 ListPendingRevisions 查询,管理后台独立展示"修订待审核"区域
- 详情页展示"修订审核中"标识,编辑页加载待审内容
- 通过修订后直接覆盖,不保留历史版本
2026-05-30 20:24:43 +08:00
89fa50a013 fix: 锁定机制不再改变帖子状态,锁定与退回独立
- Post 模型新增 IsLocked 字段,与 Status 解耦
- Lock 仅设 IsLocked=true(不改 Status),已通过帖子锁定后仍公开可见
- Unlock 仅设 IsLocked=false(不改 Status)
- Update/EditPage 编辑检查改用 IsLocked 而非 Status==locked
- Reject 与 Lock 独立,可单独退回或锁定+退回组合使用
- 新增 ErrPostCannotLock 错误哨兵
- 前端模板编辑按钮/锁定标识基于 IsLocked 渲染
2026-05-30 20:08:41 +08:00
bacfd4945d feat: 编辑器与帖子展示布局优化 + 新增个人空间
- 编辑器投稿页布局优化:标题与编辑器高度动态适配,工具栏与内容区视觉对齐
- 稿件展示页布局优化:MD 渲染区与评论区视觉分离,代码块主题微调
- CSRF 中间件:图像上传端点豁免,解决 Vditor 拖拽/粘贴上传 403
- Post 状态映射、GetGinUser、SaveUploadedFile 提取至 common 包,遵循审计建议
- 新增个人空间功能:/space(需登录)重定向到 /space/:uid,/space/:uid 公开访问
- 空间页模板:参考 B 站布局,展示头像、用户名、个性签名、UID、加入时间及稿件列表
- 导航栏:用户名链接指向 /space,新增「设置」入口
- 分层实现:SpaceController → SpaceService → PostRepo.FindByUserID,严格 ISP 接口隔离
2026-05-30 19:06:10 +08:00
91f2cbebc1 fix: 修复帖子提交审核权限缺失 + 防重复提交 + 分页逻辑复用
- 修复 Submit API 缺少 uid 权限检查,任意登录用户可提交他人帖子审核
- 前端 handleSubmit 添加 submitting 锁和按钮禁用/恢复,防止重复提交
- 分页计算 TotalPages/PrevPage/NextPage 提取为 Pagination 方法,消除三处重复代码
2026-05-28 14:47:14 +08:00
e45d66fb77 fix: 修复帖子相关逻辑的严重安全与错误处理问题
- 修复 Service 层所有 FindByID 错误均返回 ErrUserNotFound 的严重 bug,新增 findPost/findPostWithAuthor 正确区分 gorm.ErrRecordNotFound 和数据库错误
- 新增帖子相关错误哨兵:ErrPostNotFound/ErrPostCannotEdit/ErrPostCannotSubmit/ErrPostCannotApprove/ErrPostCannotReject/ErrPostCannotUnlock
- 修复 ShowAPI 缺少权限控制,非 approved 帖子可被任意用户通过 API 获取
- 修复 EditPage 缺少权限检查,非作者可访问编辑页面
- 修复 Update/Delete API 中 uid 断言未做 ok 检查
- Controller 层区分业务错误和内部错误,避免透传 Service 层错误信息给客户端
- 将 postStore 接口从 post_service.go 移至 repository.go,与其他仓储接口保持一致
- 移除 new.html 中孤立的 </template> 标签
2026-05-28 14:44:22 +08:00
8a8d801187 fix: 修复帖子系统5项缺陷 + 代码块插入位置/language-class/分割线占位
- 作者显示 用户名(UID): 修正Post.AuthorName GORM标签从 -:all 改为 -:migration;<-:false;column:author_name
- 审核流程: 帖子详情页新增"提交审核"按钮(draft/rejected时作者可见)
- 图片上传: 新增 POST /api/posts/upload-image 端点,限制5MB/jpg/png/gif/webp
- 代码块语言标注: 工具栏插入代码块时弹出语言输入框,生成 language-xxx class
- 状态中文显示: 管理后台/帖子详情页状态改为 PostStatusDisplayNames 映射
- 修复代码块插入位置错误: init时调用switchMode同步DOM; 无选区时appendChild; 防<pre>嵌套
- 修复 bluemonday.UGCPolicy() 剥离 code/pre 的 class 属性,显式 AllowAttrs("class")
- 修复分割线工具栏插入多余text占位符: hr/link/image以外不强制填占位文本
2026-05-27 19:22:47 +08:00
03a01a09be feat: 实现内容系统 MVC(Post CRUD + 审核流转)
按 content-system.md 设计文档,实现帖子内容系统的最小可行 MVC。

新增:
- Model: Post 模型,含 5 种状态(draft/pending/approved/rejected/locked)
- Repository: post_repo.go,分页查询(前台 approved 列表 + 后台全状态筛选)
- Service: post_service.go,核心业务逻辑(状态流转、Markdown 渲染 Goldmark)
- Controller: post_controller + admin_post_controller,SSR 页面 6 个 + API 13 个
- Template: 列表/详情/编辑器/404 + 管理员列表,各配 CSS/JS
- 路由: /posts, /posts/:id, /posts/new, /posts/:id/edit, REST API, Admin API
- gomod: + github.com/yuin/goldmark v1.8.2

修改:
- Main: AutoMigrate Post 表
- Router: deps 注册 PostService/Controller,路由注册
- Nav: 新增“帖子”导航链接
- Admin Sidebar: 新增“内容管理”入口

设计:
- 审核开关复用 audit.enabled,开启时帖子为 draft,关闭后直接 approved
- 仅 approved 公开可见,作者/admin 可预览非公开状态帖子
- 严格分层 ISP 接口: Controller → postUseCase, Service → postStore, Repo → *PostRepo
- 状态保护: pending/locked 禁止编辑,rejected 编辑后自动重置为 draft
2026-05-27 18:22:48 +08:00
7bc2dbd970 refactor: 拆分 middleware/router 为单一职责文件,新增站点设置管理页面
middleware:
- 拆分 auth.go → auth.go + auth_token.go + auth_parser.go + auth_admin.go
- 拆分 csrf.go → csrf.go + csrf_token.go
- 拆分 ratelimit.go → ratelimit.go + ratelimit_core.go + ratelimit_cleanup.go
- 修复 import 未使用/缺失问题

router:
- 拆分 router.go → admin.go + api.go + frontend.go + deps_core.go + deps_extra.go

feat(admin): 站点设置管理页面
- 新增 SSR 页面 /admin/site-settings(仅 Owner)
- 审核开关 Toggle 即时保存
- 通用设置展示
- 侧边栏新增站点设置入口
- 注册 UpdateBoolSetting/GetBoolSetting API 路由
2026-05-27 15:03:04 +08:00
f26da8f06e refactor: 清理死代码 + 修复ISP接口注释
- 移除未使用的DTO类型(ChangePasswordRequest/DeleteAccountRequest)
- 移除service层未引用的错误重导出(auth_service/audit_service)
- 删除未使用的SiteSettingRepo(数据访问由config.SiteSettings直接处理)
- 删除未使用的FindByStatus方法(user_repo)
- 删除未使用的AutoMigrate方法(audit_repo/notification_repo)
- 删除未使用的PaginatedResult/NewPaginatedResult(pagination.go)
- 修复接口注释:notifProvider(5→4)、auditUseCase(4→3)、siteSettingUseCase(3→4)
- 移除auditStatusProvider未使用的FindByUsername方法
- 统一使用common.ErrXxx直接引用,消除跨service错误重导出耦合
2026-05-27 13:52:42 +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
3937945b43 feat(admin): 管理首页标题修正、角色中文显示及用户总数补全
- 修正 admin layout title 后缀为「MetaLab 管理面板」
- 当前角色从原始字符串改为中文显示(注入 RoleDisplayName)
- 补全管理首页「用户总数」统计,新增 CountUsers 方法
- 遵循 ISP 最小接口,Service 复用已有 CountSearchUsers
2026-05-26 23:21:32 +08:00
39d13993ba fix: 设计原则审查修复 — DIP/ISP, LoD, DRY, OCP, URL, 301缓存
- P0 DIP+ISP: 全链路注入接口,消除零接口紧耦合
- P0 URL: auth 301→302,修复登出后浏览器缓存陷阱
- P1 DRY: JWT 认证逻辑收敛至 TokenService+中间件
- P2 DRY: 前后端角色/状态映射统一为 model 常量
- P2 LoD: 新增 SettingsController,router 不再跨层调 repo
- P2 URL: settings ?tab= → /settings/:tab 伪静态
- P3 OCP: 角色权限 map 化,告别硬编码 switch
2026-05-26 21:12:19 +08:00
483fdd919f 初始化项目:基础设施 + 用户认证 + 后台管理系统 + AGPL 3.0 许可 2026-05-26 13:46:33 +08:00