Wildcard matched rules
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
package perm
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -59,6 +60,27 @@ func (a Action) MarshalText() ([]byte, error) {
|
||||
return []byte(a.String()), nil
|
||||
}
|
||||
|
||||
// globAction is a helper to pack globs better.
|
||||
type globAction struct {
|
||||
Glob string
|
||||
Act Action
|
||||
}
|
||||
|
||||
func (g *globAction) UnmarshalJSON(b []byte) error {
|
||||
m := make(map[string]Action)
|
||||
if err := json.Unmarshal(b, &m); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(m) != 1 {
|
||||
return errors.New("Glob action object does not have & only have one key")
|
||||
}
|
||||
for k, v := range m {
|
||||
g.Glob = k
|
||||
g.Act = v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Config is a list of address and actions, for each source address.
|
||||
// It can just be Marshal/Unmarshaled into/from json.
|
||||
type Config struct {
|
||||
@ -70,6 +92,12 @@ type Config struct {
|
||||
// Port number is extracted by net/url.splitHostPort, copied below.
|
||||
// Port number is optional, but must be numeric when present.
|
||||
Match map[string]Action
|
||||
|
||||
// Object which holds wildcard matches.
|
||||
// This is searched after Match. It appends the default port if not found.
|
||||
//
|
||||
// Unlike Match, this is a list that is searched top-to-bottom.
|
||||
MatchWildcard []globAction
|
||||
}
|
||||
|
||||
// validOptionalPort reports whether port is either an empty string
|
||||
|
@ -6,11 +6,14 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"edgaru089.ink/go/regolith/internal/util"
|
||||
)
|
||||
|
||||
type int_perm struct {
|
||||
match map[string]Action
|
||||
def Action
|
||||
match map[string]Action
|
||||
match_glob []globAction
|
||||
def Action
|
||||
}
|
||||
|
||||
// Perm matches address:port strings to Actions
|
||||
@ -77,6 +80,29 @@ func (p *Perm) Load(cs map[string]Config) {
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, glob := range c.MatchWildcard {
|
||||
addr, port := splitHostPort(glob.Glob)
|
||||
if port != "" {
|
||||
log.Printf("loading glob target %s, action %s", glob.Glob, glob.Act)
|
||||
p_int.match_glob = append(
|
||||
p_int.match_glob,
|
||||
globAction{
|
||||
Glob: glob.Glob,
|
||||
Act: glob.Act,
|
||||
})
|
||||
} else {
|
||||
// TODO change this to sth faster
|
||||
for _, def_port := range c.DefaultPort {
|
||||
log.Printf("loading glob target %s, action %s", net.JoinHostPort(addr, strconv.Itoa(def_port)), glob.Act)
|
||||
p_int.match_glob = append(
|
||||
p_int.match_glob,
|
||||
globAction{
|
||||
Glob: net.JoinHostPort(addr, strconv.Itoa(def_port)),
|
||||
Act: glob.Act,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -108,9 +134,18 @@ func (p *Perm) Match(src, dest string) Action {
|
||||
// find its source struct
|
||||
p_int, ok_int := p.source[src]
|
||||
// only check if dest is directly listed
|
||||
if ok_int && p_int.match != nil {
|
||||
if action, ok := p_int.match[dest]; ok {
|
||||
return action
|
||||
if ok_int {
|
||||
// first check direct match
|
||||
if p_int.match != nil {
|
||||
if action, ok := p_int.match[dest]; ok {
|
||||
return action
|
||||
}
|
||||
}
|
||||
// then check glob match
|
||||
for _, g := range p_int.match_glob {
|
||||
if util.Match(g.Glob, dest) {
|
||||
return g.Act
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,6 +155,12 @@ func (p *Perm) Match(src, dest string) Action {
|
||||
return action
|
||||
}
|
||||
}
|
||||
// then check global glob match
|
||||
for _, g := range p.global.match_glob {
|
||||
if util.Match(g.Glob, dest) {
|
||||
return g.Act
|
||||
}
|
||||
}
|
||||
|
||||
// directly listed in neither.
|
||||
if ok_int {
|
||||
|
Reference in New Issue
Block a user