mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 16:29:17 +08:00
feat: 实现防火墙批量删除及修改功能
This commit is contained in:
parent
c9d36d84f7
commit
db74d010d7
@ -54,7 +54,7 @@ func (b *BaseApi) OperatePortRule(c *gin.Context) {
|
|||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := firewallService.OperatePortRule(req); err != nil {
|
if err := firewallService.OperatePortRule(req, true); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -80,7 +80,82 @@ func (b *BaseApi) OperateIPRule(c *gin.Context) {
|
|||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
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)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package dto
|
|||||||
|
|
||||||
type RuleSearch struct {
|
type RuleSearch struct {
|
||||||
PageInfo
|
PageInfo
|
||||||
|
Info string `json:"info"`
|
||||||
Type string `json:"type" validate:"required"`
|
Type string `json:"type" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,3 +19,18 @@ type AddrRuleOperate struct {
|
|||||||
Address string `json:"address" validate:"required"`
|
Address string `json:"address" validate:"required"`
|
||||||
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
|
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"`
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/firewall"
|
"github.com/1Panel-dev/1Panel/backend/utils/firewall"
|
||||||
fireClient "github.com/1Panel-dev/1Panel/backend/utils/firewall/client"
|
fireClient "github.com/1Panel-dev/1Panel/backend/utils/firewall/client"
|
||||||
@ -11,8 +13,11 @@ type FirewallService struct{}
|
|||||||
|
|
||||||
type IFirewallService interface {
|
type IFirewallService interface {
|
||||||
SearchWithPage(search dto.RuleSearch) (int64, interface{}, error)
|
SearchWithPage(search dto.RuleSearch) (int64, interface{}, error)
|
||||||
OperatePortRule(req dto.PortRuleOperate) error
|
OperatePortRule(req dto.PortRuleOperate, reload bool) error
|
||||||
OperateAddressRule(req dto.AddrRuleOperate) 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 {
|
func NewIFirewallService() IFirewallService {
|
||||||
@ -33,13 +38,29 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
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 {
|
} else {
|
||||||
address, err := client.ListAddress()
|
datas = ports
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addrs, err := client.ListAddress()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
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
|
total, start, end := len(datas), (req.Page-1)*req.PageSize, req.Page*req.PageSize
|
||||||
if start > total {
|
if start > total {
|
||||||
@ -54,25 +75,36 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
|
|||||||
return int64(total), backDatas, nil
|
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()
|
client, err := firewall.NewFirewallClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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" {
|
if req.Protocol == "tcp/udp" {
|
||||||
req.Protocol = "tcp"
|
req.Protocol = "tcp"
|
||||||
if err := u.createPort(client, req); err != nil {
|
if err := u.operatePort(client, req); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
req.Protocol = "udp"
|
req.Protocol = "udp"
|
||||||
}
|
}
|
||||||
if err := u.createPort(client, req); err != nil {
|
if err := u.operatePort(client, req); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if reload {
|
||||||
return client.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()
|
client, err := firewall.NewFirewallClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -82,18 +114,86 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate) error {
|
|||||||
if err := copier.Copy(&fireInfo, &req); err != nil {
|
if err := copier.Copy(&fireInfo, &req); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
if err := client.RichRules(fireInfo, req.Operation); err != nil {
|
||||||
return err
|
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()
|
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
|
var fireInfo fireClient.FireInfo
|
||||||
if err := copier.Copy(&fireInfo, &req); err != nil {
|
if err := copier.Copy(&fireInfo, &req); err != nil {
|
||||||
return err
|
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" {
|
if len(fireInfo.Address) != 0 || fireInfo.Strategy == "drop" {
|
||||||
return client.RichRules(fireInfo, req.Operation)
|
return client.RichRules(fireInfo, req.Operation)
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,9 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
|
|||||||
hostRouter.POST("/firewall/search", baseApi.SearchFirewallRule)
|
hostRouter.POST("/firewall/search", baseApi.SearchFirewallRule)
|
||||||
hostRouter.POST("/firewall/port", baseApi.OperatePortRule)
|
hostRouter.POST("/firewall/port", baseApi.OperatePortRule)
|
||||||
hostRouter.POST("/firewall/ip", baseApi.OperateIPRule)
|
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.GET("/command", baseApi.ListCommand)
|
||||||
hostRouter.POST("/command", baseApi.CreateCommand)
|
hostRouter.POST("/command", baseApi.CreateCommand)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FirewallClient interface {
|
type FirewallClient interface {
|
||||||
|
Name() string
|
||||||
Start() error
|
Start() error
|
||||||
Stop() error
|
Stop() error
|
||||||
Reload() error
|
Reload() error
|
||||||
|
@ -21,6 +21,10 @@ func NewFirewalld() (*Firewall, error) {
|
|||||||
return &Firewall{Client: ConnInfo}, nil
|
return &Firewall{Client: ConnInfo}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Firewall) Name() string {
|
||||||
|
return "firewalld"
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Firewall) Status() (string, error) {
|
func (f *Firewall) Status() (string, error) {
|
||||||
stdout, err := f.Client.Run("firewall-cmd --state")
|
stdout, err := f.Client.Run("firewall-cmd --state")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -80,7 +84,7 @@ func (f *Firewall) ListPort() ([]FireInfo, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
itemRule := f.loadInfo(rule)
|
itemRule := f.loadInfo(rule)
|
||||||
if len(itemRule.Port) != 0 {
|
if len(itemRule.Port) != 0 && itemRule.Family == "ipv4" {
|
||||||
datas = append(datas, itemRule)
|
datas = append(datas, itemRule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,10 @@ func NewUfw() (*Ufw, error) {
|
|||||||
return &Ufw{Client: ConnInfo}, nil
|
return &Ufw{Client: ConnInfo}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Ufw) Name() string {
|
||||||
|
return "ufw"
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Ufw) Status() (string, error) {
|
func (f *Ufw) Status() (string, error) {
|
||||||
stdout, err := f.Client.Run("sudo ufw status")
|
stdout, err := f.Client.Run("sudo ufw status")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -49,10 +53,6 @@ func (f *Ufw) Stop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Ufw) Reload() 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,8 @@ func (f *Ufw) ListPort() ([]FireInfo, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
itemFire := f.loadInfo(line, "port")
|
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)
|
datas = append(datas, itemFire)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,7 +101,11 @@ func (f *Ufw) ListAddress() ([]FireInfo, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
itemFire := f.loadInfo(line, "address")
|
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)
|
datas = append(datas, itemFire)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,16 +113,19 @@ func (f *Ufw) ListAddress() ([]FireInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Ufw) Port(port FireInfo, operation string) error {
|
func (f *Ufw) Port(port FireInfo, operation string) error {
|
||||||
switch operation {
|
switch port.Strategy {
|
||||||
case "add":
|
case "accept":
|
||||||
operation = "allow"
|
port.Strategy = "allow"
|
||||||
case "remove":
|
case "drop":
|
||||||
operation = "deny"
|
port.Strategy = "deny"
|
||||||
default:
|
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 {
|
if len(port.Protocol) != 0 {
|
||||||
command += fmt.Sprintf("/%s", port.Protocol)
|
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 {
|
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 {
|
if len(rule.Protocol) != 0 {
|
||||||
ruleStr += fmt.Sprintf("proto %s ", rule.Protocol)
|
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)
|
ruleStr += fmt.Sprintf("from %s ", rule.Address)
|
||||||
}
|
}
|
||||||
if len(rule.Port) != 0 {
|
if len(rule.Port) != 0 {
|
||||||
@ -169,9 +191,12 @@ func (f *Ufw) loadInfo(line string, fireType string) FireInfo {
|
|||||||
if len(fields) < 4 {
|
if len(fields) < 4 {
|
||||||
return itemInfo
|
return itemInfo
|
||||||
}
|
}
|
||||||
|
if fields[1] == "(v6)" {
|
||||||
|
return itemInfo
|
||||||
|
}
|
||||||
if fields[0] == "Anywhere" && fireType != "port" {
|
if fields[0] == "Anywhere" && fireType != "port" {
|
||||||
itemInfo.Strategy = "drop"
|
itemInfo.Strategy = "drop"
|
||||||
if fields[2] == "ALLOW" {
|
if fields[1] == "ALLOW" {
|
||||||
itemInfo.Strategy = "accept"
|
itemInfo.Strategy = "accept"
|
||||||
}
|
}
|
||||||
itemInfo.Address = fields[3]
|
itemInfo.Address = fields[3]
|
||||||
@ -184,19 +209,6 @@ func (f *Ufw) loadInfo(line string, fireType string) FireInfo {
|
|||||||
itemInfo.Port = fields[0]
|
itemInfo.Port = fields[0]
|
||||||
itemInfo.Protocol = "tcp/udp"
|
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]
|
|
||||||
} else {
|
|
||||||
itemInfo.Family = "ipv4"
|
itemInfo.Family = "ipv4"
|
||||||
if fields[1] == "ALLOW" {
|
if fields[1] == "ALLOW" {
|
||||||
itemInfo.Strategy = "accept"
|
itemInfo.Strategy = "accept"
|
||||||
@ -204,7 +216,6 @@ func (f *Ufw) loadInfo(line string, fireType string) FireInfo {
|
|||||||
itemInfo.Strategy = "drop"
|
itemInfo.Strategy = "drop"
|
||||||
}
|
}
|
||||||
itemInfo.Address = fields[3]
|
itemInfo.Address = fields[3]
|
||||||
}
|
|
||||||
|
|
||||||
return itemInfo
|
return itemInfo
|
||||||
}
|
}
|
||||||
|
@ -77,4 +77,16 @@ export namespace Host {
|
|||||||
address: string;
|
address: string;
|
||||||
strategy: string;
|
strategy: string;
|
||||||
}
|
}
|
||||||
|
export interface UpdatePortRule {
|
||||||
|
oldRule: RulePort;
|
||||||
|
newRule: RulePort;
|
||||||
|
}
|
||||||
|
export interface UpdateAddrRule {
|
||||||
|
oldRule: RuleIP;
|
||||||
|
newRule: RuleIP;
|
||||||
|
}
|
||||||
|
export interface BatchRule {
|
||||||
|
type: string;
|
||||||
|
rules: Array<RulePort>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,3 +81,12 @@ export const operatePortRule = (params: Host.RulePort) => {
|
|||||||
export const operateIPRule = (params: Host.RuleIP) => {
|
export const operateIPRule = (params: Host.RuleIP) => {
|
||||||
return http.post<Host.RuleIP>(`/hosts/firewall/ip`, params);
|
return http.post<Host.RuleIP>(`/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);
|
||||||
|
};
|
||||||
|
@ -1184,12 +1184,16 @@ const message = {
|
|||||||
firewall: '防火墙',
|
firewall: '防火墙',
|
||||||
protocol: '协议',
|
protocol: '协议',
|
||||||
port: '端口',
|
port: '端口',
|
||||||
|
portHelper: '支持输入多个端口,如 80,81 或者范围端口,如 80-88',
|
||||||
strategy: '策略',
|
strategy: '策略',
|
||||||
accept: '允许',
|
accept: '允许',
|
||||||
drop: '拒绝',
|
drop: '拒绝',
|
||||||
source: '来源',
|
source: '来源',
|
||||||
anyWhere: '所有 IP',
|
anyWhere: '所有 IP',
|
||||||
address: '指定 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',
|
allIP: '所有 IP',
|
||||||
portRule: '端口规则',
|
portRule: '端口规则',
|
||||||
ipRule: 'IP 规则',
|
ipRule: 'IP 规则',
|
||||||
|
@ -4,10 +4,27 @@
|
|||||||
<LayoutContent v-loading="loading" :title="$t('firewall.firewall')">
|
<LayoutContent v-loading="loading" :title="$t('firewall.firewall')">
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="20">
|
<el-col :span="16">
|
||||||
<el-button type="primary" @click="onOpenDialog('create')">
|
<el-button type="primary" @click="onOpenDialog('create')">
|
||||||
{{ $t('commons.button.create') }} {{ $t('firewall.ipRule') }}
|
{{ $t('commons.button.create') }} {{ $t('firewall.ipRule') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button @click="onDelete(null)">
|
||||||
|
{{ $t('commons.button.delete') }}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<TableSetting @search="search()" />
|
||||||
|
<div class="search-button">
|
||||||
|
<el-input
|
||||||
|
v-model="searchName"
|
||||||
|
clearable
|
||||||
|
@clear="search()"
|
||||||
|
suffix-icon="Search"
|
||||||
|
@keyup.enter="search()"
|
||||||
|
@blur="search()"
|
||||||
|
:placeholder="$t('commons.button.search')"
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
@ -50,9 +67,10 @@
|
|||||||
import ComplexTable from '@/components/complex-table/index.vue';
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
import OperatrDialog from '@/views/host/firewall/ip/operate/index.vue';
|
import OperatrDialog from '@/views/host/firewall/ip/operate/index.vue';
|
||||||
import FireRouter from '@/views/host/firewall/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 LayoutContent from '@/layout/layout-content.vue';
|
||||||
import { onMounted, reactive, ref } from '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 { Host } from '@/api/interface/host';
|
||||||
import { ElMessageBox } from 'element-plus';
|
import { ElMessageBox } from 'element-plus';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
@ -61,6 +79,7 @@ import { MsgSuccess } from '@/utils/message';
|
|||||||
const loading = ref();
|
const loading = ref();
|
||||||
const activeTag = ref('address');
|
const activeTag = ref('address');
|
||||||
const selects = ref<any>([]);
|
const selects = ref<any>([]);
|
||||||
|
const searchName = ref();
|
||||||
|
|
||||||
const data = ref();
|
const data = ref();
|
||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
@ -102,19 +121,36 @@ const onOpenDialog = async (
|
|||||||
dialogRef.value!.acceptParams(params);
|
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'), {
|
ElMessageBox.confirm(i18n.global.t('commons.msg.delete'), i18n.global.t('commons.msg.deleteTitle'), {
|
||||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
let params = {
|
let rules = [];
|
||||||
|
if (row) {
|
||||||
|
rules.push({
|
||||||
operation: 'remove',
|
operation: 'remove',
|
||||||
address: row.address,
|
address: row.address,
|
||||||
|
port: '',
|
||||||
|
source: '',
|
||||||
|
protocol: '',
|
||||||
strategy: row.strategy,
|
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;
|
loading.value = true;
|
||||||
await operateIPRule(params)
|
await batchOperateRule({ type: 'port', rules: rules })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
@ -127,9 +163,15 @@ const onDelete = async (row: Host.RuleInfo | null) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.edit'),
|
||||||
|
click: (row: Host.RuleIP) => {
|
||||||
|
onOpenDialog('edit', row);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('commons.button.delete'),
|
label: i18n.global.t('commons.button.delete'),
|
||||||
click: (row: Host.RuleInfo) => {
|
click: (row: Host.RuleIP) => {
|
||||||
onDelete(row);
|
onDelete(row);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
clearable
|
clearable
|
||||||
v-model="dialogData.rowData!.address"
|
v-model="dialogData.rowData!.address"
|
||||||
/>
|
/>
|
||||||
|
<span class="input-help">{{ $t('firewall.addressHelper1') }}</span>
|
||||||
|
<span class="input-help">{{ $t('firewall.addressHelper2') }}</span>
|
||||||
|
<span class="input-help">{{ $t('firewall.addressHelper3') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('firewall.strategy')" prop="strategy">
|
<el-form-item :label="$t('firewall.strategy')" prop="strategy">
|
||||||
<el-radio-group v-model="dialogData.rowData!.strategy">
|
<el-radio-group v-model="dialogData.rowData!.strategy">
|
||||||
@ -44,13 +47,15 @@ import { ElForm } from 'element-plus';
|
|||||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { Host } from '@/api/interface/host';
|
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 loading = ref();
|
||||||
|
const oldRule = ref<Host.RuleIP>();
|
||||||
|
|
||||||
interface DialogProps {
|
interface DialogProps {
|
||||||
title: string;
|
title: string;
|
||||||
rowData?: Host.RulePort;
|
rowData?: Host.RuleIP;
|
||||||
getTableList?: () => Promise<any>;
|
getTableList?: () => Promise<any>;
|
||||||
}
|
}
|
||||||
const title = ref<string>('');
|
const title = ref<string>('');
|
||||||
@ -60,6 +65,9 @@ const dialogData = ref<DialogProps>({
|
|||||||
});
|
});
|
||||||
const acceptParams = (params: DialogProps): void => {
|
const acceptParams = (params: DialogProps): void => {
|
||||||
dialogData.value = params;
|
dialogData.value = params;
|
||||||
|
if (dialogData.value.title === 'edit') {
|
||||||
|
oldRule.value = deepCopy(params.rowData);
|
||||||
|
}
|
||||||
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
||||||
drawerVisiable.value = true;
|
drawerVisiable.value = true;
|
||||||
};
|
};
|
||||||
@ -83,11 +91,31 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
dialogData.value.rowData.operation = 'add';
|
dialogData.value.rowData.operation = 'add';
|
||||||
if (!dialogData.value.rowData) return;
|
if (!dialogData.value.rowData) return;
|
||||||
await operateIPRule(dialogData.value.rowData);
|
if (dialogData.value.title === 'create') {
|
||||||
|
await operateIPRule(dialogData.value.rowData)
|
||||||
|
.then(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
emit('search');
|
emit('search');
|
||||||
drawerVisiable.value = false;
|
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;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,10 +4,27 @@
|
|||||||
<LayoutContent v-loading="loading" :title="$t('firewall.firewall')">
|
<LayoutContent v-loading="loading" :title="$t('firewall.firewall')">
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="20">
|
<el-col :span="16">
|
||||||
<el-button type="primary" @click="onOpenDialog('create')">
|
<el-button type="primary" @click="onOpenDialog('create')">
|
||||||
{{ $t('commons.button.create') }}{{ $t('firewall.portRule') }}
|
{{ $t('commons.button.create') }}{{ $t('firewall.portRule') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button @click="onDelete(null)">
|
||||||
|
{{ $t('commons.button.delete') }}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<TableSetting @search="search()" />
|
||||||
|
<div class="search-button">
|
||||||
|
<el-input
|
||||||
|
v-model="searchName"
|
||||||
|
clearable
|
||||||
|
@clear="search()"
|
||||||
|
suffix-icon="Search"
|
||||||
|
@keyup.enter="search()"
|
||||||
|
@blur="search()"
|
||||||
|
:placeholder="$t('commons.button.search')"
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
@ -51,10 +68,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ComplexTable from '@/components/complex-table/index.vue';
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
import FireRouter from '@/views/host/firewall/index.vue';
|
import FireRouter from '@/views/host/firewall/index.vue';
|
||||||
|
import TableSetting from '@/components/table-setting/index.vue';
|
||||||
import OperatrDialog from '@/views/host/firewall/port/operate/index.vue';
|
import OperatrDialog from '@/views/host/firewall/port/operate/index.vue';
|
||||||
import LayoutContent from '@/layout/layout-content.vue';
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
import { operatePortRule, searchFireRule } from '@/api/modules/host';
|
import { batchOperateRule, searchFireRule } from '@/api/modules/host';
|
||||||
import { Host } from '@/api/interface/host';
|
import { Host } from '@/api/interface/host';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
@ -63,6 +81,7 @@ import { ElMessageBox } from 'element-plus';
|
|||||||
const loading = ref();
|
const loading = ref();
|
||||||
const activeTag = ref('port');
|
const activeTag = ref('port');
|
||||||
const selects = ref<any>([]);
|
const selects = ref<any>([]);
|
||||||
|
const searchName = ref();
|
||||||
|
|
||||||
const data = ref();
|
const data = ref();
|
||||||
const paginationConfig = reactive({
|
const paginationConfig = reactive({
|
||||||
@ -74,7 +93,7 @@ const paginationConfig = reactive({
|
|||||||
const search = async () => {
|
const search = async () => {
|
||||||
let params = {
|
let params = {
|
||||||
type: activeTag.value,
|
type: activeTag.value,
|
||||||
info: '',
|
info: searchName.value,
|
||||||
page: paginationConfig.currentPage,
|
page: paginationConfig.currentPage,
|
||||||
pageSize: paginationConfig.pageSize,
|
pageSize: paginationConfig.pageSize,
|
||||||
};
|
};
|
||||||
@ -112,16 +131,30 @@ const onDelete = async (row: Host.RuleInfo | null) => {
|
|||||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
}).then(async () => {
|
}).then(async () => {
|
||||||
let params = {
|
let rules = [];
|
||||||
|
if (row) {
|
||||||
|
rules.push({
|
||||||
operation: 'remove',
|
operation: 'remove',
|
||||||
address: row.address,
|
address: row.address,
|
||||||
port: row.port,
|
port: row.port,
|
||||||
source: '',
|
source: '',
|
||||||
protocol: row.protocol,
|
protocol: row.protocol,
|
||||||
strategy: row.strategy,
|
strategy: row.strategy,
|
||||||
};
|
});
|
||||||
|
} else {
|
||||||
|
for (const item of selects.value) {
|
||||||
|
rules.push({
|
||||||
|
operation: 'remove',
|
||||||
|
address: item.address,
|
||||||
|
port: item.port,
|
||||||
|
source: '',
|
||||||
|
protocol: item.protocol,
|
||||||
|
strategy: item.strategy,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await operatePortRule(params)
|
await batchOperateRule({ type: 'port', rules: rules })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
@ -134,6 +167,12 @@ const onDelete = async (row: Host.RuleInfo | null) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.edit'),
|
||||||
|
click: (row: Host.RulePort) => {
|
||||||
|
onOpenDialog('edit', row);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: i18n.global.t('commons.button.delete'),
|
label: i18n.global.t('commons.button.delete'),
|
||||||
click: (row: Host.RuleInfo) => {
|
click: (row: Host.RuleInfo) => {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
<el-form-item :label="$t('firewall.port')" prop="port">
|
<el-form-item :label="$t('firewall.port')" prop="port">
|
||||||
<el-input clearable v-model.trim="dialogData.rowData!.port" />
|
<el-input clearable v-model.trim="dialogData.rowData!.port" />
|
||||||
|
<span class="input-help">{{ $t('firewall.portHelper') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('firewall.source')" prop="source">
|
<el-form-item :label="$t('firewall.source')" prop="source">
|
||||||
@ -63,9 +64,11 @@ import { ElForm } from 'element-plus';
|
|||||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { Host } from '@/api/interface/host';
|
import { Host } from '@/api/interface/host';
|
||||||
import { operatePortRule } from '@/api/modules/host';
|
import { operatePortRule, updatePortRule } from '@/api/modules/host';
|
||||||
|
import { deepCopy } from '@/utils/util';
|
||||||
|
|
||||||
const loading = ref();
|
const loading = ref();
|
||||||
|
const oldRule = ref<Host.RulePort>();
|
||||||
|
|
||||||
interface DialogProps {
|
interface DialogProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -79,6 +82,14 @@ const dialogData = ref<DialogProps>({
|
|||||||
});
|
});
|
||||||
const acceptParams = (params: DialogProps): void => {
|
const acceptParams = (params: DialogProps): void => {
|
||||||
dialogData.value = params;
|
dialogData.value = params;
|
||||||
|
if (dialogData.value.title === 'edit') {
|
||||||
|
if (params.rowData.address && params.rowData.address !== 'Anywhere') {
|
||||||
|
dialogData.value.rowData.source = 'address';
|
||||||
|
} else {
|
||||||
|
dialogData.value.rowData.source = 'anyWhere';
|
||||||
|
}
|
||||||
|
oldRule.value = deepCopy(params.rowData);
|
||||||
|
}
|
||||||
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
||||||
drawerVisiable.value = true;
|
drawerVisiable.value = true;
|
||||||
};
|
};
|
||||||
@ -101,14 +112,34 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
|||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
formEl.validate(async (valid) => {
|
formEl.validate(async (valid) => {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
loading.value = true;
|
|
||||||
dialogData.value.rowData.operation = 'add';
|
dialogData.value.rowData.operation = 'add';
|
||||||
if (!dialogData.value.rowData) return;
|
if (!dialogData.value.rowData) return;
|
||||||
await operatePortRule(dialogData.value.rowData);
|
loading.value = true;
|
||||||
|
if (dialogData.value.title === 'create') {
|
||||||
|
await operatePortRule(dialogData.value.rowData)
|
||||||
|
.then(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
emit('search');
|
emit('search');
|
||||||
drawerVisiable.value = false;
|
drawerVisiable.value = false;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
oldRule.value.operation = 'remove';
|
||||||
|
dialogData.value.rowData.operation = 'add';
|
||||||
|
await updatePortRule({ 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;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user