收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展 Confidence: medium Scope-risk: broad Directive: 后续修改需保持审计事件与业务事务边界一致 Tested: git diff --cached --check Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
This commit is contained in:
@@ -2,11 +2,17 @@ package device_import
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
infraAudit "github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
assetAuditSvc "github.com/break/junhong_cmp_fiber/internal/service/asset_audit"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/auditfailure"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
)
|
||||
|
||||
// AssetAuditService 资产审计服务接口。
|
||||
@@ -14,62 +20,62 @@ type AssetAuditService interface {
|
||||
LogOperation(ctx context.Context, log *model.AssetOperationLog)
|
||||
}
|
||||
|
||||
func (s *Service) logDeviceImportAudit(ctx context.Context, p assetAuditSvc.BuildLogParams) {
|
||||
if s == nil || s.assetAudit == nil {
|
||||
func (s *Service) writeDeviceImportTaskAudit(ctx context.Context, tx *gorm.DB, task *model.DeviceImportTask, before, after map[string]any, result, phase, errorCode, errorSummary string) error {
|
||||
scopeType, scopeID := constants.AuditScopePlatform, ""
|
||||
if task.OperatorShopID != nil {
|
||||
scopeType, scopeID = constants.AuditScopeShop, strconv.FormatUint(uint64(*task.OperatorShopID), 10)
|
||||
}
|
||||
return s.auditWriter.WriteTask(ctx, tx, infraAudit.TaskInput{
|
||||
EventID: infraAudit.TaskEventID(constants.AuditResourceDeviceImportTask, task.ID, phase),
|
||||
ActionCode: constants.AuditActionDeviceImportTaskCreated, Summary: "创建设备导入任务",
|
||||
TaskID: task.ID, TaskNo: task.TaskNo,
|
||||
Actor: infraAudit.ActorInput{
|
||||
Kind: constants.AuditActorAccount, ID: strconv.FormatUint(uint64(middleware.GetUserIDFromContext(ctx)), 10),
|
||||
Name: middleware.GetUsernameFromContext(ctx), ShopID: task.OperatorShopID,
|
||||
},
|
||||
Source: constants.AuditSourceAdminAPI, ScopeType: scopeType, ScopeID: scopeID,
|
||||
Result: result, ErrorCode: errorCode, ErrorSummary: errorSummary,
|
||||
IdentitySnapshot: map[string]any{
|
||||
"id": task.ID, "task_no": task.TaskNo, "file_name": task.FileName,
|
||||
"operation_type": task.OperationType, "target_id": task.TargetID,
|
||||
"batch_no": task.BatchNo, "realname_policy": task.RealnamePolicy,
|
||||
},
|
||||
BeforeData: before, AfterData: after,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) recordDeviceImportTaskAudit(ctx context.Context, task *model.DeviceImportTask, before, after map[string]any, result, phase string, errorCode int, summary string) {
|
||||
if s == nil || s.db == nil || s.auditWriter == nil || task == nil || task.TaskNo == "" {
|
||||
return
|
||||
}
|
||||
if p.Operator.Type == "" {
|
||||
p.Operator = assetAuditSvc.OperatorFromContext(ctx)
|
||||
}
|
||||
if p.OperationType == "" {
|
||||
p.OperationType = constants.AssetAuditOpDeviceImportTaskCreate
|
||||
}
|
||||
if p.AssetType == "" {
|
||||
p.AssetType = constants.AssetTypeDevice
|
||||
}
|
||||
p.BeforeData, p.AfterData = assetAuditSvc.WrapOperationContent(p.BeforeData, p.AfterData, nil)
|
||||
s.assetAudit.LogOperation(ctx, assetAuditSvc.BuildLog(ctx, p))
|
||||
}
|
||||
|
||||
func newDeviceImportAuditParams(
|
||||
taskID uint,
|
||||
taskNo string,
|
||||
req *dto.ImportDeviceRequest,
|
||||
resultStatus string,
|
||||
err error,
|
||||
) assetAuditSvc.BuildLogParams {
|
||||
afterData := map[string]any{}
|
||||
if req != nil {
|
||||
afterData["batch_no"] = req.BatchNo
|
||||
afterData["file_key"] = req.FileKey
|
||||
afterData["realname_policy"] = req.RealnamePolicy
|
||||
}
|
||||
errorCode, errorMsg := assetAuditSvc.BuildErrorInfo(err)
|
||||
return assetAuditSvc.BuildLogParams{
|
||||
AssetID: taskID,
|
||||
AssetIdentifier: taskNo,
|
||||
OperationDesc: "创建设备导入任务",
|
||||
ResultStatus: resultStatus,
|
||||
ErrorCode: errorCode,
|
||||
ErrorMsg: errorMsg,
|
||||
AfterData: afterData,
|
||||
code := strconv.Itoa(errorCode)
|
||||
if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
return s.writeDeviceImportTaskAudit(ctx, tx, task, before, after, result, phase, code, summary)
|
||||
}); err != nil {
|
||||
auditfailure.RecordSecondaryWriteFailure(constants.AuditActionDeviceImportTaskCreated, task.TaskNo, "", task.TaskNo, code, err)
|
||||
}
|
||||
}
|
||||
|
||||
func newDeviceBatchAllocationAuditParams(taskID uint, taskNo string, req *dto.CreateDeviceBatchAllocationRequest, resultStatus string, err error) assetAuditSvc.BuildLogParams {
|
||||
afterData := map[string]any{}
|
||||
if req != nil {
|
||||
afterData["file_key"] = req.FileKey
|
||||
afterData["operation_type"] = req.OperationType
|
||||
if req.OperationType != constants.DeviceImportOperationRecall {
|
||||
afterData["target_id"] = req.TargetID
|
||||
func (s *Service) failEnqueueWithAudit(ctx context.Context, task *model.DeviceImportTask, summary string) error {
|
||||
before := deviceImportTaskState(task)
|
||||
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
now := time.Now()
|
||||
if err := tx.WithContext(ctx).Model(&model.DeviceImportTask{}).Where("id = ?", task.ID).Updates(map[string]any{
|
||||
"status": model.ImportTaskStatusFailed, "error_message": summary, "completed_at": now, "updated_at": now,
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
task.Status, task.ErrorMessage = model.ImportTaskStatusFailed, summary
|
||||
return s.writeDeviceImportTaskAudit(ctx, tx, task, before, deviceImportTaskState(task), constants.AuditResultFailed, "enqueue_failed", strconv.Itoa(errors.CodeTaskQueueError), summary)
|
||||
})
|
||||
}
|
||||
|
||||
func deviceImportTaskState(task *model.DeviceImportTask) map[string]any {
|
||||
if task == nil {
|
||||
return nil
|
||||
}
|
||||
errorCode, errorMsg := assetAuditSvc.BuildErrorInfo(err)
|
||||
return assetAuditSvc.BuildLogParams{
|
||||
AssetID: taskID, AssetIdentifier: taskNo,
|
||||
OperationType: constants.AssetAuditOpDeviceBatchTaskCreate,
|
||||
OperationDesc: "创建设备CSV批量操作任务", ResultStatus: resultStatus,
|
||||
ErrorCode: errorCode, ErrorMsg: errorMsg, AfterData: afterData,
|
||||
return map[string]any{
|
||||
"status": task.Status, "total_count": task.TotalCount, "success_count": task.SuccessCount,
|
||||
"skip_count": task.SkipCount, "fail_count": task.FailCount, "warning_count": task.WarningCount,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user