Files
junhong_cmp_fiber/internal/service/iot_card/polling_audit.go
break c64f3d8b80
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m31s
全局审计完成
2026-08-07 11:02:52 +08:00

86 lines
3.9 KiB
Go

package iot_card
import (
"context"
"strconv"
"github.com/google/uuid"
"gorm.io/gorm"
infraAudit "github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
"github.com/break/junhong_cmp_fiber/internal/model"
assetAuditSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_audit"
"github.com/break/junhong_cmp_fiber/pkg/auditcontext"
"github.com/break/junhong_cmp_fiber/pkg/auditfailure"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
)
func (s *Service) appendPollingStatusAudit(ctx context.Context, tx *gorm.DB, card *model.IotCard, before, after bool) error {
return s.appendCardLifecycleAudit(ctx, tx, constants.AuditActionIotCardPollingStatusUpdated, "更新 IoT 卡轮询开关", constants.AuditResultSuccess, card,
map[string]any{"enable_polling": before}, map[string]any{"enable_polling": after}, nil)
}
func (s *Service) appendBatchPollingStatusAudit(ctx context.Context, tx *gorm.DB, cards []*model.IotCard, enablePolling bool) error {
if s.auditWriter == nil {
return errors.New(errors.CodeInvalidStatus, "IoT 卡统一审计接缝未配置")
}
linkage := auditcontext.From(ctx)
batchKey := linkage.RequestID
if batchKey == "" {
batchKey = uuid.NewString()
}
rootEventID := "evt_" + uuid.NewSHA1(uuid.NameSpaceOID, []byte("iot-card-polling-status:"+batchKey)).String()
children := make([]infraAudit.AppendInput, 0, len(cards))
for _, card := range cards {
if card == nil || card.ID == 0 {
continue
}
id := strconv.FormatUint(uint64(card.ID), 10)
children = append(children, infraAudit.AppendInput{
EventID: "evt_" + uuid.NewSHA1(uuid.NameSpaceOID, []byte(rootEventID+":"+id)).String(),
ActionCode: constants.AuditActionIotCardPollingStatusUpdated,
Summary: "批量更新 IoT 卡轮询开关",
Result: constants.AuditResultSuccess,
Resources: []infraAudit.ResourceInput{{
Type: constants.AuditResourceIotCard, ID: &id, Key: infraAudit.IotCardResourceKey(card), DisplayName: card.ICCID,
Relation: constants.AuditResourceRelationPrimary, Role: constants.AuditResourceRoleIotCardTarget,
IdentitySnapshot: infraAudit.IotCardIdentitySnapshot(card),
BeforeData: map[string]any{"enable_polling": card.EnablePolling}, AfterData: map[string]any{"enable_polling": enablePolling},
SubjectVisibility: constants.AuditSubjectResult, SubjectSummary: "IoT 卡轮询开关已更新",
}},
})
}
return s.auditWriter.AppendBatch(ctx, tx, infraAudit.BatchInput{
Root: infraAudit.AppendInput{
EventID: rootEventID,
ActionCode: constants.AuditActionIotCardPollingStatusBatchUpdated,
Summary: "批量更新 IoT 卡轮询开关", Result: constants.AuditResultSuccess,
BatchTotal: len(children), SuccessCount: len(children),
Resources: []infraAudit.ResourceInput{{
Type: constants.AuditResourceIotCardBatch, Key: batchKey, DisplayName: batchKey,
Relation: constants.AuditResourceRelationPrimary, Role: constants.AuditResourceRoleIotCardBatch,
IdentitySnapshot: map[string]any{"card_count": len(children), "enable_polling": enablePolling},
SubjectVisibility: constants.AuditSubjectInternalOnly,
}},
},
Children: children,
})
}
func (s *Service) recordPollingStatusFailure(ctx context.Context, actionCode, result string, card *model.IotCard, enablePolling bool, businessErr error) {
if card == nil || card.ID == 0 || s.db == nil || s.auditWriter == nil {
return
}
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
return s.appendCardLifecycleAudit(ctx, tx, actionCode, "更新 IoT 卡轮询开关失败", result, card, nil,
map[string]any{"enable_polling": enablePolling}, businessErr)
})
if err == nil {
return
}
linkage := auditcontext.From(ctx)
errorCode, _ := assetAuditSvc.BuildErrorInfo(businessErr)
auditfailure.RecordSecondaryWriteFailure(actionCode, strconv.FormatUint(uint64(card.ID), 10), linkage.RequestID, linkage.CorrelationID, errorCode, err)
}