收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
73
internal/infrastructure/audit/polling.go
Normal file
73
internal/infrastructure/audit/polling.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package audit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
pkgerrors "github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
)
|
||||
|
||||
// PollingInput 描述轮询配置、规则或人工任务的审计事实。
|
||||
type PollingInput struct {
|
||||
EventID string
|
||||
ActionCode string
|
||||
Summary string
|
||||
ResourceType string
|
||||
ResourceID uint
|
||||
ResourceKey string
|
||||
DisplayName string
|
||||
OperatorID uint
|
||||
IdentitySnapshot map[string]any
|
||||
BeforeData map[string]any
|
||||
AfterData map[string]any
|
||||
Metadata map[string]any
|
||||
Cards []*model.IotCard
|
||||
Result string
|
||||
ErrorCode string
|
||||
ErrorSummary string
|
||||
}
|
||||
|
||||
// WritePolling 将轮询配置、规则或人工任务转换为统一 Audit Event。
|
||||
func (w *Writer) WritePolling(ctx context.Context, tx *gorm.DB, input PollingInput) error {
|
||||
if input.OperatorID == 0 || input.ResourceType == "" || input.ResourceKey == "" {
|
||||
return pkgerrors.New(pkgerrors.CodeInvalidParam, "轮询审计资源或操作者不完整")
|
||||
}
|
||||
resourceID := optionalResourceID(input.ResourceID)
|
||||
resources := []ResourceInput{{
|
||||
Type: input.ResourceType, ID: resourceID, Key: input.ResourceKey, DisplayName: input.DisplayName,
|
||||
Relation: constants.AuditResourceRelationPrimary, Role: constants.AuditResourceRolePollingTarget,
|
||||
IdentitySnapshot: input.IdentitySnapshot, BeforeData: input.BeforeData, AfterData: input.AfterData,
|
||||
SubjectVisibility: constants.AuditSubjectInternalOnly,
|
||||
}}
|
||||
for index, card := range input.Cards {
|
||||
if card == nil || card.ID == 0 {
|
||||
continue
|
||||
}
|
||||
resources = append(resources, ResourceInput{
|
||||
Type: constants.AuditResourceIotCard, ID: optionalResourceID(card.ID),
|
||||
Key: iotCardResourceKey(card), DisplayName: card.ICCID,
|
||||
Relation: constants.AuditResourceRelationReference, Role: constants.AuditResourceRolePollingCard,
|
||||
IdentitySnapshot: iotCardIdentity(card), SubjectVisibility: constants.AuditSubjectInternalOnly,
|
||||
SortOrder: index + 1,
|
||||
})
|
||||
}
|
||||
result := input.Result
|
||||
if result == "" {
|
||||
result = constants.AuditResultSuccess
|
||||
}
|
||||
return w.Append(ctx, tx, AppendInput{
|
||||
EventID: input.EventID, ActionCode: input.ActionCode, Summary: input.Summary,
|
||||
Actor: ActorInput{
|
||||
Kind: constants.AuditActorAccount, ID: strconv.FormatUint(uint64(input.OperatorID), 10),
|
||||
Name: middleware.GetUsernameFromContext(ctx),
|
||||
},
|
||||
Source: constants.AuditSourceAdminAPI, ScopeType: constants.AuditScopePlatform,
|
||||
Result: result, ErrorCode: input.ErrorCode, ErrorSummary: input.ErrorSummary,
|
||||
Metadata: input.Metadata, Resources: resources,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user