// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. //go:build plus package services import ( "context" "encoding/json" "errors" "fmt" teaconst "github.com/TeaOSLab/EdgeAPI/internal/const" "github.com/TeaOSLab/EdgeAPI/internal/db/models" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/userconfigs" "github.com/iwind/TeaGo/types" ) // PlanService 套餐相关服务 type PlanService struct { BaseService } // CreatePlan 创建套餐 func (this *PlanService) CreatePlan(ctx context.Context, req *pb.CreatePlanRequest) (*pb.CreatePlanResponse, error) { if !teaconst.IsPlus { return nil, this.NotImplementedYet() } _, err := this.ValidateAdmin(ctx) if err != nil { return nil, err } // check features if len(req.FeaturesJSON) > 0 { var featureCodes = []string{} err = json.Unmarshal(req.FeaturesJSON, &featureCodes) if err != nil { return nil, fmt.Errorf("decode features failed: %w", err) } for _, featureCode := range featureCodes { if !userconfigs.CheckUserFeature(featureCode) { return nil, errors.New("wrong feature code '" + featureCode + "'") } } } var tx = this.NullTx() planId, err := models.SharedPlanDAO.CreatePlan(tx, req.Name, req.Description, req.ClusterId, req.TrafficLimitJSON, req.BandwidthLimitPerNodeJSON, req.HasFullFeatures, req.FeaturesJSON, req.PriceType, req.TrafficPriceJSON, req.BandwidthPriceJSON, req.MonthlyPrice, req.SeasonallyPrice, req.YearlyPrice, req.TotalServers, req.TotalServerNames, req.TotalServerNamesPerServer, req.DailyRequests, req.MonthlyRequests, req.DailyWebsocketConnections, req.MonthlyWebsocketConnections, req.MaxUploadSizeJSON) if err != nil { return nil, err } return &pb.CreatePlanResponse{PlanId: planId}, nil } // UpdatePlan 修改套餐 func (this *PlanService) UpdatePlan(ctx context.Context, req *pb.UpdatePlanRequest) (*pb.RPCSuccess, error) { if !teaconst.IsPlus { return nil, this.NotImplementedYet() } _, err := this.ValidateAdmin(ctx) if err != nil { return nil, err } // check features if len(req.FeaturesJSON) > 0 { var featureCodes = []string{} err = json.Unmarshal(req.FeaturesJSON, &featureCodes) if err != nil { return nil, fmt.Errorf("decode features failed: %w", err) } for _, featureCode := range featureCodes { if !userconfigs.CheckUserFeature(featureCode) { return nil, errors.New("wrong feature code '" + featureCode + "'") } } } var tx = this.NullTx() err = models.SharedPlanDAO.UpdatePlan(tx, req.PlanId, req.Name, req.Description, req.IsOn, req.ClusterId, req.TrafficLimitJSON, req.BandwidthLimitPerNodeJSON, req.HasFullFeatures, req.FeaturesJSON, req.PriceType, req.TrafficPriceJSON, req.BandwidthPriceJSON, req.MonthlyPrice, req.SeasonallyPrice, req.YearlyPrice, req.TotalServers, req.TotalServerNames, req.TotalServerNamesPerServer, req.DailyRequests, req.MonthlyRequests, req.DailyWebsocketConnections, req.MonthlyWebsocketConnections, req.MaxUploadSizeJSON) if err != nil { return nil, err } return this.Success() } // DeletePlan 删除套餐 func (this *PlanService) DeletePlan(ctx context.Context, req *pb.DeletePlanRequest) (*pb.RPCSuccess, error) { if !teaconst.IsPlus { return nil, this.NotImplementedYet() } _, err := this.ValidateAdmin(ctx) if err != nil { return nil, err } var tx = this.NullTx() err = models.SharedPlanDAO.DisablePlan(tx, req.PlanId) if err != nil { return nil, err } return this.Success() } // FindEnabledPlan 查找单个套餐 func (this *PlanService) FindEnabledPlan(ctx context.Context, req *pb.FindEnabledPlanRequest) (*pb.FindEnabledPlanResponse, error) { _, _, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() plan, err := models.SharedPlanDAO.FindEnabledPlan(tx, req.PlanId, nil) if err != nil { return nil, err } if plan == nil { return &pb.FindEnabledPlanResponse{Plan: nil}, nil } return &pb.FindEnabledPlanResponse{ Plan: &pb.Plan{ Id: int64(plan.Id), IsOn: plan.IsOn, Name: plan.Name, Description: plan.Description, ClusterId: int64(plan.ClusterId), TrafficLimitJSON: plan.TrafficLimit, BandwidthLimitPerNodeJSON: plan.BandwidthLimitPerNode, HasFullFeatures: plan.HasFullFeatures, FeaturesJSON: plan.Features, PriceType: plan.PriceType, TrafficPriceJSON: plan.TrafficPrice, BandwidthPriceJSON: plan.BandwidthPrice, MonthlyPrice: plan.MonthlyPrice, SeasonallyPrice: plan.SeasonallyPrice, YearlyPrice: plan.YearlyPrice, TotalServers: types.Int32(plan.TotalServers), TotalServerNames: types.Int32(plan.TotalServerNames), TotalServerNamesPerServer: types.Int32(plan.TotalServerNamesPerServer), DailyRequests: int64(plan.DailyRequests), MonthlyRequests: int64(plan.MonthlyRequests), DailyWebsocketConnections: int64(plan.DailyWebsocketConnections), MonthlyWebsocketConnections: int64(plan.MonthlyWebsocketConnections), MaxUploadSizeJSON: plan.MaxUploadSize, }, }, nil } // FindBasicPlan 查找套餐基本信息 func (this *PlanService) FindBasicPlan(ctx context.Context, req *pb.FindBasicPlanRequest) (*pb.FindBasicPlanResponse, error) { _, _, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() plan, err := models.SharedPlanDAO.FindBasicPlan(tx, req.PlanId) if err != nil { return nil, err } if plan == nil { return &pb.FindBasicPlanResponse{Plan: nil}, nil } return &pb.FindBasicPlanResponse{ Plan: &pb.Plan{ Id: int64(plan.Id), Name: plan.Name, IsOn: plan.IsOn, }, }, nil } // CountAllEnabledPlans 计算套餐数量 func (this *PlanService) CountAllEnabledPlans(ctx context.Context, req *pb.CountAllEnabledPlansRequest) (*pb.RPCCountResponse, error) { _, err := this.ValidateAdmin(ctx) if err != nil { return nil, err } var tx = this.NullTx() count, err := models.SharedPlanDAO.CountAllEnabledPlans(tx) if err != nil { return nil, err } return this.SuccessCount(count) } // ListEnabledPlans 列出单页套餐 func (this *PlanService) ListEnabledPlans(ctx context.Context, req *pb.ListEnabledPlansRequest) (*pb.ListEnabledPlansResponse, error) { _, _, err := this.ValidateAdminAndUser(ctx, false) if err != nil { return nil, err } var tx = this.NullTx() plans, err := models.SharedPlanDAO.ListEnabledPlans(tx, req.Offset, req.Size) if err != nil { return nil, err } var pbPlans = []*pb.Plan{} for _, plan := range plans { pbPlans = append(pbPlans, &pb.Plan{ Id: int64(plan.Id), IsOn: plan.IsOn, Name: plan.Name, Description: plan.Description, ClusterId: int64(plan.ClusterId), TrafficLimitJSON: plan.TrafficLimit, BandwidthLimitPerNodeJSON: plan.BandwidthLimitPerNode, HasFullFeatures: plan.HasFullFeatures, FeaturesJSON: plan.Features, PriceType: plan.PriceType, TrafficPriceJSON: plan.TrafficPrice, BandwidthPriceJSON: plan.BandwidthPrice, MonthlyPrice: plan.MonthlyPrice, SeasonallyPrice: plan.SeasonallyPrice, YearlyPrice: plan.YearlyPrice, TotalServers: types.Int32(plan.TotalServers), TotalServerNames: types.Int32(plan.TotalServerNames), TotalServerNamesPerServer: types.Int32(plan.TotalServerNamesPerServer), DailyRequests: int64(plan.DailyRequests), MonthlyRequests: int64(plan.MonthlyRequests), DailyWebsocketConnections: int64(plan.DailyWebsocketConnections), MonthlyWebsocketConnections: int64(plan.MonthlyWebsocketConnections), MaxUploadSizeJSON: plan.MaxUploadSize, }) } return &pb.ListEnabledPlansResponse{Plans: pbPlans}, nil } // FindAllAvailablePlans 列出所有可用的套餐 func (this *PlanService) FindAllAvailablePlans(ctx context.Context, req *pb.FindAllAvailablePlansRequest) (*pb.FindAllAvailablePlansResponse, error) { _, _, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() plans, err := models.SharedPlanDAO.FindAllAvailablePlans(tx) if err != nil { return nil, err } var pbPlans = []*pb.Plan{} for _, plan := range plans { pbPlans = append(pbPlans, &pb.Plan{ Id: int64(plan.Id), IsOn: plan.IsOn, Name: plan.Name, Description: plan.Description, ClusterId: int64(plan.ClusterId), TrafficLimitJSON: plan.TrafficLimit, BandwidthLimitPerNodeJSON: plan.BandwidthLimitPerNode, HasFullFeatures: plan.HasFullFeatures, FeaturesJSON: plan.Features, PriceType: plan.PriceType, TrafficPriceJSON: plan.TrafficPrice, BandwidthPriceJSON: plan.BandwidthPrice, MonthlyPrice: plan.MonthlyPrice, SeasonallyPrice: plan.SeasonallyPrice, YearlyPrice: plan.YearlyPrice, TotalServers: types.Int32(plan.TotalServers), TotalServerNames: types.Int32(plan.TotalServerNames), TotalServerNamesPerServer: types.Int32(plan.TotalServerNamesPerServer), DailyRequests: int64(plan.DailyRequests), MonthlyRequests: int64(plan.MonthlyRequests), DailyWebsocketConnections: int64(plan.DailyWebsocketConnections), MonthlyWebsocketConnections: int64(plan.MonthlyWebsocketConnections), MaxUploadSizeJSON: plan.MaxUploadSize, }) } return &pb.FindAllAvailablePlansResponse{Plans: pbPlans}, nil } // FindAllAvailableBasicPlans 列出所有可用的套餐的基本信息 func (this *PlanService) FindAllAvailableBasicPlans(ctx context.Context, req *pb.FindAllAvailableBasicPlansRequest) (*pb.FindAllAvailableBasicPlansResponse, error) { _, err := this.ValidateNode(ctx) if err != nil { return nil, err } var tx = this.NullTx() plans, err := models.SharedPlanDAO.FindAllAvailableBasicPlans(tx) if err != nil { return nil, err } var pbPlans = []*pb.Plan{} for _, plan := range plans { pbPlans = append(pbPlans, &pb.Plan{ Id: int64(plan.Id), Name: plan.Name, BandwidthLimitPerNodeJSON: plan.BandwidthLimitPerNode, TrafficLimitJSON: plan.TrafficLimit, MaxUploadSizeJSON: plan.MaxUploadSize, }) } return &pb.FindAllAvailableBasicPlansResponse{Plans: pbPlans}, nil } // SortPlans 对套餐进行排序 func (this *PlanService) SortPlans(ctx context.Context, req *pb.SortPlansRequest) (*pb.RPCSuccess, error) { _, err := this.ValidateAdmin(ctx) if err != nil { return nil, err } var tx = this.NullTx() err = models.SharedPlanDAO.SortPlans(tx, req.PlanIds) if err != nil { return nil, err } return this.Success() }