修复(#51): 修正封禁用户订阅返回码
封禁用户拉订阅时返回纯文本 500 退化为业务码 20004,统一走 result.HttpResult。覆盖 /api/subscribe 和泛域名两条入口,补回归测试。
This commit is contained in:
@@ -43,6 +43,7 @@ logs/
|
|||||||
/test/
|
/test/
|
||||||
*_test.go
|
*_test.go
|
||||||
!tests/acceptance/*_test.go
|
!tests/acceptance/*_test.go
|
||||||
|
!internal/handler/subscribe_test.go
|
||||||
*_test_config.go
|
*_test_config.go
|
||||||
**/logtest/
|
**/logtest/
|
||||||
*_test.yaml
|
*_test.yaml
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/perfect-panel/server/internal/svc"
|
"github.com/perfect-panel/server/internal/svc"
|
||||||
"github.com/perfect-panel/server/internal/types"
|
"github.com/perfect-panel/server/internal/types"
|
||||||
"github.com/perfect-panel/server/pkg/logger"
|
"github.com/perfect-panel/server/pkg/logger"
|
||||||
|
"github.com/perfect-panel/server/pkg/result"
|
||||||
"github.com/perfect-panel/server/pkg/tool"
|
"github.com/perfect-panel/server/pkg/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ func SubscribeHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
|
|||||||
l := subscribe.NewSubscribeLogic(c, svcCtx)
|
l := subscribe.NewSubscribeLogic(c, svcCtx)
|
||||||
resp, err := l.Handler(&req)
|
resp, err := l.Handler(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, "Internal Server")
|
result.HttpResult(c, nil, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Header("subscription-userinfo", resp.Header)
|
c.Header("subscription-userinfo", resp.Header)
|
||||||
|
|||||||
@@ -0,0 +1,332 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/alicebob/miniredis/v2"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/perfect-panel/server/internal/config"
|
||||||
|
logiccommon "github.com/perfect-panel/server/internal/logic/common"
|
||||||
|
"github.com/perfect-panel/server/internal/model/client"
|
||||||
|
"github.com/perfect-panel/server/internal/model/user"
|
||||||
|
"github.com/perfect-panel/server/internal/svc"
|
||||||
|
"github.com/perfect-panel/server/pkg/xerr"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSubscribeHandlerReturnsBusinessErrorForDisabledUser(t *testing.T) {
|
||||||
|
gin.SetMode(gin.TestMode)
|
||||||
|
redisServer, err := miniredis.Run()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("miniredis.Run() error = %v", err)
|
||||||
|
}
|
||||||
|
defer redisServer.Close()
|
||||||
|
|
||||||
|
rdb := redis.NewClient(&redis.Options{Addr: redisServer.Addr()})
|
||||||
|
defer func() {
|
||||||
|
_ = rdb.Close()
|
||||||
|
}()
|
||||||
|
if err := rdb.Set(context.Background(), logiccommon.UserEnableCacheKey(83696), "false", 0).Err(); err != nil {
|
||||||
|
t.Fatalf("seed user enable cache: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
router := gin.New()
|
||||||
|
router.GET("/api/subscribe", SubscribeHandler(&svc.ServiceContext{
|
||||||
|
Config: config.Config{
|
||||||
|
Subscribe: config.SubscribeConfig{
|
||||||
|
SubscribePath: "/api/subscribe",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ClientModel: subscribeClientModelStub{
|
||||||
|
list: []*client.SubscribeApplication{
|
||||||
|
{
|
||||||
|
Id: 1,
|
||||||
|
UserAgent: "clashmeta",
|
||||||
|
IsDefault: true,
|
||||||
|
OutputFormat: "yaml",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Redis: rdb,
|
||||||
|
UserModel: subscribeUserModelStub{
|
||||||
|
subscribe: &user.Subscribe{Id: 35446, UserId: 83696, SubscribeId: 1, Token: "disabled-token"},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/api/subscribe?token=disabled-token", nil)
|
||||||
|
req.Header.Set("User-Agent", "ClashMetaForAndroid/2.11.7.Meta")
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
|
||||||
|
router.ServeHTTP(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("expected HTTP 200, got %d", rec.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp struct {
|
||||||
|
Code uint32 `json:"code"`
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
||||||
|
t.Fatalf("unmarshal response: %v", err)
|
||||||
|
}
|
||||||
|
if resp.Code != xerr.UserDisabled {
|
||||||
|
t.Fatalf("expected code %d, got %d (%s)", xerr.UserDisabled, resp.Code, resp.Msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type subscribeClientModelStub struct {
|
||||||
|
list []*client.SubscribeApplication
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeClientModelStub) Insert(context.Context, *client.SubscribeApplication) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeClientModelStub) FindOne(context.Context, int64) (*client.SubscribeApplication, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeClientModelStub) Update(context.Context, *client.SubscribeApplication) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeClientModelStub) Delete(context.Context, int64) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeClientModelStub) List(context.Context) ([]*client.SubscribeApplication, error) {
|
||||||
|
return s.list, s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeClientModelStub) Transaction(context.Context, func(*gorm.DB) error) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type subscribeUserModelStub struct {
|
||||||
|
subscribe *user.Subscribe
|
||||||
|
subErr error
|
||||||
|
findOne *user.User
|
||||||
|
findOneErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) Insert(context.Context, *user.User, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOne(context.Context, int64) (*user.User, error) {
|
||||||
|
if s.findOneErr != nil {
|
||||||
|
return nil, s.findOneErr
|
||||||
|
}
|
||||||
|
return s.findOne, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) Update(context.Context, *user.User, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) UpdateCommission(context.Context, int64, int64, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) Delete(context.Context, int64, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) Transaction(context.Context, func(*gorm.DB) error) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryPageList(context.Context, int, int, *user.UserFilterParams) ([]*user.User, int64, error) {
|
||||||
|
return nil, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneByReferCode(context.Context, string) (*user.User, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) BatchDeleteUser(context.Context, []int64, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) InsertSubscribe(context.Context, *user.Subscribe, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneSubscribeByToken(context.Context, string) (*user.Subscribe, error) {
|
||||||
|
if s.subErr != nil {
|
||||||
|
return nil, s.subErr
|
||||||
|
}
|
||||||
|
return s.subscribe, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindSingleModeAnchorSubscribe(context.Context, int64) (*user.Subscribe, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneSubscribeByOrderId(context.Context, int64) (*user.Subscribe, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneSubscribe(context.Context, int64) (*user.Subscribe, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) UpdateSubscribe(context.Context, *user.Subscribe, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) DeleteSubscribe(context.Context, string, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) DeleteSubscribeById(context.Context, int64, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryUserSubscribe(context.Context, int64, ...int64) ([]*user.SubscribeDetails, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneSubscribeDetailsById(context.Context, int64) (*user.SubscribeDetails, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneUserSubscribe(context.Context, int64) (*user.SubscribeDetails, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindUsersSubscribeBySubscribeId(context.Context, int64) ([]*user.Subscribe, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) UpdateUserSubscribeWithTraffic(context.Context, int64, int64, int64, bool, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryResisterUserTotalByDate(context.Context, time.Time) (int64, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryResisterUserTotalByMonthly(context.Context, time.Time) (int64, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryResisterUserTotal(context.Context) (int64, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryAdminUsers(context.Context) ([]*user.User, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) UpdateUserCache(context.Context, *user.User) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) UpdateUserSubscribeCache(context.Context, *user.Subscribe) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryActiveSubscriptions(context.Context, ...int64) (map[int64]int64, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindUserAuthMethods(context.Context, int64) ([]*user.AuthMethods, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) InsertUserAuthMethods(context.Context, *user.AuthMethods, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) UpdateUserAuthMethods(context.Context, *user.AuthMethods, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) DeleteUserAuthMethods(context.Context, int64, string, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindUserAuthMethodByOpenID(context.Context, string, string) (*user.AuthMethods, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindUserAuthMethodByUserId(context.Context, string, int64) (*user.AuthMethods, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindUserAuthMethodByPlatform(context.Context, int64, string) (*user.AuthMethods, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneByEmail(context.Context, string) (*user.User, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneDevice(context.Context, int64) (*user.Device, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryDeviceList(context.Context, int64) ([]*user.Device, int64, error) {
|
||||||
|
return nil, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryDeviceListByUserIds(context.Context, []int64) ([]*user.Device, int64, error) {
|
||||||
|
return nil, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryDevicePageList(context.Context, int64, int64, int, int) ([]*user.Device, int64, error) {
|
||||||
|
return nil, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) UpdateDevice(context.Context, *user.Device, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindOneDeviceByIdentifier(context.Context, string) (*user.Device, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) DeleteDevice(context.Context, int64, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) InsertDevice(context.Context, *user.Device, ...*gorm.DB) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) ClearSubscribeCache(context.Context, ...*user.Subscribe) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) ClearUserCache(context.Context, ...*user.User) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) ClearDeviceCache(context.Context, ...*user.Device) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryDailyUserStatisticsList(context.Context, time.Time) ([]user.UserStatisticsWithDate, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) QueryMonthlyUserStatisticsList(context.Context, time.Time) ([]user.UserStatisticsWithDate, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindActiveSubscribe(context.Context, int64) (*user.Subscribe, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s subscribeUserModelStub) FindActiveSubscribesByUserIds(context.Context, []int64) (map[int64]*user.UserStatusInfo, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/perfect-panel/server/internal/svc"
|
"github.com/perfect-panel/server/internal/svc"
|
||||||
"github.com/perfect-panel/server/internal/types"
|
"github.com/perfect-panel/server/internal/types"
|
||||||
"github.com/perfect-panel/server/pkg/logger"
|
"github.com/perfect-panel/server/pkg/logger"
|
||||||
|
"github.com/perfect-panel/server/pkg/result"
|
||||||
"github.com/perfect-panel/server/pkg/tool"
|
"github.com/perfect-panel/server/pkg/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,6 +67,8 @@ func PanDomainMiddleware(svc *svc.ServiceContext) func(c *gin.Context) {
|
|||||||
l := subscribe.NewSubscribeLogic(c, svc)
|
l := subscribe.NewSubscribeLogic(c, svc)
|
||||||
resp, err := l.Handler(&request)
|
resp, err := l.Handler(&request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
result.HttpResult(c, nil, err)
|
||||||
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Header("subscription-userinfo", resp.Header)
|
c.Header("subscription-userinfo", resp.Header)
|
||||||
|
|||||||
Reference in New Issue
Block a user