package firewall
import (
"golang.org/x/net/html"
"os"
"strings"
"testing"
)
func TestUIOnlyOffersImplementedFirewallOptions(t *testing.T) {
data, err := os.ReadFile("../web/static/index.html")
if err != nil {
t.Fatal(err)
}
doc, err := html.Parse(strings.NewReader(string(data)))
if err != nil {
t.Fatal(err)
}
caps := Capabilities()
actions := caps["actions"].(map[string][]string)
fields := caps["fields"].(map[string][]string)
keyMap := map[string]string{"src": "src_address", "dst": "dst_address", "srclist": "src_address_list", "dstlist": "dst_address_list", "srcgeo": "src_geoip", "dstgeo": "dst_geoip", "proto": "protocol", "sport": "src_port", "dport": "dst_port", "anyport": "any_port", "iniface": "in_interface", "outiface": "out_interface", "inifacelist": "in_interface_list", "outifacelist": "out_interface_list", "pktmark": "packet_mark", "connmark": "connection_mark", "routingmark": "routing_mark", "conntype": "connection_type", "content": "content", "srcmac": "src_mac_address", "inbridgeport": "in_bridge_port", "outbridgeport": "out_bridge_port", "ipsec": "ipsec_policy", "dscp": "dscp", "tcpmss": "tcp_mss", "tos": "tos", "pktsize": "packet_size", "random": "random", "tcpflags": "tcp_flags", "icmpoptions": "icmp_options", "ttl": "ttl", "time": "time", "limit": "limit", "nth": "nth", "connlimit": "connection_limit", "srcaddrtype": "src_address_type", "dstaddrtype": "dst_address_type", "ipfragment": "ip_fragment", "logprefix": "log_prefix"}
contains := func(items []string, s string) bool {
for _, item := range items {
if item == s {
return true
}
}
return false
}
var visit func(*html.Node)
visit = func(n *html.Node) {
attrs := map[string]string{}
for _, a := range n.Attr {
attrs[a.Key] = a.Val
}
id := attrs["id"]
for prefix, kind := range map[string]string{"fw": "filter", "nat": "nat", "mangle": "mangle"} {
if strings.HasPrefix(id, prefix+"-val-") {
key := strings.TrimPrefix(id, prefix+"-val-")
field := keyMap[key]
if field == "" || !contains(fields[kind], field) {
t.Errorf("UI control %s has no supported API/compiler field", id)
}
}
}
for _, kind := range []string{"filter", "nat", "mangle"} {
if n.Type == html.ElementNode && n.Data == "select" && id == kind+"-modal-action" {
for child := n.FirstChild; child != nil; child = child.NextSibling {
if child.Type == html.ElementNode && child.Data == "option" {
for _, a := range child.Attr {
if a.Key == "value" && !contains(actions[kind], a.Val) {
t.Errorf("unsupported %s UI action %s", kind, a.Val)
}
}
}
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
visit(c)
}
}
visit(doc)
}