feat(cloudflare): add DNS pointing integration

Implement Cloudflare connection management, pointing groups and members, asynchronous A-record reconciliation, node IP triggers, admin APIs, management pages, migrations, tests, and documentation.
This commit is contained in:
ryan
2026-08-04 12:32:37 +08:00
parent 99f0f63b99
commit 3edcdb9e9f
47 changed files with 7019 additions and 49 deletions
+4
View File
@@ -22,6 +22,10 @@ sidebar: false
## [unreleased]
### 新增
- 新增 Cloudflare DNS 指向管理:可复用现有 Cloudflare DNS 账号或配置独立 Token,按分组将 ZoneDomain 的单条 A 记录异步同步到边缘节点 IPv4,并支持成员橙云、同步状态与节点 IP 变更联动。
### 改进
- 统一数据访问分层:业务持久化经 `internal/repository`,`internal/model` 仅保留实体与无 IO 领域规则,避免双轨 CRUD 与职责混淆。
+26 -4
View File
@@ -65,7 +65,7 @@ OpenResty (Agent, TLS/WAF)
| 组件 | 职责 | 详细设计参考 |
| --------------- | ---------------------------------------------------------------------- | ------------ |
| **Server** | 管理端 UI/API、控制面状态持久化、配置编译渲染、发布版本控制、Pages 部署包存储、访问日志入库与业务流量聚合、Uptime Kuma 监控同步与登录验证码防护 | [Agent 与发布模型](./agent-design.md) / [边缘可观测与业务流量统计](./observability-design.md) / [Uptime Kuma 监控同步设计](./kuma-design.md) / [登录验证码设计](./login-captcha.md) |
| **Server** | 管理端 UI/API、控制面状态持久化、配置编译渲染、发布版本控制、Pages 部署包存储、Cloudflare A 记录指向、访问日志入库与业务流量聚合、Uptime Kuma 监控同步与登录验证码防护 | [Agent 与发布模型](./agent-design.md) / [Cloudflare DNS 指向设计](./cloudflare-pointing.md) / [边缘可观测与业务流量统计](./observability-design.md) / [Uptime Kuma 监控同步设计](./kuma-design.md) / [登录验证码设计](./login-captcha.md) |
| **Agent** | 周期心跳与 WS 同步、静态资源包拉取与解压、OpenResty 配置写入/校验/重载与自愈;观测仅上报访问明细与主机/健康读数,不做业务预聚合 | [Agent 与发布模型](./agent-design.md) / [边缘可观测与业务流量统计](./observability-design.md) |
| **OpenResty** | 接收真实流量,执行 WAF 过滤、PoW 防护、Basic Auth 认证与静态/反代服务 | [WAF 设计](./waf-design.md) / [Pages 设计](./pages-design.md) |
| **Relay** | 部署于边缘节点,管理 `frps` 守护进程生命周期,接受心跳派发的穿透中继配置 | [内网穿透设计](./tunnel-design.md) |
@@ -81,6 +81,7 @@ OpenResty (Agent, TLS/WAF)
* 边缘节点协议走 `/api/v1/agent|relay|tunnel/*`,分别使用 `X-Agent-Token` / `X-Tunnel-Token` 鉴权。
* 包含配置编译器(Compiler),将数据库中的规则、证书与全局参数统一编译为不可变的配置快照及 OpenResty 物理配置文件文本。
* 统一接收 Pages 本地上传、Remote URL 与公开 GitHub Release 预构建产物,完成来源检查、受限下载、归档校验和不可变 deployment;manual 上传生成待显式激活的 candidate,持久来源 sync 才 create-or-load 并原子激活。Server 向 Agent 提供受控的 latest 下载接口;内部 scanner 负责 GitHub latest 的限量检查、租约恢复、可选自动发布与孤儿上传记录补偿,通用任务管理入口不能修改该排程。未来仓库源码构建由独立 Server build executor 扩展,Agent 不执行第三方拉取或构建命令。
* 提供可选的 Cloudflare DNS 指向控制面:以 ZoneDomain 为成员维护分组期望状态,通过 Asynq 将单条 A 记录幂等同步到当前生效节点 IPv4;节点 IP 变化只做 best-effort 入队,一期不执行自动故障切换。
* 后台集成 Uptime Kuma 监控同步服务,自动为可用站点维护 HTTP 探测任务。
* 启动入口为根目录 `main.go` + `internal/cmd/`(`api` / `worker` / `scheduler` / `all`);OpenFlare 业务在 `internal/apps/openflare/`,边缘协议处理在 `internal/apps/openflare/{agent,relay,flared}/`。
* *详细设计请参阅:[Agent 与发布模型设计](./agent-design.md) 以及 [Uptime Kuma 监控同步设计](./kuma-design.md)*
@@ -154,6 +155,24 @@ OpenResty 健康与连接数 --> 边缘健康(瞬时,不作 24h 业务总量
* **原则**:Agent 只上报事实,Server 解释事实;业务流量唯一真相为访问日志。`openresty_tx` 与「已提供数据」不得双轨并存。
* *传输模型、示例与采集频率详见:[观测数据传输模型](./observability-transport-model.md);字段收敛与迁移详见:[边缘可观测与业务流量统计](./observability-design.md)*
### 5. Cloudflare DNS 指向流
```text
管理员配置连接/分组/成员 -> Server 持久化期望状态 -> Asynq 同步任务
|
v
Cloudflare Zone / DNS API
|
v
单条 A 记录 -> active_node IPv4
节点 IP 手动更新或 Agent 心跳变化 --------------------> 按节点 best-effort 入队
```
* Cloudflare 模块只管理其缓存或接管的唯一同名 A 记录,不把 Zone 核心扩展为权威 DNS 控制面;同名多 A 时停止同步并要求管理员先在 Cloudflare 清理。
* 分组备用节点与生效节点为后续故障切换预留,一期固定使用主节点,不根据心跳离线状态自动切换。
* *连接、模型、幂等同步与分期边界详见:[Cloudflare DNS 指向设计](./cloudflare-pointing.md)。*
---
## 核心对象
@@ -161,6 +180,7 @@ OpenResty 健康与连接数 --> 边缘健康(瞬时,不作 24h 业务总量
当前系统核心实体包括:
* **反代与配置**:`zones` (根域管理边界), `zone_domains` (明确域名与证书/路由关联), `proxy_routes` (路由策略), `origins` (源站), `config_versions` (配置版本), `tls_certificates` (证书). 详见 [Zone 与域名资源设计](./zone-design.md)。
* **Cloudflare DNS 指向**:`of_cf_connections` (全局连接), `of_cf_pointing_groups` (主/备/生效节点与默认橙云), `of_cf_pointing_members` (ZoneDomain 成员、记录缓存与同步状态). 详见 [Cloudflare DNS 指向设计](./cloudflare-pointing.md)。
* **Pages 静态托管**:`of_pages_projects` (Pages项目), `of_pages_project_sources` / `of_pages_project_source_runtime` (可变来源配置与运行态), `of_pages_deployments` (不可变部署), `of_pages_deployment_files` (部署文件清单).
* **节点与穿透**:`nodes` (节点), `tunnels` (隧道客户端), `node_system_profiles` (系统概况), `apply_logs` (应用日志).
* **WAF 与安全**:`waf_rule_groups` (WAF规则组), `waf_ip_groups` (WAF IP组), `waf_rule_group_bindings` (网站WAF绑定).
@@ -176,6 +196,7 @@ OpenResty 健康与连接数 --> 边缘健康(瞬时,不作 24h 业务总量
| Agent 主动拉取 | Server 不需要 SSH 权限,降低安全风险;支持 HTTP 与 WebSocket 双协议灵活切换 |
| 全局单激活版本 | 降低控制面复杂度,保证所有节点默认一致;提供一键秒级回滚的稳定机制 |
| Zone 域名与路由策略分离 | Zone 提供根域入口与域名边界;路由仍可复用同一套站点级策略并按域名绑定证书 |
| Cloudflare 指向独立于 Zone 核心 | ZoneDomain 只提供明确 FQDN;Cloudflare 模块以库表期望状态驱动单 A 记录,不扩大 Zone 为通用 DNS 控制面 |
| 内网穿透基于 frp 整合 | 复用成熟隧道协议,避免自研隧道引起稳定性风险;其 Vhost 机制天然适配反代路由 |
| 运行时配置与控制库解耦 | WAF 规则发布时编译并随 OpenResty reload 加载;动态 IP 组通过 checksum 驱动的内存快照独立刷新 |
| 业务流量以访问日志为唯一真相 | Agent 禁止业务预聚合;看板与 Zone 共用 Server 侧聚合,避免 openresty_tx 与 bytes_sent 双轨 |
@@ -189,12 +210,13 @@ OpenResty 健康与连接数 --> 边缘健康(瞬时,不作 24h 业务总量
修改系统架构或开发新功能前,请按以下顺序阅读:
1. **[产品边界](./index.md)**:了解 OpenFlare 核心定位与不允许逾越的设计边界。
3. **[Agent 与发布模型](./agent-design.md)**:理解版本快照同步及失败回滚的安全兜底逻辑。
4. **细分领域设计**:
2. **[Agent 与发布模型](./agent-design.md)**:理解版本快照同步及失败回滚的安全兜底逻辑。
3. **细分领域设计**:
* Zone 与域名相关开发:阅读 [Zone 与域名资源设计](./zone-design.md)。
* Cloudflare DNS 指向开发:阅读 [Cloudflare DNS 指向设计](./cloudflare-pointing.md)。
* 穿透相关开发:阅读 [内网穿透隧道设计](./tunnel-design.md)。
* WAF 相关开发:阅读 [WAF 设计](./waf-design.md) 与 [WAF 可编排规则设计](./waf-orchestration-design.md)。
* Pages 托管开发:阅读 [Pages 静态托管设计](./pages-design.md)。
* 监控同步开发:阅读 [Uptime Kuma 监控同步设计](./kuma-design.md)。
* 看板/访问日志/节点指标开发:阅读 [观测数据传输模型](./observability-transport-model.md) 与 [边缘可观测与业务流量统计](./observability-design.md)。
5. **[仓库结构](./index.md#仓库结构)**:明确各个物理目录分层职责,避免堆砌和重复开发。
4. **[仓库结构](./index.md#仓库结构)**:明确各个物理目录分层职责,避免堆砌和重复开发。
+1
View File
@@ -24,6 +24,7 @@ OpenFlare 适合需要统一管理多台 OpenResty 代理节点的团队,具
| **反代配置管理** | 以网站规则(Proxy Route)为聚合边界,支持多域名与多上游负载均衡 | [新建反代配置](../guide/proxy-config.md) |
| **边缘缓存** | 单节点 OpenResty `proxy_cache`;默认 static 扩展名 + 源站头/Set-Cookie 闸门 + 默认 Edge TTL(对标 CF 默认模型) | [边缘缓存策略设计](./edge-cache-design.md) |
| **Zone 与域名管理** | 以可注册根域为管理入口,聚合明确域名、域名证书与反代路由 | [Zone 与域名资源设计](./zone-design.md) |
| **Cloudflare DNS 指向** | 以 ZoneDomain 为粒度,将单条 Cloudflare A 记录幂等指向边缘节点 IPv4;支持连接配置、分组、成员橙云与异步同步,一期不含自动故障切换 | [Cloudflare DNS 指向设计](./cloudflare-pointing.md) |
| **配置版本控制** | 支持全局单一激活版本的预览、发布、不可变快照历史与秒级一键回滚 | [Agent 与发布模型](./agent-design.md) |
| **WAF 安全防护** | 支持可视化 DAG 编排规则、手动/自动/订阅型 IP 组、GeoIP 匹配与 PoW CC 防护 | [WAF 设计](./waf-design.md) / [WAF 可编排规则设计](./waf-orchestration-design.md) / [WAF 使用指南](../guide/waf-usage.md) |
| **内网穿透** | 通过中继节点(Relay)与内网客户端(OpenFlared),反向穿透暴露内网 Web 服务 | [内网穿透设计](./tunnel-design.md) / [穿透使用指南](../guide/tunnel-usage.md) |
+1030
View File
File diff suppressed because it is too large Load Diff
+151
View File
@@ -0,0 +1,151 @@
# Cloudflare DNS 指向实现计划
> 状态:代码实施完成(2026-08-04;范围内自动化验证完成;全量前端仅保留任务开始前已存在的 Zone 文案断言失败)
> **执行方式**:使用 `superpowers:executing-plans` 在当前会话按任务逐项实施;每项遵循测试先行(RED → GREEN → REFACTOR)。
## 1. 目标与背景 (Goal & Context)
* **需求背景**:落实提交 `21fb303e` 中的 Cloudflare DNS 指向设计,让管理员以 ZoneDomain 为粒度,将明确 FQDN 的单条 A 记录幂等指向 OpenFlare 边缘节点 IPv4,避免在 Cloudflare 控制台重复手工操作。
* **开发范围 (Scope)**:
* 全局一份 Cloudflare 连接,支持从现有 Cloudflare DNS 账号导入或独立录入 API Token。
* 指向分组、成员、主/备/生效节点、成员橙云、同步状态与错误信息。
* Cloudflare Zone/DNS Record HTTP 客户端与单成员幂等 reconcile。
* 手动同步、成员/分组变更同步、节点 IP 变化 best-effort 入队。
* 管理 API、Swagger、前端总览/设置/分组列表/分组详情和侧边栏入口。
* **Out of Scope**:自动故障切换/回切、AAAA、多 A 负载、CNAME、定时全量对账、非 Cloudflare DNS 厂商、多 Cloudflare 账号并行。
## 2. 设计与决策 (Design & Decisions)
### 核心对象/数据模型
* `of_cf_connections`:全局连接;`source` 为 `dns_account` 或 `standalone`,独立 Token 使用现有 `enc:v1:` 密文格式,响应永不暴露凭据。
* `of_cf_pointing_groups`:分组名、主节点、可选备用节点、生效节点、默认橙云和启用状态;一期 `active_node_id = primary_node_id`。
* `of_cf_pointing_members`:分组、全局唯一 `zone_domain_id`、成员橙云、Cloudflare Zone/Record ID 缓存、期望 IP 与同步状态。
* PostgreSQL/SQLite 使用同版本 Goose DDL,不建立物理外键,关系字段显式索引,数据库默认值与 Go 零值一致。
### API 与鉴权设计
* 前缀 `/api/v1/d/cloudflare`,统一使用 `apiutil.AdminMiddlewares()`。
* 连接:`GET/PUT /connection`、`POST /connection/verify`、`POST /connection/clear`。
* 总览:`GET /overview`。
* 分组:`GET/POST /groups`、`GET /groups/:id`、`POST /groups/:id/update|delete|sync`。
* 成员:`GET/POST /groups/:id/members`、`POST /groups/:id/members/:memberId/update|remove|sync`。
* 可用域名:`GET /domains/available`。
* 成功统一 HTTP 200 + `response.OK`;失败通过 `response.Abort*` 交由全局中间件写出。
### 数据流与架构图
```mermaid
flowchart LR
UI[Cloudflare 管理页面] --> API[/api/v1/d/cloudflare]
API --> Logic[cloudflare 业务逻辑]
Logic --> Repo[repository]
Repo --> DB[(PG / SQLite)]
Logic --> Queue[Asynq]
Queue --> Worker[Cloudflare 同步 Handler]
Worker --> Reconcile[成员 Reconcile]
Reconcile --> CF[Cloudflare Zone / DNS API]
Reconcile --> Repo
Node[节点手动更新或心跳] --> Queue
```
### 设计决策权衡
* 使用标准库 `net/http` 自建最小 Cloudflare 客户端,避免引入覆盖面过大的 SDK;接口只暴露 verify、Zone 查找和 A 记录 CRUD,便于 mock。
* 单成员同步采用进程内 keyed mutex 防止同一 Worker 进程并发双写;数据库状态在调用远端前标记 `syncing`,完成后写回 `ok/error`。
* 整组、按节点和常规变更统一通过 Asynq 投递单成员任务;请求路径只做校验和状态变更,避免管理 API 被远端网络延迟阻塞。连接测试是唯一同步调用 Cloudflare 的管理操作。
* 删除成员/分组默认先删除已缓存或唯一同名 A 记录,再删除本地记录;远端删除失败时保留本地成员并返回可读错误,避免失去重试依据。
* 将 TLS 包内的敏感字段加解密提取为 `internal/apps/openflare/credential`,保持既有密文兼容并让 Cloudflare 复用,避免业务包重复实现凭据存储。
## 3. 具体修改文件清单 (Proposed Changes)
### Task 1:凭据共享与数据库模型
**测试先行**:验证旧明文、`enc:v1:` 密文、无 SessionSecret 和缺少密钥时的兼容行为;验证迁移能创建三张表和唯一索引。
* **[NEW]** `internal/apps/openflare/credential/sensitive.go`、`sensitive_test.go`:提供 `Seal` / `Open`。
* **[MODIFY]** `internal/apps/openflare/tls/sensitive.go` 及调用点:委派到共享凭据包,保留 TLS 对外行为。
* **[NEW]** `internal/model/openflare_cloudflare.go`:连接、分组、成员实体和同步状态常量。
* **[NEW]** `internal/infra/persistence/migrator/goose/{postgres,sqlite}/202608040001_create_cloudflare_pointing.sql`。
* **[MODIFY]** `internal/infra/persistence/migrator/migrator_test.go`:检查表、索引和唯一约束。
### Task 2:Repository 与 Cloudflare HTTP 客户端
**测试先行**:覆盖连接 upsert/clear、分组/成员 CRUD、可用域名、按 active node 查询成员;使用 `httptest.Server` 覆盖 Token verify、Zone 查找、A 记录 list/create/update/delete、API 错误和 429 `Retry-After`。
* **[NEW]** `internal/repository/openflare_cloudflare.go`、`openflare_cloudflare_test.go`:唯一持久化入口和必要事务。
* **[NEW]** `internal/apps/openflare/cloudflare/client.go`、`client_test.go`:最小 Cloudflare API 接口与 HTTP 实现。
* **[NEW]** `internal/apps/openflare/cloudflare/types.go`、`errs.go`:输入/输出 DTO、内部状态和用户可见错误常量。
### Task 3:Reconcile、业务逻辑与异步任务
**测试先行**:覆盖 Token 来源解析、0/1/多条同名 A、缓存 Record ID 失效回退、非法 IPv4、成员默认橙云初始化、成员更新、移出删除远端、分组变更入队、按节点 IP 变更入队和同成员串行执行。
* **[NEW]** `internal/apps/openflare/cloudflare/reconcile.go`、`reconcile_test.go`:单成员期望状态计算与幂等同步。
* **[NEW]** `internal/apps/openflare/cloudflare/logics.go`、`logics_test.go`:连接、总览、分组、成员业务编排。
* **[NEW]** `internal/apps/openflare/cloudflare/tasks.go`、`tasks_test.go`:`cloudflare:sync_member`、`sync_group`、`sync_by_node` Handler、Meta、payload 校验与投递函数。
* **[MODIFY]** `internal/infra/task/handlers/register.go`:集中注册 Cloudflare 任务。
* **[MODIFY]** `internal/apps/openflare/node/logics.go`、`internal/apps/openflare/agent/logics.go`:节点 IP 真正变化后 best-effort 投递,不阻断原流程;失败记录日志。
### Task 4:管理 API 与 Swagger
**测试先行**:使用 Gin 测试覆盖管理员路由、参数绑定、404/409/未就绪映射、Token 响应脱敏和主要成功响应。
* **[NEW]** `internal/apps/openflare/cloudflare/routers.go`、`routers_test.go`:Handlers 与 Swagger 注释。
* **[NEW]** `internal/router/v1/openflare/register_cloudflare.go`。
* **[MODIFY]** `internal/router/v1/openflare/v1.go`:注册 Cloudflare 路由委派。
* **[GENERATED]** `docs/docs.go`、`docs/swagger.json`、`docs/swagger.yaml`:运行 `make swagger` 生成。
### Task 5:前端服务、导航与页面
**测试先行**:覆盖 service 路径/载荷、未就绪引导、连接配置不回显 Token、分组创建、成员添加/橙云更新、同步与删除确认。
* **[NEW]** `frontend/lib/services/openflare/cloudflare.service.ts`。
* **[MODIFY]** `frontend/lib/services/openflare/types.ts`、`index.ts`:类型、导出和 `openflareServices.cloudflare`。
* **[MODIFY]** `frontend/lib/navigation/openflare-nav.ts`:网站管理组增加 Cloudflare 入口与子路由高亮。
* **[NEW]** `frontend/app/(main)/cloudflare/page.tsx`:总览和就绪门禁。
* **[NEW]** `frontend/app/(main)/cloudflare/settings/page.tsx`:DNS 账号导入/独立 Token 配置与连接测试。
* **[NEW]** `frontend/app/(main)/cloudflare/groups/page.tsx`:分组列表、创建、同步、删除确认。
* **[NEW]** `frontend/app/(main)/cloudflare/groups/[id]/page.tsx` 及邻近 `components/`:分组配置、成员列表、添加/更新/同步/移除。
* **[NEW]** `frontend/tests/cloudflare/*.test.ts(x)`:服务和关键交互测试。
### Task 6:设计边界、变更日志与收尾
* **[MODIFY]** `docs/design/architecture.md`、`docs/design/index.md`:补充 Cloudflare 可选控制面能力与阅读入口。
* **[MODIFY]** `docs/changelog/index.md`:在 `[Unreleased]` 添加中文用户可见条目。
* **[MODIFY]** `docs/plan/index.md`:登记本计划;完成时保留计划并标记状态。
## 4. 验证计划 (Verification Plan)
### 自动化单元测试
* `go test ./internal/apps/openflare/credential ./internal/apps/openflare/cloudflare ./internal/repository ./internal/infra/persistence/migrator ./internal/apps/openflare/node ./internal/apps/openflare/agent`
* `pnpm --dir frontend test -- --run frontend/tests/cloudflare`
* `go test ./...`
### 生成与质量门禁
* `make license`
* `make swagger`
* `make format`
* `make code-check`
### 手动验收路径
1. 在 `/cloudflare/settings` 选择现有 Cloudflare DNS 账号或录入独立 Token,测试连接成功。
2. 在 `/cloudflare/groups` 新建分组,选择具有合法 IPv4 的 edge 节点。
3. 在详情页加入 ZoneDomain,观察状态从 `pending/syncing` 变为 `ok`,Cloudflare 上出现单条 A 记录。
4. 修改成员橙云并同步,确认远端 `proxied` 与期望一致。
5. 构造同名多 A,确认同步失败并提示先在 Cloudflare 清理。
6. 移出成员,确认默认删除本模块管理的远端 A;修改节点 IP 后确认相关成员重新入队。
## 5. 实施结果与验证记录
* 已完成共享凭据加密、双数据库迁移、repository、Cloudflare HTTP 客户端、成员 reconcile、三类异步任务、管理 API、节点 IP 变化联动、前端服务与四级管理页面。
* 删除远端记录时,缓存 Record ID 失效会回退到唯一同名 A;停用分组内修改成员只标记 `pending`,不投递必然失败的同步任务。
* 已运行 `make license`、`make swagger`、`make format`;Swagger 已生成 Cloudflare 管理接口。
* `go test ./...` 通过。
* `make code-check` 通过,包含架构守卫、golangci-lint、TypeScript 与 ESLint。
* `pnpm exec vitest run tests/cloudflare` 通过(2 个测试文件、2 个测试)。
* 前端全量 Vitest 为 20/21 个测试文件、106/107 个测试通过;唯一失败为既存 `tests/zone/zone-page.test.tsx` 仍断言页面展示“唯一访问者”,与本功能无关且在本任务基线中已存在。
+2
View File
@@ -24,6 +24,8 @@
## 已完成的计划
* [Cloudflare DNS 指向](./20260804-cloudflare-pointing.md):已完成连接配置、分组与成员管理、单 A 记录幂等同步、节点 IP 变化联动、异步任务和管理页面。
* [model / repository 分层治理](./20260724-model-repository-layering.md):model 无 IO;repository 唯一持久化;已完成 OpenFlare/平台 CRUD 迁入 repository。
* [Pages 项目部署源与 GitHub Releases 自动更新 V2](./20260719-pages-source-sync-v2.md):已完成 Remote URL / GitHub Release 来源、不可变部署、自动检查更新与安全回滚,并预留独立仓库构建 Provider 边界;生产环境验收边界见计划内验证记录。
+1030
View File
File diff suppressed because it is too large Load Diff
+608
View File
@@ -295,6 +295,148 @@ definitions:
- solutions
- token
type: object
cloudflare.AvailableDomain:
properties:
domain:
type: string
id:
type: integer
zone_id:
type: integer
type: object
cloudflare.ConnectionInput:
properties:
api_token:
type: string
dns_account_id:
type: integer
source:
type: string
type: object
cloudflare.ConnectionView:
properties:
configured:
type: boolean
dns_account_id:
type: integer
ready:
type: boolean
source:
type: string
status:
type: string
verified_at:
type: string
type: object
cloudflare.GroupDetail:
properties:
group:
$ref: '#/definitions/cloudflare.GroupItem'
members:
items:
$ref: '#/definitions/cloudflare.MemberItem'
type: array
type: object
cloudflare.GroupInput:
properties:
backup_node_id:
type: integer
default_proxied:
type: boolean
enabled:
type: boolean
name:
type: string
primary_node_id:
type: integer
type: object
cloudflare.GroupItem:
properties:
active_node:
$ref: '#/definitions/cloudflare.NodeOption'
backup_node:
$ref: '#/definitions/cloudflare.NodeOption'
created_at:
type: string
default_proxied:
type: boolean
enabled:
type: boolean
id:
type: integer
member_count:
type: integer
name:
type: string
primary_node:
$ref: '#/definitions/cloudflare.NodeOption'
updated_at:
type: string
type: object
cloudflare.MemberCreateInput:
properties:
proxied:
type: boolean
zone_domain_id:
type: integer
type: object
cloudflare.MemberItem:
properties:
desired_ip:
type: string
domain:
type: string
group_id:
type: integer
id:
type: integer
last_error:
type: string
proxied:
type: boolean
sync_status:
type: string
synced_at:
type: string
zone_domain_id:
type: integer
zone_id:
type: integer
type: object
cloudflare.MemberUpdateInput:
properties:
proxied:
type: boolean
type: object
cloudflare.NodeOption:
properties:
id:
type: integer
ip:
type: string
name:
type: string
type: object
cloudflare.Overview:
properties:
connection:
$ref: '#/definitions/cloudflare.ConnectionView'
error_count:
type: integer
group_count:
type: integer
member_count:
type: integer
ok_count:
type: integer
pending_count:
type: integer
type: object
cloudflare.SyncReceipt:
properties:
task_id:
type: string
type: object
config_version.CleanupInput:
properties:
keep_count:
@@ -7693,6 +7835,472 @@ paths:
summary: 清理配置下发日志
tags:
- openflare-apply-log
/api/v1/d/cloudflare/connection:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.ConnectionView'
type: object
security:
- SessionCookie: []
summary: 获取 Cloudflare 连接
tags:
- openflare-cloudflare
put:
consumes:
- application/json
parameters:
- description: 连接参数
in: body
name: body
required: true
schema:
$ref: '#/definitions/cloudflare.ConnectionInput'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.ConnectionView'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 保存 Cloudflare 连接
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/connection/clear:
post:
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 清除 Cloudflare 连接
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/connection/verify:
post:
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.ConnectionView'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 测试 Cloudflare 连接
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/domains/available:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
items:
$ref: '#/definitions/cloudflare.AvailableDomain'
type: array
type: object
security:
- SessionCookie: []
summary: 获取可加入 Cloudflare 指向的域名
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
items:
$ref: '#/definitions/cloudflare.GroupItem'
type: array
type: object
security:
- SessionCookie: []
summary: 获取 Cloudflare 指向分组
tags:
- openflare-cloudflare
post:
consumes:
- application/json
parameters:
- description: 分组参数
in: body
name: body
required: true
schema:
$ref: '#/definitions/cloudflare.GroupInput'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.GroupItem'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 创建 Cloudflare 指向分组
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups/{id}:
get:
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.GroupDetail'
type: object
"404":
description: Not Found
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 获取 Cloudflare 指向分组详情
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups/{id}/delete:
post:
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Any'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.Any'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 删除 Cloudflare 指向分组
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups/{id}/members:
get:
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
items:
$ref: '#/definitions/cloudflare.MemberItem'
type: array
type: object
security:
- SessionCookie: []
summary: 获取 Cloudflare 指向分组成员
tags:
- openflare-cloudflare
post:
consumes:
- application/json
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
- description: 成员参数
in: body
name: body
required: true
schema:
$ref: '#/definitions/cloudflare.MemberCreateInput'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.MemberItem'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.Any'
"409":
description: Conflict
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 添加 Cloudflare 指向成员
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups/{id}/members/{memberId}/remove:
post:
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
- description: 成员 ID
in: path
name: memberId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 移出 Cloudflare 指向成员
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups/{id}/members/{memberId}/sync:
post:
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
- description: 成员 ID
in: path
name: memberId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.SyncReceipt'
type: object
security:
- SessionCookie: []
summary: 同步 Cloudflare 指向成员
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups/{id}/members/{memberId}/update:
post:
consumes:
- application/json
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
- description: 成员 ID
in: path
name: memberId
required: true
type: integer
- description: 成员参数
in: body
name: body
required: true
schema:
$ref: '#/definitions/cloudflare.MemberUpdateInput'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.MemberItem'
type: object
security:
- SessionCookie: []
summary: 更新 Cloudflare 指向成员
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups/{id}/sync:
post:
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.SyncReceipt'
type: object
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 同步 Cloudflare 指向分组
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/groups/{id}/update:
post:
consumes:
- application/json
parameters:
- description: 分组 ID
in: path
name: id
required: true
type: integer
- description: 分组参数
in: body
name: body
required: true
schema:
$ref: '#/definitions/cloudflare.GroupInput'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.GroupItem'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.Any'
"404":
description: Not Found
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 更新 Cloudflare 指向分组
tags:
- openflare-cloudflare
/api/v1/d/cloudflare/overview:
get:
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/cloudflare.Overview'
type: object
security:
- SessionCookie: []
summary: 获取 Cloudflare 指向总览
tags:
- openflare-cloudflare
/api/v1/d/config-versions:
get:
description: 返回所有已发布的 OpenResty 配置版本摘要,按创建时间倒序排列,需要管理员权限