From 8e0c10419a8b2879956d4f55eb625b3a157debbd Mon Sep 17 00:00:00 2001
From: GoEdgeLab
Date: Thu, 8 Oct 2020 11:11:37 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0WAF=E9=83=A8=E5=88=86?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
go.mod | 1 +
go.sum | 1 +
internal/rpc/rpc_client.go | 4 +
.../servers/components/waf/createRulePopup.go | 104 ++++++++++++
.../servers/components/waf/createSetPopup.go | 159 ++++++++++++++++++
.../servers/components/waf/deleteSet.go | 50 ++++++
.../default/servers/components/waf/group.go | 107 ++++++++++++
.../default/servers/components/waf/init.go | 9 +-
.../default/servers/components/waf/sets.go | 15 --
.../servers/components/waf/sortSets.go | 53 ++++++
.../components/waf/updateGroupPopup.go | 66 ++++++++
.../servers/components/waf/updateSetOn.go | 26 +++
.../servers/components/waf/updateSetPopup.go | 152 +++++++++++++++++
.../models/http_firewall_rule_group_dao.go | 39 +++++
.../web/models/http_firewall_rule_set_dao.go | 35 ++++
web/public/js/components/common/sortable.js | 3 +
.../server/http-firewall-rules-box.js | 50 ++++++
.../components/waf/createRulePopup.html | 86 ++++++++++
.../servers/components/waf/createRulePopup.js | 70 ++++++++
.../components/waf/createSetPopup.html | 67 ++++++++
.../servers/components/waf/createSetPopup.js | 43 +++++
.../servers/components/waf/group.html | 69 ++++++++
.../@default/servers/components/waf/group.js | 82 +++++++++
.../servers/components/waf/groups.html | 4 +-
.../components/waf/updateGroupPopup.html | 38 +++++
.../components/waf/updateGroupPopup.js | 3 +
.../components/waf/updateSetPopup.html | 67 ++++++++
.../servers/components/waf/updateSetPopup.js | 57 +++++++
28 files changed, 1443 insertions(+), 17 deletions(-)
create mode 100644 internal/web/actions/default/servers/components/waf/createRulePopup.go
create mode 100644 internal/web/actions/default/servers/components/waf/createSetPopup.go
create mode 100644 internal/web/actions/default/servers/components/waf/deleteSet.go
create mode 100644 internal/web/actions/default/servers/components/waf/group.go
delete mode 100644 internal/web/actions/default/servers/components/waf/sets.go
create mode 100644 internal/web/actions/default/servers/components/waf/sortSets.go
create mode 100644 internal/web/actions/default/servers/components/waf/updateGroupPopup.go
create mode 100644 internal/web/actions/default/servers/components/waf/updateSetOn.go
create mode 100644 internal/web/actions/default/servers/components/waf/updateSetPopup.go
create mode 100644 internal/web/models/http_firewall_rule_group_dao.go
create mode 100644 internal/web/models/http_firewall_rule_set_dao.go
create mode 100644 web/public/js/components/server/http-firewall-rules-box.js
create mode 100644 web/views/@default/servers/components/waf/createRulePopup.html
create mode 100644 web/views/@default/servers/components/waf/createRulePopup.js
create mode 100644 web/views/@default/servers/components/waf/createSetPopup.html
create mode 100644 web/views/@default/servers/components/waf/createSetPopup.js
create mode 100644 web/views/@default/servers/components/waf/group.html
create mode 100644 web/views/@default/servers/components/waf/group.js
create mode 100644 web/views/@default/servers/components/waf/updateGroupPopup.html
create mode 100644 web/views/@default/servers/components/waf/updateGroupPopup.js
create mode 100644 web/views/@default/servers/components/waf/updateSetPopup.html
create mode 100644 web/views/@default/servers/components/waf/updateSetPopup.js
diff --git a/go.mod b/go.mod
index aab24f69..b2870a80 100644
--- a/go.mod
+++ b/go.mod
@@ -13,6 +13,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect
+ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa
google.golang.org/grpc v1.32.0
google.golang.org/protobuf v1.25.0 // indirect
)
diff --git a/go.sum b/go.sum
index 007d83c7..1b77d9d5 100644
--- a/go.sum
+++ b/go.sum
@@ -154,6 +154,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go
index 6bf66aae..113f0062 100644
--- a/internal/rpc/rpc_client.go
+++ b/internal/rpc/rpc_client.go
@@ -131,6 +131,10 @@ func (this *RPCClient) HTTPFirewallRuleGroupRPC() pb.HTTPFirewallRuleGroupServic
return pb.NewHTTPFirewallRuleGroupServiceClient(this.pickConn())
}
+func (this *RPCClient) HTTPFirewallRuleSetRPC() pb.HTTPFirewallRuleSetServiceClient {
+ return pb.NewHTTPFirewallRuleSetServiceClient(this.pickConn())
+}
+
func (this *RPCClient) HTTPLocationRPC() pb.HTTPLocationServiceClient {
return pb.NewHTTPLocationServiceClient(this.pickConn())
}
diff --git a/internal/web/actions/default/servers/components/waf/createRulePopup.go b/internal/web/actions/default/servers/components/waf/createRulePopup.go
new file mode 100644
index 00000000..1042c66f
--- /dev/null
+++ b/internal/web/actions/default/servers/components/waf/createRulePopup.go
@@ -0,0 +1,104 @@
+package waf
+
+import (
+ "encoding/json"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
+ "github.com/iwind/TeaGo/actions"
+ "github.com/iwind/TeaGo/lists"
+ "github.com/iwind/TeaGo/maps"
+)
+
+type CreateRulePopupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *CreateRulePopupAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *CreateRulePopupAction) RunGet(params struct {
+ Type string
+}) {
+ // check points
+ checkpointList := []maps.Map{}
+ for _, def := range firewallconfigs.AllCheckpoints {
+ if (params.Type == "inbound" && def.IsRequest) || (params.Type == "outbound" && !def.IsRequest) {
+ checkpointList = append(checkpointList, maps.Map{
+ "name": def.Name,
+ "prefix": def.Prefix,
+ "description": def.Description,
+ "hasParams": len(def.Params) > 0,
+ "params": def.Params,
+ "options": def.Options,
+ })
+ }
+ }
+
+ // operators
+ this.Data["operators"] = lists.Map(firewallconfigs.AllRuleOperators, func(k int, v interface{}) interface{} {
+ def := v.(*firewallconfigs.RuleOperatorDefinition)
+ return maps.Map{
+ "name": def.Name,
+ "code": def.Code,
+ "description": def.Description,
+ "case": def.CaseInsensitive,
+ }
+ })
+
+ this.Data["checkpoints"] = checkpointList
+
+ this.Show()
+}
+
+func (this *CreateRulePopupAction) RunPost(params struct {
+ RuleId int64
+ Prefix string
+ Operator string
+ Param string
+ OptionsJSON []byte
+ Value string
+ Case bool
+
+ Must *actions.Must
+}) {
+ params.Must.
+ Field("prefix", params.Prefix).
+ Require("请选择参数")
+
+ rule := &firewallconfigs.HTTPFirewallRule{
+ Id: params.RuleId,
+ IsOn: true,
+ }
+ if len(params.Param) > 0 {
+ rule.Param = "${" + params.Prefix + "." + params.Param + "}"
+ } else {
+ rule.Param = "${" + params.Prefix + "}"
+ }
+ rule.Operator = params.Operator
+ rule.Value = params.Value
+ rule.IsCaseInsensitive = params.Case
+
+ if len(params.OptionsJSON) > 0 {
+ options := []maps.Map{}
+ err := json.Unmarshal(params.OptionsJSON, &options)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ rule.CheckpointOptions = map[string]interface{}{}
+ for _, option := range options {
+ rule.CheckpointOptions[option.GetString("code")] = option.GetString("value")
+ }
+ }
+
+ // 校验
+ err := rule.Init()
+ if err != nil {
+ this.Fail("校验规则 '" + rule.Param + " " + rule.Operator + " " + rule.Value + "' 失败,原因:" + err.Error())
+ }
+
+ this.Data["rule"] = rule
+ this.Success()
+}
diff --git a/internal/web/actions/default/servers/components/waf/createSetPopup.go b/internal/web/actions/default/servers/components/waf/createSetPopup.go
new file mode 100644
index 00000000..c5212138
--- /dev/null
+++ b/internal/web/actions/default/servers/components/waf/createSetPopup.go
@@ -0,0 +1,159 @@
+package waf
+
+import (
+ "encoding/json"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/models"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
+ "github.com/iwind/TeaGo/actions"
+ "github.com/iwind/TeaGo/maps"
+ "strconv"
+ "strings"
+)
+
+type CreateSetPopupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *CreateSetPopupAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *CreateSetPopupAction) RunGet(params struct {
+ FirewallPolicyId int64
+ GroupId int64
+ Type string
+}) {
+ this.Data["groupId"] = params.GroupId
+ this.Data["type"] = params.Type
+
+ firewallPolicy, err := models.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if firewallPolicy == nil {
+ this.NotFound("firewallPolicy", params.FirewallPolicyId)
+ return
+ }
+ this.Data["firewallPolicy"] = firewallPolicy
+
+ // 一些配置
+ this.Data["connectors"] = []maps.Map{
+ {
+ "name": "和(AND)",
+ "value": firewallconfigs.HTTPFirewallRuleConnectorAnd,
+ "description": "所有规则都满足才视为匹配",
+ },
+ {
+ "name": "或(OR)",
+ "value": firewallconfigs.HTTPFirewallRuleConnectorOr,
+ "description": "任一规则满足了就视为匹配",
+ },
+ }
+
+ actionMaps := []maps.Map{}
+ for _, action := range firewallconfigs.AllActions {
+ actionMaps = append(actionMaps, maps.Map{
+ "name": action.Name,
+ "description": action.Description,
+ "code": action.Code,
+ })
+ }
+ this.Data["actions"] = actionMaps
+
+ this.Show()
+}
+
+func (this *CreateSetPopupAction) RunPost(params struct {
+ GroupId int64
+
+ Name string
+ RulesJSON []byte
+ Connector string
+ Action string
+
+ Must *actions.Must
+}) {
+ groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if groupConfig == nil {
+ this.Fail("找不到分组,Id:" + strconv.FormatInt(params.GroupId, 10))
+ }
+
+ params.Must.
+ Field("name", params.Name).
+ Require("请输入规则集名称")
+
+ if len(params.RulesJSON) == 0 {
+ this.Fail("请添加至少一个规则")
+ }
+ rules := []*firewallconfigs.HTTPFirewallRule{}
+ err = json.Unmarshal(params.RulesJSON, &rules)
+ if err != nil {
+ this.ErrorPage(err)
+ }
+ if len(rules) == 0 {
+ this.Fail("请添加至少一个规则")
+ }
+
+ setConfig := &firewallconfigs.HTTPFirewallRuleSet{
+ Id: 0,
+ IsOn: true,
+ Name: params.Name,
+ Code: "",
+ Description: "",
+ Connector: params.Connector,
+ RuleRefs: nil,
+ Rules: rules,
+ Action: params.Action,
+ ActionOptions: maps.Map{},
+ }
+
+ for k, v := range this.ParamsMap {
+ if len(v) == 0 {
+ continue
+ }
+ index := strings.Index(k, "action_")
+ if index > -1 {
+ setConfig.ActionOptions[k[len("action_"):]] = v[0]
+ }
+ }
+
+ setConfigJSON, err := json.Marshal(setConfig)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ createUpdateResp, err := this.RPC().HTTPFirewallRuleSetRPC().CreateOrUpdateHTTPFirewallRuleSetFromConfig(this.AdminContext(), &pb.CreateOrUpdateHTTPFirewallRuleSetFromConfigRequest{FirewallRuleSetConfigJSON: setConfigJSON})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ groupConfig.SetRefs = append(groupConfig.SetRefs, &firewallconfigs.HTTPFirewallRuleSetRef{
+ IsOn: true,
+ SetId: createUpdateResp.FirewallRuleSetId,
+ })
+
+ setRefsJSON, err := json.Marshal(groupConfig.SetRefs)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ _, err = this.RPC().HTTPFirewallRuleGroupRPC().UpdateHTTPFirewallRuleGroupSets(this.AdminContext(), &pb.UpdateHTTPFirewallRuleGroupSetsRequest{
+ FirewallRuleGroupId: params.GroupId,
+ FirewallRuleSetsJSON: setRefsJSON,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
diff --git a/internal/web/actions/default/servers/components/waf/deleteSet.go b/internal/web/actions/default/servers/components/waf/deleteSet.go
new file mode 100644
index 00000000..f623d0f1
--- /dev/null
+++ b/internal/web/actions/default/servers/components/waf/deleteSet.go
@@ -0,0 +1,50 @@
+package waf
+
+import (
+ "encoding/json"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/models"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
+)
+
+type DeleteSetAction struct {
+ actionutils.ParentAction
+}
+
+func (this *DeleteSetAction) RunPost(params struct {
+ GroupId int64
+ SetId int64
+}) {
+ groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if groupConfig == nil {
+ this.NotFound("firewallRuleGroup", params.GroupId)
+ return
+ }
+
+ newRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
+ for _, ref := range groupConfig.SetRefs {
+ if ref.SetId != params.SetId {
+ newRefs = append(newRefs, ref)
+ }
+ }
+ newRefsJSON, err := json.Marshal(newRefs)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ _, err = this.RPC().HTTPFirewallRuleGroupRPC().UpdateHTTPFirewallRuleGroupSets(this.AdminContext(), &pb.UpdateHTTPFirewallRuleGroupSetsRequest{
+ FirewallRuleGroupId: params.GroupId,
+ FirewallRuleSetsJSON: newRefsJSON,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
diff --git a/internal/web/actions/default/servers/components/waf/group.go b/internal/web/actions/default/servers/components/waf/group.go
new file mode 100644
index 00000000..6b7fe9b8
--- /dev/null
+++ b/internal/web/actions/default/servers/components/waf/group.go
@@ -0,0 +1,107 @@
+package waf
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/models"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
+ "github.com/iwind/TeaGo/lists"
+ "github.com/iwind/TeaGo/maps"
+ "strconv"
+ "strings"
+)
+
+type GroupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *GroupAction) Init() {
+ this.Nav("", "", this.ParamString("type"))
+}
+
+func (this *GroupAction) RunGet(params struct {
+ FirewallPolicyId int64
+ GroupId int64
+ Type string
+}) {
+ this.Data["type"] = params.Type
+
+ // policy
+ firewallPolicy, err := models.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if firewallPolicy == nil {
+ this.NotFound("firewallPolicy", params.FirewallPolicyId)
+ return
+ }
+
+ // group config
+ groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if groupConfig == nil {
+ this.NotFound("firewallRuleGroup", params.GroupId)
+ return
+ }
+
+ this.Data["group"] = groupConfig
+
+ // rule sets
+ this.Data["sets"] = lists.Map(groupConfig.Sets, func(k int, v interface{}) interface{} {
+ set := v.(*firewallconfigs.HTTPFirewallRuleSet)
+
+ // 动作说明
+ actionLinks := []maps.Map{}
+ if set.Action == firewallconfigs.HTTPFirewallActionGoGroup {
+ nextGroup := firewallPolicy.FindRuleGroup(set.ActionOptions.GetInt64("groupId"))
+ if nextGroup != nil {
+ actionLinks = append(actionLinks, maps.Map{
+ "name": nextGroup.Name,
+ "url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
+ })
+ }
+ } else if set.Action == firewallconfigs.HTTPFirewallActionGoSet {
+ nextGroup := firewallPolicy.FindRuleGroup(set.ActionOptions.GetInt64("groupId"))
+ if nextGroup != nil {
+ actionLinks = append(actionLinks, maps.Map{
+ "name": nextGroup.Name,
+ "url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
+ })
+
+ nextSet := nextGroup.FindRuleSet(set.ActionOptions.GetInt64("setId"))
+ if nextSet != nil {
+ actionLinks = append(actionLinks, maps.Map{
+ "name": nextSet.Name,
+ "url": "/servers/components/waf/group?firewallPolicyId=" + strconv.FormatInt(params.FirewallPolicyId, 10) + "&type=" + params.Type + "&groupId=" + strconv.FormatInt(nextGroup.Id, 10),
+ })
+ }
+ }
+ }
+
+ return maps.Map{
+ "id": set.Id,
+ "name": set.Name,
+ "rules": lists.Map(set.Rules, func(k int, v interface{}) interface{} {
+ rule := v.(*firewallconfigs.HTTPFirewallRule)
+
+ return maps.Map{
+ "param": rule.Param,
+ "operator": rule.Operator,
+ "value": rule.Value,
+ "isCaseInsensitive": rule.IsCaseInsensitive,
+ }
+ }),
+ "isOn": set.IsOn,
+ "action": strings.ToUpper(set.Action),
+ "actionOptions": set.ActionOptions,
+ "actionName": firewallconfigs.FindActionName(set.Action),
+ "actionLinks": actionLinks,
+ "connector": strings.ToUpper(set.Connector),
+ }
+ })
+
+ this.Show()
+}
diff --git a/internal/web/actions/default/servers/components/waf/init.go b/internal/web/actions/default/servers/components/waf/init.go
index b404a531..88dd4fc5 100644
--- a/internal/web/actions/default/servers/components/waf/init.go
+++ b/internal/web/actions/default/servers/components/waf/init.go
@@ -18,7 +18,7 @@ func init() {
Post("/delete", new(DeleteAction)).
Get("/policy", new(PolicyAction)).
Get("/groups", new(GroupsAction)).
- Get("/sets", new(SetsAction)).
+ Get("/group", new(GroupAction)).
Get("/log", new(LogAction)).
GetPost("/update", new(UpdateAction)).
GetPost("/test", new(TestAction)).
@@ -29,6 +29,13 @@ func init() {
GetPost("/ipadmin", new(IpadminAction)).
GetPost("/createGroupPopup", new(CreateGroupPopupAction)).
Post("/sortGroups", new(SortGroupsAction)).
+ GetPost("/updateGroupPopup", new(UpdateGroupPopupAction)).
+ GetPost("/createSetPopup", new(CreateSetPopupAction)).
+ GetPost("/createRulePopup", new(CreateRulePopupAction)).
+ Post("/sortSets", new(SortSetsAction)).
+ Post("/updateSetOn", new(UpdateSetOnAction)).
+ Post("/deleteSet", new(DeleteSetAction)).
+ GetPost("/updateSetPopup", new(UpdateSetPopupAction)).
EndAll()
})
}
diff --git a/internal/web/actions/default/servers/components/waf/sets.go b/internal/web/actions/default/servers/components/waf/sets.go
deleted file mode 100644
index 04c2e912..00000000
--- a/internal/web/actions/default/servers/components/waf/sets.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package waf
-
-import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
-
-type SetsAction struct {
- actionutils.ParentAction
-}
-
-func (this *SetsAction) Init() {
- this.Nav("", "", "")
-}
-
-func (this *SetsAction) RunGet(params struct{}) {
- this.Show()
-}
diff --git a/internal/web/actions/default/servers/components/waf/sortSets.go b/internal/web/actions/default/servers/components/waf/sortSets.go
new file mode 100644
index 00000000..65c84fa4
--- /dev/null
+++ b/internal/web/actions/default/servers/components/waf/sortSets.go
@@ -0,0 +1,53 @@
+package waf
+
+import (
+ "encoding/json"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/models"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
+)
+
+type SortSetsAction struct {
+ actionutils.ParentAction
+}
+
+func (this *SortSetsAction) RunPost(params struct {
+ GroupId int64
+ SetIds []int64
+}) {
+ groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if groupConfig == nil {
+ this.NotFound("firewallRuleGroup", params.GroupId)
+ return
+ }
+
+ setMap := map[int64]*firewallconfigs.HTTPFirewallRuleSetRef{}
+ for _, setRef := range groupConfig.SetRefs {
+ setMap[setRef.SetId] = setRef
+ }
+
+ newRefs := []*firewallconfigs.HTTPFirewallRuleSetRef{}
+ for _, setId := range params.SetIds {
+ ref, ok := setMap[setId]
+ if ok {
+ newRefs = append(newRefs, ref)
+ }
+ }
+ newRefsJSON, err := json.Marshal(newRefs)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ _, err = this.RPC().HTTPFirewallRuleGroupRPC().UpdateHTTPFirewallRuleGroupSets(this.AdminContext(), &pb.UpdateHTTPFirewallRuleGroupSetsRequest{
+ FirewallRuleGroupId: params.GroupId,
+ FirewallRuleSetsJSON: newRefsJSON,
+ })
+
+ this.Success()
+}
diff --git a/internal/web/actions/default/servers/components/waf/updateGroupPopup.go b/internal/web/actions/default/servers/components/waf/updateGroupPopup.go
new file mode 100644
index 00000000..0eb2e69b
--- /dev/null
+++ b/internal/web/actions/default/servers/components/waf/updateGroupPopup.go
@@ -0,0 +1,66 @@
+package waf
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/models"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/iwind/TeaGo/actions"
+ "github.com/iwind/TeaGo/maps"
+)
+
+type UpdateGroupPopupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *UpdateGroupPopupAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *UpdateGroupPopupAction) RunGet(params struct {
+ GroupId int64
+}) {
+ groupConfig, err := models.SharedHTTPFirewallRuleGroupDAO.FindRuleGroupConfig(this.AdminContext(), params.GroupId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if groupConfig == nil {
+ this.NotFound("ruleGroup", params.GroupId)
+ return
+ }
+
+ this.Data["group"] = maps.Map{
+ "id": groupConfig.Id,
+ "name": groupConfig.Name,
+ "description": groupConfig.Description,
+ "isOn": groupConfig.IsOn,
+ }
+
+ this.Show()
+}
+
+func (this *UpdateGroupPopupAction) RunPost(params struct {
+ GroupId int64
+ Name string
+ Description string
+ IsOn bool
+
+ Must *actions.Must
+}) {
+ params.Must.
+ Field("name", params.Name).
+ Require("请输入分组名称")
+
+ _, err := this.RPC().HTTPFirewallRuleGroupRPC().UpdateHTTPFirewallRuleGroup(this.AdminContext(), &pb.UpdateHTTPFirewallRuleGroupRequest{
+ FirewallRuleGroupId: params.GroupId,
+ IsOn: params.IsOn,
+ Name: params.Name,
+ Description: params.Description,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
diff --git a/internal/web/actions/default/servers/components/waf/updateSetOn.go b/internal/web/actions/default/servers/components/waf/updateSetOn.go
new file mode 100644
index 00000000..18059f5c
--- /dev/null
+++ b/internal/web/actions/default/servers/components/waf/updateSetOn.go
@@ -0,0 +1,26 @@
+package waf
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+)
+
+type UpdateSetOnAction struct {
+ actionutils.ParentAction
+}
+
+func (this *UpdateSetOnAction) RunPost(params struct {
+ SetId int64
+ IsOn bool
+}) {
+ _, err := this.RPC().HTTPFirewallRuleSetRPC().UpdateHTTPFirewallRuleSetIsOn(this.AdminContext(), &pb.UpdateHTTPFirewallRuleSetIsOnRequest{
+ FirewallRuleSetId: params.SetId,
+ IsOn: params.IsOn,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
diff --git a/internal/web/actions/default/servers/components/waf/updateSetPopup.go b/internal/web/actions/default/servers/components/waf/updateSetPopup.go
new file mode 100644
index 00000000..6e14cc5f
--- /dev/null
+++ b/internal/web/actions/default/servers/components/waf/updateSetPopup.go
@@ -0,0 +1,152 @@
+package waf
+
+import (
+ "encoding/json"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/models"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
+ "github.com/iwind/TeaGo/actions"
+ "github.com/iwind/TeaGo/maps"
+ "strings"
+)
+
+type UpdateSetPopupAction struct {
+ actionutils.ParentAction
+}
+
+func (this *UpdateSetPopupAction) Init() {
+ this.Nav("", "", "")
+}
+
+func (this *UpdateSetPopupAction) RunGet(params struct {
+ FirewallPolicyId int64
+ GroupId int64
+ Type string
+ SetId int64
+}) {
+ this.Data["groupId"] = params.GroupId
+ this.Data["type"] = params.Type
+
+ firewallPolicy, err := models.SharedHTTPFirewallPolicyDAO.FindEnabledPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if firewallPolicy == nil {
+ this.NotFound("firewallPolicy", params.FirewallPolicyId)
+ return
+ }
+ this.Data["firewallPolicy"] = firewallPolicy
+
+ // 一些配置
+ this.Data["connectors"] = []maps.Map{
+ {
+ "name": "和(AND)",
+ "value": firewallconfigs.HTTPFirewallRuleConnectorAnd,
+ "description": "所有规则都满足才视为匹配",
+ },
+ {
+ "name": "或(OR)",
+ "value": firewallconfigs.HTTPFirewallRuleConnectorOr,
+ "description": "任一规则满足了就视为匹配",
+ },
+ }
+
+ actionMaps := []maps.Map{}
+ for _, action := range firewallconfigs.AllActions {
+ actionMaps = append(actionMaps, maps.Map{
+ "name": action.Name,
+ "description": action.Description,
+ "code": action.Code,
+ })
+ }
+ this.Data["actions"] = actionMaps
+
+ // 规则集信息
+ setConfig, err := models.SharedHTTPFirewallRuleSetDAO.FindRuleSetConfig(this.AdminContext(), params.SetId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if setConfig == nil {
+ this.NotFound("firewallRuleSet", params.SetId)
+ return
+ }
+ this.Data["setConfig"] = setConfig
+
+ this.Show()
+}
+
+func (this *UpdateSetPopupAction) RunPost(params struct {
+ GroupId int64
+ SetId int64
+
+ Name string
+ RulesJSON []byte
+ Connector string
+ Action string
+
+ Must *actions.Must
+}) {
+ // 规则集信息
+ setConfig, err := models.SharedHTTPFirewallRuleSetDAO.FindRuleSetConfig(this.AdminContext(), params.SetId)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if setConfig == nil {
+ this.NotFound("firewallRuleSet", params.SetId)
+ return
+ }
+
+ params.Must.
+ Field("name", params.Name).
+ Require("请输入规则集名称")
+
+ if len(params.RulesJSON) == 0 {
+ this.Fail("请添加至少一个规则")
+ }
+ rules := []*firewallconfigs.HTTPFirewallRule{}
+ err = json.Unmarshal(params.RulesJSON, &rules)
+ if err != nil {
+ this.ErrorPage(err)
+ }
+ if len(rules) == 0 {
+ this.Fail("请添加至少一个规则")
+ }
+
+ setConfig.Name = params.Name
+ setConfig.Connector = params.Connector
+ setConfig.Rules = rules
+ setConfig.Action = params.Action
+ setConfig.ActionOptions = maps.Map{}
+
+ for k, v := range this.ParamsMap {
+ if len(v) == 0 {
+ continue
+ }
+ index := strings.Index(k, "action_")
+ if index > -1 {
+ setConfig.ActionOptions[k[len("action_"):]] = v[0]
+ }
+ }
+
+ setConfigJSON, err := json.Marshal(setConfig)
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ _, err = this.RPC().HTTPFirewallRuleSetRPC().CreateOrUpdateHTTPFirewallRuleSetFromConfig(this.AdminContext(), &pb.CreateOrUpdateHTTPFirewallRuleSetFromConfigRequest{FirewallRuleSetConfigJSON: setConfigJSON})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+
+ this.Success()
+}
diff --git a/internal/web/models/http_firewall_rule_group_dao.go b/internal/web/models/http_firewall_rule_group_dao.go
new file mode 100644
index 00000000..a3e42507
--- /dev/null
+++ b/internal/web/models/http_firewall_rule_group_dao.go
@@ -0,0 +1,39 @@
+package models
+
+import (
+ "context"
+ "encoding/json"
+ "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
+)
+
+var SharedHTTPFirewallRuleGroupDAO = new(HTTPFirewallRuleGroupDAO)
+
+type HTTPFirewallRuleGroupDAO struct {
+}
+
+// 查找分组配置
+func (this *HTTPFirewallRuleGroupDAO) FindRuleGroupConfig(ctx context.Context, groupId int64) (*firewallconfigs.HTTPFirewallRuleGroup, error) {
+ client, err := rpc.SharedRPC()
+ if err != nil {
+ return nil, err
+ }
+
+ groupResp, err := client.HTTPFirewallRuleGroupRPC().FindHTTPFirewallRuleGroupConfig(ctx, &pb.FindHTTPFirewallRuleGroupConfigRequest{FirewallRuleGroupId: groupId})
+ if err != nil {
+ return nil, err
+ }
+
+ if len(groupResp.FirewallRuleGroupJSON) == 0 {
+ return nil, nil
+ }
+
+ groupConfig := &firewallconfigs.HTTPFirewallRuleGroup{}
+ err = json.Unmarshal(groupResp.FirewallRuleGroupJSON, groupConfig)
+ if err != nil {
+ return nil, err
+ }
+
+ return groupConfig, nil
+}
diff --git a/internal/web/models/http_firewall_rule_set_dao.go b/internal/web/models/http_firewall_rule_set_dao.go
new file mode 100644
index 00000000..adb0ee42
--- /dev/null
+++ b/internal/web/models/http_firewall_rule_set_dao.go
@@ -0,0 +1,35 @@
+package models
+
+import (
+ "context"
+ "encoding/json"
+ "github.com/TeaOSLab/EdgeAdmin/internal/rpc"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
+)
+
+var SharedHTTPFirewallRuleSetDAO = new(HTTPFirewallRuleSetDAO)
+
+type HTTPFirewallRuleSetDAO struct {
+}
+
+// 查找规则集配置
+func (this *HTTPFirewallRuleSetDAO) FindRuleSetConfig(ctx context.Context, setId int64) (*firewallconfigs.HTTPFirewallRuleSet, error) {
+ client, err := rpc.SharedRPC()
+ if err != nil {
+ return nil, err
+ }
+ resp, err := client.HTTPFirewallRuleSetRPC().FindHTTPFirewallRuleSetConfig(ctx, &pb.FindHTTPFirewallRuleSetConfigRequest{FirewallRuleSetId: setId})
+ if err != nil {
+ return nil, err
+ }
+ if len(resp.FirewallRuleSetJSON) == 0 {
+ return nil, err
+ }
+ config := &firewallconfigs.HTTPFirewallRuleSet{}
+ err = json.Unmarshal(resp.FirewallRuleSetJSON, config)
+ if err != nil {
+ return nil, err
+ }
+ return config, nil
+}
diff --git a/web/public/js/components/common/sortable.js b/web/public/js/components/common/sortable.js
index 45384421..fa431779 100644
--- a/web/public/js/components/common/sortable.js
+++ b/web/public/js/components/common/sortable.js
@@ -6,6 +6,9 @@ function sortTable(callback) {
jsFile.addEventListener("load", function () {
// 初始化
let box = document.querySelector("#sortable-table")
+ if (box == null) {
+ return
+ }
Sortable.create(box, {
draggable: "tbody",
handle: ".icon.handle",
diff --git a/web/public/js/components/server/http-firewall-rules-box.js b/web/public/js/components/server/http-firewall-rules-box.js
new file mode 100644
index 00000000..9ed7a7db
--- /dev/null
+++ b/web/public/js/components/server/http-firewall-rules-box.js
@@ -0,0 +1,50 @@
+Vue.component("http-firewall-rules-box", {
+ props: ["v-rules", "v-type"],
+ data: function () {
+ let rules = this.vRules
+ if (rules == null) {
+ rules = []
+ }
+ return {
+ rules: rules
+ }
+ },
+ methods: {
+ addRule: function () {
+ window.UPDATING_RULE = null
+ let that = this
+ teaweb.popup("/servers/components/waf/createRulePopup?type=" + this.vType, {
+ callback: function (resp) {
+ that.rules.push(resp.data.rule)
+ }
+ })
+ },
+ updateRule: function (index, rule) {
+ window.UPDATING_RULE = rule
+ let that = this
+ teaweb.popup("/servers/components/waf/createRulePopup?type=" + this.vType, {
+ callback: function (resp) {
+ Vue.set(that.rules, index, resp.data.rule)
+ }
+ })
+ },
+ removeRule: function (index) {
+ let that = this
+ teaweb.confirm("确定要删除此规则吗?", function () {
+ that.rules.$remove(index)
+ })
+ }
+ },
+ template: `
+
+
+
+
{{rule.param}} {{rule.operator}} {{rule.value}}
+
+
+
+
+
+
+
+
`
+})
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/createRulePopup.html b/web/views/@default/servers/components/waf/createRulePopup.html
new file mode 100644
index 00000000..e587caab
--- /dev/null
+++ b/web/views/@default/servers/components/waf/createRulePopup.html
@@ -0,0 +1,86 @@
+{$layout "layout_popup"}
+
+添加规则
+修改规则
+
+
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/createRulePopup.js b/web/views/@default/servers/components/waf/createRulePopup.js
new file mode 100644
index 00000000..d369c378
--- /dev/null
+++ b/web/views/@default/servers/components/waf/createRulePopup.js
@@ -0,0 +1,70 @@
+Tea.context(function () {
+ this.success = NotifyPopup
+
+ this.isUpdating = (window.parent.UPDATING_RULE != null)
+ this.rule = {
+ id: 0,
+ param: "",
+ checkpointPrefix: "",
+ checkpointParam: "",
+ value: "",
+ isCaseInsensitive: false,
+ operator: "match",
+ checkpointOptions: null,
+ description: "",
+ isOn: true
+ }
+ if (window.parent.UPDATING_RULE != null) {
+ this.rule = window.parent.UPDATING_RULE
+
+ let param = this.rule.param.substring(this.rule.param.indexOf("${") + 2, this.rule.param.indexOf("}"))
+ let index = param.indexOf(".")
+ if (index > 0) {
+ this.rule.checkpointPrefix = param.substring(0, index)
+ this.rule.checkpointParam = param.substring(index + 1)
+ } else {
+ this.rule.checkpointPrefix = param
+ }
+ this.$delay(function () {
+ this.changeCheckpoint()
+ if (this.rule.checkpointOptions != null && this.checkpoint != null && this.checkpoint.options != null) {
+ let that = this
+ this.checkpoint.options.forEach(function (option) {
+ if (typeof (that.rule.checkpointOptions[option.code]) != "undefined") {
+ option.value = that.rule.checkpointOptions[option.code]
+ }
+ })
+ }
+ })
+ }
+
+ /**
+ * checkpoint
+ */
+ this.checkpoint = null
+ this.changeCheckpoint = function () {
+ if (this.rule.checkpointPrefix.length == 0) {
+ this.checkpoint = null
+ return
+ }
+ let that = this
+ this.checkpoint = this.checkpoints.$find(function (k, v) {
+ return v.prefix == that.rule.checkpointPrefix
+ })
+ }
+
+
+ /**
+ * operator
+ */
+ this.changeOperator = function () {
+ let that = this;
+ this.operator = this.operators.$find(function (k, v) {
+ return v.code == that.rule.operator
+ })
+ if (!this.isUpdating) {
+ this.rule.isCaseInsensitive = (this.operator.case == "yes")
+ }
+ };
+ this.changeOperator()
+})
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/createSetPopup.html b/web/views/@default/servers/components/waf/createSetPopup.html
new file mode 100644
index 00000000..bc264a13
--- /dev/null
+++ b/web/views/@default/servers/components/waf/createSetPopup.html
@@ -0,0 +1,67 @@
+{$layout "layout_popup"}
+
+添加规则集
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/createSetPopup.js b/web/views/@default/servers/components/waf/createSetPopup.js
new file mode 100644
index 00000000..ba4be577
--- /dev/null
+++ b/web/views/@default/servers/components/waf/createSetPopup.js
@@ -0,0 +1,43 @@
+Tea.context(function () {
+ this.success = NotifyPopup
+
+ // rules
+ this.rules = []
+
+ // connector
+ this.selectedConnector = this.connectors[1].value
+ this.selectedConnectorDescription = ""
+ this.changeConnector = function () {
+ let that = this
+ this.selectedConnectorDescription = this.connectors.$find(function (k, v) {
+ return v.value == that.selectedConnector
+ }).description
+ }
+ this.changeConnector()
+
+ // action
+ this.action = "block"
+
+ // action:go_group
+ this.actionGroupId = 0
+
+ // action:go_set
+ this.actionSetId = 0
+ this.groupSets = function (groupId) {
+ let group = null
+ this.firewallPolicy.inbound.groups.forEach(function (v) {
+ if (v.id == groupId) {
+ group = v
+ }
+ })
+ this.firewallPolicy.outbound.groups.forEach(function (v) {
+ if (v.id == groupId) {
+ group = v
+ }
+ })
+ if (group == null) {
+ return []
+ }
+ return group.sets
+ }
+})
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/group.html b/web/views/@default/servers/components/waf/group.html
new file mode 100644
index 00000000..9ac4c203
--- /dev/null
+++ b/web/views/@default/servers/components/waf/group.html
@@ -0,0 +1,69 @@
+{$layout}
+{$template "/left_menu"}
+
+
+ {$template "waf_menu"}
+
+
+
+
+ 名称
+ {{group.name}}
+
+
+ 描述
+
+ 暂时还没有描述。
+ {{group.description}}
+
+
+
+ 启用状态
+
+
+
+
+
+
+
+
+
+
+
+
+ 规则集名称
+ 规则
+ 关系
+ 动作
+ 操作
+
+
+
+
+
+ {{set.name}}
+
+
+
+
+
+
+ {{rule.name}}[{{rule.param}}] {{rule.operator}} {{rule.value}}
+
+ 暂时还没有规则
+
+ {{set.connector.toUpperCase()}}
+ {{set.actionName}}[{{set.action.toUpperCase()}}]
+
+
+
+ 修改 停用 启用 删除
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/group.js b/web/views/@default/servers/components/waf/group.js
new file mode 100644
index 00000000..f5bf9c20
--- /dev/null
+++ b/web/views/@default/servers/components/waf/group.js
@@ -0,0 +1,82 @@
+Tea.context(function () {
+ this.$delay(function () {
+ let that = this
+ sortTable(function () {
+ let setIds = []
+ document
+ .querySelectorAll("tbody[data-set-id]")
+ .forEach(function (v) {
+ setIds.push(v.getAttribute("data-set-id"))
+ })
+ that.$post(".sortSets")
+ .params({
+ groupId: that.group.id,
+ setIds: setIds
+ })
+ .success(function () {
+ teaweb.successToast("排序保存成功")
+ })
+ })
+ })
+
+ // 更改分组
+ this.updateGroup = function (groupId) {
+ teaweb.popup("/servers/components/waf/updateGroupPopup?groupId=" + groupId, {
+ height: "16em",
+ callback: function () {
+ teaweb.success("保存成功", function () {
+ window.location.reload()
+ })
+ }
+ })
+ }
+
+ // 创建规则集
+ this.createSet = function (groupId) {
+ teaweb.popup("/servers/components/waf/createSetPopup?firewallPolicyId=" + this.firewallPolicyId + "&groupId=" + groupId + "&type=" + this.type, {
+ width: "50em",
+ height: "30em",
+ callback: function () {
+ teaweb.success("保存成功", function () {
+ window.location.reload()
+ })
+ }
+ })
+ }
+
+ // 修改规则集
+ this.updateSet = function (setId) {
+ teaweb.popup("/servers/components/waf/updateSetPopup?firewallPolicyId=" + this.firewallPolicyId + "&groupId=" + this.group.id + "&type=" + this.type + "&setId=" + setId, {
+ width: "50em",
+ height: "30em",
+ callback: function () {
+ teaweb.success("保存成功", function () {
+ window.location.reload()
+ })
+ }
+ })
+ }
+
+ // 停用|启用规则集
+ this.updateSetOn = function (setId, isOn) {
+ this.$post(".updateSetOn")
+ .params({
+ setId: setId,
+ isOn: isOn ? 1 : 0
+ })
+ .refresh()
+ }
+
+ // 删除规则集
+ this.deleteSet = function (setId) {
+ let that = this
+ teaweb.confirm("确定要删除此规则集吗?", function () {
+ that.$post(".deleteSet")
+ .params({
+ groupId: this.group.id,
+ setId: setId
+ })
+ .refresh()
+ })
+ }
+})
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/groups.html b/web/views/@default/servers/components/waf/groups.html
index 99758477..e7f926e2 100644
--- a/web/views/@default/servers/components/waf/groups.html
+++ b/web/views/@default/servers/components/waf/groups.html
@@ -32,7 +32,7 @@
- {{group.countSets}}
+ {{group.countSets}}
详情
@@ -42,4 +42,6 @@
+
+
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/updateGroupPopup.html b/web/views/@default/servers/components/waf/updateGroupPopup.html
new file mode 100644
index 00000000..caadd3e6
--- /dev/null
+++ b/web/views/@default/servers/components/waf/updateGroupPopup.html
@@ -0,0 +1,38 @@
+{$layout "layout_popup"}
+
+修改分组
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/updateGroupPopup.js b/web/views/@default/servers/components/waf/updateGroupPopup.js
new file mode 100644
index 00000000..c8fe9515
--- /dev/null
+++ b/web/views/@default/servers/components/waf/updateGroupPopup.js
@@ -0,0 +1,3 @@
+Tea.context(function () {
+ this.success = NotifyPopup
+})
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/updateSetPopup.html b/web/views/@default/servers/components/waf/updateSetPopup.html
new file mode 100644
index 00000000..6f6e9b94
--- /dev/null
+++ b/web/views/@default/servers/components/waf/updateSetPopup.html
@@ -0,0 +1,67 @@
+{$layout "layout_popup"}
+
+修改规则集
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/views/@default/servers/components/waf/updateSetPopup.js b/web/views/@default/servers/components/waf/updateSetPopup.js
new file mode 100644
index 00000000..e1275b90
--- /dev/null
+++ b/web/views/@default/servers/components/waf/updateSetPopup.js
@@ -0,0 +1,57 @@
+Tea.context(function () {
+ this.success = NotifyPopup
+
+ // rules
+ this.rules = this.setConfig.rules
+
+ // connector
+ this.selectedConnector = this.setConfig.connector
+ this.selectedConnectorDescription = ""
+ this.changeConnector = function () {
+ let that = this
+ this.selectedConnectorDescription = this.connectors.$find(function (k, v) {
+ return v.value == that.selectedConnector
+ }).description
+ }
+ this.changeConnector()
+
+ // action
+ this.action = this.setConfig.action
+
+ // action:go_group
+ this.actionGroupId = 0
+ if (this.action == "go_group" || this.action == "go_set" && this.setConfig.actionOptions != null) {
+ this.$delay(function () {
+ this.actionGroupId = this.setConfig.actionOptions["groupId"]
+ })
+ }
+
+ // action:go_set
+ this.actionSetId = 0
+ if (this.action == "go_set" && this.setConfig.actionOptions != null) {
+ this.$delay(function () {
+ this.actionSetId = this.setConfig.actionOptions["setId"]
+ })
+ }
+
+ this.groupSets = function (groupId) {
+ if (this.firewallPolicy == null) {
+ return
+ }
+ let group = null
+ this.firewallPolicy.inbound.groups.forEach(function (v) {
+ if (v.id == groupId) {
+ group = v
+ }
+ })
+ this.firewallPolicy.outbound.groups.forEach(function (v) {
+ if (v.id == groupId) {
+ group = v
+ }
+ })
+ if (group == null) {
+ return []
+ }
+ return group.sets
+ }
+})
\ No newline at end of file