Files
jiang13-bbs/docs/site-operations.md
freefire 1d862a0dd3 feat: 站点媒体库与移动端底部导航,服务测试补强
- 新增媒体库:media_library/media_thumbs 服务(WebP 缩略图)、管理端 media 页面
- 移动端底部导航 MobileTabBar 替换 MobilePostBar
- 旧数据导入增强与测试、路由与登录会话/板块侧边栏测试补强
- site-doc 组件精简(移除 Breadcrumb),文档新增迁移公告说明
2026-09-27 02:36:11 +08:00

149 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 站点设置五模块:实现与交付说明
验证日期:2026-09-21。本次修改位于工作区,未发布到生产。测试使用独立 PostgreSQL 数据库、临时数据目录、SMTP/S3 协议测试设施,没有向真实用户发信或清理生产数据。
## 现有能力与改动归属
- 原有基本信息、互动与安全(含原内容互动与访问安全)、主题变量、管理权限、CSRF、Cookie 会话、上传校验、附件下载授权继续使用。站点设置各分区为独立路由(/admin/settings/basic 等)。时间线编辑器仍支持从 GitHub/Gitea 导入提交(内置规则,不可在站点设置中编辑)。
- 原有开放注册及上传大小/扩展名/数量设置迁到对应新模块。实际值仍由原 SiteSetting 键提供,模块保存通过同一事务更新,旧通用接口拒绝写入这些已迁移键,避免双重来源。
- 新增独立模块版本、机密加密、共享计数、SMTP 任务与验证码、S3 适配器、统一内容匹配、维护访问守卫及受控临时文件清理。
- 原站点没有独立应用缓存和订阅邮件流程,不展示清空缓存或群发通知的虚假能力。
- 延续现有明暗主题与品牌令牌。截图来自隔离站点默认蓝色主题,没有覆盖真实站点已保存的绿色或其他主题色。
## 文件与关键实现
- backend/model/operations.go、model/db.go、model/models.go:模块、审计、额度、持久邮件、验证码、对象引用和临时上传记录;附件新增 object_id。
- backend/service/operations.go:默认值、完整校验、AES-256-GCM、版本比较、跨模块事务依赖、旧键兼容。
- backend/service/operations_security.go:PostgreSQL 原子共享计数、账号/来源登录保护、受控服务目标解析与连接。
- backend/service/operations_mail.go:验证证书的 TLS/STARTTLS、测试连接/实际测试发信、品牌模板、加密队列、租约恢复、有限重试、验证码。
- backend/service/operations_storage.go:S3 签名请求、专用前缀读写删除探测、不可变配置快照、公开图片/CDN与私有附件隔离。
- backend/service/operations_filter.go:CommonMark 可读文本、NFKC/大小写归一化、匹配位置和局部例外、拦截优先、脱敏审计。
- backend/service/operations_maintenance.go、operations_temporary.go:密码重置、真实诊断、日志清理、带跨实例上传锁的临时文件扫描与清理。
- backend/handler/operations.go、handlers.go、router/router.go:复用 PermSettings 和 CSRF;管理接口、公开白名单、业务配额、维护访问控制。
- backend/handler/auth.go、post.go、setting.go;service/auth.go、post.go、comment.go、upload.go、post_file.go、brand_store.go:实际注册/登录/发布/编辑/上传/下载接入。
- backend/service/ratelimit.go、middleware/ratelimit.go:修复原限流器把完整请求键当类别查找的问题,加入 Retry-After 和过期清理。
- backend/go.mod、go.sum:MinIO Go S3 客户端及 Goldmark 解析器。
- frontend/app/admin/settings/OperationsPanel.tsx、FilterRules.tsx、SettingsAdmin.tsx:五模块表单、独立保存、草稿测试、版本错误、导航离开保护、规则导入/编辑/批量操作、诊断与确认清理。
- frontend/app/admin/settings/BasicIdentityPanel.tsx:只读正式地址来源与 SEO 关键词说明修正。
- frontend/lib/api.ts、app/register/page.tsx、app/login/page.tsx、app/reset-password/page.tsx:注册验证码、找回密码、管理调用。
- frontend/components/OperationalBanner.tsx、app/layout.tsx:只读提示,最多约 30 秒刷新提示;服务器写入限制立即生效。
- frontend/middleware.ts:服务端读取维护状态并返回真正的 HTTP 503,保留原有会话恢复和 robots 大小写改写。
- frontend/app/globals.css:复用设计令牌的表单、结果、规则和窄屏布局。
- backend/service/operations_test.go、backend/tests/operations-api.mjs:风险驱动的服务与 HTTP 回归。
- .env.example、deploy/.env.example、deploy/docker-compose.yml、deploy/CHANGELOG.md:部署变量与升级说明。
## 设置项与校验
以下是缺失项的初始值;已有注册、文件限制继续使用数据库有效值。每个模块有独立版本,保存后立即供下一次服务请求读取;不需要重启应用。SMTP/S3 服务状态只是配置状态,测试结果是带时间的历史结果,不表示持续在线。
### 访问与安全
- allow_register:默认 true,继承原配置。关闭后接口拒绝新注册,前台仍保留注册入口以便展示 register_notice;现有账号不受影响。
- register_notice:默认空,最多 200 字;关闭注册时在注册页展示。
- verify_email、password_reset:默认 false。启用前要求邮件已启用、凭据可解密、正式地址有效且 SMTP 连接/认证通过;依赖存在时禁止停用邮件或清空必需凭据。注册验证码在创建账号前消费,不批量改变老账号状态。
- login_window:600 秒,范围 60–3600;login_failures:5 次,范围 3–50。账号与来源分开计数,来源阈值为账号阈值四倍,窗口到期自动恢复;成功登录清除账号失败计数。
- post_interval:6 秒;comment_interval:2 秒,均允许 0–3600。根据原有每分钟 10/30 次校准,新规则采用最小间隔,0 仅关闭该最小间隔。原有积分/等级业务发帖冷却仍有效,不能把两者视作相互替代。
- resend_interval:60 秒,范围 30–3600,目标邮箱+用途;email_hourly:5 次,范围 1–20,按规范化邮箱共享;另外每来源最多 20 次/小时。
- search_minute:30 次/分钟,范围 1–120;登录用户按 ID、游客按真实可信来源计量。
- 新增安全额度使用 PostgreSQL 原子计数、哈希键及到期清理,多实例共享。原有其他交互接口的内存防滥用限流仍按进程工作,不宣称全站一致。
- 密码沿用既有 6–64 字节、bcrypt、会话版本规则;重置后撤销旧会话。第三方验证码/MFA 不在本期。
### 邮件服务
- enabled:默认 false;host/username/password/from:启用时必填,主机不能含协议或路径;密码保存前必须有主密钥。
- tls:默认 tls(隐式 TLS),也支持 starttls(必须升级且验证证书);port 默认 465,范围 1–65535。STARTTLS 常用 587,由站长按服务商实际端口填写。没有忽略证书或明文降级选项。
- from_name:留空复用站点名称,最多 120 字节;reply_to:可空,非空需为邮箱;用户名最多 256 字节,禁止邮件头换行。
- timeout:10 秒,范围 2–30;retention:30 天,范围 1–365。缩短保留时间不立即删除记录,需另行确认清理。
- 正式地址和浅色 Logo 复用基本信息/部署 SITE_URL。主题与正文可在后台自由编辑,注册验证和找回密码共用;留空恢复内置模板。变量为 {{site_name}}、{{purpose}}、{{code}}、{{link}}、{{site_url}}、{{logo_url}}(绝对图片 URL)、{{logo}}(完整 img 标签,勿写入 src)。正文必须保留 {{code}};不做 HTML 过滤。发送时变量值会转义,并把 `<style>` 中的简单 class 规则内联到元素(手机 QQ 等客户端会丢弃 style 标签);邮件以 quoted-printable HTML 发出。预览与实发使用同一渲染结果。邮件链接回到可信正式地址,由用户粘贴验证码完成验证/重置。
- 凭据读取只返回已配置标志,不回显原文,拒绝掩码占位符。未保存时直接填写;已保存时默认沿用,可单独更换或移除。更换与移除互斥,留空且不移除则保持旧值。
- 保存启用的邮件配置前实际验证连接与认证。测试按钮使用当前草稿,测试连接不投递;发送测试邮件只发给管理员指定地址。
- 业务邮件记录排队/发送中/重试/失败/服务器已接受。最多 3 次尝试,2 分钟租约用于崩溃恢复;任务去重与稳定 Message-ID。SMTP 在“远端接受后本地未记录”的故障窗口可能重投,不承诺严格 exactly-once。
- 队列有效载荷加密,完成/最终失败后清空;日志不记录验证码、正文或凭据。服务器接受不等于送达;SPF/DKIM/DMARC只给指引,未检测则不显示通过。
### 文件与存储
- backend:默认 local;本地根目录由 DATA_DIR 固定,只读显示。切换 S3 只影响新头像、正文图片和普通附件。站点 Logo/背景继续保存在部署品牌目录;媒体库中的远程图片可按权限复制为品牌素材。
- endpoint:生产 HTTPS origin,开发允许 HTTP;bucket:3–63 位符合桶名格式;region:默认 us-east-1,1–64 位字母/数字/_/-;access_key、secret_key:机密交互同邮件。
- prefix:默认 jiang13/uploads/,受控相对目录,以 / 结束,不允许越界;path_style:默认 true,支持路径或虚拟主机寻址。
- cdn:默认空,可选 HTTPS 基址。只用于已声明公开图片,部署方必须配置其桶/前缀权限。私有文件仍走鉴权下载;CDN 不是将私有桶设为公开的指令。
- image_max_mb:默认 5 MiB,范围 1–50;attachment_max_mb:默认 20 MiB,范围 1–100;attachment_max_count:默认每帖 10,范围 1–20。原 API 每次上传一个文件,前端批量仍受每帖上限约束。
- attachment_ext_limit:默认 true;attachment_exts:继承原业务白名单,1–80 个小写字母数字扩展名。原站点支持软件安装包和技术文本;这些仍只作为强制下载附件,不能内联执行。
- 正文图片复用 JPEG/PNG/WebP/GIF 解码检查与最大 4096px,其中 JPEG/PNG 落盘前统一转存 WebP(JPEG 有损 q80、PNG 无损;GIF 动图与已是 WebP 的原样保留,转码失败降级为保留原格式);头像保持 2 MiB、64–512px WebP;SVG 仅保留管理员品牌上传能力。附件复用真实图片头校验,伪装/活跃内容降为二进制并强制 attachment/nosniff。
- 1 MiB=1,048,576 字节;仓库 Nginx 示例与 Next 代理缓冲均为 512 MiB,仍需确认实际部署入口没有更低限制。
- 保存 S3 前验证合并后的草稿,在专用 tests/ 前缀上传、读回并删除一个随机测试对象,不扫描桶。失败不更新配置;不会自动切回其他存储。
- 每个远程对象保存不可变 storage-N 配置引用与对象键。切换后原本地 URL、历史远程配置继续可读;界面显示历史引用数,不提供删除历史配置按钮。
- 删除媒体时先撤销本站公开资源访问,再删除远程对象;清理失败保留配置引用,需运维处理残留对象。自行配置的 CDN 缓存失效由部署方处理。
### 内容过滤
- enabled:默认 false;rules:默认空,最多 2000。每条 ID 唯一且最多 64 字节,词语 1–80 字,备注最多 500 字节,最多 20 条例外,每条例外最多 240 字节且非空。
- scopes:username/title/body/comment;action:block/log;每条规则独立启停。NFKC 归一化并忽略大小写,仅用于匹配,原始内容不改写。
- 正文/评论从 CommonMark AST 提取可读文本,跳过代码块、行内代码、链接目标/自动链接、HTML块/标签;普通链接显示文字参与匹配。测试显示归一化文本及 0 起始字符位置。
- 例外仅覆盖对应规则的对应出现位置,同文其他命中仍拦截;拦截优先于记录。创建/编辑帖子与评论、注册/修改昵称在服务层检查,导入草稿最终发布同样走该服务。
- TXT 每行一个词,300 KB 上限;预览新增/重复/无效项,默认合并,覆盖需确认,应用导入仅修改草稿,保存后生效。导出 TXT 仅词语,范围/例外不作为无损备份。
- 不改写历史内容,不自动换星号,不伪造审核工作流。正则和复杂审核为后续增强。
### 维护与诊断
- mode:默认 normal,可选 readonly/paused;readonly 阻止普通用户内容写入,paused 公开页面及业务 API 返回 503。
- title:默认“站点维护中”,最多 240 字节;message:最多 4000 字节;contact:最多 500 字节;均按纯文本处理。
- until:默认空,有值必须是含时区的 RFC3339;仅展示,不会自动恢复。
- retry_after:默认 300 秒,范围 30–86400;temp_days:默认 7 天,范围 1–365。
- 登录、退出、会话恢复、找回密码、站点状态、健康检查保持可用;管理接口继续独立权限校验。后台绕过基于实时真实 PermSettings;robots 保留原响应,不用 robots 实现停站。
- Go 实际拒绝写入;Next 页面/RSC 请求查询实时状态,暂停时返回 503 + Retry-After + private,no-store。状态不可读时安全失败为 503。已打开页面的只读提示会定期更新,后端限制不依赖提示是否刷新。
- 数据库 ping、本地创建/删除探测、队列查询、版本/运行时长和带时间的历史邮件测试是真实数据;无独立缓存如实标注,S3 连续健康未知,使用专用测试按钮检测。
- 临时扫描不删除;一次清理最多 100 个受控候选。只清理本版本登记、过期且不在上传中的 .partial,执行前复查引用和跨实例数据库会话锁;正文/草稿附件、未知来源旧 partial 均保留。返回成功/跳过/失败数量,可重新扫描重试。
- 清理邮件记录仅影响超出保留期的终态记录,不删除排队任务、会话、限流计数。
- 无在线清库、重置全站、备份恢复或程序更新按钮。
## 数据库迁移与部署
1. 升级前备份数据库和 DATA_DIR;多个实例滚动部署时,先让数据库执行新增迁移,再统一升级服务。旧版本不认识维护守卫和 S3 引用,不应长期与新版本混跑。
2. 启动时 GORM AutoMigrate 新增 module_configs、settings_audits、action_counters、mail_tasks、email_challenges、stored_objects、temporary_uploads,并为 post_attachments 新增 object_id。既有行为空值表示本地附件,不批量重写历史链接。
3. SETTINGS_MASTER_KEY 必须为安全随机 32 字节的标准 Base64;例如在安全终端使用 openssl rand -base64 32 生成。不要使用测试用的全零密钥。本地开发写在 `backend/app.ini` 的 `[security]`;生产与多实例用同名环境变量,环境变量优先于 ini。各 API 实例配置相同密钥,单独备份,不写入仓库或与密文一同存库。更换/丢失密钥会使队列与所有历史存储凭据不可解密;本期没有在线轮换功能。修改后需重启 API。
4. Go 与 Next 的 SITE_URL 必须一致且为正式外部 HTTPS origin;后台基本信息只读显示。Next 的 BACKEND_URL 指向可达 API,不使用请求 Host 生成邮件地址。
5. SERVICE_PRIVATE_HOSTS 为逗号分隔的精确主机名。默认拒绝私网、回环、链路本地及特殊地址,DNS 解析后连接已经检查的 IP;确有自建 SMTP/S3 时只放行对应主机。虚拟主机 S3 寻址时要按实际连接的 bucket.endpoint 主机配置。
6. TRUSTED_PROXIES 仅列出真正的代理 IP/CIDR。默认不信任转发头;不要直接填任意全网,避免登录/IP额度绕过。
Compose 部署下不配置时 ClientIP 会记录为反代容器内网地址(如 172.19.0.4),登录日志与访问统计全部失真。
取真实 IP:先 `docker network inspect <网络名>` 查看子网(常见 172.18.0.0/16–172.31.0.0/16),再把该网段填入
`TRUSTED_PROXIES`(如 `172.16.0.0/12` 覆盖全部 Docker bridge),反代需设置 `X-Forwarded-For`/`X-Real-IP`。
未配置时后端启动会输出警告日志便于排查。经 Cloudflare 等平台代理时改用 `TRUSTED_PLATFORM=CF-Connecting-IP`。
7. MAINTENANCE_RECOVERY=1 是部署级紧急恢复:重启 API 后强制正常访问;修复后台模式,再撤销该变量并重启。不会悄悄覆写数据库保存模式。
8. Compose 已透传四个新变量并保留原服务/端口/数据卷。参见 deploy/CHANGELOG.md。JWT、DB_DSN、Cookie安全属性仍保持部署级管理。
9. 反代/CDN不得缓存 HTML、/api/site-state、鉴权接口、503;停站和恢复后验证外部入口的真实状态码及缓存头。外部 CDN 未在本地测试范围内。
10. 多实例本地文件存储需要共享相同数据卷;所有实例使用一致数据库、密钥、正式地址。临时上传锁通过相对路径在数据库中协调。S3需保留历史配置/主密钥以及桶内对象。
## 验证记录与复现
服务测试使用临时 schema,结束删除 schema;API脚本只允许显式声明隔离的 3301 本机后端。不要把这些测试指向现有真实站点。
- 后端:设置 OPS_TEST_DATABASE_URL=postgres://…/ops_test?sslmode=disable 后,在 backend 运行 go test ./...。已通过完整测试。覆盖加密/AAD/缺失密钥、失败保存不改变配置、版本争用和依赖原子性、共享限流/到期恢复、SMTP认证成功/失败/超时/证书拒绝、队列去重/重启租约恢复/有限重试、邮箱跨来源限流/验证码单次消费、S3读写删除/历史私有对象、Unicode/例外/Markdown过滤、临时文件活跃锁/正文引用/草稿保护。
- HTTP:OPS_TEST_BASE_URL=http://127.0.0.1:3301、OPS_TEST_CONFIRM=isolated,运行 node tests/operations-api.mjs,配合指向同后端的 Next :3000。已通过权限/CSRF/注册关闭/并发200+409/登录429与Retry-After/创建编辑过滤/评论间隔/只读写入拒绝/暂停API和页面503/robots200/恢复入口/恢复页面200。
- 前端:npx next typegen、npx tsc --noEmit --incremental false、npm run build 均通过;npm test 的 16 项已有 SEO/JSON-LD 测试也通过。现有 middleware 文件命名有 Next 的弃用提示,仍可构建;本次保留原文件及用户已有 robots 修改,未另做 proxy 迁移。
- 实际浏览器:安全设置保存显示新版本及已生效;服务重启后仍读取已保存版本;本地存储测试真实成功;未配置 SMTP 测试显示错误;过滤测试显示局部例外及代码跳过;TXT预览正确显示新增1/重复2;导入未保存离开确认、取消保留及放弃行为正常;规则变化后旧测试标为过期;诊断与临时扫描正常。
- 1440px 桌面与 390px 手机、浅/暗主题人工截图检查。手机文档宽度390px,无横向页面溢出。全部截图来自一次性测试账号和数据,规则/维护标题不是生产默认值。
### 页面截图
- [访问与安全(桌面)](screenshots/settings/security-desktop.jpg)
- [邮件服务(桌面)](screenshots/settings/mail-desktop.jpg)
- [文件与存储(桌面)](screenshots/settings/storage-desktop.jpg)
- [内容过滤(桌面)](screenshots/settings/filter-desktop.jpg)
- [维护与诊断(桌面)](screenshots/settings/maintenance-desktop.jpg)
- [邮件服务(手机)](screenshots/settings/mail-mobile.jpg)
- [文件与存储(手机)](screenshots/settings/storage-mobile.jpg)
- [内容过滤(手机)](screenshots/settings/filter-mobile.jpg)
- [维护与诊断(手机)](screenshots/settings/maintenance-mobile.jpg)
- [访问与安全(手机浅色)](screenshots/settings/security-mobile.jpg)
- [访问与安全(手机暗色)](screenshots/settings/security-mobile-dark.jpg)
- [访问与安全(桌面暗色)](screenshots/settings/security-desktop-dark.jpg)
## 仍需站长配置与外部验收
- 填写正式 SITE_URL、随机 SETTINGS_MASTER_KEY、可信代理及必要的内部服务允许列表。
- 提供真实 SMTP 主机/端口/模式/账号授权码/发件邮箱;先连接测试,再只向指定测试邮箱发送。真实供应商、STARTTLS供应商互操作、垃圾邮件归类及 SPF/DKIM/DMARC 未做外部实测。
- 使用 S3 时提供 Endpoint/Bucket/Region/两项密钥/专用前缀和必要 CDN 权限,验证真实服务的小文件、大文件上传与私有下载。协议设施通过不等于所有云厂商均兼容;真实 MinIO/云供应商、CDN 和反代组合尚需部署验收。
- 现有公开图片继续公开;私有附件保留鉴权/帖子可见性/积分规则。历史附件批量迁移、密钥在线轮换、专用云SDK、第三方验证码、MFA、订阅通知、正则审核、数据库在线恢复是后续增强。
验证结束后已停止本次启动的临时前端、后端与 PostgreSQL;截图和源码保留在仓库内。