diff --git a/internal/db/models/plan_dao.go b/internal/db/models/plan_dao.go index a12f13ec..82f07542 100644 --- a/internal/db/models/plan_dao.go +++ b/internal/db/models/plan_dao.go @@ -49,7 +49,11 @@ func (this *PlanDAO) DisablePlan(tx *dbs.Tx, id int64) error { Pk(id). Set("state", PlanStateDisabled). Update() - return err + if err != nil { + return err + } + + return this.NotifyUpdate(tx, id) } // FindEnabledPlan 查找启用中的条目 @@ -106,6 +110,16 @@ func (this *PlanDAO) UpdatePlan(tx *dbs.Tx, planId int64, name string, isOn bool if planId <= 0 { return errors.New("invalid planId") } + + // 检查集群有无变化 + oldClusterId, err := this.Query(tx). + Pk(planId). + Result("clusterId"). + FindInt64Col(0) + if err != nil { + return err + } + var op = NewPlanOperator() op.Id = planId op.Name = name @@ -136,7 +150,25 @@ func (this *PlanDAO) UpdatePlan(tx *dbs.Tx, planId int64, name string, isOn bool } else { op.YearlyPrice = 0 } - return this.Save(tx, op) + err = this.Save(tx, op) + if err != nil { + return err + } + + if oldClusterId != clusterId { + // 修改服务所属集群 + err = SharedServerDAO.UpdateServersClusterIdWithPlanId(tx, planId, clusterId) + if err != nil { + return err + } + + err = SharedNodeClusterDAO.NotifyUpdate(tx, oldClusterId) + if err != nil { + return err + } + } + + return this.NotifyUpdate(tx, planId) } // CountAllEnabledPlans 计算套餐的数量 @@ -177,3 +209,19 @@ func (this *PlanDAO) SortPlans(tx *dbs.Tx, planIds []int64) error { } return nil } + +// NotifyUpdate 通知变更 +func (this *PlanDAO) NotifyUpdate(tx *dbs.Tx, planId int64) error { + // 这里不要加入状态参数,因为需要适应删除后的更新 + clusterId, err := this.Query(tx). + Pk(planId). + Result("clusterId"). + FindInt64Col(0) + if err != nil { + return err + } + if clusterId > 0 { + return SharedNodeClusterDAO.NotifyUpdate(tx, clusterId) + } + return nil +} diff --git a/internal/db/models/server_dao.go b/internal/db/models/server_dao.go index c591bbd3..c316a12b 100644 --- a/internal/db/models/server_dao.go +++ b/internal/db/models/server_dao.go @@ -149,7 +149,8 @@ func (this *ServerDAO) CreateServer(tx *dbs.Tx, clusterId int64, includeNodesJSON string, excludeNodesJSON string, - groupIds []int64) (serverId int64, err error) { + groupIds []int64, + userPlanId int64) (serverId int64, err error) { op := NewServerOperator() op.UserId = userId op.AdminId = adminId @@ -211,6 +212,8 @@ func (this *ServerDAO) CreateServer(tx *dbs.Tx, } op.DnsName = dnsName + op.UserPlanId = userPlanId + op.Version = 1 op.IsOn = 1 op.State = ServerStateEnabled @@ -1051,6 +1054,22 @@ func (this *ServerDAO) ComposeServerConfig(tx *dbs.Tx, server *Server, cacheMap } } + // 用户套餐 + if server.UserPlanId > 0 { + userPlan, err := SharedUserPlanDAO.FindEnabledUserPlan(tx, int64(server.UserPlanId)) + if err != nil { + return nil, err + } + if userPlan != nil { + if len(userPlan.DayTo) == 0 { + userPlan.DayTo = DefaultUserPlanMaxDay + } + config.UserPlan = &serverconfigs.UserPlanConfig{ + DayTo: userPlan.DayTo, + } + } + } + return config, nil } @@ -1378,6 +1397,14 @@ func (this *ServerDAO) FindServerUserId(tx *dbs.Tx, serverId int64) (userId int6 return one.GetInt64("userId"), nil } +// FindServerUserPlanId 查找服务的套餐ID +func (this *ServerDAO) FindServerUserPlanId(tx *dbs.Tx, serverId int64) (userPlanId int64, err error) { + return this.Query(tx). + Pk(serverId). + Result("userPlanId"). + FindInt64Col(0) +} + // CheckUserServer 检查用户服务 func (this *ServerDAO) CheckUserServer(tx *dbs.Tx, userId int64, serverId int64) error { if serverId <= 0 || userId <= 0 { @@ -1928,6 +1955,53 @@ func (this *ServerDAO) ResetServerTotalBandwidth(tx *dbs.Tx, serverId int64) err UpdateQuickly() } +// FindEnabledServerIdWithUserPlanId 查找使用某个套餐的服务 +func (this *ServerDAO) FindEnabledServerIdWithUserPlanId(tx *dbs.Tx, userPlanId int64) (int64, error) { + return this.Query(tx). + State(ServerStateEnabled). + Attr("userPlanId", userPlanId). + ResultPk(). + FindInt64Col(0) +} + +// UpdateServersClusterIdWithPlanId 修改套餐所在集群 +func (this *ServerDAO) UpdateServersClusterIdWithPlanId(tx *dbs.Tx, planId int64, clusterId int64) error { + return this.Query(tx). + Where("userPlanId IN (SELECT id FROM "+SharedUserPlanDAO.Table+" WHERE planId=:planId AND state=1)"). + Param("planId", planId). + Set("clusterId", clusterId). + UpdateQuickly() +} + +// UpdateServerUserPlanId 设置服务所属套餐 +func (this *ServerDAO) UpdateServerUserPlanId(tx *dbs.Tx, serverId int64, userPlanId int64) error { + userPlan, err := SharedUserPlanDAO.FindEnabledUserPlan(tx, userPlanId) + if err != nil { + return err + } + if userPlan == nil { + return errors.New("can not find user plan with id '" + types.String(userPlanId) + "'") + } + + plan, err := SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId)) + if err != nil { + return err + } + if plan == nil { + return errors.New("can not find plan with id '" + types.String(userPlan.PlanId) + "'") + } + + err = this.Query(tx). + Pk(serverId). + Set("userPlanId", userPlanId). + Set("clusterId", plan.ClusterId). + UpdateQuickly() + if err != nil { + return err + } + return this.NotifyUpdate(tx, serverId) +} + // NotifyUpdate 同步集群 func (this *ServerDAO) NotifyUpdate(tx *dbs.Tx, serverId int64) error { // 创建任务 diff --git a/internal/db/models/user_plan_dao.go b/internal/db/models/user_plan_dao.go index 6ef1b056..6bac9fe1 100644 --- a/internal/db/models/user_plan_dao.go +++ b/internal/db/models/user_plan_dao.go @@ -12,6 +12,8 @@ import ( const ( UserPlanStateEnabled = 1 // 已启用 UserPlanStateDisabled = 0 // 已禁用 + + DefaultUserPlanMaxDay = "3000-01-01" ) type UserPlanDAO dbs.DAO @@ -50,13 +52,16 @@ func (this *UserPlanDAO) DisableUserPlan(tx *dbs.Tx, id int64) error { Pk(id). Set("state", UserPlanStateDisabled). Update() - return err + if err != nil { + return err + } + return this.NotifyUpdate(tx, id) } // FindEnabledUserPlan 查找启用中的条目 -func (this *UserPlanDAO) FindEnabledUserPlan(tx *dbs.Tx, id int64) (*UserPlan, error) { +func (this *UserPlanDAO) FindEnabledUserPlan(tx *dbs.Tx, userPlanId int64) (*UserPlan, error) { result, err := this.Query(tx). - Pk(id). + Pk(userPlanId). Attr("state", UserPlanStateEnabled). Find() if result == nil { @@ -87,11 +92,14 @@ func (this *UserPlanDAO) CountAllEnabledUserPlans(tx *dbs.Tx, isAvailable bool, } // ListEnabledUserPlans 列出单页套餐 -func (this *UserPlanDAO) ListEnabledUserPlans(tx *dbs.Tx, isAvailable bool, isExpired bool, expiringDays int32, offset int64, size int64) (result []*UserPlan, err error) { +func (this *UserPlanDAO) ListEnabledUserPlans(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int32, offset int64, size int64) (result []*UserPlan, err error) { var query = this.Query(tx). State(UserPlanStateEnabled). Where("userId IN (SELECT id FROM " + SharedUserDAO.Table + " WHERE state=1)"). Where("planId IN (SELECT id FROM " + SharedPlanDAO.Table + " WHERE state=1)") + if userId > 0 { + query.Attr("userId", userId) + } var today = timeutil.Format("Y-m-d") if isAvailable { query.Gte("dayTo", today) @@ -134,7 +142,11 @@ func (this *UserPlanDAO) UpdateUserPlan(tx *dbs.Tx, userPlanId int64, planId int op.PlanId = planId op.DayTo = dayTo op.IsOn = isOn - return this.Save(tx, op) + err := this.Save(tx, op) + if err != nil { + return err + } + return this.NotifyUpdate(tx, userPlanId) } // UpdateUserPlanDayTo 修改套餐日期 @@ -145,5 +157,40 @@ func (this *UserPlanDAO) UpdateUserPlanDayTo(tx *dbs.Tx, userPlanId int64, dayTo var op = NewUserPlanOperator() op.Id = userPlanId op.DayTo = dayTo - return this.Save(tx, op) + err := this.Save(tx, op) + if err != nil { + return err + } + return this.NotifyUpdate(tx, userPlanId) +} + +// FindAllEnabledPlansForServer 列出服务可用的套餐 +func (this *UserPlanDAO) FindAllEnabledPlansForServer(tx *dbs.Tx, userId int64, serverId int64) (result []*UserPlan, err error) { + var query = this.Query(tx). + State(UserPlanStateEnabled). + Attr("userId", userId). + Where("planId IN (SELECT id FROM " + SharedPlanDAO.Table + " WHERE state=1)") + if serverId > 0 { + query.Where("id NOT IN (SELECT userPlanId FROM " + SharedServerDAO.Table + " WHERE state=1 AND id!=:serverId)") + query.Param("serverId", serverId) + } else { + query.Where("id NOT IN (SELECT userPlanId FROM " + SharedServerDAO.Table + " WHERE state=1)") + } + _, err = query. + DescPk(). + Slice(&result). + FindAll() + return +} + +// NotifyUpdate 通知更新 +func (this *UserPlanDAO) NotifyUpdate(tx *dbs.Tx, userPlanId int64) error { + serverId, err := SharedServerDAO.FindEnabledServerIdWithUserPlanId(tx, userPlanId) + if err != nil { + return err + } + if serverId > 0 { + return SharedServerDAO.NotifyUpdate(tx, serverId) + } + return nil } diff --git a/internal/rpc/services/service_server.go b/internal/rpc/services/service_server.go index 4bf1a2ab..f3b04005 100644 --- a/internal/rpc/services/service_server.go +++ b/internal/rpc/services/service_server.go @@ -61,6 +61,24 @@ func (this *ServerService) CreateServer(ctx context.Context, req *pb.CreateServe } } } + + // 集群 + nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, userId) + if err != nil { + return nil, err + } + if nodeClusterId > 0 { + req.NodeClusterId = nodeClusterId + } + } else if req.UserId > 0 { + // 集群 + nodeClusterId, err := models.SharedUserDAO.FindUserClusterId(tx, req.UserId) + if err != nil { + return nil, err + } + if nodeClusterId > 0 { + req.NodeClusterId = nodeClusterId + } } // 是否需要审核 @@ -82,7 +100,45 @@ func (this *ServerService) CreateServer(ctx context.Context, req *pb.CreateServe } } - serverId, err := models.SharedServerDAO.CreateServer(tx, req.AdminId, req.UserId, req.Type, req.Name, req.Description, serverNamesJSON, isAuditing, auditingServerNamesJSON, string(req.HttpJSON), string(req.HttpsJSON), string(req.TcpJSON), string(req.TlsJSON), string(req.UnixJSON), string(req.UdpJSON), req.WebId, req.ReverseProxyJSON, req.NodeClusterId, string(req.IncludeNodesJSON), string(req.ExcludeNodesJSON), req.ServerGroupIds) + // 校验用户套餐 + if req.UserPlanId > 0 { + userPlan, err := models.SharedUserPlanDAO.FindEnabledUserPlan(tx, req.UserPlanId) + if err != nil { + return nil, err + } + if userPlan == nil { + return nil, errors.New("can not find user plan with id '" + types.String(req.UserPlanId) + "'") + } + if userId > 0 && int64(userPlan.UserId) != userId { + return nil, errors.New("invalid user plan") + } + if req.UserId > 0 && int64(userPlan.UserId) != req.UserId { + return nil, errors.New("invalid user plan") + } + + // 套餐 + plan, err := models.SharedPlanDAO.FindEnabledPlan(tx, int64(userPlan.PlanId)) + if err != nil { + return nil, err + } + if plan == nil { + return nil, errors.New("invalid plan: " + types.String(userPlan.PlanId)) + } + if plan.ClusterId > 0 { + req.NodeClusterId = int64(plan.ClusterId) + } + + // 检查是否已经被别的服务所占用 + planServerId, err := models.SharedServerDAO.FindEnabledServerIdWithUserPlanId(tx, req.UserPlanId) + if err != nil { + return nil, err + } + if planServerId > 0 { + return nil, errors.New("the user plan is used by another server '" + types.String(planServerId) + "'") + } + } + + serverId, err := models.SharedServerDAO.CreateServer(tx, req.AdminId, req.UserId, req.Type, req.Name, req.Description, serverNamesJSON, isAuditing, auditingServerNamesJSON, string(req.HttpJSON), string(req.HttpsJSON), string(req.TcpJSON), string(req.TlsJSON), string(req.UnixJSON), string(req.UdpJSON), req.WebId, req.ReverseProxyJSON, req.NodeClusterId, string(req.IncludeNodesJSON), string(req.ExcludeNodesJSON), req.ServerGroupIds, req.UserPlanId) if err != nil { return nil, err } @@ -738,13 +794,15 @@ func (this *ServerService) FindEnabledServer(ctx context.Context, req *pb.FindEn } return &pb.FindEnabledServerResponse{Server: &pb.Server{ - Id: int64(server.Id), - IsOn: server.IsOn == 1, - Type: server.Type, - Name: server.Name, - Description: server.Description, - DnsName: server.DnsName, - SupportCNAME: server.SupportCNAME == 1, + Id: int64(server.Id), + IsOn: server.IsOn == 1, + Type: server.Type, + Name: server.Name, + Description: server.Description, + DnsName: server.DnsName, + SupportCNAME: server.SupportCNAME == 1, + UserPlanId: int64(server.UserPlanId), + Config: configJSON, ServerNamesJSON: []byte(server.ServerNames), HttpJSON: []byte(server.Http), @@ -1660,6 +1718,8 @@ func (this *ServerService) FindEnabledServerBandwidthLimit(ctx context.Context, return nil, err } + // TODO 检查用户权限 + var tx = this.NullTx() limitConfig, err := models.SharedServerDAO.FindServerBandwidthLimitConfig(tx, req.ServerId, nil) if err != nil { @@ -1676,7 +1736,7 @@ func (this *ServerService) FindEnabledServerBandwidthLimit(ctx context.Context, // UpdateServerBandwidthLimit 设置带宽限制 func (this *ServerService) UpdateServerBandwidthLimit(ctx context.Context, req *pb.UpdateServerBandwidthLimitRequest) (*pb.RPCSuccess, error) { - _, _, err := this.ValidateAdminAndUser(ctx, 0, 0) + _, err := this.ValidateAdmin(ctx, 0) if err != nil { return nil, err } @@ -1692,5 +1752,69 @@ func (this *ServerService) UpdateServerBandwidthLimit(ctx context.Context, req * if err != nil { return nil, err } + return this.Success() +} + +// UpdateServerUserPlan 修改服务套餐 +func (this *ServerService) UpdateServerUserPlan(ctx context.Context, req *pb.UpdateServerUserPlanRequest) (*pb.RPCSuccess, error) { + _, err := this.ValidateAdmin(ctx, 0) + if err != nil { + return nil, err + } + + var tx = this.NullTx() + + // TODO 支持用户调用 + + // 检查套餐 + if req.UserPlanId < 0 { + req.UserPlanId = 0 + } + if req.UserPlanId > 0 { + userId, err := models.SharedServerDAO.FindServerUserId(tx, req.ServerId) + if err != nil { + return nil, err + } + if userId == 0 { + return nil, errors.New("the server is not belong to any user") + } + + userPlan, err := models.SharedUserPlanDAO.FindEnabledUserPlan(tx, req.UserPlanId) + if err != nil { + return nil, err + } + if userPlan == nil { + return nil, errors.New("can not find user plan with id '" + types.String(req.UserPlanId) + "'") + } + if int64(userPlan.UserId) != userId { + return nil, errors.New("can not find user plan with id '" + types.String(req.UserPlanId) + "'") + } + + // 检查是否已经被别的服务所使用 + serverId, err := models.SharedServerDAO.FindEnabledServerIdWithUserPlanId(tx, req.UserPlanId) + if err != nil { + return nil, err + } + if serverId > 0 && serverId != req.ServerId { + return nil, errors.New("the user plan is used by other server") + } + } + + // 检查是否有变化 + oldUserPlanId, err := models.SharedServerDAO.FindServerUserPlanId(tx, req.ServerId) + if err != nil { + return nil, err + } + if req.UserPlanId == oldUserPlanId { + return this.Success() + } + + err = models.SharedServerDAO.UpdateServerUserPlanId(tx, req.ServerId, req.UserPlanId) + if err != nil { + return nil, err + } + + + return this.Success() } diff --git a/internal/rpc/services/service_user_plan_community.go b/internal/rpc/services/service_user_plan_community.go index de6ac94a..cb2bfe23 100644 --- a/internal/rpc/services/service_user_plan_community.go +++ b/internal/rpc/services/service_user_plan_community.go @@ -15,8 +15,13 @@ type UserPlanService struct { } // CreateUserPlan 添加已购套餐 -func (this *UserPlanService) CreateUserPlan(ctx context.Context, req *pb.CreateUserPlanRequest) (*pb.CreateUserPlanResponse, error) { - return &pb.CreateUserPlanResponse{UserPlanId: 0}, nil +func (this *UserPlanService) BuyUserPlan(ctx context.Context, req *pb.BuyUserPlanRequest) (*pb.BuyUserPlanResponse, error) { + return &pb.BuyUserPlanResponse{UserPlanId: 0}, nil +} + +// RenewUserPlan 续费套餐 +func (this *UserPlanService) RenewUserPlan(ctx context.Context, req *pb.RenewUserPlanRequest) (*pb.RPCSuccess, error) { + return this.Success() } // FindEnabledUserPlan 查找单个已购套餐信息 @@ -43,3 +48,8 @@ func (this *UserPlanService) CountAllEnabledUserPlans(ctx context.Context, req * func (this *UserPlanService) ListEnabledUserPlans(ctx context.Context, req *pb.ListEnabledUserPlansRequest) (*pb.ListEnabledUserPlansResponse, error) { return &pb.ListEnabledUserPlansResponse{UserPlans: nil}, nil } + +// FindAllEnabledUserPlansForServer 查找所有服务可用的套餐 +func (this *UserPlanService) FindAllEnabledUserPlansForServer(ctx context.Context, req *pb.FindAllEnabledUserPlansForServerRequest) (*pb.FindAllEnabledUserPlansForServerResponse, error) { + return &pb.FindAllEnabledUserPlansForServerResponse{}, nil +}