Scert/backend/internal/repository/history_scope.go
xuans 413a0e66a9 完成手动续期后台任务及权限隔离并更新回归进度
保留管理与业务续期调度,增加系统级幂等任务、取消传播和统计审计原子收尾;前端跟踪真实任务状态。原生 Linux 全后端、静态检查、相关专项二十次重复及前端二百七十二项测试和生产构建通过,未进行正式生产部署。
2026-10-02 21:32:30 +08:00

73 lines
2.3 KiB
Go

package repository
import (
"context"
"database/sql"
"errors"
)
const (
ScopeProject = "project"
ScopeSystem = "system"
ScopeUnknown = "unknown"
ManagementResourceID = "management-certificate"
RenewalCheckResourceID = "global-renewal-check"
)
// HistoryScope 保存事件发生时的范围,资源或项目删除后仍保留;不是项目授权凭证。
// 未知历史归属保持为空,不自动降级为系统范围,也不归入默认项目。
type HistoryScope struct {
ScopeType string `json:"scope_type"`
ProjectID string `json:"project_id"`
}
func (s HistoryScope) matches(actual HistoryScope) bool {
return (s.ScopeType == "" || s.ScopeType == actual.ScopeType) && (s.ProjectID == "" || s.ProjectID == actual.ProjectID)
}
func (r *SQLAuditRepository) resolveScope(ctx context.Context, item AuditLog) (HistoryScope, error) {
if item.TaskID != "" {
task, err := NewSQLTaskRepository(r.db, r.driver).GetTask(ctx, item.TaskID)
if err != nil {
return HistoryScope{}, err
}
valid := item.ResourceType == "task" && item.ResourceID == task.ID
if item.ResourceType == "domain" || item.ResourceType == "certificate" {
valid = task.ScopeType != ScopeSystem && item.ResourceID == task.DomainID
}
if item.ResourceType == "management_certificate" {
valid = task.ScopeType == ScopeSystem && item.ResourceID == ManagementResourceID
}
if !valid {
return HistoryScope{}, errors.New("审计任务与资源不匹配")
}
return task.HistoryScope, nil
}
var table string
switch item.ResourceType {
case "auth", "user", "super_admin":
return HistoryScope{ScopeType: ScopeSystem}, nil
case "management_certificate":
if item.ResourceID == ManagementResourceID {
return HistoryScope{ScopeType: ScopeSystem}, nil
}
case "domain", "certificate":
table = "domains"
case "server":
table = "servers"
}
result := HistoryScope{ScopeType: ScopeUnknown}
if table != "" {
err := r.db.QueryRowContext(ctx, r.query("SELECT project_id FROM "+table+" WHERE id = ?"), item.ResourceID).Scan(&result.ProjectID)
if errors.Is(err, sql.ErrNoRows) {
// 对不存在资源的失败操作也需要审计,但不能伪造其项目。
return result, nil
}
if err != nil {
return HistoryScope{}, err
}
result.ScopeType = ScopeProject
}
return result, nil
}