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, }) }