This commit is contained in:
@@ -83,10 +83,6 @@ func (s *Service) Get(ctx context.Context, id uint) (*dto.CarrierResponse, error
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "获取运营商失败")
|
||||
}
|
||||
if s.audit == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "运营商配置审计接缝未配置")
|
||||
}
|
||||
before := *carrier
|
||||
return s.toResponse(carrier), nil
|
||||
}
|
||||
|
||||
@@ -103,6 +99,7 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateCarrierReq
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "获取运营商失败")
|
||||
}
|
||||
before := *carrier
|
||||
|
||||
if req.CarrierName != nil {
|
||||
carrier.CarrierName = *req.CarrierName
|
||||
|
||||
@@ -65,12 +65,12 @@ func (s *Service) AllocateDevices(ctx context.Context, enterpriseID uint, req *d
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "企业设备授权审计接缝未配置")
|
||||
}
|
||||
if err := validateEnterpriseDeviceActor(ctx); err != nil {
|
||||
s.recordDeviceFailure(ctx, constants.AuditActionEnterpriseDevicesAllocated, "向企业授权设备被拒绝", &model.Enterprise{ID: enterpriseID}, nil, nil, err)
|
||||
s.recordDeviceFailure(ctx, constants.AuditActionEnterpriseDevicesAllocated, "向企业授权设备被拒绝", &model.Enterprise{Model: gorm.Model{ID: enterpriseID}}, nil, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
if err := middleware.CanManageEnterprise(ctx, enterpriseID, s.enterpriseStore); err != nil {
|
||||
permissionErr := errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||
s.recordDeviceFailure(ctx, constants.AuditActionEnterpriseDevicesAllocated, "向企业授权设备被拒绝", &model.Enterprise{ID: enterpriseID}, nil, nil, permissionErr)
|
||||
s.recordDeviceFailure(ctx, constants.AuditActionEnterpriseDevicesAllocated, "向企业授权设备被拒绝", &model.Enterprise{Model: gorm.Model{ID: enterpriseID}}, nil, nil, permissionErr)
|
||||
return nil, permissionErr
|
||||
}
|
||||
enterprise, err := s.enterpriseStore.GetByID(ctx, enterpriseID)
|
||||
@@ -417,12 +417,12 @@ func (s *Service) RecallDevices(ctx context.Context, enterpriseID uint, req *dto
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "企业设备授权审计接缝未配置")
|
||||
}
|
||||
if err := validateEnterpriseDeviceActor(ctx); err != nil {
|
||||
s.recordDeviceFailure(ctx, constants.AuditActionEnterpriseDevicesRecalled, "回收企业设备授权被拒绝", &model.Enterprise{ID: enterpriseID}, nil, nil, err)
|
||||
s.recordDeviceFailure(ctx, constants.AuditActionEnterpriseDevicesRecalled, "回收企业设备授权被拒绝", &model.Enterprise{Model: gorm.Model{ID: enterpriseID}}, nil, nil, err)
|
||||
return nil, err
|
||||
}
|
||||
if err := middleware.CanManageEnterprise(ctx, enterpriseID, s.enterpriseStore); err != nil {
|
||||
permissionErr := errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在")
|
||||
s.recordDeviceFailure(ctx, constants.AuditActionEnterpriseDevicesRecalled, "回收企业设备授权被拒绝", &model.Enterprise{ID: enterpriseID}, nil, nil, permissionErr)
|
||||
s.recordDeviceFailure(ctx, constants.AuditActionEnterpriseDevicesRecalled, "回收企业设备授权被拒绝", &model.Enterprise{Model: gorm.Model{ID: enterpriseID}}, nil, nil, permissionErr)
|
||||
return nil, permissionErr
|
||||
}
|
||||
enterprise, err := s.enterpriseStore.GetByID(ctx, enterpriseID)
|
||||
|
||||
@@ -23,38 +23,46 @@ func (s *Service) SetAccessAudit(writer *audit.Writer) {
|
||||
s.auditWriter = writer
|
||||
}
|
||||
|
||||
// WriteCardStateAudit 将卡观测事务中的人工状态操作写入统一 Audit Event。
|
||||
// WriteCardStateAudit 将卡观测事务中的人工、回调或 Worker 状态变化写入统一 Audit Event。
|
||||
func (s *Service) WriteCardStateAudit(ctx context.Context, tx *gorm.DB, input cardapp.StateAudit) error {
|
||||
extraResources := make([]audit.ResourceInput, 0, 1)
|
||||
if input.IntegrationID != "" {
|
||||
extraResources = append(extraResources, callbackIntegrationAuditResource(ctx, input.IntegrationID))
|
||||
extraResources = append(extraResources, cardStateIntegrationAuditResource(ctx, input.IntegrationID))
|
||||
}
|
||||
return s.appendCardLifecycleAudit(ctx, tx, input.ActionCode, input.Summary, constants.AuditResultSuccess,
|
||||
input.Card, input.BeforeData, input.AfterData, nil, extraResources...)
|
||||
}
|
||||
|
||||
// WriteCardStateFailure 使用独立短事务记录已解析卡资源后的回调失败。
|
||||
// WriteCardStateFailure 使用独立短事务记录已解析卡资源后的回调或 Worker 失败。
|
||||
func (s *Service) WriteCardStateFailure(ctx context.Context, input cardapp.StateAudit, businessErr error) {
|
||||
extraResources := make([]audit.ResourceInput, 0, 1)
|
||||
if input.IntegrationID != "" {
|
||||
extraResources = append(extraResources, callbackIntegrationAuditResource(ctx, input.IntegrationID))
|
||||
extraResources = append(extraResources, cardStateIntegrationAuditResource(ctx, input.IntegrationID))
|
||||
}
|
||||
s.recordCardLifecycleFailure(ctx, input.ActionCode, input.Summary, constants.AuditResultFailed,
|
||||
input.Card, input.Card.ID, businessErr, extraResources...)
|
||||
}
|
||||
|
||||
func callbackIntegrationAuditResource(ctx context.Context, integrationID string) audit.ResourceInput {
|
||||
func cardStateIntegrationAuditResource(ctx context.Context, integrationID string) audit.ResourceInput {
|
||||
linkage := auditcontext.From(ctx)
|
||||
correlationID := linkage.CorrelationID
|
||||
if correlationID == "" {
|
||||
correlationID = linkage.RequestID
|
||||
}
|
||||
direction := constants.IntegrationDirectionInbound
|
||||
role := constants.AuditResourceRoleCallbackIntegration
|
||||
provider := linkage.ActorID
|
||||
if linkage.Source == constants.AuditSourceWorker {
|
||||
direction = constants.IntegrationDirectionOutbound
|
||||
role = constants.AuditResourceRoleWorkerIntegration
|
||||
provider = constants.IntegrationProviderGateway
|
||||
}
|
||||
return audit.ResourceInput{
|
||||
Type: constants.AuditResourceIntegrationLog, Key: integrationID, DisplayName: integrationID,
|
||||
Relation: constants.AuditResourceRelationReference, Role: constants.AuditResourceRoleCallbackIntegration,
|
||||
Relation: constants.AuditResourceRelationReference, Role: role,
|
||||
IdentitySnapshot: map[string]any{
|
||||
"integration_id": integrationID, "provider": linkage.ActorID,
|
||||
"direction": constants.IntegrationDirectionInbound, "correlation_id": correlationID,
|
||||
"integration_id": integrationID, "provider": provider,
|
||||
"direction": direction, "correlation_id": correlationID,
|
||||
},
|
||||
SubjectVisibility: constants.AuditSubjectInternalOnly,
|
||||
}
|
||||
|
||||
@@ -2709,8 +2709,12 @@ func (s *Service) enqueueCommissionCalculation(ctx context.Context, orderID uint
|
||||
return
|
||||
}
|
||||
|
||||
linkage := auditcontext.From(ctx)
|
||||
// 直接传 map,由 EnqueueTask 内部统一序列化一次(传 []byte 会导致 sonic.Marshal 二次 base64 编码)
|
||||
if err := s.queueClient.EnqueueTask(ctx, constants.TaskTypeCommission, map[string]any{"order_id": orderID}); err != nil {
|
||||
if err := s.queueClient.EnqueueTask(ctx, constants.TaskTypeCommission, map[string]any{
|
||||
"order_id": orderID, "request_id": linkage.RequestID, "correlation_id": linkage.CorrelationID,
|
||||
"parent_event_id": linkage.ParentEventID,
|
||||
}); err != nil {
|
||||
s.logger.Error("佣金计算任务入队失败",
|
||||
zap.Uint("order_id", orderID),
|
||||
zap.Error(err),
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/redis/go-redis/v9"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
// ResumeCallback 复机回调接口
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||||
"github.com/break/junhong_cmp_fiber/internal/task"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/auditcontext"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/queue"
|
||||
@@ -227,7 +228,11 @@ func (s *Service) HandlePaymentCallback(ctx context.Context, paymentNo string, p
|
||||
|
||||
linkedIDs := rechargeOrder.LinkedPackageIDs
|
||||
if len(linkedIDs) > 0 {
|
||||
taskPayload := task.AutoPurchasePayload{RechargeOrderID: rechargeOrder.ID}
|
||||
linkage := auditcontext.From(ctx)
|
||||
taskPayload := task.AutoPurchasePayload{
|
||||
RechargeOrderID: rechargeOrder.ID, RequestID: linkage.RequestID,
|
||||
CorrelationID: linkage.CorrelationID, ParentEventID: linkage.ParentEventID,
|
||||
}
|
||||
if err := s.queueClient.EnqueueTask(ctx, constants.TaskTypeAutoPurchaseAfterRecharge, taskPayload,
|
||||
asynq.MaxRetry(3),
|
||||
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeAutoPurchaseAfterRecharge)),
|
||||
|
||||
@@ -132,12 +132,12 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateRoleReques
|
||||
if req.RoleName != nil && *req.RoleName != role.RoleName {
|
||||
exists, err := s.roleStore.ExistsByName(ctx, *req.RoleName, id)
|
||||
if err != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionRoleUpdated, "更新角色失败", constants.AuditResultFailed, role, beforeData, nil, err)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleUpdated, "更新角色失败", constants.AuditResultFailed, role, nil, beforeData, err)
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "检查角色名失败")
|
||||
}
|
||||
if exists {
|
||||
appErr := errors.New(errors.CodeRoleNameExists)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleUpdated, "拒绝更新重复角色名", constants.AuditResultDenied, role, beforeData, nil, appErr)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleUpdated, "拒绝更新重复角色名", constants.AuditResultDenied, role, nil, beforeData, appErr)
|
||||
return nil, appErr
|
||||
}
|
||||
role.RoleName = *req.RoleName
|
||||
@@ -162,7 +162,7 @@ func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateRoleReques
|
||||
OperatorID: currentUserID, Role: role, BeforeData: beforeData, AfterData: roleAuditData(role),
|
||||
})
|
||||
}); err != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionRoleUpdated, "更新角色失败", constants.AuditResultFailed, role, beforeData, nil, err)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleUpdated, "更新角色失败", constants.AuditResultFailed, role, nil, beforeData, err)
|
||||
return nil, errors.Wrap(errors.CodeInternalError, err, "更新角色失败")
|
||||
}
|
||||
|
||||
@@ -181,19 +181,19 @@ func (s *Service) Delete(ctx context.Context, id uint) error {
|
||||
|
||||
accountCount, err := s.accountRoleStore.CountByRoleID(ctx, id)
|
||||
if err != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionRoleDeleted, "删除角色失败", constants.AuditResultFailed, role, roleAuditData(role), nil, err)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleDeleted, "删除角色失败", constants.AuditResultFailed, role, nil, roleAuditData(role), err)
|
||||
return errors.Wrap(errors.CodeInternalError, err, "检查角色分配情况失败")
|
||||
}
|
||||
|
||||
shopCount, err := s.shopRoleStore.CountByRoleID(ctx, id)
|
||||
if err != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionRoleDeleted, "删除角色失败", constants.AuditResultFailed, role, roleAuditData(role), nil, err)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleDeleted, "删除角色失败", constants.AuditResultFailed, role, nil, roleAuditData(role), err)
|
||||
return errors.Wrap(errors.CodeInternalError, err, "检查角色分配情况失败")
|
||||
}
|
||||
|
||||
if accountCount > 0 || shopCount > 0 {
|
||||
appErr := errors.New(errors.CodeRoleInUse, fmt.Sprintf("该角色已分配给 %d 个账号、%d 个店铺,请先移除相关分配后再删除", accountCount, shopCount))
|
||||
s.recordFailure(ctx, constants.AuditActionRoleDeleted, "拒绝删除使用中的角色", constants.AuditResultDenied, role, roleAuditData(role), nil, appErr)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleDeleted, "拒绝删除使用中的角色", constants.AuditResultDenied, role, nil, roleAuditData(role), appErr)
|
||||
return appErr
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ func (s *Service) Delete(ctx context.Context, id uint) error {
|
||||
OperatorID: operatorID, Role: role, BeforeData: beforeData, AfterData: map[string]any{"deleted": true},
|
||||
})
|
||||
}); err != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionRoleDeleted, "删除角色失败", constants.AuditResultFailed, role, beforeData, nil, err)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleDeleted, "删除角色失败", constants.AuditResultFailed, role, nil, beforeData, err)
|
||||
return errors.Wrap(errors.CodeInternalError, err, "删除角色失败")
|
||||
}
|
||||
|
||||
@@ -510,19 +510,19 @@ func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
||||
if status == constants.StatusDisabled {
|
||||
accountCount, err := s.accountRoleStore.CountByRoleID(ctx, id)
|
||||
if err != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionRoleStatusUpdated, "更新角色状态失败", constants.AuditResultFailed, role, roleAuditData(role), nil, err)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleStatusUpdated, "更新角色状态失败", constants.AuditResultFailed, role, nil, roleAuditData(role), err)
|
||||
return errors.Wrap(errors.CodeInternalError, err, "检查角色分配情况失败")
|
||||
}
|
||||
|
||||
shopCount, err := s.shopRoleStore.CountByRoleID(ctx, id)
|
||||
if err != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionRoleStatusUpdated, "更新角色状态失败", constants.AuditResultFailed, role, roleAuditData(role), nil, err)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleStatusUpdated, "更新角色状态失败", constants.AuditResultFailed, role, nil, roleAuditData(role), err)
|
||||
return errors.Wrap(errors.CodeInternalError, err, "检查角色分配情况失败")
|
||||
}
|
||||
|
||||
if accountCount > 0 || shopCount > 0 {
|
||||
appErr := errors.New(errors.CodeRoleInUse, fmt.Sprintf("该角色已分配给 %d 个账号、%d 个店铺,请先移除相关分配后再禁用", accountCount, shopCount))
|
||||
s.recordFailure(ctx, constants.AuditActionRoleStatusUpdated, "拒绝禁用使用中的角色", constants.AuditResultDenied, role, roleAuditData(role), nil, appErr)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleStatusUpdated, "拒绝禁用使用中的角色", constants.AuditResultDenied, role, nil, roleAuditData(role), appErr)
|
||||
return appErr
|
||||
}
|
||||
}
|
||||
@@ -540,7 +540,7 @@ func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
||||
OperatorID: currentUserID, Role: role, BeforeData: beforeData, AfterData: roleAuditData(role),
|
||||
})
|
||||
}); err != nil {
|
||||
s.recordFailure(ctx, constants.AuditActionRoleStatusUpdated, "更新角色状态失败", constants.AuditResultFailed, role, beforeData, nil, err)
|
||||
s.recordFailure(ctx, constants.AuditActionRoleStatusUpdated, "更新角色状态失败", constants.AuditResultFailed, role, nil, beforeData, err)
|
||||
return errors.Wrap(errors.CodeInternalError, err, "更新角色状态失败")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user