Scert/backend/internal/repository/history_scope.go
xuans 0ccdb14b26 完善任务审计范围快照与身份关联并同步整改进度
新增三库第13号迁移和历史范围回填,保留已删除资源的任务与审计。补充仓储、调用链、身份来源及迁移失败重试回归,同步任务清单、支持矩阵和运维边界。项目成员授权与生产验收仍待完成。
2026-09-28 11:48:27 +08:00

72 lines
2.2 KiB
Go

package repository
import (
"context"
"database/sql"
"errors"
)
const (
ScopeProject = "project"
ScopeSystem = "system"
ScopeUnknown = "unknown"
ManagementResourceID = "management-certificate"
)
// 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
}