固化七月迭代审计治理进展以隔离线上热修

Constraint: 切换 main 前必须保存当前七月分支全部项目进展,套餐生效提案仅属于 Iteration/7-11。

Rejected: 将七月套餐修复直接移植到 main | 两个分支的可靠投递架构不同。

Confidence: medium

Scope-risk: broad

Directive: 不得将本提交整体 cherry-pick 到 main;main 套餐热修必须基于其纯 Asynq 代码独立实施。

Tested: git diff --check;openspec validate fix-package-activation-starvation --strict。

Not-tested: 按用户要求未运行自动化测试;go build ./... 因当前审计改造中的 Enterprise 模型字面量和 role.recordFailure 参数类型错误未通过。
This commit is contained in:
2026-08-03 09:47:22 +08:00
parent cf2ff0ac1c
commit b3499adfca
114 changed files with 16961 additions and 2782 deletions

View File

@@ -3,7 +3,9 @@ package role
import (
"context"
stdErrors "errors"
accessauditapp "github.com/break/junhong_cmp_fiber/internal/application/accessaudit"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
@@ -20,11 +22,12 @@ type PermissionChecker interface {
type DefaultCreditService struct {
db *gorm.DB
permissionChecker PermissionChecker
accessAudit accessauditapp.Writer
}
// NewDefaultCreditService 创建角色默认信用模板服务。
func NewDefaultCreditService(db *gorm.DB, permissionChecker PermissionChecker) *DefaultCreditService {
return &DefaultCreditService{db: db, permissionChecker: permissionChecker}
func NewDefaultCreditService(db *gorm.DB, permissionChecker PermissionChecker, accessAudit accessauditapp.Writer) *DefaultCreditService {
return &DefaultCreditService{db: db, permissionChecker: permissionChecker, accessAudit: accessAudit}
}
// Update 更新模板;该操作不扫描或修改任何既有钱包。
@@ -39,8 +42,8 @@ func (s *DefaultCreditService) Update(ctx context.Context, roleID uint, enabled
if err := validateDefaultCredit(enabled, limit); err != nil {
return nil, err
}
var role model.Role
var beforeData map[string]any
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Clauses().First(&role, roleID).Error; err != nil {
if err == gorm.ErrRecordNotFound {
@@ -48,6 +51,7 @@ func (s *DefaultCreditService) Update(ctx context.Context, roleID uint, enabled
}
return errors.Wrap(errors.CodeInternalError, err, "读取角色失败")
}
beforeData = defaultCreditAuditData(&role)
if role.RoleType != constants.RoleTypeCustomer {
return errors.New(errors.CodeInvalidParam, "只有客户角色可以配置新建代理默认信用")
}
@@ -68,14 +72,46 @@ func (s *DefaultCreditService) Update(ctx context.Context, roleID uint, enabled
role.DefaultCreditEnabled = enabled
role.DefaultCreditLimit = limit
role.Updater = operatorID
return nil
if s.accessAudit == nil {
return errors.New(errors.CodeInvalidStatus, "角色默认信用审计接缝未配置")
}
return s.accessAudit.WriteAccessChange(ctx, tx, accessauditapp.ChangeAudit{
ActionCode: constants.AuditActionRoleDefaultCreditUpdated, Summary: "更新角色默认信用模板", Result: constants.AuditResultSuccess,
OperatorID: operatorID, Role: &role, BeforeData: beforeData, AfterData: defaultCreditAuditData(&role),
})
})
if err != nil {
if role.ID != 0 {
accessauditapp.RecordFailure(ctx, s.db, s.accessAudit, accessauditapp.ChangeAudit{
ActionCode: constants.AuditActionRoleDefaultCreditUpdated, Summary: "更新角色默认信用模板失败",
Result: defaultCreditAuditResult(err), OperatorID: operatorID, Role: &role, BeforeData: beforeData,
}, err)
}
return nil, err
}
return &role, nil
}
func defaultCreditAuditData(role *model.Role) map[string]any {
return map[string]any{
"role_name": role.RoleName, "role_type": role.RoleType,
"default_credit_enabled": role.DefaultCreditEnabled, "default_credit_limit": role.DefaultCreditLimit,
}
}
func defaultCreditAuditResult(err error) string {
var appErr *errors.AppError
if !stdErrors.As(err, &appErr) {
return constants.AuditResultFailed
}
switch appErr.Code {
case errors.CodeInternalError, errors.CodeDatabaseError, errors.CodeRedisError:
return constants.AuditResultFailed
default:
return constants.AuditResultDenied
}
}
func (s *DefaultCreditService) authorize(ctx context.Context, operatorID uint) error {
userType := middleware.GetUserTypeFromContext(ctx)
if userType == constants.UserTypeSuperAdmin {