|
|
5a8b0ca79c
|
feat: 实现 FallbackStore 会话存储降级保护
- 新增 session/fallback_store.go,包装 RedisStore + MemoryStore 双后端
- 后台 goroutine 周期性 ping Redis,自动降级/恢复
- Store 接口新增 Metrics() 方法,MemoryStore/RedisStore/FallbackStore 均已实现
- deps_core.go 改造为始终创建 MemoryStore 兜底,Redis 启用时包装为 FallbackStore
- Manager 新增 GetStoreMetrics() 暴露存储状态
|
2026-05-31 11:38:20 +08:00 |
|
|
|
d6d03a7c3c
|
feat: 实现 Redis 会话存储,支持内存/Redis 双模式自动切换
- 新增 go-redis/v9 依赖
- 新增 config.yaml redis 配置段 + RedisConfig 结构体 + REDIS_PASSWORD 环境变量覆盖
- 新增 common/redis.go Redis 客户端初始化
- 完整实现 session/redis_store.go,实现 Store 接口全部 7 个方法
- Redis TTL 自动过期,无须后台清理 goroutine
- deps_core.go 根据 cfg.Redis.Enabled 自动选择 RedisStore/MemoryStore
- router.go + main.go 透传 redisClient 参数
|
2026-05-31 11:28:27 +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 |
|
|
|
e1fb28e8fb
|
fix: 修复登录重定向失效 + 404页面友好化
- ShowPage 未登录用户看未发布帖子时引导登录(携带 redirect 参数),替代直接 404
- login.js 无 redirect 参数时回退到同站 Referer 页面
- 404 页面重设计:SVG 图标 + 中文提示 + 返回首页和浏览帖子双按钮
- posts.css 新增 404 页面按钮样式
|
2026-05-31 03:39:18 +08:00 |
|
|
|
8b075f7387
|
perf: WebP 二分压缩下限从 50 改为 1,匹配原图实际质量
- encodeWebPBinary 质量区间从 50~80 扩大为 1~80
- 低质量原图自动匹配低质量 WebP,不再无故回退原格式
- 回退路径中 WebP 不再重编码,避免低质量 WebP 被 quality 80 撑大
- 回退路径仅对 JPEG/PNG 重编码剥离元数据
|
2026-05-31 03:16:55 +08:00 |
|
|
|
48186085d8
|
fix: 回退存储路径也解码重编码,彻底剥离 EXIF/元数据
- fallback 路径不再直接写原始上传字节,而是解码后重编码
- JPEG: decode → jpeg.Encode(quality 92),剥离 EXIF/GPS/注释
- PNG: decode → png.Encode,剥离元数据块
- WebP: decode → webp.Encode(quality 80),剥离元数据
- GIF 例外:重编码会丢失动画帧,仅解码验证后原样存储
- 导入 jpeg/png 从空白导入改为命名导入,以使用 Encode 函数
|
2026-05-31 03:12:10 +08:00 |
|
|
|
d8e58b5f8c
|
perf: 文章图片 WebP 转换改为二分查找质量,目标 ≤ 原文件大小
- 不再仅试 quality 80,改为二分查找 (50~80) 找最高质量 ≤ 原文件大小
- 新增 encodeWebPBinary 辅助函数:先试 80,太大则二分降到 50
- 降到 50 仍超限时回退原格式,避免产生马赛克级质量
- 与头像的激进二分(最低 quality 1)区分,文章图片保底 quality 50
|
2026-05-31 03:08:33 +08:00 |
|
|
|
6ea4e5365e
|
fix: 文章图片上传增加内容解码验证,防伪扩展名和图片投毒
- 所有格式(JPEG/PNG/GIF/WebP)上传后强制解码验证是否为有效图片
- 解码失败直接拒绝,不再回退原样存储
- 消除 .php 改名为 .jpg 绕过检查的安全漏洞
- JPEG/PNG 解码与 WebP 编码合并为一次解码,避免重复读
|
2026-05-31 03:04:45 +08:00 |
|
|
|
5fbd010b71
|
feat: 文章图片上传 JPEG/PNG 自动转 WebP 压缩存储
- JPEG/PNG 上传后自动转为 WebP quality 80 存储,保留原尺寸不 resize
- 仅当 WebP 比原文件小时才采用,否则回退原格式
- GIF/WebP 保持不变直存
- 移除对 common.SaveUploadedFile 的依赖,改用 io.ReadAll + os.WriteFile
|
2026-05-31 02:59:35 +08:00 |
|
|
|
da7560b918
|
perf: 客户端裁剪直接缩放到 512×512 再上传,进一步节省带宽
- cropOnClient 输出尺寸从 min(size, 2048) 改为固定 512px
- 服务端收到的已是 512×512,解码后 resize 和 WebP 编码近乎瞬时
- 上传体积从数十 KB~数 MB 降至 ~30-60KB
|
2026-05-31 02:43:58 +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 |
|
|
|
09a9394c30
|
fix: 修复静态资源哈希 key 与模板 URL 路径不匹配导致版本号全为 0
- 重构 walkStaticDir 统一处理三个 static 目录
- URL key 基于文件相对于 static 目录的路径,不含主题目录名
|
2026-05-31 02:18:20 +08:00 |
|
|
|
eabceecaae
|
refactor: 静态资源哈希算法从 SHA-1 改为 CRC32
- CRC32 更快且语义更匹配缓存破坏场景
- 输出自然为 8 位 hex,无需截取
|
2026-05-31 02:06:41 +08:00 |
|
|
|
d3e5cbe18b
|
refactor: 静态资源缓存破坏改为文件级哈希,重启不刷新未修改文件的缓存
- 启动时计算每个 JS/CSS 的 SHA-1 前 8 位作为版本号
- 文件不变则哈希不变,浏览器继续用缓存,重启零压力
- 替换全局 AssetVersion 为 assetV 模板函数,按文件路径查询哈希
- 移除 BuildPageData 中的全局版本号注入
|
2026-05-31 01:53:17 +08:00 |
|
|
|
b8658712bb
|
fix: 静态资源加缓存破坏版本号,解决浏览器缓存旧 JS 导致功能不生效
- 启动时生成 AssetVersion(base36 时间戳),注入模板 {{.V}}
- 所有 JS/CSS 引用加 ?v={{.V}},重启即刷新缓存
- 涉及前端、管理后台共 12 个模板文件
|
2026-05-31 01:46:47 +08:00 |
|
|
|
0bcaadceb4
|
fix: 注销恢复流程文案统一为'撤销注销',消除歧义
- '恢复'易误解为故障恢复,改为'撤销注销'明确表达取消注销操作
- 涉及后端错误提示、API 响应、前端弹窗及按钮文案共 9 处
|
2026-05-31 01:26:04 +08:00 |
|
|
|
a62039e6bb
|
fix: 登录/注册支持 redirect 参数,未登录跳转自动携带来源页
- login.js/register.js 登录成功后优先跳转 redirect 参数指定页面
- 新增 common.RedirectToLogin 辅助函数,自动携带当前路径
- 替换所有 9 处硬编码 /auth/login 重定向
|
2026-05-31 01:23:09 +08:00 |
|
|
|
9d84d6bf25
|
feat: 临时会话超时从 24 小时缩短为 2 小时
- idle_timeout: 1440 → 120 分钟
- 前端已有 10 分钟心跳续期机制,写文章等长时间操作不会丢失会话
|
2026-05-31 00:51:44 +08:00 |
|
|
|
213b2a571e
|
feat: 登录管理设备列表显示会话类型和剩余有效期
- 临时会话显示橙色'临时会话'徽章
- 非当前设备显示剩余有效时间(临时/长期均显示)
- 当前设备不显示剩余时间(持续续期,显示无意义)
- 新增 formatTTL 模板函数,分钟数转人类可读格式
- sessionConfig 接口增加 GetRememberTimeout 方法
|
2026-05-31 00:36:25 +08:00 |
|
|
|
e244bccb5c
|
fix: 移除服务端登录会话去重逻辑
- 去重会合并标准模式/无痕模式的独立会话,不符合预期
- 防重复提交由前端按钮禁用保证即可,服务端无需干预
|
2026-05-31 00:29:47 +08:00 |
|
|
|
d5d33c3ace
|
fix: 修复登录重复创建会话 + 备注输入框不可交互
- login.js 增加防重复提交锁,请求期间禁用按钮
- Manager.Create 增加幂等检查,同用户同IP同UA 10秒内复用已有会话
- 移除当前设备备注输入框的 readonly 限制,改为 data-current 标记
- 修复 readonly 状态下输入框完全透明无法点击的问题
|
2026-05-31 00:28:00 +08:00 |
|
|
|
47ef3f2a99
|
fix: 重写设置页模板,修复 sessions tab 重复和结构损坏
- 移除 sessions tab 重复3次的冗余内容
- 修复 profile 内容碎片混入 sessions 区块的问题
- 恢复正确的三tab结构(profile / sessions / account)
|
2026-05-31 00:18:47 +08:00 |
|
|
|
b63dc9075f
|
fix: 修复 MemoryStore.Set 重复追加 byUID 索引导致会话列表重复
|
2026-05-31 00:08:08 +08:00 |
|
|
|
2180c27b16
|
fix: 修复设置页模板中文引号与 HTML 属性冲突导致渲染报错
|
2026-05-31 00:06:24 +08:00 |
|
|
|
d203447eb3
|
feat: 设置页新增登录管理 TAB
- Session 结构体新增 IP、UserAgent、Remark 字段,登录/注册时记录设备信息
- Store 接口新增 ListByUID、DeleteByUIDExclude 方法,MemoryStore 完整实现
- SessionManager 新增 ListByUID、DestroyOtherByUID、UpdateRemark 方法
- 新增 UA 轻量解析器(session/ua.go),提取浏览器/OS/设备类型
- 新增 settings_api_sessions.go,提供列表/踢出/一键踢出/备注 4 个 API
- 控制器层声明 sessionManager 最小接口(ISP),SettingsController 注入依赖
- Auth 中间件注入 sid 到 gin context,支持识别当前会话
- 设置页左侧导航增加登录管理入口,tab 白名单新增 sessions
- 前端实现设备列表展示(浏览器/OS/设备图标/IP/时间)、当前设备标识、备注输入、踢出按钮、一键踢出
- settings.css 新增会话管理全套样式及响应式适配
|
2026-05-30 23:58:37 +08:00 |
|
|
|
e3853071d6
|
chore: 清理 JWT 向后兼容残留,移除全部死代码
- 删除 5 个空壳占位文件:auth_token.go/auth_parser.go/repository.go(middleware)/token_service.go/provider.go
- 移除 Config.JWT 字段、JWTConfig 结构体、JWT_SECRET 环境变量绑定
- 移除 config.yaml 中的 jwt 配置段
- 移除 model.User.TokenVersion 字段(session DestroyByUID 替代)
- 移除 service/repository.go 中已废弃的 userTokenStore 接口
|
2026-05-30 23:42:27 +08:00 |
|
|
|
d9ba1cdf28
|
refactor: 移除 Session 架构下已无用的 TokenVersion 即时吊销机制
- 删除 UserRepo.IncrementTokenVersion/FindTokenVersion 方法
- 从 userAuthStore/userAdminStore 接口移除 IncrementTokenVersion
- 删除 middleware.tokenVersionStore 接口(中间件不再查询 token_version)
- auth_service: DeleteAccount/InvalidateSessions 仅调用 DestroyByUID
- admin_service: UpdateUserStatus/ResetUserToken 仅调用 DestroyByUID
- FindByIDForAuth/FindByIDUnscoped Select 移除 token_version 列
- 新架构下登出/改密/封禁统一走 sessionManager.DestroyByUID,无需 token_version
|
2026-05-30 23:38:42 +08:00 |
|
|
|
daf87f895b
|
refactor: JWT 无状态认证替换为服务端 Session,修复记住我掉线问题
- 新增 internal/session 包:Session 结构体、Store 接口、MemoryStore(内存+后台清理)、RedisStore 预留
- Cookie 从 3 个精简为 1 个 mlb_sid(HttpOnly),移除 JWT access/refresh cookie
- 会话过期采用滑动窗口:每次请求自动续期,记住我 30 天无操作过期
- AuthMiddleware/AuthAdmin/Maintenance 中间件改用 SessionManager.Validate()
- AuthService Login/Register/ConfirmRestore 去除 token 生成,返回 *model.User
- Controller 层在登录/注册后调用 SessionManager.Create 创建会话
- AdminService UpdateUserStatus/ResetUserToken 同步销毁 session 实现即时退登
- 改密/注销时通过 DestroyByUID 删除所有 session(替换 TokenVersion 检查)
- config.yaml 新增 session 配置段(idle_timeout/remember_timeout/cleanup_interval)
- TokenService/auth_parser/auth_token 标记废弃,移除 JWT 到期字段依赖
|
2026-05-30 23:36:52 +08:00 |
|
|
|
53f84bfcc4
|
fix: 修复编辑模式下 Vditor 不加载稿件内容
- 创作中心编辑文章时,after 回调中显式调用 vditor.setValue(initialMD)
- 修复 Vditor 3.x wysiwyg 模式下 value 选项可能不渲染内容的问题
|
2026-05-30 21:29:29 +08:00 |
|
|
|
67444434b9
|
feat: 对接稿件审核通知系统 + 消息页面系统消息区域
- 新增通知类型 post_approved / post_rejected
- PostService.Approve/Reject 完成后通知作者(通知失败不影响主流程)
- NotificationService 新增 NotifyPostApproved/NotifyPostRejected 方法
- 消息页面顶部增加系统消息标识和分隔线,之下为全部消息列表
- 稿件审核通过通知卡片点击跳转到 /posts/{id} 页面
- 稿件审核拒绝通知卡片点击跳转到 /studio/posts 创作中心
- 新增 postNotifier 接口遵循 ISP 原则
|
2026-05-30 21:24:30 +08:00 |
|
|
|
fb94ce60ae
|
fix: 维护期间登录一律返回统一提示,不泄露账号状态
- 维护检查提前到 FindByEmail 之后、所有状态检查之前
- 非站长账号(不存在/已封禁/已锁定等)统一走模拟 bcrypt 防时序 → 返回维护提示
- 站长角色正常通过,走完整登录流程
- 旧实现:维护检查在 banned/locked/deleted 之后,会泄露账号状态
|
2026-05-30 21:10:41 +08:00 |
|
|
|
c1357cf4af
|
fix: 维护条对站长显示“正处于维护状态”提醒 + BuildPageData 注入 IsOwner
- BuildPageData 新增 IsOwner 变量,所有前端页面可获取站长角色
- Nav 维护条:站长显示“社区正处于维护状态”(防止忘记关闭),非站长显示“仅站长可访问”
- 维护中间件 API 拦截验证:所有非 /api/auth/ 的 API 对非 Owner 返回 403,正确
|
2026-05-30 21:06:32 +08:00 |
|
|
|
fe683900bb
|
fix: 维护状态下登录页隐藏“立即注册”链接
|
2026-05-30 21:01:54 +08:00 |
|
|
|
1b4a74c23d
|
fix: 维护开关初始状态显示与实际不符
- maintenance.enabled 默认 false,但 JS 用 registration 同逻辑导致首次显示为 ON
- 分离 maintenance 判断:仅当保存过 true 时才显示 ON
- registration 保持原逻辑(默认 true,仅当 !== false 时 ON)
|
2026-05-30 20:58:05 +08:00 |
|
|
|
6229c81f6e
|
feat: 新增维护模式 + 修复注册关闭页面标题显示问题
- 修复注册关闭时标题“创建账号”和副标题仍显示的问题,三态互斥(维护中 > 关闭注册 > 正常)
- 新增 maintenance.enabled 站点设置,默认关闭,仅 Owner 可见可调节
- 维护中间件:全局拦截,维护期间仅站长可访问,白名单放行登录相关路径
- 登录服务:维护期间仅 Owner 角色可登录,Register 优先检查维护状态
- Nav 模板新增维护通知条(黄色横幅)
- 管理后台站点设置新增“启用维护模式”开关
- BuildPageData 自动注入 IsMaintenance 到所有页面模板
|
2026-05-30 20:54:23 +08:00 |
|
|
|
fb2eff5f23
|
feat: 注册关闭时页面隐藏表单并显示友好提示,保留登录入口
- RegisterPage 传入 RegistrationEnabled 标志到模板
- 注册关闭时隐藏输入框和按钮,显示“当前暂不开放注册”提示
- 保留“已有账号?立即登录”链接
- API 层已有拦截(AuthService.Register 返回 403),无需修改
- authUseCase 接口新增 IsRegistrationEnabled 方法(ISP)
|
2026-05-30 20:38:55 +08:00 |
|
|
|
90d17ed4b1
|
feat: 管理后台待审稿件置顶优先显示
- FindAdminPageable 新增 pageResultsAdmin,使用 CASE WHEN 排序
- pending 和有 PendingBody 的 approved 帖子排在最前
- 其余帖子按创建时间倒序排在后面
|
2026-05-30 20:33:14 +08:00 |
|
|
|
8bb87cd685
|
fix: 去掉独立修订表格,消除帖子重复显示
- 移除管理后台独立的"修订待审核"表格区域
- 修订标识和按钮已在主列表中内联展示,无需额外表格
- PostsPage 不再额外查询 Revisions 列表
|
2026-05-30 20:31:19 +08:00 |
|
|
|
95311704fe
|
fix: 修订状态标识仅对作者可见,不公开显示
|
2026-05-30 20:28:59 +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 |
|
|
|
7659aee468
|
feat: 新增创作中心(/studio),支持数据概览、内容管理、草稿箱、写文章
- 新增 StudioController,依赖 studioUseCase 接口,遵循 ISP 接口隔离
- PostRepo 新增 FindByUserIDAndStatus 方法,按用户+状态分页查询
- PostService 新增 ListByUser、GetOverview 及 StudioOverview 统计
- /studio 页面路由(概览/管理/草稿箱/写文章/数据分析)+ /api/studio API
- 复用 Vditor 编辑器,studio-editor.js 对接 /api/studio/posts 端点
- 新增 studio.css(B站风格三栏布局+统计卡片+状态筛选tabs)
- 模板引擎注册 add/subtract 函数,分页模板中直接使用
|
2026-05-30 19:55:29 +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 |
|
|
|
40f0529cbf
|
docs: 更新 README,移除暂停开发通知,补充 Vditor 编辑器与帖子功能
- 移除状态 badge(status-hiatus)和暂停说明
- 技术栈新增 Vditor 3.11 编辑器
- 当前功能新增:帖子 CRUD、代码高亮、Shortcode 卡片、草稿、审核工作流
- 计划中去掉已完成的帖子系统,新增评论系统
|
2026-05-30 15:59:06 +08:00 |
|
|
|
6ec12010f3
|
feat: Tiptap替换为Vditor + MD存储重构 + Shortcode卡片扩展
- 编辑器:Tiptap 替换为 Vditor 3.11.2(wysiwyg 模式,本地托管 5.8MB,去 CDN)
- 存储:Body 字段从 HTML 改为 Markdown,去除 BodyHTML,新增 Excerpt 列表摘要
- 安全:去除 bluemonday 依赖(MD 纯文本无 XSS 风险),go.mod 已清理
- Shortcode:新增 [zone:type:params] 扩展语法,支持活动/游戏/投票/资源卡片
- 图片上传:POST /api/posts/upload-image 直接返回 Vditor 原生响应格式
- 草稿:localStorage 键名改为 draft_post_body_md,与旧 HTML 草稿隔离
- 详情页:Vditor.method.min.js 客户端 MD → HTML 渲染,去 highlight.js CDN
- 样式:去 Tiptap 样式 ~190 行,精简工具栏 CSS,新增卡片样式
- 文档:vditor-migration-plan.md 完整记录迁移决策、架构、用法
|
2026-05-30 15:56:22 +08:00 |
|
|
|
c9808ab9b2
|
docs: 标注项目暂停开发及原因
- 状态徽标从 dev 改为 hiatus
- 说明编辑器集成问题未解决
- 说明将先采用 Flarum 上线社区
|
2026-05-28 15:28:22 +08:00 |
|
|
|
fe81c879b0
|
fix: 修复代码块语法高亮丢失 + 语言标签注入 + 安全性增强
- 新增 cdnjs.cloudflare.com CSP 白名单,允许加载 highlight.js
- 消毒策略放行 span 元素,保留 highlight.js 高亮 class
- 详情页和新帖子页引入 highlight.js 库和 GitHub 主题
- 代码块语言选择器默认 text,支持 prev/next 循环切换语言
- 代码块语言标签注入兼容 data-language 和 code class 双来源
- 修复 utils.js defer 导致 common.js 执行时 getCSRFToken 未定义
|
2026-05-28 15:21:44 +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 |
|
|
|
36b18c0ffe
|
feat: 代码块语法高亮 + 语言选择 + 样式统一
- 引入 @tiptap/extension-code-block-lowlight + lowlight 实现代码语法高亮
- 工具栏新增语言下拉选择器,光标在代码块内时显示,支持 27 种常用语言
- 默认语言 text,高亮主题适配 MetaLab 深蓝背景 (#1a2332)
- 代码块语言标签用 JS 动态注入 DOM 元素(避免 ::before 在 overflow 容器中失效)
- 详情页同步代码块高亮和语言标签显示
- 编辑器与详情页样式统一:代码块暗色背景、引用蓝色边框、链接 accent 蓝
- sanitizePolicy 放行 data-language 属性和 hljs-* class
- 修复 import map 避免 keyed plugin 重复实例
- 修复详情页代码块开头空白行(移除多余的 padding-top)
- 修复语法错误(多余的闭合括号)
|
2026-05-28 14:34:58 +08:00 |
|