From a0cb11c28f74fbf744c208cf7477fb30e63b72b5 Mon Sep 17 00:00:00 2001 From: xuans Date: Tue, 29 Sep 2026 21:15:00 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=90=8C=E6=AD=A5=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E5=9B=9E=E5=BD=92=E6=B5=8B=E8=AF=95=E5=B9=B6=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E8=BF=9B=E5=BA=A6=E6=B8=85=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 补充同步证书申请的项目权限与 DNS 凭据权限回归测试,记录后端与前端验证结果,并保持 P0-03 待复审状态。 --- backend/internal/httpapi/review_test.go | 73 ++++++++++++++++++++++++- doc/Scert开发任务清单.md | 12 ++++ doc/Scert整改任务执行清单.md | 12 ++++ doc/Scert整改合并优化清单.md | 12 ++++ doc/基础整改任务规格.md | 12 ++++ 5 files changed, 120 insertions(+), 1 deletion(-) diff --git a/backend/internal/httpapi/review_test.go b/backend/internal/httpapi/review_test.go index 6d213e7..dffd590 100644 --- a/backend/internal/httpapi/review_test.go +++ b/backend/internal/httpapi/review_test.go @@ -17,6 +17,7 @@ import ( "git.pcux.cn/xuans/Scert/backend/internal/config" "git.pcux.cn/xuans/Scert/backend/internal/deployment" "git.pcux.cn/xuans/Scert/backend/internal/domain" + "git.pcux.cn/xuans/Scert/backend/internal/repository" ) type stubDomainRepository struct { @@ -216,9 +217,13 @@ func TestUpdateDomainRejectsInvalidEnvironment(t *testing.T) { func TestIssueDomainUsesCertificateWorkflow(t *testing.T) { cfg := readyTestConfig(t.TempDir()) + repo := &stubDomainRepository{loaded: domain.Domain{ID: "domain-1", ResourceScope: domain.ResourceScope{ProjectID: domain.DefaultProjectID}}} calledID := "" server := New(Dependencies{ - Config: cfg, Repository: &stubDomainRepository{}, + Config: cfg, + Repository: repo, + ProjectResources: projectResourceReaderStub{domains: repo}, + ProjectDomains: projectDomainRepositoryStub{DomainRepository: repo}, IssueCertificate: func(_ context.Context, id string) (certificate.IssueResult, deployment.Report, error) { calledID = id return certificate.IssueResult{DomainID: id}, deployment.Report{Status: "success"}, nil @@ -230,3 +235,69 @@ func TestIssueDomainUsesCertificateWorkflow(t *testing.T) { t.Fatalf("证书申请接口响应错误:%d %s", response.Code, response.Body.String()) } } + +func TestSynchronousIssueRequiresProjectPermissions(t *testing.T) { + cfg := readyTestConfig(t.TempDir()) + repo := &stubDomainRepository{loaded: domain.Domain{ID: "domain-1", ResourceScope: domain.ResourceScope{ProjectID: "project-a"}}} + calls := 0 + server := New(Dependencies{ + Config: cfg, + Repository: repo, + ProjectResources: projectResourceReaderStub{domains: repo}, + ProjectDomains: projectDomainRepositoryStub{ + DomainRepository: repo, + authorize: func(_ context.Context, _ string, _ string, permission domain.ProjectPermission) error { + if permission == domain.PermissionCertificateManage { + return repository.ErrProjectAccessDenied + } + return nil + }, + }, + IssueCertificate: func(_ context.Context, _ string) (certificate.IssueResult, deployment.Report, error) { + calls++ + return certificate.IssueResult{}, deployment.Report{}, nil + }, + }) + + response := httptest.NewRecorder() + serveAdminHTTP(server, response, httptest.NewRequest(http.MethodPost, "/api/v1/domains/domain-1/issue", nil)) + if response.Code != http.StatusForbidden { + t.Fatalf("同步证书申请缺少项目权限时未拒绝:%d %s", response.Code, response.Body.String()) + } + if calls != 0 { + t.Fatalf("同步证书申请权限拒绝后仍调用证书工作流:%d", calls) + } +} + +func TestSynchronousIssueRequiresDNSCredentialPermission(t *testing.T) { + cfg := readyTestConfig(t.TempDir()) + repo := &stubDomainRepository{loaded: domain.Domain{ID: "domain-1", ResourceScope: domain.ResourceScope{ProjectID: "project-a"}}} + calls := 0 + server := New(Dependencies{ + Config: cfg, + Repository: repo, + ProjectResources: projectResourceReaderStub{domains: repo}, + ProjectDomains: projectDomainRepositoryStub{DomainRepository: repo}, + ProjectMembers: permissionProjectMemberRepository{ + allow: func(permission domain.ProjectPermission) error { + if permission == domain.PermissionDNSCredentialUse { + return repository.ErrProjectAccessDenied + } + return nil + }, + }, + IssueCertificate: func(_ context.Context, _ string) (certificate.IssueResult, deployment.Report, error) { + calls++ + return certificate.IssueResult{}, deployment.Report{}, nil + }, + }) + + response := httptest.NewRecorder() + serveAdminHTTP(server, response, httptest.NewRequest(http.MethodPost, "/api/v1/domains/domain-1/issue", nil)) + if response.Code != http.StatusForbidden { + t.Fatalf("同步证书申请缺少 DNS 凭据权限时未拒绝:%d %s", response.Code, response.Body.String()) + } + if calls != 0 { + t.Fatalf("DNS 凭据权限拒绝后仍调用证书工作流:%d", calls) + } +} diff --git a/doc/Scert开发任务清单.md b/doc/Scert开发任务清单.md index 8c3c013..51c77ec 100644 --- a/doc/Scert开发任务清单.md +++ b/doc/Scert开发任务清单.md @@ -3451,3 +3451,15 @@ Linux Ubuntu 22.04 上的 `Scert-admin` 手动启停、无开机自启动、无 - [x] 已提交 35260bc、aa587d3;最后一次推送成功。 - [~] P0-07 总项仍在进行中,其他资源写入、三库矩阵、浏览器、远端部署和生产验证仍需继续。 - [!] 总体验收位置保持 **P0-03 完成,待复审**,不得提前标记复审通过。 + +## 本轮开发进度(2026-09-29) + +总体验收位置继续保持 **P0-03:完成,待复审**,本轮仅推进 P0-07 的同步证书申请权限闭环,不将局部自动化测试结果视为生产部署验收通过。 + +- `[x]` 无任务仓储的同步证书申请路径已补齐项目资源可见性、`certificate.manage`、`deployment.execute` 与 DNS 凭据使用权限校验。 +- `[x]` 已补充项目证书权限不足、DNS 凭据使用权限不足及权限拒绝后不调用证书工作流的回归测试。 +- `[x]` 当前候选后端 `go test ./...`、`go vet ./...` 通过;该结果仅代表本地自动化验证,不代表三数据库、浏览器、远端服务器或生产部署验收通过。 +- `[~]` P0-07 其他资源写入权限、三数据库矩阵、浏览器清缓存验收、密码 SSH、远端部署及 Linux/Windows 生产服务仍需继续开发或复审。 +- `[!]` 总体验收不得升级,P0-03 仍为“完成,待复审”。 + +下一步继续执行前端回归与生产构建,再提交并推送本轮测试代码;完成开发阶段后,统一进行三数据库、浏览器、远端服务器和生产部署测试。 \ No newline at end of file diff --git a/doc/Scert整改任务执行清单.md b/doc/Scert整改任务执行清单.md index 0021d2a..6767bb3 100644 --- a/doc/Scert整改任务执行清单.md +++ b/doc/Scert整改任务执行清单.md @@ -747,3 +747,15 @@ P0-05 从 `[!]` 调整为 `[~]`,并未标记完成;P0-04 剩余门禁和全 - [x] 已提交 35260bc、aa587d3,最后一次远程推送成功。 - [~] P0-07 继续进行;待完成三数据库矩阵、浏览器、SSH/HTTPS、远端部署和生产门禁。 - [!] 总体验收仍停在 **P0-03 完成,待复审**,不能将局部测试结果写成生产验收通过。 + +## 本轮开发进度(2026-09-29) + +总体验收位置继续保持 **P0-03:完成,待复审**,本轮仅推进 P0-07 的同步证书申请权限闭环,不将局部自动化测试结果视为生产部署验收通过。 + +- `[x]` 无任务仓储的同步证书申请路径已补齐项目资源可见性、`certificate.manage`、`deployment.execute` 与 DNS 凭据使用权限校验。 +- `[x]` 已补充项目证书权限不足、DNS 凭据使用权限不足及权限拒绝后不调用证书工作流的回归测试。 +- `[x]` 当前候选后端 `go test ./...`、`go vet ./...` 通过;该结果仅代表本地自动化验证,不代表三数据库、浏览器、远端服务器或生产部署验收通过。 +- `[~]` P0-07 其他资源写入权限、三数据库矩阵、浏览器清缓存验收、密码 SSH、远端部署及 Linux/Windows 生产服务仍需继续开发或复审。 +- `[!]` 总体验收不得升级,P0-03 仍为“完成,待复审”。 + +下一步继续执行前端回归与生产构建,再提交并推送本轮测试代码;完成开发阶段后,统一进行三数据库、浏览器、远端服务器和生产部署测试。 \ No newline at end of file diff --git a/doc/Scert整改合并优化清单.md b/doc/Scert整改合并优化清单.md index da8065d..ba295a5 100644 --- a/doc/Scert整改合并优化清单.md +++ b/doc/Scert整改合并优化清单.md @@ -1387,3 +1387,15 @@ P0-11 生产验收门禁 - [x] 本轮提交 35260bc、aa587d3 已提交;本轮最后一次推送成功。 - [~] P0-07 仍为并行开发,任务重试子项完成待复审;三数据库矩阵、浏览器、SSH、远端部署、生产部署和完整权限联动仍未完成。 - [!] 当前总体验收位置仍为 **P0-03 完成,待复审**;本轮自动化测试和源码开发不构成生产部署验收通过。 + +## 本轮开发进度(2026-09-29) + +总体验收位置继续保持 **P0-03:完成,待复审**,本轮仅推进 P0-07 的同步证书申请权限闭环,不将局部自动化测试结果视为生产部署验收通过。 + +- `[x]` 无任务仓储的同步证书申请路径已补齐项目资源可见性、`certificate.manage`、`deployment.execute` 与 DNS 凭据使用权限校验。 +- `[x]` 已补充项目证书权限不足、DNS 凭据使用权限不足及权限拒绝后不调用证书工作流的回归测试。 +- `[x]` 当前候选后端 `go test ./...`、`go vet ./...` 通过;该结果仅代表本地自动化验证,不代表三数据库、浏览器、远端服务器或生产部署验收通过。 +- `[~]` P0-07 其他资源写入权限、三数据库矩阵、浏览器清缓存验收、密码 SSH、远端部署及 Linux/Windows 生产服务仍需继续开发或复审。 +- `[!]` 总体验收不得升级,P0-03 仍为“完成,待复审”。 + +下一步继续执行前端回归与生产构建,再提交并推送本轮测试代码;完成开发阶段后,统一进行三数据库、浏览器、远端服务器和生产部署测试。 \ No newline at end of file diff --git a/doc/基础整改任务规格.md b/doc/基础整改任务规格.md index 1fee142..465a68d 100644 --- a/doc/基础整改任务规格.md +++ b/doc/基础整改任务规格.md @@ -336,3 +336,15 @@ P0-06 与 P0-07 均维持 `[~]`,六阶段中的隔离、生产和最终验收 - [x] 当前本地自动化验证已通过:后端全量测试、静态检查、前端 230 项测试和生产构建。 - [~] P0-07 的其他资源权限、三数据库、浏览器、SSH、远端部署和生产验收仍未闭环。 - [!] 总体验收仍为 **P0-03 完成,待复审**;本节开发证据不替代实机生产验收证据。 + +## 本轮开发进度(2026-09-29) + +总体验收位置继续保持 **P0-03:完成,待复审**,本轮仅推进 P0-07 的同步证书申请权限闭环,不将局部自动化测试结果视为生产部署验收通过。 + +- `[x]` 无任务仓储的同步证书申请路径已补齐项目资源可见性、`certificate.manage`、`deployment.execute` 与 DNS 凭据使用权限校验。 +- `[x]` 已补充项目证书权限不足、DNS 凭据使用权限不足及权限拒绝后不调用证书工作流的回归测试。 +- `[x]` 当前候选后端 `go test ./...`、`go vet ./...` 通过;该结果仅代表本地自动化验证,不代表三数据库、浏览器、远端服务器或生产部署验收通过。 +- `[~]` P0-07 其他资源写入权限、三数据库矩阵、浏览器清缓存验收、密码 SSH、远端部署及 Linux/Windows 生产服务仍需继续开发或复审。 +- `[!]` 总体验收不得升级,P0-03 仍为“完成,待复审”。 + +下一步继续执行前端回归与生产构建,再提交并推送本轮测试代码;完成开发阶段后,统一进行三数据库、浏览器、远端服务器和生产部署测试。 \ No newline at end of file