fix: pass operator id to audit logs

This commit is contained in:
2026-01-13 11:21:35 +08:00
parent 84c8d1b394
commit 4e35dff05c
3 changed files with 17 additions and 8 deletions

View File

@@ -1780,7 +1780,10 @@ func (s *super) ListWithdrawals(ctx context.Context, filter *super_dto.SuperOrde
}, nil }, nil
} }
func (s *super) ApproveWithdrawal(ctx context.Context, id int64) error { func (s *super) ApproveWithdrawal(ctx context.Context, operatorID, id int64) error {
if operatorID == 0 {
return errorx.ErrUnauthorized.WithMsg("缺少操作者信息")
}
o, err := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(id)).First() o, err := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(id)).First()
if err != nil { if err != nil {
return errorx.ErrRecordNotFound return errorx.ErrRecordNotFound
@@ -1796,7 +1799,7 @@ func (s *super) ApproveWithdrawal(ctx context.Context, id int64) error {
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
}) })
if err == nil && Audit != nil { if err == nil && Audit != nil {
Audit.Log(ctx, 0, "approve_withdrawal", cast.ToString(id), "Approved withdrawal") Audit.Log(ctx, operatorID, "approve_withdrawal", cast.ToString(id), "Approved withdrawal")
} }
return err return err
} }
@@ -1956,7 +1959,10 @@ func (s *super) formatTime(t time.Time) string {
return t.Format(time.RFC3339) return t.Format(time.RFC3339)
} }
func (s *super) RejectWithdrawal(ctx context.Context, id int64, reason string) error { func (s *super) RejectWithdrawal(ctx context.Context, operatorID, id int64, reason string) error {
if operatorID == 0 {
return errorx.ErrUnauthorized.WithMsg("缺少操作者信息")
}
err := models.Q.Transaction(func(tx *models.Query) error { err := models.Q.Transaction(func(tx *models.Query) error {
o, err := tx.Order.WithContext(ctx).Where(tx.Order.ID.Eq(id)).First() o, err := tx.Order.WithContext(ctx).Where(tx.Order.ID.Eq(id)).First()
if err != nil { if err != nil {
@@ -1990,7 +1996,7 @@ func (s *super) RejectWithdrawal(ctx context.Context, id int64, reason string) e
Type: consts.TenantLedgerTypeAdjustment, Type: consts.TenantLedgerTypeAdjustment,
Amount: o.AmountPaid, Amount: o.AmountPaid,
Remark: "提现拒绝返还: " + reason, Remark: "提现拒绝返还: " + reason,
OperatorUserID: 0, // System/Admin OperatorUserID: operatorID,
IdempotencyKey: uuid.NewString(), IdempotencyKey: uuid.NewString(),
} }
if err := tx.TenantLedger.WithContext(ctx).Create(ledger); err != nil { if err := tx.TenantLedger.WithContext(ctx).Create(ledger); err != nil {
@@ -2001,7 +2007,7 @@ func (s *super) RejectWithdrawal(ctx context.Context, id int64, reason string) e
}) })
if err == nil && Audit != nil { if err == nil && Audit != nil {
Audit.Log(ctx, 0, "reject_withdrawal", cast.ToString(id), "Rejected: "+reason) Audit.Log(ctx, operatorID, "reject_withdrawal", cast.ToString(id), "Rejected: "+reason)
} }
return err return err
} }

View File

@@ -105,7 +105,8 @@ func (s *SuperTestSuite) Test_WithdrawalApproval() {
database.Truncate(ctx, s.DB, models.TableNameOrder, models.TableNameUser, models.TableNameTenantLedger) database.Truncate(ctx, s.DB, models.TableNameOrder, models.TableNameUser, models.TableNameTenantLedger)
u := &models.User{Username: "user_w", Balance: 1000} // Initial 10.00 u := &models.User{Username: "user_w", Balance: 1000} // Initial 10.00
models.UserQuery.WithContext(ctx).Create(u) admin := &models.User{Username: "admin_w"}
models.UserQuery.WithContext(ctx).Create(u, admin)
// Create Withdrawal Order (Pending) // Create Withdrawal Order (Pending)
o1 := &models.Order{ o1 := &models.Order{
@@ -124,7 +125,7 @@ func (s *SuperTestSuite) Test_WithdrawalApproval() {
}) })
Convey("should approve withdrawal", func() { Convey("should approve withdrawal", func() {
err := Super.ApproveWithdrawal(ctx, o1.ID) err := Super.ApproveWithdrawal(ctx, admin.ID, o1.ID)
So(err, ShouldBeNil) So(err, ShouldBeNil)
oReload, _ := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(o1.ID)).First() oReload, _ := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(o1.ID)).First()
@@ -145,7 +146,7 @@ func (s *SuperTestSuite) Test_WithdrawalApproval() {
// But here we set balance manually to 1000. Let's assume it was 1200 before. // But here we set balance manually to 1000. Let's assume it was 1200 before.
// Current balance 1000. Refund 200 -> Expect 1200. // Current balance 1000. Refund 200 -> Expect 1200.
err := Super.RejectWithdrawal(ctx, o2.ID, "Invalid account") err := Super.RejectWithdrawal(ctx, admin.ID, o2.ID, "Invalid account")
So(err, ShouldBeNil) So(err, ShouldBeNil)
oReload, _ := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(o2.ID)).First() oReload, _ := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(o2.ID)).First()
@@ -158,6 +159,7 @@ func (s *SuperTestSuite) Test_WithdrawalApproval() {
l, _ := models.TenantLedgerQuery.WithContext(ctx).Where(models.TenantLedgerQuery.OrderID.Eq(o2.ID)).First() l, _ := models.TenantLedgerQuery.WithContext(ctx).Where(models.TenantLedgerQuery.OrderID.Eq(o2.ID)).First()
So(l, ShouldNotBeNil) So(l, ShouldNotBeNil)
So(l.Type, ShouldEqual, consts.TenantLedgerTypeAdjustment) So(l.Type, ShouldEqual, consts.TenantLedgerTypeAdjustment)
So(l.OperatorUserID, ShouldEqual, admin.ID)
}) })
}) })
} }

View File

@@ -195,6 +195,7 @@
- OTP 登录流程与租户成员校验(未加入拒绝登录)。 - OTP 登录流程与租户成员校验(未加入拒绝登录)。
- ID 类型已统一为 int64仅保留 upload_id/external_id/uuid 等非数字标识)。 - ID 类型已统一为 int64仅保留 upload_id/external_id/uuid 等非数字标识)。
- 内容资源权限与预览差异化(未购预览、已购/管理员/成员全量)。 - 内容资源权限与预览差异化(未购预览、已购/管理员/成员全量)。
- 审计操作显式传入操作者信息(服务层不再依赖 ctx 读取)。
## 里程碑建议 ## 里程碑建议
- M1完成 P0 - M1完成 P0