修复 code review 问题:DTO 内部字段、错误消息、重复代码与测试覆盖
- 删除 ExpiryBaseOverrideSet 字段的 description 标签(json:"-" 内部字段不进文档) - ValidateExpiryBaseOverride 两处 CodeInvalidParam 补充中文错误消息 - 提取 initPackageExpiryBaseFields 消除 toResponse/toResponseWithAllocation 中的重复初始化 - 删除 order/service.go 中"行业卡永远直接激活"过时注释 - 补充 T01 系列授权 HTTP 集成测试(Create + ManagePackages 两个入口) - 补充 T03 C 端购买和平台代购(无分配)快照集成测试 - 补充 T04 from_purchase 默认值、卡未实名仍立即激活的自动购包测试 - 新增 testutil.NewRedisClient 供激活接续测试使用 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,345 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
internalMiddleware "github.com/break/junhong_cmp_fiber/internal/middleware"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
batchAllocationService "github.com/break/junhong_cmp_fiber/internal/service/shop_package_batch_allocation"
|
||||
grantService "github.com/break/junhong_cmp_fiber/internal/service/shop_series_grant"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||||
"github.com/break/junhong_cmp_fiber/internal/testutil"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// TestBatchAllocatePackagesHTTPRequiresExplicitExpiryBase 验证批量分配显式选择并固化到全部记录。
|
||||
func TestBatchAllocatePackagesHTTPRequiresExplicitExpiryBase(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
field string
|
||||
expected *string
|
||||
}{
|
||||
{name: "跟随默认", field: "null"},
|
||||
{name: "购买即生效", field: `"from_purchase"`, expected: stringPointer(constants.PackageExpiryBaseFromPurchase)},
|
||||
{name: "实名即生效", field: `"from_activation"`, expected: stringPointer(constants.PackageExpiryBaseFromActivation)},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
tx, fixture := newExpiryBaseHTTPFixture(t)
|
||||
app := fixture.newApp(constants.UserTypeSuperAdmin, 0)
|
||||
body := `{"shop_id":` + strconv.FormatUint(uint64(fixture.shop.ID), 10) + `,"series_id":` + strconv.FormatUint(uint64(fixture.series.ID), 10) + `,"expiry_base_override":` + testCase.field + `}`
|
||||
status, responseBody := expiryBaseHTTPRequest(t, app, http.MethodPost, "/api/admin/shop-package-allocations/batch", body)
|
||||
if status != http.StatusOK {
|
||||
t.Fatalf("批量分配失败:status=%d body=%s", status, responseBody)
|
||||
}
|
||||
var allocations []model.ShopPackageAllocation
|
||||
if err := tx.Where("shop_id = ?", fixture.shop.ID).Order("package_id").Find(&allocations).Error; err != nil {
|
||||
t.Fatalf("查询套餐分配失败:%v", err)
|
||||
}
|
||||
if len(allocations) != len(fixture.packages) {
|
||||
t.Fatalf("期望创建 %d 条分配,实际 %d", len(fixture.packages), len(allocations))
|
||||
}
|
||||
for _, allocation := range allocations {
|
||||
if !nullableStringEqual(allocation.ExpiryBaseOverride, testCase.expected) {
|
||||
t.Fatalf("分配 %d 的覆盖值错误:%v", allocation.ID, allocation.ExpiryBaseOverride)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestBatchAllocatePackagesHTTPRejectsMissingAndInvalidExpiryBase 验证字段缺失与非法枚举统一拒绝且不写入。
|
||||
func TestBatchAllocatePackagesHTTPRejectsMissingAndInvalidExpiryBase(t *testing.T) {
|
||||
for _, bodySuffix := range []string{"", `,"expiry_base_override":"invalid"`} {
|
||||
t.Run(bodySuffix, func(t *testing.T) {
|
||||
tx, fixture := newExpiryBaseHTTPFixture(t)
|
||||
app := fixture.newApp(constants.UserTypeSuperAdmin, 0)
|
||||
body := `{"shop_id":` + strconv.FormatUint(uint64(fixture.shop.ID), 10) + `,"series_id":` + strconv.FormatUint(uint64(fixture.series.ID), 10) + bodySuffix + `}`
|
||||
status, responseBody := expiryBaseHTTPRequest(t, app, http.MethodPost, "/api/admin/shop-package-allocations/batch", body)
|
||||
if status != http.StatusBadRequest {
|
||||
t.Fatalf("期望参数错误,实际 status=%d body=%s", status, responseBody)
|
||||
}
|
||||
var count int64
|
||||
if err := tx.Model(&model.ShopPackageAllocation{}).Where("shop_id = ?", fixture.shop.ID).Count(&count).Error; err != nil || count != 0 {
|
||||
t.Fatalf("失败请求不应留下套餐分配:count=%d err=%v", count, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestUpdateAllocationExpiryBaseHTTP 验证 PATCH 的恢复默认、幂等、权限和历史快照隔离。
|
||||
func TestUpdateAllocationExpiryBaseHTTP(t *testing.T) {
|
||||
tx, fixture := newExpiryBaseHTTPFixture(t)
|
||||
override := constants.PackageExpiryBaseFromPurchase
|
||||
allocation := &model.ShopPackageAllocation{ShopID: fixture.shop.ID, PackageID: fixture.packages[0].ID, AllocatorShopID: 101, CostPrice: 1, RetailPrice: 2, ExpiryBaseOverride: &override, Status: constants.StatusEnabled, ShelfStatus: 1}
|
||||
if err := tx.Create(allocation).Error; err != nil {
|
||||
t.Fatalf("创建套餐分配失败:%v", err)
|
||||
}
|
||||
usage := completeExpiryBaseTestUsage(fixture.packages[0].ID)
|
||||
if err := tx.Create(usage).Error; err != nil {
|
||||
t.Fatalf("创建既有购买记录失败:%v", err)
|
||||
}
|
||||
app := fixture.newApp(constants.UserTypeSuperAdmin, 0)
|
||||
path := "/api/admin/shop-package-allocations/" + strconv.FormatUint(uint64(allocation.ID), 10) + "/expiry-base"
|
||||
|
||||
for _, body := range []string{`{"expiry_base_override":"from_activation"}`, `{"expiry_base_override":"from_activation"}`, `{"expiry_base_override":null}`} {
|
||||
status, responseBody := expiryBaseHTTPRequest(t, app, http.MethodPatch, path, body)
|
||||
if status != http.StatusOK {
|
||||
t.Fatalf("修改覆盖值失败:status=%d body=%s", status, responseBody)
|
||||
}
|
||||
}
|
||||
var refreshed model.ShopPackageAllocation
|
||||
if err := tx.First(&refreshed, allocation.ID).Error; err != nil || refreshed.ExpiryBaseOverride != nil {
|
||||
t.Fatalf("显式 null 应恢复跟随默认:allocation=%+v err=%v", refreshed, err)
|
||||
}
|
||||
var refreshedUsage model.PackageUsage
|
||||
if err := tx.First(&refreshedUsage, usage.ID).Error; err != nil {
|
||||
t.Fatalf("查询既有购买记录失败:%v", err)
|
||||
}
|
||||
if refreshedUsage.ExpiryBaseSnapshot != usage.ExpiryBaseSnapshot || refreshedUsage.CalendarTypeSnapshot != usage.CalendarTypeSnapshot || refreshedUsage.DurationDaysSnapshot != usage.DurationDaysSnapshot {
|
||||
t.Fatalf("修改分配不应改变既有购买快照:before=%+v after=%+v", usage, refreshedUsage)
|
||||
}
|
||||
|
||||
for _, body := range []string{`{}`, `{"expiry_base_override":"invalid"}`} {
|
||||
status, _ := expiryBaseHTTPRequest(t, app, http.MethodPatch, path, body)
|
||||
if status != http.StatusBadRequest {
|
||||
t.Fatalf("字段缺失或非法值应返回 400,body=%s status=%d", body, status)
|
||||
}
|
||||
}
|
||||
forbiddenApp := fixture.newApp(constants.UserTypeAgent, 202)
|
||||
status, _ := expiryBaseHTTPRequest(t, forbiddenApp, http.MethodPatch, path, `{"expiry_base_override":null}`)
|
||||
if status != http.StatusForbidden {
|
||||
t.Fatalf("越权修改应返回 403,实际 %d", status)
|
||||
}
|
||||
if err := tx.Delete(&refreshed).Error; err != nil {
|
||||
t.Fatalf("软删除分配失败:%v", err)
|
||||
}
|
||||
status, _ = expiryBaseHTTPRequest(t, app, http.MethodPatch, path, `{"expiry_base_override":null}`)
|
||||
if status != http.StatusForbidden {
|
||||
t.Fatalf("软删除分配应使用统一 403 语义,实际 %d", status)
|
||||
}
|
||||
}
|
||||
|
||||
type expiryBaseHTTPFixture struct {
|
||||
tx *gorm.DB
|
||||
shop *model.Shop
|
||||
series *model.PackageSeries
|
||||
packages []*model.Package
|
||||
}
|
||||
|
||||
func newExpiryBaseHTTPFixture(t *testing.T) (*gorm.DB, *expiryBaseHTTPFixture) {
|
||||
t.Helper()
|
||||
tx := testutil.NewPostgresTransaction(t)
|
||||
suffix := strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||
shop := &model.Shop{ShopName: "UR55测试店铺", ShopCode: "UR55-SHOP-" + suffix, Status: constants.StatusEnabled}
|
||||
series := &model.PackageSeries{SeriesCode: "UR55-SERIES-" + suffix, SeriesName: "UR55测试系列", Status: constants.StatusEnabled}
|
||||
if err := tx.Create(shop).Error; err != nil {
|
||||
t.Fatalf("创建测试店铺失败:%v", err)
|
||||
}
|
||||
if err := tx.Create(series).Error; err != nil {
|
||||
t.Fatalf("创建测试系列失败:%v", err)
|
||||
}
|
||||
packages := make([]*model.Package, 0, 2)
|
||||
for index, expiryBase := range []string{constants.PackageExpiryBaseFromActivation, constants.PackageExpiryBaseFromPurchase} {
|
||||
pkg := &model.Package{PackageCode: "UR55-PKG-" + suffix + "-" + strconv.Itoa(index), PackageName: "UR55测试套餐", SeriesID: series.ID, PackageType: constants.PackageTypeFormal, DurationMonths: 1, DurationDays: 30, CalendarType: constants.PackageCalendarTypeByDay, ExpiryBase: expiryBase, Status: constants.StatusEnabled, ShelfStatus: 1, PriceConfigStatus: 2}
|
||||
if err := tx.Create(pkg).Error; err != nil {
|
||||
t.Fatalf("创建测试套餐失败:%v", err)
|
||||
}
|
||||
packages = append(packages, pkg)
|
||||
}
|
||||
seriesAllocation := &model.ShopSeriesAllocation{ShopID: shop.ID, SeriesID: series.ID, Status: constants.StatusEnabled}
|
||||
if err := tx.Create(seriesAllocation).Error; err != nil {
|
||||
t.Fatalf("创建系列授权失败:%v", err)
|
||||
}
|
||||
return tx, &expiryBaseHTTPFixture{tx: tx, shop: shop, series: series, packages: packages}
|
||||
}
|
||||
|
||||
func (f *expiryBaseHTTPFixture) newApp(userType int, shopID uint) *fiber.App {
|
||||
service := batchAllocationService.New(f.tx, postgres.NewPackageStore(f.tx), postgres.NewShopPackageAllocationStore(f.tx), postgres.NewShopSeriesAllocationStore(f.tx), postgres.NewShopStore(f.tx, nil), nil)
|
||||
handler := NewShopPackageBatchAllocationHandler(service)
|
||||
app := fiber.New(fiber.Config{JSONEncoder: sonic.Marshal, JSONDecoder: sonic.Unmarshal, ErrorHandler: internalMiddleware.ErrorHandler(zap.NewNop())})
|
||||
setContext := func(c *fiber.Ctx) error {
|
||||
ctx := middleware.SetUserContext(c.UserContext(), &middleware.UserContextInfo{UserID: 9001, UserType: userType, Username: "UR55测试账号", ShopID: shopID})
|
||||
c.SetUserContext(ctx)
|
||||
return c.Next()
|
||||
}
|
||||
app.Post("/api/admin/shop-package-allocations/batch", setContext, handler.BatchAllocate)
|
||||
app.Patch("/api/admin/shop-package-allocations/:id/expiry-base", setContext, handler.UpdateExpiryBase)
|
||||
return app
|
||||
}
|
||||
|
||||
func expiryBaseHTTPRequest(t *testing.T, app *fiber.App, method, path, body string) (int, []byte) {
|
||||
t.Helper()
|
||||
request, err := http.NewRequestWithContext(context.Background(), method, path, bytes.NewBufferString(body))
|
||||
if err != nil {
|
||||
t.Fatalf("创建 HTTP 请求失败:%v", err)
|
||||
}
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
response, err := app.Test(request, -1)
|
||||
if err != nil {
|
||||
t.Fatalf("执行 HTTP 请求失败:%v", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
responseBody, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("读取 HTTP 响应失败:%v", err)
|
||||
}
|
||||
return response.StatusCode, responseBody
|
||||
}
|
||||
|
||||
func completeExpiryBaseTestUsage(packageID uint) *model.PackageUsage {
|
||||
unique := uint(time.Now().UnixNano() & 0x7fffffff)
|
||||
return &model.PackageUsage{OrderID: unique, OrderNo: "UR55-PATCH-USAGE", PackageID: packageID, UsageType: constants.AssetWalletResourceTypeIotCard, IotCardID: unique, DataLimitMB: 1, Status: constants.PackageUsageStatusPending, Priority: 1, PackageName: "UR55测试套餐", Generation: 1, ExpiryBaseSnapshot: constants.PackageExpiryBaseFromPurchase, CalendarTypeSnapshot: constants.PackageCalendarTypeByDay, DurationDaysSnapshot: 30}
|
||||
}
|
||||
|
||||
func stringPointer(value string) *string { return &value }
|
||||
|
||||
func nullableStringEqual(left, right *string) bool {
|
||||
return left == nil && right == nil || left != nil && right != nil && *left == *right
|
||||
}
|
||||
|
||||
// TestSeriesGrantCreateHTTPRequiresExplicitExpiryBase 验证系列首次授权(含套餐)固化生效条件到分配记录。
|
||||
func TestSeriesGrantCreateHTTPRequiresExplicitExpiryBase(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
field string
|
||||
expected *string
|
||||
}{
|
||||
{name: "跟随默认", field: "null"},
|
||||
{name: "购买即生效", field: `"from_purchase"`, expected: stringPointer(constants.PackageExpiryBaseFromPurchase)},
|
||||
{name: "实名即生效", field: `"from_activation"`, expected: stringPointer(constants.PackageExpiryBaseFromActivation)},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
tx, fixture := newExpiryBaseHTTPFixture(t)
|
||||
targetShop := &model.Shop{ShopName: "UR55授权目标店铺", ShopCode: "UR55-TARGET-" + strconv.FormatInt(time.Now().UnixNano(), 10), Status: constants.StatusEnabled}
|
||||
if err := tx.Create(targetShop).Error; err != nil {
|
||||
t.Fatalf("创建目标店铺失败:%v", err)
|
||||
}
|
||||
app := fixture.newGrantApp(constants.UserTypeSuperAdmin, 0, tx)
|
||||
pkg := fixture.packages[0]
|
||||
body := `{"shop_id":` + strconv.FormatUint(uint64(targetShop.ID), 10) +
|
||||
`,"series_id":` + strconv.FormatUint(uint64(fixture.series.ID), 10) +
|
||||
`,"packages":[{"package_id":` + strconv.FormatUint(uint64(pkg.ID), 10) + `,"cost_price":100}]` +
|
||||
`,"expiry_base_override":` + testCase.field + `}`
|
||||
status, responseBody := expiryBaseHTTPRequest(t, app, http.MethodPost, "/api/admin/shop-series-grants", body)
|
||||
if status != http.StatusOK {
|
||||
t.Fatalf("系列授权创建失败:status=%d body=%s", status, responseBody)
|
||||
}
|
||||
var alloc model.ShopPackageAllocation
|
||||
if err := tx.Where("shop_id = ? AND package_id = ?", targetShop.ID, pkg.ID).First(&alloc).Error; err != nil {
|
||||
t.Fatalf("查询套餐分配失败:%v", err)
|
||||
}
|
||||
if !nullableStringEqual(alloc.ExpiryBaseOverride, testCase.expected) {
|
||||
t.Fatalf("系列授权覆盖值错误:got=%v want=%v", alloc.ExpiryBaseOverride, testCase.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestSeriesGrantCreateHTTPRejectsMissingAndInvalidExpiryBase 验证字段缺失与非法枚举拒绝系列授权创建。
|
||||
func TestSeriesGrantCreateHTTPRejectsMissingAndInvalidExpiryBase(t *testing.T) {
|
||||
for _, bodySuffix := range []string{"", `,"expiry_base_override":"invalid"`} {
|
||||
t.Run(bodySuffix, func(t *testing.T) {
|
||||
tx, fixture := newExpiryBaseHTTPFixture(t)
|
||||
targetShop := &model.Shop{ShopName: "UR55授权目标店铺", ShopCode: "UR55-TARGET-" + strconv.FormatInt(time.Now().UnixNano(), 10), Status: constants.StatusEnabled}
|
||||
if err := tx.Create(targetShop).Error; err != nil {
|
||||
t.Fatalf("创建目标店铺失败:%v", err)
|
||||
}
|
||||
app := fixture.newGrantApp(constants.UserTypeSuperAdmin, 0, tx)
|
||||
pkg := fixture.packages[0]
|
||||
body := `{"shop_id":` + strconv.FormatUint(uint64(targetShop.ID), 10) +
|
||||
`,"series_id":` + strconv.FormatUint(uint64(fixture.series.ID), 10) +
|
||||
`,"packages":[{"package_id":` + strconv.FormatUint(uint64(pkg.ID), 10) + `,"cost_price":100}]` +
|
||||
bodySuffix + `}`
|
||||
status, responseBody := expiryBaseHTTPRequest(t, app, http.MethodPost, "/api/admin/shop-series-grants", body)
|
||||
if status != http.StatusBadRequest {
|
||||
t.Fatalf("期望 400,实际 status=%d body=%s", status, responseBody)
|
||||
}
|
||||
var count int64
|
||||
if err := tx.Model(&model.ShopPackageAllocation{}).Where("shop_id = ?", targetShop.ID).Count(&count).Error; err != nil || count != 0 {
|
||||
t.Fatalf("失败请求不应留下套餐分配:count=%d err=%v", count, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestSeriesGrantManagePackagesHTTPRequiresExplicitExpiryBase 验证后续追加套餐固化生效条件到新分配记录。
|
||||
func TestSeriesGrantManagePackagesHTTPRequiresExplicitExpiryBase(t *testing.T) {
|
||||
tx, fixture := newExpiryBaseHTTPFixture(t)
|
||||
targetShop := &model.Shop{ShopName: "UR55追加目标店铺", ShopCode: "UR55-MANAGE-" + strconv.FormatInt(time.Now().UnixNano(), 10), Status: constants.StatusEnabled}
|
||||
if err := tx.Create(targetShop).Error; err != nil {
|
||||
t.Fatalf("创建目标店铺失败:%v", err)
|
||||
}
|
||||
// 先创建不含套餐的系列授权
|
||||
seriesAlloc := &model.ShopSeriesAllocation{ShopID: targetShop.ID, SeriesID: fixture.series.ID, AllocatorShopID: 0, Status: constants.StatusEnabled}
|
||||
if err := tx.Create(seriesAlloc).Error; err != nil {
|
||||
t.Fatalf("创建系列授权失败:%v", err)
|
||||
}
|
||||
app := fixture.newGrantApp(constants.UserTypeSuperAdmin, 0, tx)
|
||||
path := "/api/admin/shop-series-grants/" + strconv.FormatUint(uint64(seriesAlloc.ID), 10) + "/packages"
|
||||
pkg := fixture.packages[0]
|
||||
|
||||
// 有效追加(from_purchase)
|
||||
body := `{"packages":[{"package_id":` + strconv.FormatUint(uint64(pkg.ID), 10) + `,"cost_price":50}],"expiry_base_override":"from_purchase"}`
|
||||
status, responseBody := expiryBaseHTTPRequest(t, app, http.MethodPut, path, body)
|
||||
if status != http.StatusOK {
|
||||
t.Fatalf("追加套餐失败:status=%d body=%s", status, responseBody)
|
||||
}
|
||||
var alloc model.ShopPackageAllocation
|
||||
if err := tx.Where("shop_id = ? AND package_id = ?", targetShop.ID, pkg.ID).First(&alloc).Error; err != nil {
|
||||
t.Fatalf("查询新建套餐分配失败:%v", err)
|
||||
}
|
||||
expected := constants.PackageExpiryBaseFromPurchase
|
||||
if !nullableStringEqual(alloc.ExpiryBaseOverride, &expected) {
|
||||
t.Fatalf("追加套餐覆盖值错误:%v", alloc.ExpiryBaseOverride)
|
||||
}
|
||||
|
||||
// 缺失 expiry_base_override 字段应返回 400
|
||||
for _, badBody := range []string{
|
||||
`{"packages":[{"package_id":` + strconv.FormatUint(uint64(fixture.packages[1].ID), 10) + `,"cost_price":50}]}`,
|
||||
`{"packages":[{"package_id":` + strconv.FormatUint(uint64(fixture.packages[1].ID), 10) + `,"cost_price":50}],"expiry_base_override":"invalid"}`,
|
||||
} {
|
||||
s, _ := expiryBaseHTTPRequest(t, app, http.MethodPut, path, badBody)
|
||||
if s != http.StatusBadRequest {
|
||||
t.Fatalf("缺失/非法 expiry_base_override 应返回 400,实际 %d", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *expiryBaseHTTPFixture) newGrantApp(userType int, shopID uint, tx *gorm.DB) *fiber.App {
|
||||
svc := grantService.New(
|
||||
tx,
|
||||
postgres.NewShopSeriesAllocationStore(tx),
|
||||
postgres.NewShopPackageAllocationStore(tx),
|
||||
postgres.NewShopPackageAllocationPriceHistoryStore(tx),
|
||||
postgres.NewShopStore(tx, nil),
|
||||
postgres.NewPackageStore(tx),
|
||||
postgres.NewPackageSeriesStore(tx),
|
||||
zap.NewNop(),
|
||||
)
|
||||
handler := NewShopSeriesGrantHandler(svc)
|
||||
app := fiber.New(fiber.Config{JSONEncoder: sonic.Marshal, JSONDecoder: sonic.Unmarshal, ErrorHandler: internalMiddleware.ErrorHandler(zap.NewNop())})
|
||||
setContext := func(c *fiber.Ctx) error {
|
||||
ctx := middleware.SetUserContext(c.UserContext(), &middleware.UserContextInfo{UserID: 9001, UserType: userType, Username: "UR55测试账号", ShopID: shopID})
|
||||
c.SetUserContext(ctx)
|
||||
return c.Next()
|
||||
}
|
||||
app.Post("/api/admin/shop-series-grants", setContext, handler.Create)
|
||||
app.Put("/api/admin/shop-series-grants/:id/packages", setContext, handler.ManagePackages)
|
||||
return app
|
||||
}
|
||||
|
||||
var _ = errors.CodeSuccess
|
||||
Reference in New Issue
Block a user