From f856dc7c01acd97c074267db6f75891a231aaad9 Mon Sep 17 00:00:00 2001 From: Chang lue Tsen Date: Wed, 30 Apr 2025 12:53:01 +0900 Subject: [PATCH] fix(server): update server filtering to support multiple tags --- .../logic/admin/server/getNodeListLogic.go | 6 ++- .../logic/admin/server/getNodeTagListLogic.go | 26 +------------ internal/logic/subscribe/subscribeLogic.go | 26 ++++++++++++- internal/model/server/model.go | 39 +++++++++++++++++-- internal/model/server/server.go | 2 +- 5 files changed, 68 insertions(+), 31 deletions(-) diff --git a/internal/logic/admin/server/getNodeListLogic.go b/internal/logic/admin/server/getNodeListLogic.go index 24b72c7..544c85d 100644 --- a/internal/logic/admin/server/getNodeListLogic.go +++ b/internal/logic/admin/server/getNodeListLogic.go @@ -32,11 +32,15 @@ func NewGetNodeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetNo } func (l *GetNodeListLogic) GetNodeList(req *types.GetNodeServerListRequest) (resp *types.GetNodeServerListResponse, err error) { + tags := make([]string, 0) + if req.Tags != "" { + tags = strings.Split(req.Tags, ",") + } total, list, err := l.svcCtx.ServerModel.FindServerListByFilter(l.ctx, &server.ServerFilter{ Page: req.Page, Size: req.Size, Search: req.Search, - Tag: req.Tag, + Tags: tags, Group: req.GroupId, }) if err != nil { diff --git a/internal/logic/admin/server/getNodeTagListLogic.go b/internal/logic/admin/server/getNodeTagListLogic.go index 6bab097..36eb9e7 100644 --- a/internal/logic/admin/server/getNodeTagListLogic.go +++ b/internal/logic/admin/server/getNodeTagListLogic.go @@ -2,16 +2,10 @@ package server import ( "context" - "strings" - - "github.com/perfect-panel/server/internal/model/server" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/logger" "github.com/perfect-panel/server/pkg/tool" - "github.com/perfect-panel/server/pkg/xerr" - "github.com/pkg/errors" - "gorm.io/gorm" ) type GetNodeTagListLogic struct { @@ -30,24 +24,8 @@ func NewGetNodeTagListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Ge } func (l *GetNodeTagListLogic) GetNodeTagList() (resp *types.GetNodeTagListResponse, err error) { - var nodeTags, tags []string - err = l.svcCtx.ServerModel.Transaction(l.ctx, func(db *gorm.DB) error { - - return db.Model(&server.Server{}).Select("tags").Pluck("tags", &nodeTags).Error - }) - - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get node tag list failed, %s", err.Error()) - } - - for _, tag := range nodeTags { - tags = append(tags, strings.Split(tag, ",")...) - } - - // Remove duplicate tags - tags = tool.RemoveDuplicateElements(tags...) - + tags, err := l.svcCtx.ServerModel.FindServerTags(l.ctx) return &types.GetNodeTagListResponse{ - Tags: tags, + Tags: tool.RemoveDuplicateElements(tags...), }, nil } diff --git a/internal/logic/subscribe/subscribeLogic.go b/internal/logic/subscribe/subscribeLogic.go index 97af485..e723f99 100644 --- a/internal/logic/subscribe/subscribeLogic.go +++ b/internal/logic/subscribe/subscribeLogic.go @@ -175,10 +175,32 @@ func (l *SubscribeLogic) getRules() ([]*server.RuleGroup, error) { } func (l *SubscribeLogic) buildClientConfig(req *types.SubscribeRequest, userSub *user.Subscribe, servers []*server.Server, rules []*server.RuleGroup) ([]byte, string, error) { - proxyManager := adapter.NewAdapter(servers, rules) + tags := make(map[string][]*server.Server) + + groups, err := l.svc.ServerModel.QueryAllGroup(l.ctx) + if err != nil { + l.Errorw("[Generate Subscribe]find group error: %v", logger.Field("error", err.Error())) + return nil, "", errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find group error: %v", err.Error()) + } + for _, group := range groups { + total, servers, err := l.svc.ServerModel.FindServerListByFilter(l.ctx, &server.ServerFilter{ + Tags: []string{group.Name}, + }) + if err != nil { + continue + } + if total > 0 { + tags[group.Name] = servers + } + } + + proxyManager := adapter.NewAdapter(&adapter.Config{ + Nodes: servers, + Rules: rules, + Tags: make(map[string][]*server.Server), + }) clientType := l.getClientType(req) var resp []byte - var err error l.Logger.Info(fmt.Sprintf("[Generate Subscribe] %s", clientType), logger.Field("ua", req.UA), logger.Field("flag", req.Flag)) diff --git a/internal/model/server/model.go b/internal/model/server/model.go index 5284e98..fbfe59d 100644 --- a/internal/model/server/model.go +++ b/internal/model/server/model.go @@ -3,6 +3,7 @@ package server import ( "context" "fmt" + "strings" "github.com/perfect-panel/server/internal/config" "gorm.io/gorm" @@ -29,6 +30,8 @@ type customServerLogicModel interface { UpdateRuleGroup(ctx context.Context, data *RuleGroup) error DeleteRuleGroup(ctx context.Context, id int64) error QueryAllRuleGroup(ctx context.Context) ([]*RuleGroup, error) + FindServersByTag(ctx context.Context, tag string) ([]*Server, error) + FindServerTags(ctx context.Context) ([]string, error) } var ( @@ -227,10 +230,16 @@ func (m *customServerModel) FindServerListByFilter(ctx context.Context, filter * query = conn.Where("group_id = ?", filter.Group) } if filter.Search != "" { - query = query.Where("name LIKE ? OR server_addr LIKE ?", "%"+filter.Search+"%", "%"+filter.Search+"%") + query = query.Where("name LIKE ? OR server_addr LIKE ? OR tags LIKE ?", "%"+filter.Search+"%", "%"+filter.Search+"%", "%"+filter.Search+"%") } - if filter.Tag != "" { - query = query.Where("tag LIKE ?", "%"+filter.Tag+"%") + if len(filter.Tags) > 0 { + for i, tag := range filter.Tags { + if i == 0 { + query = query.Where("tags LIKE ?", "%"+tag+"%") + } else { + query = query.Or("tags LIKE ?", "%"+tag+"%") + } + } } return query.Count(&total).Limit(filter.Size).Offset((filter.Page - 1) * filter.Size).Find(v).Error }) @@ -239,3 +248,27 @@ func (m *customServerModel) FindServerListByFilter(ctx context.Context, filter * } return total, data, nil } + +func (m *customServerModel) FindServerTags(ctx context.Context) ([]string, error) { + var data []string + err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error { + return conn.Model(&Server{}).Distinct("tags").Pluck("tags", v).Error + }) + var tags []string + for _, tag := range data { + if strings.Contains(tag, ",") { + tags = append(tags, strings.Split(tag, ",")...) + } else { + tags = append(tags, tag) + } + } + return tags, err +} + +func (m *customServerModel) FindServersByTag(ctx context.Context, tag string) ([]*Server, error) { + var data []*Server + err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, v interface{}) error { + return conn.Model(&Server{}).Where("FIND_IN_SET(?, tags)", tag).Order("sort ASC").Find(v).Error + }) + return data, err +} diff --git a/internal/model/server/server.go b/internal/model/server/server.go index 57accf8..bdbae76 100644 --- a/internal/model/server/server.go +++ b/internal/model/server/server.go @@ -16,7 +16,7 @@ const ( type ServerFilter struct { Id int64 - Tag string + Tags []string Group int64 Search string Page int