package api import ( "net/url" "reflect" "regexp" "strconv" "strings" "git.sxidc.com/go-framework/baize/framework/core/infrastructure/logger" "git.sxidc.com/go-tools/utils/strutils" "git.sxidc.com/go-tools/utils/template" "github.com/pkg/errors" ) type UrlInstruction interface { FormUrlInstruction() (string, error) } func FormUrlInstruction(instructions ...UrlInstruction) string { if instructions == nil || len(instructions) == 0 { return "" } urlInstructions := make([]string, 0) for _, instruction := range instructions { if instruction == nil { continue } urlInstruction, err := instruction.FormUrlInstruction() if err != nil { panic(err) } urlInstructions = append(urlInstructions, urlInstruction) } if urlInstructions == nil || len(urlInstructions) == 0 { return "" } return "${" + strings.Join(urlInstructions, " ") + "}$" } const ( permUrlInstructionTpl = `perm:"group:{{ .Group }};name:{{ .Name }};{{- if .Description -}}description:{{ .Description }};{{- end -}}{{- if .NeedCheckExpire -}}needCheckExpire;{{- end -}}{{- if .SensitiveWordScene -}}sensitiveWordScene:{{ .SensitiveWordScene }};{{- end -}}"` ) type PermUrlInstruction struct { Group string Name string Description string NeedCheckExpire bool SensitiveWordScene int } func (cmd *PermUrlInstruction) check() error { if strutils.IsStringEmpty(cmd.Group) { return errors.New("没有传递权限组") } if strutils.IsStringEmpty(cmd.Name) { return errors.New("没有传递权限名称") } return nil } func (cmd *PermUrlInstruction) FormUrlInstruction() (string, error) { err := cmd.check() if err != nil { return "", err } permUrlInstruction, err := template.ParseTemplateStringToString(permUrlInstructionTpl, cmd) if err != nil { return "", err } return permUrlInstruction, nil } // Perm指令定义 const ( tagPartSeparator = ";" tagPartKeyValueSeparator = ":" ) const ( permTagKey = "perm" permTagPartGroup = "group" permTagPartName = "name" permTagPartDescription = "description" permTagPartNeedCheckExpire = "needCheckExpire" permTagPartSensitiveWordScene = "sensitiveWordScene" ) func parseRelativePathPerm(basePath string, relativePathPattern string, method string) (string, *PermissionItem, error) { re := regexp.MustCompile(`\$\{(.+)\}\$`) matches := re.FindStringSubmatch(relativePathPattern) if len(matches) == 0 { return relativePathPattern, nil, nil } relativePath := re.ReplaceAllString(relativePathPattern, "") permTag, ok := reflect.StructTag(matches[1]).Lookup(permTagKey) if !ok { return relativePath, nil, nil } tagParts := strings.Split(permTag, tagPartSeparator) if tagParts == nil || len(tagParts) == 0 { return relativePath, nil, nil } fullPath, err := url.JoinPath(basePath, relativePath) if err != nil { return "", nil, err } permissionItem := &PermissionItem{ Group: "", Name: "", Description: "", Resource: fullPath, Action: method, NeedCheckExpire: false, SensitiveWordScene: 0, } for _, tagPart := range tagParts { tagPartKeyValue := strings.SplitN(strings.TrimSpace(tagPart), tagPartKeyValueSeparator, 2) if strutils.IsStringEmpty(tagPartKeyValue[0]) { continue } switch tagPartKeyValue[0] { case permTagPartGroup: permissionItem.Group = tagPartKeyValue[1] case permTagPartName: permissionItem.Name = tagPartKeyValue[1] case permTagPartDescription: permissionItem.Description = tagPartKeyValue[1] case permTagPartNeedCheckExpire: permissionItem.NeedCheckExpire = true case permTagPartSensitiveWordScene: scene, err := strconv.Atoi(tagPartKeyValue[1]) if err != nil { return relativePath, nil, err } if scene < 1 || scene > 4 { return relativePath, nil, errors.New("不支持的敏感词场景: " + tagPartKeyValue[1]) } permissionItem.SensitiveWordScene = scene default: err := errors.New(permTagKey + "不支持的tag: " + tagPartKeyValue[0]) logger.GetInstance().Error(err) continue } } err = permissionItem.check() if err != nil { return "", nil, err } return relativePath, permissionItem, nil }