feat: implement tenant-side creator audit feature and update related tests and documentation

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-02-09 06:54:04 +08:00
parent 3126ed5e64
commit 05a0d07dbb
23 changed files with 7205 additions and 112 deletions

View File

@@ -2,9 +2,11 @@ package services
import (
"database/sql"
"errors"
"testing"
"quyun/v2/app/commands/testx"
"quyun/v2/app/errorx"
order_dto "quyun/v2/app/http/v1/dto"
"quyun/v2/database"
"quyun/v2/database/models"
@@ -168,3 +170,74 @@ func (s *OrderTestSuite) Test_PlatformCommission() {
})
})
}
func (s *OrderTestSuite) Test_Pay_DenyCrossTenantOrder() {
Convey("Pay should deny cross-tenant order", s.T(), func() {
ctx := s.T().Context()
database.Truncate(
ctx,
s.DB,
models.TableNameUser,
models.TableNameTenant,
models.TableNameOrder,
)
buyer := &models.User{Username: "buyer_cross_tenant", Balance: 5000}
So(models.UserQuery.WithContext(ctx).Create(buyer), ShouldBeNil)
tenantA := &models.Tenant{UserID: buyer.ID, Code: "order_pay_cross_a", Name: "Tenant A", Status: consts.TenantStatusVerified}
tenantB := &models.Tenant{UserID: buyer.ID, Code: "order_pay_cross_b", Name: "Tenant B", Status: consts.TenantStatusVerified}
So(models.TenantQuery.WithContext(ctx).Create(tenantA, tenantB), ShouldBeNil)
order := &models.Order{
TenantID: tenantA.ID,
UserID: buyer.ID,
Type: consts.OrderTypeContentPurchase,
Status: consts.OrderStatusCreated,
AmountPaid: 1000,
}
So(models.OrderQuery.WithContext(ctx).Create(order), ShouldBeNil)
_, err := Order.Pay(ctx, tenantB.ID, buyer.ID, order.ID, &order_dto.OrderPayForm{Method: "balance"})
So(err, ShouldNotBeNil)
var appErr *errorx.AppError
So(errors.As(err, &appErr), ShouldBeTrue)
So(appErr.Code, ShouldEqual, errorx.ErrForbidden.Code)
})
}
func (s *OrderTestSuite) Test_Status_DenyCrossTenantOrder() {
Convey("Status should deny cross-tenant order", s.T(), func() {
ctx := s.T().Context()
database.Truncate(
ctx,
s.DB,
models.TableNameUser,
models.TableNameTenant,
models.TableNameOrder,
)
buyer := &models.User{Username: "buyer_status_cross", Balance: 5000}
So(models.UserQuery.WithContext(ctx).Create(buyer), ShouldBeNil)
tenantA := &models.Tenant{UserID: buyer.ID, Code: "order_status_cross_a", Name: "Tenant A", Status: consts.TenantStatusVerified}
tenantB := &models.Tenant{UserID: buyer.ID, Code: "order_status_cross_b", Name: "Tenant B", Status: consts.TenantStatusVerified}
So(models.TenantQuery.WithContext(ctx).Create(tenantA, tenantB), ShouldBeNil)
order := &models.Order{
TenantID: tenantA.ID,
UserID: buyer.ID,
Type: consts.OrderTypeContentPurchase,
Status: consts.OrderStatusCreated,
}
So(models.OrderQuery.WithContext(ctx).Create(order), ShouldBeNil)
_, err := Order.Status(ctx, tenantB.ID, buyer.ID, order.ID)
So(err, ShouldNotBeNil)
var appErr *errorx.AppError
So(errors.As(err, &appErr), ShouldBeTrue)
So(appErr.Code, ShouldEqual, errorx.ErrForbidden.Code)
})
}