// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. //go:build plus package nameservers import ( "context" "github.com/TeaOSLab/EdgeAPI/internal/db/models" "github.com/TeaOSLab/EdgeAPI/internal/db/models/clients" "github.com/TeaOSLab/EdgeAPI/internal/db/models/nameservers" "github.com/TeaOSLab/EdgeAPI/internal/errors" "github.com/TeaOSLab/EdgeAPI/internal/rpc/services" rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils" "github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/types" "sort" ) // NSRouteService 线路相关服务 type NSRouteService struct { services.BaseService } // CreateNSRoute 创建自定义线路 func (this *NSRouteService) CreateNSRoute(ctx context.Context, req *pb.CreateNSRouteRequest) (*pb.CreateNSRouteResponse, error) { _, userId, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() if userId > 0 { req.UserId = userId // 暂时不允许在集群和域名下创建线路 req.NsClusterId = 0 req.NsDomainId = 0 } // TODO 检查线路数限制 // 检查分类是否存在 if req.NsRouteCategoryId > 0 { if userId > 0 { err = nameservers.SharedNSRouteCategoryDAO.CheckUserCategory(tx, userId, req.NsRouteCategoryId) if err != nil { return nil, err } } else { exists, err := nameservers.SharedNSRouteCategoryDAO.Exist(tx, req.NsRouteCategoryId) if err != nil { return nil, err } if !exists { return nil, errors.New("route category id '" + types.String(req.NsRouteCategoryId) + "' not found") } } } else { req.NsRouteCategoryId = 0 } routeId, err := nameservers.SharedNSRouteDAO.CreateRoute(tx, req.NsClusterId, req.NsDomainId, req.UserId, req.Name, req.RangesJSON, req.NsRouteCategoryId, req.Priority, req.IsPublic) if err != nil { return nil, err } return &pb.CreateNSRouteResponse{NsRouteId: routeId}, nil } // UpdateNSRoute 修改自定义线路 func (this *NSRouteService) UpdateNSRoute(ctx context.Context, req *pb.UpdateNSRouteRequest) (*pb.RPCSuccess, error) { _, userId, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() // 检查权限 if userId > 0 { err = nameservers.SharedNSRouteDAO.CheckUserRoute(tx, userId, req.NsRouteId) if err != nil { return nil, err } } // 检查分类是否存在 if req.NsRouteCategoryId > 0 { if userId > 0 { err = nameservers.SharedNSRouteCategoryDAO.CheckUserCategory(tx, userId, req.NsRouteCategoryId) if err != nil { return nil, err } } else { exists, err := nameservers.SharedNSRouteCategoryDAO.Exist(tx, req.NsRouteCategoryId) if err != nil { return nil, err } if !exists { return nil, errors.New("route category id '" + types.String(req.NsRouteCategoryId) + "' not found") } } } else { req.NsRouteCategoryId = 0 } err = nameservers.SharedNSRouteDAO.UpdateRoute(tx, req.NsRouteId, req.Name, req.RangesJSON, req.NsRouteCategoryId, req.Priority, req.IsPublic, req.IsOn) if err != nil { return nil, err } return this.Success() } // DeleteNSRoute 删除自定义线路 func (this *NSRouteService) DeleteNSRoute(ctx context.Context, req *pb.DeleteNSRouteRequest) (*pb.RPCSuccess, error) { _, userId, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() // 检查权限 if userId > 0 { err = nameservers.SharedNSRouteDAO.CheckUserRoute(tx, userId, req.NsRouteId) if err != nil { return nil, err } } err = nameservers.SharedNSRouteDAO.DisableNSRoute(tx, req.NsRouteId) if err != nil { return nil, err } return this.Success() } // FindNSRoute 获取单个自定义路线信息 func (this *NSRouteService) FindNSRoute(ctx context.Context, req *pb.FindNSRouteRequest) (*pb.FindNSRouteResponse, error) { _, userId, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() // 检查权限 if userId > 0 { err = nameservers.SharedNSRouteDAO.CheckUserRoute(tx, userId, req.NsRouteId) if err != nil { return nil, err } } route, err := nameservers.SharedNSRouteDAO.FindEnabledNSRoute(tx, req.NsRouteId) if err != nil { return nil, err } if route == nil { return &pb.FindNSRouteResponse{NsRoute: nil}, nil } // 集群 var pbCluster *pb.NSCluster if route.ClusterId > 0 { cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(route.ClusterId)) if err != nil { return nil, err } if cluster != nil { pbCluster = &pb.NSCluster{ Id: int64(cluster.Id), IsOn: cluster.IsOn, Name: cluster.Name, } } } // 域名 var pbDomain *pb.NSDomain if route.DomainId > 0 { domain, err := nameservers.SharedNSDomainDAO.FindEnabledNSDomain(tx, int64(route.DomainId)) if err != nil { return nil, err } if domain != nil { pbDomain = &pb.NSDomain{ Id: int64(domain.Id), Name: domain.Name, IsOn: domain.IsOn, } } } // 分类 var pbCategory *pb.NSRouteCategory if route.CategoryId > 0 { category, err := nameservers.SharedNSRouteCategoryDAO.FindCategory(tx, int64(route.CategoryId)) if err != nil { return nil, err } if category != nil { pbCategory = &pb.NSRouteCategory{ Id: int64(category.Id), Name: category.Name, IsOn: category.IsOn, } } } return &pb.FindNSRouteResponse{NsRoute: &pb.NSRoute{ Id: int64(route.Id), IsOn: route.IsOn, Name: route.Name, RangesJSON: route.Ranges, IsPublic: route.IsPublic, Priority: types.Int32(route.Priority), NsCluster: pbCluster, NsDomain: pbDomain, NsRouteCategory: pbCategory, }}, nil } // CountAllNSRoutes 查询自定义线路数量 func (this *NSRouteService) CountAllNSRoutes(ctx context.Context, req *pb.CountAllNSRoutesRequest) (*pb.RPCCountResponse, error) { _, userId, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } if userId > 0 { req.UserId = userId } var tx = this.NullTx() countRoutes, err := nameservers.SharedNSRouteDAO.CountAllEnabledRoutes(tx, req.NsClusterId, req.NsClusterId, req.UserId) if err != nil { return nil, err } return this.SuccessCount(countRoutes) } // FindAllNSRoutes 读取所有自定义线路 func (this *NSRouteService) FindAllNSRoutes(ctx context.Context, req *pb.FindAllNSRoutesRequest) (*pb.FindAllNSRoutesResponse, error) { _, userId, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() if userId > 0 { req.UserId = userId } routes, err := nameservers.SharedNSRouteDAO.FindAllEnabledRoutes(tx, req.NsClusterId, req.NsDomainId, req.UserId, req.NsRouteCategoryId) if err != nil { return nil, err } var pbRoutes = []*pb.NSRoute{} for _, route := range routes { // 集群 var pbCluster *pb.NSCluster if route.ClusterId > 0 { cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(tx, int64(route.ClusterId)) if err != nil { return nil, err } if cluster != nil { pbCluster = &pb.NSCluster{ Id: int64(cluster.Id), IsOn: cluster.IsOn, Name: cluster.Name, } } } // 域名 var pbDomain *pb.NSDomain if route.DomainId > 0 { domain, err := nameservers.SharedNSDomainDAO.FindEnabledNSDomain(tx, int64(route.DomainId)) if err != nil { return nil, err } if domain != nil { pbDomain = &pb.NSDomain{ Id: int64(domain.Id), Name: domain.Name, IsOn: domain.IsOn, } } } // 分类 var pbCategory *pb.NSRouteCategory if route.CategoryId > 0 { category, err := nameservers.SharedNSRouteCategoryDAO.FindCategory(tx, int64(route.CategoryId)) if err != nil { return nil, err } if category != nil { pbCategory = &pb.NSRouteCategory{ Id: int64(category.Id), Name: category.Name, IsOn: category.IsOn, Order: types.Int32(category.Order), } } } pbRoutes = append(pbRoutes, &pb.NSRoute{ Id: int64(route.Id), IsOn: route.IsOn, Code: "id:" + types.String(route.Id), Name: route.Name, IsPublic: route.IsPublic, RangesJSON: route.Ranges, Order: types.Int32(route.Order), Priority: types.Int32(route.Priority), NsCluster: pbCluster, NsDomain: pbDomain, NsRouteCategory: pbCategory, }) } // 按照分类排序 if len(pbRoutes) > 0 { sort.Slice(pbRoutes, func(i, j int) bool { var route1 = pbRoutes[i] var route2 = pbRoutes[j] // route1.category = nil if route1.NsRouteCategory == nil { if route2.NsRouteCategory == nil { if route1.Order == route2.Order { return route1.Id < route2.Id } return route1.Order > route2.Order } return true } // route1.category != nil && route2.category = nil if route2.NsRouteCategory == nil { return false } // 同一个分类 if route1.NsRouteCategory.Id == route2.NsRouteCategory.Id { if route1.Order == route2.Order { return route1.Id < route2.Id } return route1.Order > route2.Order } if route1.NsRouteCategory.Order == route2.NsRouteCategory.Order { return route1.NsRouteCategory.Id < route2.NsRouteCategory.Id } return route1.NsRouteCategory.Order > route2.NsRouteCategory.Order }) } return &pb.FindAllNSRoutesResponse{NsRoutes: pbRoutes}, nil } // FindAllPublicNSRoutes 读取所有公用的自定义线路 // 目前只允许读取系统管理员设置的公用自定义线路 func (this *NSRouteService) FindAllPublicNSRoutes(ctx context.Context, req *pb.FindAllPublicRoutesRequest) (*pb.FindAllPublicRoutesResponse, error) { _, err := this.ValidateUserNode(ctx, false) if err != nil { return nil, err } var tx = this.NullTx() routes, err := nameservers.SharedNSRouteDAO.FindAllPublicRoutes(tx) if err != nil { return nil, err } var pbRoutes = []*pb.NSRoute{} for _, route := range routes { // 分类 var pbCategory *pb.NSRouteCategory if route.CategoryId > 0 { category, err := nameservers.SharedNSRouteCategoryDAO.FindCategory(tx, int64(route.CategoryId)) if err != nil { return nil, err } if category != nil { // 如果分类未启用,则当前分类下面的线路也不显示 if !category.IsOn { continue } pbCategory = &pb.NSRouteCategory{ Id: int64(category.Id), Name: category.Name, IsOn: category.IsOn, Order: types.Int32(category.Order), } } } pbRoutes = append(pbRoutes, &pb.NSRoute{ Id: int64(route.Id), IsOn: route.IsOn, Code: "id:" + types.String(route.Id), Name: route.Name, IsPublic: route.IsPublic, RangesJSON: route.Ranges, Order: types.Int32(route.Order), Priority: types.Int32(route.Priority), NsCluster: nil, NsDomain: nil, NsRouteCategory: pbCategory, }) } // 按照分类排序 if len(pbRoutes) > 0 { sort.Slice(pbRoutes, func(i, j int) bool { var route1 = pbRoutes[i] var route2 = pbRoutes[j] // route1.category = nil if route1.NsRouteCategory == nil { if route2.NsRouteCategory == nil { if route1.Order == route2.Order { return route1.Id < route2.Id } return route1.Order > route2.Order } return true } // route1.category != nil && route2.category = nil if route2.NsRouteCategory == nil { return false } // 同一个分类 if route1.NsRouteCategory.Id == route2.NsRouteCategory.Id { if route1.Order == route2.Order { return route1.Id < route2.Id } return route1.Order > route2.Order } if route1.NsRouteCategory.Order == route2.NsRouteCategory.Order { return route1.NsRouteCategory.Id < route2.NsRouteCategory.Id } return route1.NsRouteCategory.Order > route2.NsRouteCategory.Order }) } return &pb.FindAllPublicRoutesResponse{NsRoutes: pbRoutes}, nil } // UpdateNSRouteOrders 设置自定义线路排序 func (this *NSRouteService) UpdateNSRouteOrders(ctx context.Context, req *pb.UpdateNSRouteOrdersRequest) (*pb.RPCSuccess, error) { _, userId, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() // 检查权限 if userId > 0 { for _, routeId := range req.NsRouteIds { err = nameservers.SharedNSRouteDAO.CheckUserRoute(tx, userId, routeId) if err != nil { return nil, err } } } err = nameservers.SharedNSRouteDAO.UpdateRouteOrders(tx, req.NsRouteIds) if err != nil { return nil, err } return this.Success() } // ListNSRoutesAfterVersion 根据版本列出一组自定义线路 func (this *NSRouteService) ListNSRoutesAfterVersion(ctx context.Context, req *pb.ListNSRoutesAfterVersionRequest) (*pb.ListNSRoutesAfterVersionResponse, error) { _, _, err := this.ValidateNodeId(ctx, rpcutils.UserTypeDNS) if err != nil { return nil, err } // 集群ID var tx = this.NullTx() routes, err := nameservers.SharedNSRouteDAO.ListRoutesAfterVersion(tx, req.Version, 2000) if err != nil { return nil, err } var pbRoutes []*pb.NSRoute for _, route := range routes { // 集群 var pbCluster *pb.NSCluster if route.ClusterId > 0 { pbCluster = &pb.NSCluster{Id: int64(route.ClusterId)} } // 域名 var pbDomain *pb.NSDomain if route.DomainId > 0 { pbDomain = &pb.NSDomain{Id: int64(route.DomainId)} } pbRoutes = append(pbRoutes, &pb.NSRoute{ Id: int64(route.Id), IsOn: route.IsOn, Name: "", RangesJSON: route.Ranges, IsDeleted: route.State == nameservers.NSRouteStateDisabled, Order: types.Int32(route.Order), Priority: types.Int32(route.Priority), Version: int64(route.Version), UserId: types.Int64(route.UserId), NsCluster: pbCluster, NsDomain: pbDomain, }) } return &pb.ListNSRoutesAfterVersionResponse{NsRoutes: pbRoutes}, nil } // FindAllDefaultWorldRegionRoutes 查找默认的世界区域线路 func (this *NSRouteService) FindAllDefaultWorldRegionRoutes(ctx context.Context, req *pb.FindAllDefaultWorldRegionRoutesRequest) (*pb.FindAllDefaultWorldRegionRoutesResponse, error) { _, _, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var pbRoutes = []*pb.NSRoute{} for _, route := range dnsconfigs.AllDefaultWorldRegionRoutes { pbRoutes = append(pbRoutes, &pb.NSRoute{ Code: route.Code, Name: route.Name, }) } return &pb.FindAllDefaultWorldRegionRoutesResponse{ NsRoutes: pbRoutes, }, nil } // FindAllDefaultChinaProvinceRoutes 查找默认的中国省份线路 func (this *NSRouteService) FindAllDefaultChinaProvinceRoutes(ctx context.Context, req *pb.FindAllDefaultChinaProvinceRoutesRequest) (*pb.FindAllDefaultChinaProvinceRoutesResponse, error) { _, _, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var pbRoutes = []*pb.NSRoute{} for _, route := range dnsconfigs.AllDefaultChinaProvinceRoutes { pbRoutes = append(pbRoutes, &pb.NSRoute{ Code: route.Code, Name: route.Name, }) } return &pb.FindAllDefaultChinaProvinceRoutesResponse{ NsRoutes: pbRoutes, }, nil } // FindAllDefaultISPRoutes 查找默认的ISP线路 func (this *NSRouteService) FindAllDefaultISPRoutes(ctx context.Context, req *pb.FindAllDefaultISPRoutesRequest) (*pb.FindAllDefaultISPRoutesResponse, error) { _, _, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var pbRoutes = []*pb.NSRoute{} for _, route := range dnsconfigs.AllDefaultISPRoutes { pbRoutes = append(pbRoutes, &pb.NSRoute{ Code: route.Code, Name: route.Name, }) } return &pb.FindAllDefaultISPRoutesResponse{ NsRoutes: pbRoutes, }, nil } // FindAllAgentNSRoutes 查找默认的搜索引擎线路 func (this *NSRouteService) FindAllAgentNSRoutes(ctx context.Context, req *pb.FindAllAgentNSRoutesRequest) (*pb.FindAllAgentNSRoutesResponse, error) { _, _, err := this.ValidateAdminAndUser(ctx, true) if err != nil { return nil, err } var tx = this.NullTx() agents, err := clients.SharedClientAgentDAO.FindAllNSAgents(tx) if err != nil { return nil, err } var pbRoutes = []*pb.NSRoute{} for _, agent := range agents { pbRoutes = append(pbRoutes, &pb.NSRoute{ Code: agent.NSRouteCode(), Name: agent.Name, }) } pbRoutes = append(pbRoutes, &pb.NSRoute{ Code: "agent", Name: "搜索引擎", }) return &pb.FindAllAgentNSRoutesResponse{NsRoutes: pbRoutes}, nil }