保留管理与业务续期调度,增加系统级幂等任务、取消传播和统计审计原子收尾;前端跟踪真实任务状态。原生 Linux 全后端、静态检查、相关专项二十次重复及前端二百七十二项测试和生产构建通过,未进行正式生产部署。
94 lines
4.4 KiB
Go
94 lines
4.4 KiB
Go
package repository
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestRenewalCheckScopeVisibilityAndCompletion(t *testing.T) {
|
|
repo, db := newTaskRepositoryTest(t)
|
|
defer db.Close()
|
|
ctx := t.Context()
|
|
for _, role := range []string{UserRoleSuperAdmin, UserRoleAdmin, UserRoleUser} {
|
|
if _, err := db.ExecContext(ctx, `INSERT INTO users (id, username, password_hash, role, status) VALUES (?, ?, 'test-hash', ?, 'active')`, role, role, role); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
task := Task{ID: "global-check", DomainID: RenewalCheckResourceID, TaskType: "renewal_check", Status: "queued", Stage: "queued", OperatorID: UserRoleSuperAdmin}
|
|
for _, forged := range []Task{
|
|
{ID: "forged-domain", DomainID: "domain-1", TaskType: "renewal_check", Status: "queued", Stage: "queued"},
|
|
{ID: "forged-management", DomainID: ManagementResourceID, TaskType: "renewal_check", Status: "queued", Stage: "queued"},
|
|
{ID: "forged-type", DomainID: RenewalCheckResourceID, TaskType: "certificate_issue", Status: "queued", Stage: "queued"},
|
|
{ID: "forged-project", DomainID: RenewalCheckResourceID, TaskType: "renewal_check", Status: "queued", Stage: "queued", HistoryScope: HistoryScope{ScopeType: ScopeProject, ProjectID: "default"}},
|
|
} {
|
|
if err := repo.CreateTask(ctx, forged); err == nil {
|
|
t.Fatalf("接受了伪造范围:%+v", forged)
|
|
}
|
|
}
|
|
if err := repo.CreateTask(ctx, task); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
duplicate := task
|
|
duplicate.ID = "duplicate-check"
|
|
if err := repo.CreateTask(ctx, duplicate); !errors.Is(err, ErrTaskAlreadyRunning) {
|
|
t.Fatalf("未拒绝重复检查:%v", err)
|
|
}
|
|
if err := repo.CreateAttempt(ctx, TaskAttempt{ID: "check-attempt", TaskID: task.ID, AttemptNumber: 1, Status: "running", Stage: "renewal_check"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, role := range []string{UserRoleAdmin, UserRoleUser} {
|
|
if _, err := repo.GetVisibleTask(ctx, role, task.ID); !errors.Is(err, sql.ErrNoRows) {
|
|
t.Fatalf("全局任务越权可见:%s %v", role, err)
|
|
}
|
|
if err := repo.RequestCancelVisibleTask(ctx, role, task.ID); !errors.Is(err, ErrProjectAccessDenied) {
|
|
t.Fatalf("全局任务越权取消:%s %v", role, err)
|
|
}
|
|
}
|
|
if stored, err := repo.GetVisibleTask(ctx, UserRoleSuperAdmin, task.ID); err != nil || stored.ScopeType != ScopeSystem || stored.ProjectID != "" {
|
|
t.Fatalf("系统范围丢失:%+v %v", stored, err)
|
|
}
|
|
completion := TaskCompletion{TaskID: task.ID, AttemptID: "check-attempt", Status: "success", Stage: "renewal_check", Message: "续期检查完成:检查 2 项,成功 1 项", FinishedAt: time.Now().UTC(), AuditAction: "renewal_check"}
|
|
if _, err := db.ExecContext(ctx, `CREATE TRIGGER reject_renewal_audit BEFORE INSERT ON audit_logs BEGIN SELECT RAISE(ABORT, 'injected failure'); END`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := repo.FinishTaskAttempt(ctx, completion); err == nil {
|
|
t.Fatal("审计失败未回滚")
|
|
}
|
|
stored, err := repo.GetTask(ctx, task.ID)
|
|
if err != nil || stored.Status != "queued" {
|
|
t.Fatalf("审计失败仍保存任务成功:%+v %v", stored, err)
|
|
}
|
|
attempts, err := repo.ListAttempts(ctx, task.ID)
|
|
if err != nil || len(attempts) != 1 || attempts[0].Status != "running" {
|
|
t.Fatalf("审计失败仍保存尝试成功:%+v %v", attempts, err)
|
|
}
|
|
if _, err := db.ExecContext(ctx, `DROP TRIGGER reject_renewal_audit`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := repo.FinishTaskAttempt(ctx, completion); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var scope, resourceType, resourceID, message string
|
|
if err := db.QueryRowContext(ctx, `SELECT scope_type, resource_type, resource_id, message FROM audit_logs WHERE task_id = ?`, task.ID).Scan(&scope, &resourceType, &resourceID, &message); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if scope != ScopeSystem || resourceType != "task" || resourceID != task.ID || message != completion.Message {
|
|
t.Fatalf("全局检查被伪装为管理证书或未记录摘要:%s %s %s %s", scope, resourceType, resourceID, message)
|
|
}
|
|
for _, role := range []string{UserRoleSuperAdmin, UserRoleAdmin, UserRoleUser} {
|
|
logs, err := NewSQLProjectMemberRepository(db).ListVisibleAuditLogs(ctx, role, 10)
|
|
want := 0
|
|
if role == UserRoleSuperAdmin {
|
|
want = 1
|
|
}
|
|
if err != nil || len(logs) != want {
|
|
t.Fatalf("全局续期审计可见性错误:%s %+v %v", role, logs, err)
|
|
}
|
|
}
|
|
if _, _, err := repo.RetryVisibleTask(ctx, UserRoleSuperAdmin, task.ID, nil); !errors.Is(err, ErrTaskNotRetryable) {
|
|
t.Fatalf("全局检查不应通用重试:%v", err)
|
|
}
|
|
}
|