This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/hibiken/asynq"
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
iapmodel "github.com/perfect-panel/server/internal/model/iap/apple"
|
||||
"github.com/perfect-panel/server/internal/model/subscribe"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
@@ -47,6 +48,9 @@ func (l *AttachTransactionLogic) Attach(req *types.AttachAppleTransactionRequest
|
||||
l.Errorw("无效访问,用户信息缺失")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "invalid access")
|
||||
}
|
||||
if err := commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txPayload, err := iapapple.VerifyTransactionJWS(req.SignedTransactionJWS)
|
||||
if err != nil {
|
||||
l.Errorw("JWS 验签失败", logger.Field("error", err.Error()))
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
iapmodel "github.com/perfect-panel/server/internal/model/iap/apple"
|
||||
"github.com/perfect-panel/server/internal/model/payment"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
@@ -39,6 +40,9 @@ func (l *RestoreLogic) Restore(req *types.RestoreAppleTransactionsRequest) error
|
||||
if !ok || u == nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "invalid access")
|
||||
}
|
||||
if err := commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
pm, _ := iapapple.ParseProductMap(l.svcCtx.Config.Site.CustomData)
|
||||
// Try to load payment config to get API credentials
|
||||
var apiCfg iapapple.ServerAPIConfig
|
||||
|
||||
@@ -45,6 +45,9 @@ func (l *PreCreateOrderLogic) PreCreateOrder(req *types.PurchaseOrderRequest) (r
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err = commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.Quantity <= 0 {
|
||||
l.Debugf("[PreCreateOrder] Quantity is less than or equal to 0, setting to 1")
|
||||
|
||||
@@ -54,6 +54,9 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err = commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if req.Quantity <= 0 {
|
||||
l.Debugf("[Purchase] Quantity is less than or equal to 0, setting to 1")
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
@@ -46,6 +47,9 @@ func (l *RenewalLogic) Renewal(req *types.RenewalOrderRequest) (resp *types.Rene
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err = commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if req.Quantity <= 0 {
|
||||
l.Debugf("[Renewal] Quantity is less than or equal to 0, setting to 1")
|
||||
req.Quantity = 1
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
@@ -43,6 +44,9 @@ func (l *ResetTrafficLogic) ResetTraffic(req *types.ResetTrafficOrderRequest) (r
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err = commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// find user subscription
|
||||
userSubscribe, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, req.UserSubscribeID)
|
||||
if err != nil {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
@@ -43,6 +44,9 @@ func (l *RedeemCodeLogic) RedeemCode(req *types.RedeemCodeRequest) (resp *types.
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err = commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 使用Redis分布式锁防止并发重复兑换
|
||||
lockKey := fmt.Sprintf("redemption_lock:%d:%s", u.Id, req.Code)
|
||||
@@ -221,4 +225,4 @@ func (l *RedeemCodeLogic) RedeemCode(req *types.RedeemCodeRequest) (resp *types.
|
||||
return &types.RedeemCodeResponse{
|
||||
Message: "Redemption successful, processing...",
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
@@ -38,7 +39,12 @@ func (l *QueryUserSubscribeNodeListLogic) QueryUserSubscribeNodeList() (resp *ty
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
|
||||
userSubscribes, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, u.Id, 0, 1, 2, 3)
|
||||
entitlement, err := commonLogic.ResolveEntitlementUser(l.ctx, l.svcCtx.DB, u.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userSubscribes, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, entitlement.EffectiveUserID, 0, 1, 2, 3)
|
||||
if err != nil {
|
||||
logger.Errorw("failed to query user subscribe", logger.Field("error", err.Error()), logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "DB_ERROR")
|
||||
@@ -79,12 +85,22 @@ func (l *QueryUserSubscribeNodeListLogic) QueryUserSubscribeNodeList() (resp *ty
|
||||
if l.svcCtx.Config.Register.EnableTrial && l.svcCtx.Config.Register.TrialSubscribe == userSubscribe.SubscribeId {
|
||||
userSubscribeInfo.IsTryOut = true
|
||||
}
|
||||
fillUserSubscribeInfoEntitlementFields(&userSubscribeInfo, entitlement)
|
||||
resp.List = append(resp.List, userSubscribeInfo)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func fillUserSubscribeInfoEntitlementFields(sub *types.UserSubscribeInfo, entitlement *commonLogic.EntitlementContext) {
|
||||
if sub == nil || entitlement == nil {
|
||||
return
|
||||
}
|
||||
sub.EntitlementSource = entitlement.Source
|
||||
sub.EntitlementOwnerUserId = entitlement.OwnerUserID
|
||||
sub.ReadOnly = entitlement.ReadOnly
|
||||
}
|
||||
|
||||
func (l *QueryUserSubscribeNodeListLogic) getServers(userSub *user.Subscribe) (userSubscribeNodes []*types.UserSubscribeNodeInfo, err error) {
|
||||
userSubscribeNodes = make([]*types.UserSubscribeNodeInfo, 0)
|
||||
if l.isSubscriptionExpired(userSub) {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package subscribe
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFillUserSubscribeInfoEntitlementFields(t *testing.T) {
|
||||
sub := &types.UserSubscribeInfo{}
|
||||
entitlement := &commonLogic.EntitlementContext{
|
||||
EffectiveUserID: 3001,
|
||||
Source: commonLogic.EntitlementSourceFamilyOwner,
|
||||
OwnerUserID: 3001,
|
||||
ReadOnly: true,
|
||||
}
|
||||
|
||||
fillUserSubscribeInfoEntitlementFields(sub, entitlement)
|
||||
|
||||
require.Equal(t, commonLogic.EntitlementSourceFamilyOwner, sub.EntitlementSource)
|
||||
require.Equal(t, int64(3001), sub.EntitlementOwnerUserId)
|
||||
require.True(t, sub.ReadOnly)
|
||||
}
|
||||
@@ -118,6 +118,7 @@ func (h *familyBindingHelper) joinFamily(ownerUserId, memberUserId int64, source
|
||||
result := &familyJoinResult{
|
||||
OwnerUserId: ownerUserId,
|
||||
}
|
||||
removedSubscribes := make([]user.Subscribe, 0)
|
||||
|
||||
err := h.svcCtx.DB.WithContext(h.ctx).Transaction(func(tx *gorm.DB) error {
|
||||
ownerFamily, err := h.getOrCreateOwnerFamily(tx, ownerUserId)
|
||||
@@ -166,20 +167,24 @@ func (h *familyBindingHelper) joinFamily(ownerUserId, memberUserId int64, source
|
||||
if err = tx.Create(&memberRecord).Error; err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseInsertError), "create family member failed")
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
if memberRecord.FamilyId != ownerFamily.Id {
|
||||
memberRecord.FamilyId = ownerFamily.Id
|
||||
}
|
||||
memberRecord.Status = user.FamilyMemberActive
|
||||
memberRecord.Role = user.FamilyRoleMember
|
||||
memberRecord.JoinSource = source
|
||||
memberRecord.JoinedAt = now
|
||||
memberRecord.LeftAt = nil
|
||||
memberRecord.DeletedAt = gorm.DeletedAt{}
|
||||
if err = tx.Unscoped().Save(&memberRecord).Error; err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update family member failed")
|
||||
}
|
||||
}
|
||||
|
||||
if memberRecord.FamilyId != ownerFamily.Id {
|
||||
memberRecord.FamilyId = ownerFamily.Id
|
||||
}
|
||||
memberRecord.Status = user.FamilyMemberActive
|
||||
memberRecord.Role = user.FamilyRoleMember
|
||||
memberRecord.JoinSource = source
|
||||
memberRecord.JoinedAt = now
|
||||
memberRecord.LeftAt = nil
|
||||
memberRecord.DeletedAt = gorm.DeletedAt{}
|
||||
if err = tx.Unscoped().Save(&memberRecord).Error; err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update family member failed")
|
||||
removedSubscribes, err = clearMemberSubscribes(tx, memberUserId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -187,9 +192,63 @@ func (h *familyBindingHelper) joinFamily(ownerUserId, memberUserId int64, source
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = h.clearRemovedMemberSubscribeCache(removedSubscribes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func clearMemberSubscribes(tx *gorm.DB, memberUserId int64) ([]user.Subscribe, error) {
|
||||
var subscribes []user.Subscribe
|
||||
if err := tx.Model(&user.Subscribe{}).
|
||||
Where("user_id = ?", memberUserId).
|
||||
Find(&subscribes).Error; err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query member subscribe list failed")
|
||||
}
|
||||
if len(subscribes) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if err := tx.Where("user_id = ?", memberUserId).Delete(&user.Subscribe{}).Error; err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "delete member subscribe list failed")
|
||||
}
|
||||
return subscribes, nil
|
||||
}
|
||||
|
||||
func (h *familyBindingHelper) clearRemovedMemberSubscribeCache(removedSubscribes []user.Subscribe) error {
|
||||
if len(removedSubscribes) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
subscribeModels, subscribeIDSet := buildRemovedSubscribeCacheMeta(removedSubscribes)
|
||||
|
||||
if err := h.svcCtx.UserModel.ClearSubscribeCache(h.ctx, subscribeModels...); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "clear member subscribe cache failed")
|
||||
}
|
||||
for subscribeID := range subscribeIDSet {
|
||||
if err := h.svcCtx.SubscribeModel.ClearCache(h.ctx, subscribeID); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "clear subscribe cache failed")
|
||||
}
|
||||
}
|
||||
if err := h.svcCtx.NodeModel.ClearServerAllCache(h.ctx); err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "clear node cache failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildRemovedSubscribeCacheMeta(removedSubscribes []user.Subscribe) ([]*user.Subscribe, map[int64]struct{}) {
|
||||
subscribeModels := make([]*user.Subscribe, 0, len(removedSubscribes))
|
||||
subscribeIDSet := make(map[int64]struct{}, len(removedSubscribes))
|
||||
for i := range removedSubscribes {
|
||||
subscribeModels = append(subscribeModels, &removedSubscribes[i])
|
||||
if removedSubscribes[i].SubscribeId > 0 {
|
||||
subscribeIDSet[removedSubscribes[i].SubscribeId] = struct{}{}
|
||||
}
|
||||
}
|
||||
return subscribeModels, subscribeIDSet
|
||||
}
|
||||
|
||||
func (h *familyBindingHelper) getOrCreateOwnerFamily(tx *gorm.DB, ownerUserId int64) (*user.UserFamily, error) {
|
||||
var ownerFamily user.UserFamily
|
||||
err := tx.Unscoped().Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
|
||||
@@ -105,3 +105,24 @@ func TestValidateMemberJoinConflict(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildRemovedSubscribeCacheMeta(t *testing.T) {
|
||||
removed := []modelUser.Subscribe{
|
||||
{Id: 1, SubscribeId: 10, Token: "member-token-1"},
|
||||
{Id: 2, SubscribeId: 11, Token: "member-token-2"},
|
||||
{Id: 3, SubscribeId: 0, Token: "member-token-3"},
|
||||
}
|
||||
|
||||
models, subscribeIDSet := buildRemovedSubscribeCacheMeta(removed)
|
||||
|
||||
require.Len(t, models, 3)
|
||||
require.Equal(t, int64(1), models[0].Id)
|
||||
require.Equal(t, "member-token-2", models[1].Token)
|
||||
require.Len(t, subscribeIDSet, 2)
|
||||
_, has10 := subscribeIDSet[10]
|
||||
_, has11 := subscribeIDSet[11]
|
||||
_, has0 := subscribeIDSet[0]
|
||||
require.True(t, has10)
|
||||
require.True(t, has11)
|
||||
require.False(t, has0)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package user
|
||||
import (
|
||||
"context"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
@@ -37,7 +38,8 @@ func (l *GetSubscribeStatusLogic) GetSubscribeStatus(req *types.GetSubscribeStat
|
||||
deviceStatus := false
|
||||
if len(u.UserDevices) > 0 {
|
||||
if dev, err := l.svcCtx.UserModel.FindOneDeviceByIdentifier(l.ctx, u.UserDevices[0].Identifier); err == nil && dev.Id > 0 {
|
||||
subscribes, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, dev.UserId)
|
||||
effectiveUserID := l.resolveEntitlementUserID(dev.UserId)
|
||||
subscribes, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, effectiveUserID)
|
||||
if err == nil {
|
||||
deviceStatus = len(subscribes) > 0
|
||||
}
|
||||
@@ -48,7 +50,8 @@ func (l *GetSubscribeStatusLogic) GetSubscribeStatus(req *types.GetSubscribeStat
|
||||
emailStatus := false
|
||||
if req.Email != "" {
|
||||
if auth, err := l.svcCtx.UserModel.FindUserAuthMethodByOpenID(l.ctx, "email", req.Email); err == nil && auth.Id > 0 {
|
||||
subscribes, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, auth.UserId)
|
||||
effectiveUserID := l.resolveEntitlementUserID(auth.UserId)
|
||||
subscribes, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, effectiveUserID)
|
||||
if err == nil {
|
||||
emailStatus = len(subscribes) > 0
|
||||
}
|
||||
@@ -61,3 +64,12 @@ func (l *GetSubscribeStatusLogic) GetSubscribeStatus(req *types.GetSubscribeStat
|
||||
EmailStatus: emailStatus,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *GetSubscribeStatusLogic) resolveEntitlementUserID(userID int64) int64 {
|
||||
entitlement, err := commonLogic.ResolveEntitlementUser(l.ctx, l.svcCtx.DB, userID)
|
||||
if err != nil {
|
||||
l.Errorw("resolve family entitlement failed", logger.Field("user_id", userID), logger.Field("error", err.Error()))
|
||||
return userID
|
||||
}
|
||||
return entitlement.EffectiveUserID
|
||||
}
|
||||
|
||||
@@ -3,9 +3,14 @@ package user
|
||||
import (
|
||||
"context"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type PreUnsubscribeLogic struct {
|
||||
@@ -24,6 +29,15 @@ func NewPreUnsubscribeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Pr
|
||||
}
|
||||
|
||||
func (l *PreUnsubscribeLogic) PreUnsubscribe(req *types.PreUnsubscribeRequest) (resp *types.PreUnsubscribeResponse, err error) {
|
||||
u, ok := l.ctx.Value(constant.CtxKeyUser).(*user.User)
|
||||
if !ok {
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err = commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
remainingAmount, err := CalculateRemainingAmount(l.ctx, l.svcCtx, req.Id)
|
||||
if err != nil {
|
||||
l.Errorw("[PreUnsubscribeLogic] Calculate Remaining Amount Error:", logger.Field("err", err.Error()))
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
@@ -37,7 +38,12 @@ func (l *QueryUserSubscribeLogic) QueryUserSubscribe() (resp *types.QueryUserSub
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
data, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, u.Id, 0, 1, 2, 3)
|
||||
entitlement, err := commonLogic.ResolveEntitlementUser(l.ctx, l.svcCtx.DB, u.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, entitlement.EffectiveUserID, 0, 1, 2, 3)
|
||||
if err != nil {
|
||||
l.Errorw("[QueryUserSubscribeLogic] Query User Subscribe Error:", logger.Field("err", err.Error()))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "Query User Subscribe Error")
|
||||
@@ -71,12 +77,22 @@ func (l *QueryUserSubscribeLogic) QueryUserSubscribe() (resp *types.QueryUserSub
|
||||
}
|
||||
}
|
||||
|
||||
fillUserSubscribeEntitlementFields(&sub, entitlement)
|
||||
sub.ResetTime = calculateNextResetTime(&sub)
|
||||
resp.List = append(resp.List, sub)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func fillUserSubscribeEntitlementFields(sub *types.UserSubscribe, entitlement *commonLogic.EntitlementContext) {
|
||||
if sub == nil || entitlement == nil {
|
||||
return
|
||||
}
|
||||
sub.EntitlementSource = entitlement.Source
|
||||
sub.EntitlementOwnerUserId = entitlement.OwnerUserID
|
||||
sub.ReadOnly = entitlement.ReadOnly
|
||||
}
|
||||
|
||||
// 计算下次重置时间
|
||||
func calculateNextResetTime(sub *types.UserSubscribe) int64 {
|
||||
resetTime := time.UnixMilli(sub.ExpireTime)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFillUserSubscribeEntitlementFields(t *testing.T) {
|
||||
sub := &types.UserSubscribe{}
|
||||
entitlement := &commonLogic.EntitlementContext{
|
||||
EffectiveUserID: 2001,
|
||||
Source: commonLogic.EntitlementSourceFamilyOwner,
|
||||
OwnerUserID: 2001,
|
||||
ReadOnly: true,
|
||||
}
|
||||
|
||||
fillUserSubscribeEntitlementFields(sub, entitlement)
|
||||
|
||||
require.Equal(t, commonLogic.EntitlementSourceFamilyOwner, sub.EntitlementSource)
|
||||
require.Equal(t, int64(2001), sub.EntitlementOwnerUserId)
|
||||
require.True(t, sub.ReadOnly)
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
@@ -40,6 +41,9 @@ func (l *ResetUserSubscribeTokenLogic) ResetUserSubscribeToken(req *types.ResetU
|
||||
logger.Error("current user is not found in context")
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err := commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
userSub, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, req.UserSubscribeId)
|
||||
if err != nil {
|
||||
l.Errorw("FindOneUserSubscribe failed:", logger.Field("error", err.Error()))
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/log"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
@@ -41,6 +42,9 @@ func (l *UnsubscribeLogic) Unsubscribe(req *types.UnsubscribeRequest) error {
|
||||
logger.Error("current user is not found in context")
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err := commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// find user subscription by ID
|
||||
userSub, err := l.svcCtx.UserModel.FindOneSubscribe(l.ctx, req.Id)
|
||||
|
||||
@@ -3,6 +3,7 @@ package user
|
||||
import (
|
||||
"context"
|
||||
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
@@ -35,6 +36,9 @@ func (l *UpdateUserSubscribeNoteLogic) UpdateUserSubscribeNote(req *types.Update
|
||||
logger.Error("current user is not found in context")
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
if err := commonLogic.DenyIfFamilyMemberReadonly(l.ctx, l.svcCtx.DB, u.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userSub, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, req.UserSubscribeId)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
commonLogic "github.com/perfect-panel/server/internal/logic/common"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
"github.com/perfect-panel/server/pkg/constant"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
@@ -71,7 +72,12 @@ func (l *DeviceWsConnectLogic) DeviceWsConnect(c *gin.Context) error {
|
||||
}
|
||||
//默认在线设备1
|
||||
maxDevice := 3
|
||||
subscribe, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, userInfo.Id, 1, 2)
|
||||
entitlement, err := commonLogic.ResolveEntitlementUser(l.ctx, l.svcCtx.DB, userInfo.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
subscribe, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, entitlement.EffectiveUserID, 1, 2)
|
||||
if err == nil {
|
||||
for _, sub := range subscribe {
|
||||
if time.Now().Before(sub.ExpireTime) {
|
||||
|
||||
Reference in New Issue
Block a user