mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
193 lines
4.3 KiB
Go
193 lines
4.3 KiB
Go
package strategy_filter
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/eolinker/eosc"
|
|
|
|
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
|
)
|
|
|
|
var (
|
|
filterHandler = NewHandler()
|
|
)
|
|
|
|
type Option struct {
|
|
Name string
|
|
Title string
|
|
Type string
|
|
Pattern *regexp.Regexp
|
|
Options []string
|
|
}
|
|
|
|
const (
|
|
TypeRemote = "remote"
|
|
TypePattern = "pattern"
|
|
TypeStatic = "static"
|
|
|
|
ValuesALL = "ALL"
|
|
|
|
ScopeGlobal = "global"
|
|
ScopeTeam = "team"
|
|
ScopeService = "service"
|
|
)
|
|
|
|
const (
|
|
HttpALL = "ALL"
|
|
)
|
|
|
|
func CheckFilters(name string, scope strategy_dto.Scope, filters []*strategy_dto.Filter) error {
|
|
fs, ok := filterHandler.Options(scope.String())
|
|
if !ok {
|
|
return fmt.Errorf("unknown scope %s", scope)
|
|
}
|
|
filterNameSet := make(map[string]struct{})
|
|
for _, filter := range filters {
|
|
op, ok := fs[filter.Name]
|
|
if !ok {
|
|
return fmt.Errorf("%s filter %s not found", name, filter.Name)
|
|
}
|
|
for _, value := range filter.Values {
|
|
if op.Pattern != nil && !op.Pattern.MatchString(value) {
|
|
return fmt.Errorf("%s filter %s value %s not match pattern", name, filter.Name, value)
|
|
}
|
|
}
|
|
|
|
if len(filter.Values) == 0 {
|
|
return fmt.Errorf("%s.Options can't be null. filter.Name:%s ", name, filter.Name)
|
|
}
|
|
|
|
if _, has := filterNameSet[filter.Name]; has {
|
|
return fmt.Errorf("%s.Name %s is reduplicative. ", name, filter.Name)
|
|
}
|
|
filterNameSet[filter.Name] = struct{}{}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type OptionTitle struct {
|
|
Field string `json:"field"`
|
|
Title string `json:"title" aoi18n:""`
|
|
}
|
|
|
|
type IRemoteFilter interface {
|
|
IFilter
|
|
Titles() []OptionTitle
|
|
Key() string
|
|
Target() string
|
|
RemoteList(ctx context.Context, keyword string, condition map[string]interface{}, page int, pageSize int) ([]any, int64, error)
|
|
}
|
|
|
|
type IFilter interface {
|
|
Name() string
|
|
Title() string
|
|
Labels(values ...string) []string
|
|
Type() string
|
|
Scopes() []string
|
|
Option() *Option
|
|
}
|
|
|
|
type IFilterHandler interface {
|
|
RemoteFilter(name string) (IRemoteFilter, bool)
|
|
Options(scope string) (map[string]*Option, bool)
|
|
FilterLabel(name string, values []string) (*Info, error)
|
|
}
|
|
|
|
type Info struct {
|
|
Title string
|
|
Label string
|
|
}
|
|
|
|
type ScopeFilterOption eosc.Untyped[string, *Option]
|
|
|
|
type Handler struct {
|
|
filters eosc.Untyped[string, IFilter]
|
|
remoteFilters eosc.Untyped[string, IRemoteFilter]
|
|
options eosc.Untyped[string, ScopeFilterOption]
|
|
}
|
|
|
|
func NewHandler() *Handler {
|
|
return &Handler{
|
|
filters: eosc.BuildUntyped[string, IFilter](),
|
|
remoteFilters: eosc.BuildUntyped[string, IRemoteFilter](),
|
|
options: eosc.BuildUntyped[string, ScopeFilterOption](),
|
|
}
|
|
}
|
|
|
|
func (f *Handler) RemoteFilter(name string) (IRemoteFilter, bool) {
|
|
return f.remoteFilters.Get(name)
|
|
}
|
|
|
|
func (f *Handler) RegisterRemoteFilter(filter IRemoteFilter) {
|
|
f.remoteFilters.Set(filter.Name(), filter)
|
|
f.setScopes(filter)
|
|
}
|
|
|
|
func (f *Handler) RegisterFilter(filter IFilter) {
|
|
f.filters.Set(filter.Name(), filter)
|
|
f.setScopes(filter)
|
|
}
|
|
|
|
func (f *Handler) setScopes(filter IFilter) {
|
|
for _, scope := range filter.Scopes() {
|
|
tmp, has := f.options.Get(scope)
|
|
if !has {
|
|
tmp = eosc.BuildUntyped[string, *Option]()
|
|
f.options.Set(scope, tmp)
|
|
}
|
|
tmp.Set(filter.Name(), filter.Option())
|
|
}
|
|
}
|
|
|
|
func (f *Handler) Options(scope string) (map[string]*Option, bool) {
|
|
options, has := f.options.Get(scope)
|
|
if !has {
|
|
return nil, false
|
|
}
|
|
return options.All(), true
|
|
}
|
|
|
|
func (f *Handler) FilterLabel(name string, values []string) (*Info, error) {
|
|
if tmp, has := f.remoteFilters.Get(name); has {
|
|
return &Info{
|
|
Title: tmp.Title(),
|
|
Label: strings.Join(tmp.Labels(values...), ","),
|
|
}, nil
|
|
}
|
|
if tmp, has := f.filters.Get(name); has {
|
|
return &Info{
|
|
Title: tmp.Title(),
|
|
Label: strings.Join(tmp.Labels(values...), ","),
|
|
}, nil
|
|
}
|
|
return nil, fmt.Errorf("filter %s not found", name)
|
|
}
|
|
|
|
func RegisterRemoteFilter(filter IRemoteFilter) {
|
|
filterHandler.RegisterRemoteFilter(filter)
|
|
}
|
|
|
|
func RemoteFilter(name string) (IRemoteFilter, bool) {
|
|
return filterHandler.RemoteFilter(name)
|
|
}
|
|
|
|
func Options(scope string) (map[string]*Option, bool) {
|
|
return filterHandler.Options(scope)
|
|
}
|
|
|
|
func FilterLabel(name string, values []string) (*Info, error) {
|
|
return filterHandler.FilterLabel(name, values)
|
|
}
|
|
|
|
func FilterGet(name string) (IFilter, bool) {
|
|
f, has := filterHandler.remoteFilters.Get(name)
|
|
if has {
|
|
return f, true
|
|
}
|
|
return filterHandler.filters.Get(name)
|
|
}
|