diff --git a/backend/app/api/v1/firewall.go b/backend/app/api/v1/firewall.go index 04f8549f1..80ce04716 100644 --- a/backend/app/api/v1/firewall.go +++ b/backend/app/api/v1/firewall.go @@ -54,7 +54,7 @@ func (b *BaseApi) OperatePortRule(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - if err := firewallService.OperatePortRule(req); err != nil { + if err := firewallService.OperatePortRule(req, true); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } @@ -80,7 +80,82 @@ func (b *BaseApi) OperateIPRule(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - if err := firewallService.OperateAddressRule(req); err != nil { + if err := firewallService.OperateAddressRule(req, true); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Firewall +// @Summary Create group +// @Description 批量删除防火墙规则 +// @Accept json +// @Param request body dto.BatchRuleOperate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /hosts/firewall/ip [post] +func (b *BaseApi) BatchOperateRule(c *gin.Context) { + var req dto.BatchRuleOperate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := firewallService.BacthOperateRule(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Firewall +// @Summary Create group +// @Description 更新端口防火墙规则 +// @Accept json +// @Param request body dto.PortRuleUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /hosts/firewall/update/port [post] +func (b *BaseApi) UpdatePortRule(c *gin.Context) { + var req dto.PortRuleUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := firewallService.UpdatePortRule(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} + +// @Tags Firewall +// @Summary Create group +// @Description 更新 ip 防火墙规则 +// @Accept json +// @Param request body dto.AddrRuleUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /hosts/firewall/update/ip [post] +func (b *BaseApi) UpdateAddrRule(c *gin.Context) { + var req dto.AddrRuleUpdate + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := firewallService.UpdateAddrRule(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } diff --git a/backend/app/dto/firewall.go b/backend/app/dto/firewall.go index 77960cb34..85b049e1d 100644 --- a/backend/app/dto/firewall.go +++ b/backend/app/dto/firewall.go @@ -2,6 +2,7 @@ package dto type RuleSearch struct { PageInfo + Info string `json:"info"` Type string `json:"type" validate:"required"` } @@ -18,3 +19,18 @@ type AddrRuleOperate struct { Address string `json:"address" validate:"required"` Strategy string `json:"strategy" validate:"required,oneof=accept drop"` } + +type PortRuleUpdate struct { + OldRule PortRuleOperate `json:"oldRule"` + NewRule PortRuleOperate `json:"newRule"` +} + +type AddrRuleUpdate struct { + OldRule AddrRuleOperate `json:"oldRule"` + NewRule AddrRuleOperate `json:"newRule"` +} + +type BatchRuleOperate struct { + Type string `json:"type" validate:"required"` + Rules []PortRuleOperate `json:"rules"` +} diff --git a/backend/app/service/firewall.go b/backend/app/service/firewall.go index 7220183f2..444404f0a 100644 --- a/backend/app/service/firewall.go +++ b/backend/app/service/firewall.go @@ -1,6 +1,8 @@ package service import ( + "strings" + "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/utils/firewall" fireClient "github.com/1Panel-dev/1Panel/backend/utils/firewall/client" @@ -11,8 +13,11 @@ type FirewallService struct{} type IFirewallService interface { SearchWithPage(search dto.RuleSearch) (int64, interface{}, error) - OperatePortRule(req dto.PortRuleOperate) error - OperateAddressRule(req dto.AddrRuleOperate) error + OperatePortRule(req dto.PortRuleOperate, reload bool) error + OperateAddressRule(req dto.AddrRuleOperate, reload bool) error + UpdatePortRule(req dto.PortRuleUpdate) error + UpdateAddrRule(req dto.AddrRuleUpdate) error + BacthOperateRule(req dto.BatchRuleOperate) error } func NewIFirewallService() IFirewallService { @@ -33,13 +38,29 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{} if err != nil { return 0, nil, err } - datas = ports + if len(req.Info) != 0 { + for _, port := range ports { + if strings.Contains(port.Port, req.Info) { + datas = append(datas, port) + } + } + } else { + datas = ports + } } else { - address, err := client.ListAddress() + addrs, err := client.ListAddress() if err != nil { return 0, nil, err } - datas = address + if len(req.Info) != 0 { + for _, addr := range addrs { + if strings.Contains(addr.Address, req.Info) { + datas = append(datas, addr) + } + } + } else { + datas = addrs + } } total, start, end := len(datas), (req.Page-1)*req.PageSize, req.Page*req.PageSize if start > total { @@ -54,25 +75,36 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{} return int64(total), backDatas, nil } -func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate) error { +func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool) error { client, err := firewall.NewFirewallClient() if err != nil { return err } + if client.Name() == "ufw" { + req.Port = strings.ReplaceAll(req.Port, "-", ":") + if req.Operation == "remove" && req.Protocol == "tcp/udp" { + req.Protocol = "" + return u.operatePort(client, req) + } + } + if req.Protocol == "tcp/udp" { req.Protocol = "tcp" - if err := u.createPort(client, req); err != nil { + if err := u.operatePort(client, req); err != nil { return err } req.Protocol = "udp" } - if err := u.createPort(client, req); err != nil { + if err := u.operatePort(client, req); err != nil { return err } - return client.Reload() + if reload { + return client.Reload() + } + return nil } -func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate) error { +func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload bool) error { client, err := firewall.NewFirewallClient() if err != nil { return err @@ -82,18 +114,86 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate) error { if err := copier.Copy(&fireInfo, &req); err != nil { return err } - if err := client.RichRules(fireInfo, req.Operation); err != nil { + + addressList := strings.Split(req.Address, ",") + for _, addr := range addressList { + if len(addr) == 0 { + continue + } + fireInfo.Address = addr + if err := client.RichRules(fireInfo, req.Operation); err != nil { + return err + } + } + if reload { + return client.Reload() + } + return nil +} + +func (u *FirewallService) UpdatePortRule(req dto.PortRuleUpdate) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + if err := u.OperatePortRule(req.OldRule, false); err != nil { + return err + } + if err := u.OperatePortRule(req.NewRule, false); err != nil { return err } return client.Reload() } -func (u *FirewallService) createPort(client firewall.FirewallClient, req dto.PortRuleOperate) error { +func (u *FirewallService) UpdateAddrRule(req dto.AddrRuleUpdate) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + if err := u.OperateAddressRule(req.OldRule, false); err != nil { + return err + } + if err := u.OperateAddressRule(req.NewRule, false); err != nil { + return err + } + return client.Reload() +} + +func (u *FirewallService) BacthOperateRule(req dto.BatchRuleOperate) error { + client, err := firewall.NewFirewallClient() + if err != nil { + return err + } + if req.Type == "port" { + for _, rule := range req.Rules { + if err := u.OperatePortRule(rule, false); err != nil { + return err + } + } + return client.Reload() + } + for _, rule := range req.Rules { + itemRule := dto.AddrRuleOperate{Operation: rule.Operation, Address: rule.Address, Strategy: rule.Strategy} + if err := u.OperateAddressRule(itemRule, false); err != nil { + return err + } + } + return client.Reload() +} + +func (u *FirewallService) operatePort(client firewall.FirewallClient, req dto.PortRuleOperate) error { var fireInfo fireClient.FireInfo if err := copier.Copy(&fireInfo, &req); err != nil { return err } + if client.Name() == "ufw" { + if len(fireInfo.Address) != 0 && fireInfo.Address != "Anywhere" { + return client.RichRules(fireInfo, req.Operation) + } + return client.Port(fireInfo, req.Operation) + } + if len(fireInfo.Address) != 0 || fireInfo.Strategy == "drop" { return client.RichRules(fireInfo, req.Operation) } diff --git a/backend/router/ro_host.go b/backend/router/ro_host.go index 7e987d445..6617f742f 100644 --- a/backend/router/ro_host.go +++ b/backend/router/ro_host.go @@ -29,6 +29,9 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) { hostRouter.POST("/firewall/search", baseApi.SearchFirewallRule) hostRouter.POST("/firewall/port", baseApi.OperatePortRule) hostRouter.POST("/firewall/ip", baseApi.OperateIPRule) + hostRouter.POST("/firewall/batch", baseApi.BatchOperateRule) + hostRouter.POST("/firewall/update/port", baseApi.UpdatePortRule) + hostRouter.POST("/firewall/update/addr", baseApi.UpdateAddrRule) hostRouter.GET("/command", baseApi.ListCommand) hostRouter.POST("/command", baseApi.CreateCommand) diff --git a/backend/utils/firewall/client.go b/backend/utils/firewall/client.go index 433a6ec63..37fd4501f 100644 --- a/backend/utils/firewall/client.go +++ b/backend/utils/firewall/client.go @@ -5,6 +5,7 @@ import ( ) type FirewallClient interface { + Name() string Start() error Stop() error Reload() error diff --git a/backend/utils/firewall/client/firewalld.go b/backend/utils/firewall/client/firewalld.go index 2d34ef168..5c3df7e70 100644 --- a/backend/utils/firewall/client/firewalld.go +++ b/backend/utils/firewall/client/firewalld.go @@ -21,6 +21,10 @@ func NewFirewalld() (*Firewall, error) { return &Firewall{Client: ConnInfo}, nil } +func (f *Firewall) Name() string { + return "firewalld" +} + func (f *Firewall) Status() (string, error) { stdout, err := f.Client.Run("firewall-cmd --state") if err != nil { @@ -80,7 +84,7 @@ func (f *Firewall) ListPort() ([]FireInfo, error) { continue } itemRule := f.loadInfo(rule) - if len(itemRule.Port) != 0 { + if len(itemRule.Port) != 0 && itemRule.Family == "ipv4" { datas = append(datas, itemRule) } } diff --git a/backend/utils/firewall/client/ufw.go b/backend/utils/firewall/client/ufw.go index 33cc6edb2..d1ca15809 100644 --- a/backend/utils/firewall/client/ufw.go +++ b/backend/utils/firewall/client/ufw.go @@ -21,6 +21,10 @@ func NewUfw() (*Ufw, error) { return &Ufw{Client: ConnInfo}, nil } +func (f *Ufw) Name() string { + return "ufw" +} + func (f *Ufw) Status() (string, error) { stdout, err := f.Client.Run("sudo ufw status") if err != nil { @@ -49,10 +53,6 @@ func (f *Ufw) Stop() error { } func (f *Ufw) Reload() error { - stdout, err := f.Client.Run("sudo ufw reload") - if err != nil { - return fmt.Errorf("reload firewall failed, err: %s", stdout) - } return nil } @@ -73,7 +73,8 @@ func (f *Ufw) ListPort() ([]FireInfo, error) { continue } itemFire := f.loadInfo(line, "port") - if len(itemFire.Port) != 0 { + if len(itemFire.Port) != 0 && itemFire.Port != "Anywhere" && !strings.Contains(itemFire.Port, ".") { + itemFire.Port = strings.ReplaceAll(itemFire.Port, ":", "-") datas = append(datas, itemFire) } } @@ -100,7 +101,11 @@ func (f *Ufw) ListAddress() ([]FireInfo, error) { continue } itemFire := f.loadInfo(line, "address") - if len(itemFire.Port) == 0 { + if strings.Contains(itemFire.Port, ".") { + itemFire.Address += ("-" + itemFire.Port) + itemFire.Port = "" + } + if len(itemFire.Port) == 0 && len(itemFire.Address) != 0 { datas = append(datas, itemFire) } } @@ -108,16 +113,19 @@ func (f *Ufw) ListAddress() ([]FireInfo, error) { } func (f *Ufw) Port(port FireInfo, operation string) error { - switch operation { - case "add": - operation = "allow" - case "remove": - operation = "deny" + switch port.Strategy { + case "accept": + port.Strategy = "allow" + case "drop": + port.Strategy = "deny" default: - return fmt.Errorf("unsupport operation %s", operation) + return fmt.Errorf("unsupport strategy %s", port.Strategy) } - command := fmt.Sprintf("sudo ufw %s %s", operation, port.Port) + command := fmt.Sprintf("sudo ufw %s %s", port.Strategy, port.Port) + if operation == "remove" { + command = fmt.Sprintf("sudo ufw delete %s %s", port.Strategy, port.Port) + } if len(port.Protocol) != 0 { command += fmt.Sprintf("/%s", port.Protocol) } @@ -129,11 +137,25 @@ func (f *Ufw) Port(port FireInfo, operation string) error { } func (f *Ufw) RichRules(rule FireInfo, operation string) error { - ruleStr := "sudo ufw " + switch rule.Strategy { + case "accept": + rule.Strategy = "allow" + case "drop": + rule.Strategy = "deny" + default: + return fmt.Errorf("unsupport strategy %s", rule.Strategy) + } + + ruleStr := fmt.Sprintf("sudo ufw %s ", rule.Strategy) + if operation == "remove" { + ruleStr = fmt.Sprintf("sudo ufw delete %s ", rule.Strategy) + } if len(rule.Protocol) != 0 { ruleStr += fmt.Sprintf("proto %s ", rule.Protocol) } - if len(rule.Address) != 0 { + if strings.Contains(rule.Address, "-") { + ruleStr += fmt.Sprintf("from %s to %s ", strings.Split(rule.Address, "-")[0], strings.Split(rule.Address, "-")[1]) + } else { ruleStr += fmt.Sprintf("from %s ", rule.Address) } if len(rule.Port) != 0 { @@ -169,9 +191,12 @@ func (f *Ufw) loadInfo(line string, fireType string) FireInfo { if len(fields) < 4 { return itemInfo } + if fields[1] == "(v6)" { + return itemInfo + } if fields[0] == "Anywhere" && fireType != "port" { itemInfo.Strategy = "drop" - if fields[2] == "ALLOW" { + if fields[1] == "ALLOW" { itemInfo.Strategy = "accept" } itemInfo.Address = fields[3] @@ -184,27 +209,13 @@ func (f *Ufw) loadInfo(line string, fireType string) FireInfo { itemInfo.Port = fields[0] itemInfo.Protocol = "tcp/udp" } - - if fields[1] == "(v6)" { - if len(fields) < 5 { - return itemInfo - } - itemInfo.Family = "ipv6" - if fields[2] == "ALLOW" { - itemInfo.Strategy = "accept" - } else { - itemInfo.Strategy = "drop" - } - itemInfo.Address = fields[4] + itemInfo.Family = "ipv4" + if fields[1] == "ALLOW" { + itemInfo.Strategy = "accept" } else { - itemInfo.Family = "ipv4" - if fields[1] == "ALLOW" { - itemInfo.Strategy = "accept" - } else { - itemInfo.Strategy = "drop" - } - itemInfo.Address = fields[3] + itemInfo.Strategy = "drop" } + itemInfo.Address = fields[3] return itemInfo } diff --git a/frontend/src/api/interface/host.ts b/frontend/src/api/interface/host.ts index 6aa1b60d7..1295b76e3 100644 --- a/frontend/src/api/interface/host.ts +++ b/frontend/src/api/interface/host.ts @@ -77,4 +77,16 @@ export namespace Host { address: string; strategy: string; } + export interface UpdatePortRule { + oldRule: RulePort; + newRule: RulePort; + } + export interface UpdateAddrRule { + oldRule: RuleIP; + newRule: RuleIP; + } + export interface BatchRule { + type: string; + rules: Array; + } } diff --git a/frontend/src/api/modules/host.ts b/frontend/src/api/modules/host.ts index 05cd78068..2faafba58 100644 --- a/frontend/src/api/modules/host.ts +++ b/frontend/src/api/modules/host.ts @@ -81,3 +81,12 @@ export const operatePortRule = (params: Host.RulePort) => { export const operateIPRule = (params: Host.RuleIP) => { return http.post(`/hosts/firewall/ip`, params); }; +export const updatePortRule = (params: Host.UpdatePortRule) => { + return http.post(`/hosts/firewall/update/port`, params); +}; +export const updateAddrRule = (params: Host.UpdateAddrRule) => { + return http.post(`/hosts/firewall/update/addr`, params); +}; +export const batchOperateRule = (params: Host.BatchRule) => { + return http.post(`/hosts/firewall/batch`, params); +}; diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 7fbc47426..bdb3625d2 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1184,12 +1184,16 @@ const message = { firewall: '防火墙', protocol: '协议', port: '端口', + portHelper: '支持输入多个端口,如 80,81 或者范围端口,如 80-88', strategy: '策略', accept: '允许', drop: '拒绝', source: '来源', anyWhere: '所有 IP', address: '指定 IP', + addressHelper1: '支持输入多个 IP ,如 172.16.10.11,172.16.10.99', + addressHelper2: '支持输入 IP 段,如 172.16.10.0/24', + addressHelper3: '支持输入 IP 范围,如 172.16.10.11-172.16.10.99', allIP: '所有 IP', portRule: '端口规则', ipRule: 'IP 规则', diff --git a/frontend/src/views/host/firewall/ip/index.vue b/frontend/src/views/host/firewall/ip/index.vue index 19c626154..f229bd085 100644 --- a/frontend/src/views/host/firewall/ip/index.vue +++ b/frontend/src/views/host/firewall/ip/index.vue @@ -4,10 +4,27 @@ @@ -50,9 +67,10 @@ import ComplexTable from '@/components/complex-table/index.vue'; import OperatrDialog from '@/views/host/firewall/ip/operate/index.vue'; import FireRouter from '@/views/host/firewall/index.vue'; +import TableSetting from '@/components/table-setting/index.vue'; import LayoutContent from '@/layout/layout-content.vue'; import { onMounted, reactive, ref } from 'vue'; -import { operateIPRule, searchFireRule } from '@/api/modules/host'; +import { batchOperateRule, searchFireRule } from '@/api/modules/host'; import { Host } from '@/api/interface/host'; import { ElMessageBox } from 'element-plus'; import i18n from '@/lang'; @@ -61,6 +79,7 @@ import { MsgSuccess } from '@/utils/message'; const loading = ref(); const activeTag = ref('address'); const selects = ref([]); +const searchName = ref(); const data = ref(); const paginationConfig = reactive({ @@ -102,19 +121,36 @@ const onOpenDialog = async ( dialogRef.value!.acceptParams(params); }; -const onDelete = async (row: Host.RuleInfo | null) => { +const onDelete = async (row: Host.RuleIP | null) => { ElMessageBox.confirm(i18n.global.t('commons.msg.delete'), i18n.global.t('commons.msg.deleteTitle'), { confirmButtonText: i18n.global.t('commons.button.confirm'), cancelButtonText: i18n.global.t('commons.button.cancel'), type: 'warning', }).then(async () => { - let params = { - operation: 'remove', - address: row.address, - strategy: row.strategy, - }; + let rules = []; + if (row) { + rules.push({ + operation: 'remove', + address: row.address, + port: '', + source: '', + protocol: '', + strategy: row.strategy, + }); + } else { + for (const item of selects.value) { + rules.push({ + operation: 'remove', + address: item.address, + port: '', + source: '', + protocol: '', + strategy: item.strategy, + }); + } + } loading.value = true; - await operateIPRule(params) + await batchOperateRule({ type: 'port', rules: rules }) .then(() => { loading.value = false; MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); @@ -127,9 +163,15 @@ const onDelete = async (row: Host.RuleInfo | null) => { }; const buttons = [ + { + label: i18n.global.t('commons.button.edit'), + click: (row: Host.RuleIP) => { + onOpenDialog('edit', row); + }, + }, { label: i18n.global.t('commons.button.delete'), - click: (row: Host.RuleInfo) => { + click: (row: Host.RuleIP) => { onDelete(row); }, }, diff --git a/frontend/src/views/host/firewall/ip/operate/index.vue b/frontend/src/views/host/firewall/ip/operate/index.vue index 72a61cdeb..1d6731b25 100644 --- a/frontend/src/views/host/firewall/ip/operate/index.vue +++ b/frontend/src/views/host/firewall/ip/operate/index.vue @@ -14,6 +14,9 @@ clearable v-model="dialogData.rowData!.address" /> + {{ $t('firewall.addressHelper1') }} + {{ $t('firewall.addressHelper2') }} + {{ $t('firewall.addressHelper3') }} @@ -44,13 +47,15 @@ import { ElForm } from 'element-plus'; import DrawerHeader from '@/components/drawer-header/index.vue'; import { MsgSuccess } from '@/utils/message'; import { Host } from '@/api/interface/host'; -import { operateIPRule } from '@/api/modules/host'; +import { operateIPRule, updateAddrRule } from '@/api/modules/host'; +import { deepCopy } from '@/utils/util'; const loading = ref(); +const oldRule = ref(); interface DialogProps { title: string; - rowData?: Host.RulePort; + rowData?: Host.RuleIP; getTableList?: () => Promise; } const title = ref(''); @@ -60,6 +65,9 @@ const dialogData = ref({ }); const acceptParams = (params: DialogProps): void => { dialogData.value = params; + if (dialogData.value.title === 'edit') { + oldRule.value = deepCopy(params.rowData); + } title.value = i18n.global.t('commons.button.' + dialogData.value.title); drawerVisiable.value = true; }; @@ -83,11 +91,31 @@ const onSubmit = async (formEl: FormInstance | undefined) => { loading.value = true; dialogData.value.rowData.operation = 'add'; if (!dialogData.value.rowData) return; - await operateIPRule(dialogData.value.rowData); - loading.value = false; - MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); - emit('search'); - drawerVisiable.value = false; + if (dialogData.value.title === 'create') { + await operateIPRule(dialogData.value.rowData) + .then(() => { + loading.value = false; + MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); + emit('search'); + drawerVisiable.value = false; + }) + .catch(() => { + loading.value = false; + }); + return; + } + oldRule.value.operation = 'remove'; + dialogData.value.rowData.operation = 'add'; + await updateAddrRule({ oldRule: oldRule.value, newRule: dialogData.value.rowData }) + .then(() => { + loading.value = false; + MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); + emit('search'); + drawerVisiable.value = false; + }) + .catch(() => { + loading.value = false; + }); }); }; diff --git a/frontend/src/views/host/firewall/port/index.vue b/frontend/src/views/host/firewall/port/index.vue index be8fdb69f..edaf45c5a 100644 --- a/frontend/src/views/host/firewall/port/index.vue +++ b/frontend/src/views/host/firewall/port/index.vue @@ -4,10 +4,27 @@ @@ -51,10 +68,11 @@