Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
92 lines
2.9 KiB
Go
92 lines
2.9 KiB
Go
package audit
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
pkgerrors "github.com/break/junhong_cmp_fiber/pkg/errors"
|
|
)
|
|
|
|
// TaskInput 描述导入、批购、失效或导出任务的安全审计事实。
|
|
type TaskInput struct {
|
|
EventID string
|
|
ActionCode string
|
|
Summary string
|
|
TaskID uint
|
|
TaskNo string
|
|
DisplayName string
|
|
Actor ActorInput
|
|
Source string
|
|
ScopeType string
|
|
ScopeID string
|
|
ScopeName string
|
|
Result string
|
|
ErrorCode string
|
|
ErrorSummary string
|
|
CorrelationID string
|
|
ParentEventID string
|
|
BatchTotal int
|
|
SuccessCount int
|
|
FailCount int
|
|
IdentitySnapshot map[string]any
|
|
BeforeData map[string]any
|
|
AfterData map[string]any
|
|
Metadata map[string]any
|
|
}
|
|
|
|
// WriteTask 将任务状态与批量统计写入对应的注册任务资源。
|
|
func (w *Writer) WriteTask(ctx context.Context, tx *gorm.DB, input TaskInput) error {
|
|
if w == nil || w.registry == nil {
|
|
return pkgerrors.New(pkgerrors.CodeInvalidStatus, "任务统一审计 Writer 未正确配置")
|
|
}
|
|
action, ok := w.registry.Action(input.ActionCode)
|
|
if !ok {
|
|
return pkgerrors.New(pkgerrors.CodeInvalidParam, "任务审计动作未注册")
|
|
}
|
|
if input.TaskNo == "" {
|
|
return pkgerrors.New(pkgerrors.CodeInvalidParam, "任务审计缺少稳定任务编号")
|
|
}
|
|
var taskID *string
|
|
if input.TaskID != 0 {
|
|
value := strconv.FormatUint(uint64(input.TaskID), 10)
|
|
taskID = &value
|
|
}
|
|
displayName := input.DisplayName
|
|
if displayName == "" {
|
|
displayName = input.TaskNo
|
|
}
|
|
return w.Append(ctx, tx, AppendInput{
|
|
EventID: input.EventID, ActionCode: input.ActionCode, Summary: input.Summary,
|
|
Actor: input.Actor, Source: input.Source,
|
|
ScopeType: input.ScopeType, ScopeID: input.ScopeID, ScopeName: input.ScopeName,
|
|
Result: input.Result, ErrorCode: input.ErrorCode, ErrorSummary: input.ErrorSummary,
|
|
CorrelationID: input.CorrelationID, ParentEventID: input.ParentEventID,
|
|
BatchTotal: input.BatchTotal, SuccessCount: input.SuccessCount, FailCount: input.FailCount,
|
|
Metadata: input.Metadata,
|
|
Resources: []ResourceInput{{
|
|
Type: action.PrimaryResource, ID: taskID, Key: input.TaskNo, DisplayName: displayName,
|
|
Relation: constants.AuditResourceRelationPrimary, Role: constants.AuditResourceRoleBatchTask,
|
|
IdentitySnapshot: input.IdentitySnapshot, BeforeData: input.BeforeData, AfterData: input.AfterData,
|
|
SubjectVisibility: constants.AuditSubjectInternalOnly,
|
|
}},
|
|
})
|
|
}
|
|
|
|
// TaskEventID 返回可重试任务阶段的稳定审计事件 ID。
|
|
func TaskEventID(resourceType string, taskID uint, phase string) string {
|
|
if taskID == 0 || phase == "" {
|
|
return ""
|
|
}
|
|
value := fmt.Sprintf("task:%s:%d:%s", resourceType, taskID, phase)
|
|
if len(value) <= 64 {
|
|
return value
|
|
}
|
|
digest := sha256.Sum256([]byte(value))
|
|
return fmt.Sprintf("task:%x", digest[:16])
|
|
}
|