feat: 防火墙支持设置备注信息 (#1962)

Refs #1930 #1121 #1642
This commit is contained in:
ssongliu 2023-08-15 22:48:11 +08:00 committed by GitHub
parent a0456d0f7a
commit 89faf01391
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 458 additions and 43 deletions

View file

@ -156,6 +156,31 @@ func (b *BaseApi) BatchOperateRule(c *gin.Context) {
helper.SuccessWithData(c, nil) helper.SuccessWithData(c, nil)
} }
// @Tags Firewall
// @Summary Update rule description
// @Description 更新防火墙描述
// @Accept json
// @Param request body dto.UpdateFirewallDescription true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /hosts/firewall/update/description [post]
func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) {
var req dto.UpdateFirewallDescription
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.UpdateDescription(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags Firewall // @Tags Firewall
// @Summary Create group // @Summary Create group
// @Description 更新端口防火墙规则 // @Description 更新端口防火墙规则

View file

@ -23,12 +23,25 @@ type PortRuleOperate struct {
Port string `json:"port" validate:"required"` Port string `json:"port" validate:"required"`
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"` Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"` Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
Description string `json:"description"`
}
type UpdateFirewallDescription struct {
Address string `json:"address"`
Port string `json:"port"`
Protocol string `json:"protocol"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
Description string `json:"description"`
} }
type AddrRuleOperate struct { type AddrRuleOperate struct {
Operation string `json:"operation" validate:"required,oneof=add remove"` Operation string `json:"operation" validate:"required,oneof=add remove"`
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"`
Description string `json:"description"`
} }
type PortRuleUpdate struct { type PortRuleUpdate struct {

View file

@ -0,0 +1,11 @@
package model
type Firewall struct {
BaseModel
Port string `gorm:"type:varchar(64);not null" json:"port"`
Protocol string `gorm:"type:varchar(64);not null" json:"protocol"`
Address string `gorm:"type:varchar(64);not null" json:"address"`
Strategy string `gorm:"type:varchar(64);not null" json:"strategy"`
Description string `gorm:"type:varchar(64);not null" json:"description"`
}

View file

@ -19,6 +19,12 @@ type IHostRepo interface {
Create(host *model.Host) error Create(host *model.Host) error
Update(id uint, vars map[string]interface{}) error Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error Delete(opts ...DBOption) error
GetFirewallRecord(opts ...DBOption) (model.Firewall, error)
ListFirewallRecord() ([]model.Firewall, error)
SaveFirewallRecord(firewall *model.Firewall) error
DeleteFirewallRecordByID(id uint) error
DeleteFirewallRecord(port, protocol, address, strategy string) error
} }
func NewIHostRepo() IHostRepo { func NewIHostRepo() IHostRepo {
@ -106,3 +112,41 @@ func (h *HostRepo) Delete(opts ...DBOption) error {
} }
return db.Delete(&model.Host{}).Error return db.Delete(&model.Host{}).Error
} }
func (h *HostRepo) GetFirewallRecord(opts ...DBOption) (model.Firewall, error) {
var firewall model.Firewall
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&firewall).Error
return firewall, err
}
func (h *HostRepo) ListFirewallRecord() ([]model.Firewall, error) {
var datas []model.Firewall
if err := global.DB.Find(&datas).Error; err != nil {
return datas, nil
}
return datas, nil
}
func (h *HostRepo) SaveFirewallRecord(firewall *model.Firewall) error {
if firewall.ID != 0 {
return global.DB.Save(firewall).Error
}
var data model.Firewall
_ = global.DB.Where("port = ? AND protocol = ? AND address = ? AND strategy = ?", firewall.Port, firewall.Protocol, firewall.Address, firewall.Strategy).First(&data)
if data.ID != 0 {
firewall.ID = data.ID
}
return global.DB.Save(firewall).Error
}
func (h *HostRepo) DeleteFirewallRecordByID(id uint) error {
return global.DB.Where("id = ?", id).Delete(&model.Firewall{}).Error
}
func (h *HostRepo) DeleteFirewallRecord(port, protocol, address, strategy string) error {
return global.DB.Where("port = ? AND protocol = ? AND address = ? AND strategy = ?", port, protocol, address, strategy).Delete(&model.Firewall{}).Error
}

View file

@ -7,12 +7,14 @@ import (
"strings" "strings"
"github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/common"
"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"
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
"github.com/pkg/errors"
) )
const confPath = "/etc/sysctl.conf" const confPath = "/etc/sysctl.conf"
@ -27,6 +29,7 @@ type IFirewallService interface {
OperateAddressRule(req dto.AddrRuleOperate, reload bool) error OperateAddressRule(req dto.AddrRuleOperate, reload bool) error
UpdatePortRule(req dto.PortRuleUpdate) error UpdatePortRule(req dto.PortRuleUpdate) error
UpdateAddrRule(req dto.AddrRuleUpdate) error UpdateAddrRule(req dto.AddrRuleUpdate) error
UpdateDescription(req dto.UpdateFirewallDescription) error
BatchOperateRule(req dto.BatchRuleOperate) error BatchOperateRule(req dto.BatchRuleOperate) error
} }
@ -67,6 +70,7 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
datas []fireClient.FireInfo datas []fireClient.FireInfo
backDatas []fireClient.FireInfo backDatas []fireClient.FireInfo
) )
client, err := firewall.NewFirewallClient() client, err := firewall.NewFirewallClient()
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
@ -110,6 +114,16 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
backDatas = datas[start:end] backDatas = datas[start:end]
} }
datasFromDB, _ := hostRepo.ListFirewallRecord()
for i := 0; i < len(backDatas); i++ {
for _, des := range datasFromDB {
if backDatas[i].Port == des.Port && backDatas[i].Protocol == des.Protocol && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.Address {
backDatas[i].Description = des.Description
break
}
}
}
if req.Type == "port" { if req.Type == "port" {
apps := u.loadPortByApp() apps := u.loadPortByApp()
for i := 0; i < len(backDatas); i++ { for i := 0; i < len(backDatas); i++ {
@ -127,6 +141,7 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
} }
} }
} }
go u.cleanUnUsedData(client)
return int64(total), backDatas, nil return int64(total), backDatas, nil
} }
@ -166,59 +181,55 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
if err != nil { if err != nil {
return err return err
} }
protos := strings.Split(req.Protocol, "/")
if client.Name() == "ufw" { if client.Name() == "ufw" {
req.Port = strings.ReplaceAll(req.Port, "-", ":") if len(req.Address) == 0 {
if req.Operation == "remove" && req.Protocol == "tcp/udp" { req.Address = "Anywhere"
req.Protocol = ""
return u.operatePort(client, req)
} }
if strings.Contains(req.Port, ",") || strings.Contains(req.Port, "-") {
for _, proto := range protos {
req.Port = strings.ReplaceAll(req.Port, "-", ":")
req.Protocol = proto
if err := u.operatePort(client, req); err != nil {
return err
}
_ = u.addPortRecord(req)
}
return nil
}
if req.Protocol == "tcp/udp" {
req.Protocol = ""
}
if err := u.operatePort(client, req); err != nil {
return err
}
_ = u.addPortRecord(req)
return nil
} }
if req.Protocol == "tcp/udp" {
if client.Name() == "firewalld" && strings.Contains(req.Port, ",") { for _, proto := range protos {
if strings.Contains(req.Port, "-") {
req.Protocol = proto
if err := u.operatePort(client, req); err != nil {
return err
}
_ = u.addPortRecord(req)
} else {
ports := strings.Split(req.Port, ",") ports := strings.Split(req.Port, ",")
for _, port := range ports { for _, port := range ports {
if len(port) == 0 { if len(port) == 0 {
continue continue
} }
req.Port = port req.Port = port
req.Protocol = "tcp" req.Protocol = proto
if err := u.operatePort(client, req); err != nil { if err := u.operatePort(client, req); err != nil {
return err return err
} }
req.Protocol = "udp" _ = u.addPortRecord(req)
if err := u.operatePort(client, req); err != nil {
return err
}
}
} else {
req.Protocol = "tcp"
if err := u.operatePort(client, req); err != nil {
return err
}
req.Protocol = "udp"
if err := u.operatePort(client, req); err != nil {
return err
}
}
} else {
if strings.Contains(req.Port, ",") {
ports := strings.Split(req.Port, ",")
for _, port := range ports {
req.Port = port
if err := u.operatePort(client, req); err != nil {
return err
}
}
} else {
if err := u.operatePort(client, req); err != nil {
return err
} }
} }
} }
if reload { return client.Reload()
return client.Reload()
}
return nil
} }
func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload bool) error { func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload bool) error {
@ -241,6 +252,7 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload boo
if err := client.RichRules(fireInfo, req.Operation); err != nil { if err := client.RichRules(fireInfo, req.Operation); err != nil {
return err return err
} }
_ = u.addAddressRecord(req)
} }
if reload { if reload {
return client.Reload() return client.Reload()
@ -276,6 +288,14 @@ func (u *FirewallService) UpdateAddrRule(req dto.AddrRuleUpdate) error {
return client.Reload() return client.Reload()
} }
func (u *FirewallService) UpdateDescription(req dto.UpdateFirewallDescription) error {
var firewall model.Firewall
if err := copier.Copy(&firewall, &req); err != nil {
return errors.WithMessage(constant.ErrStructTransform, err.Error())
}
return hostRepo.SaveFirewallRecord(&firewall)
}
func (u *FirewallService) BatchOperateRule(req dto.BatchRuleOperate) error { func (u *FirewallService) BatchOperateRule(req dto.BatchRuleOperate) error {
client, err := firewall.NewFirewallClient() client, err := firewall.NewFirewallClient()
if err != nil { if err != nil {
@ -323,7 +343,7 @@ func (u *FirewallService) operatePort(client firewall.FirewallClient, req dto.Po
} }
if client.Name() == "ufw" { if client.Name() == "ufw" {
if len(fireInfo.Address) != 0 && fireInfo.Address != "Anywhere" { if len(fireInfo.Address) != 0 && !strings.EqualFold(fireInfo.Address, "Anywhere") {
return client.RichRules(fireInfo, req.Operation) return client.RichRules(fireInfo, req.Operation)
} }
return client.Port(fireInfo, req.Operation) return client.Port(fireInfo, req.Operation)
@ -363,6 +383,29 @@ func (u *FirewallService) loadPortByApp() []portOfApp {
return datas return datas
} }
func (u *FirewallService) cleanUnUsedData(client firewall.FirewallClient) {
list, _ := client.ListPort()
addressList, _ := client.ListAddress()
list = append(list, addressList...)
if len(list) == 0 {
return
}
records, _ := hostRepo.ListFirewallRecord()
if len(records) == 0 {
return
}
for _, item := range list {
for i := 0; i < len(records); i++ {
if records[i].Port == item.Port && records[i].Protocol == item.Protocol && records[i].Strategy == item.Strategy && records[i].Address == item.Address {
records = append(records[:i], records[i+1:]...)
}
}
}
for _, record := range records {
_ = hostRepo.DeleteFirewallRecordByID(record.ID)
}
}
func (u *FirewallService) pingStatus() string { func (u *FirewallService) pingStatus() string {
if _, err := os.Stat("/etc/sysctl.conf"); err != nil { if _, err := os.Stat("/etc/sysctl.conf"); err != nil {
return constant.StatusNone return constant.StatusNone
@ -441,3 +484,28 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er
return client.Reload() return client.Reload()
} }
func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error {
if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord(req.Port, req.Protocol, req.Address, req.Strategy)
}
return hostRepo.SaveFirewallRecord(&model.Firewall{
Port: req.Port,
Protocol: req.Protocol,
Address: req.Address,
Strategy: req.Strategy,
Description: req.Description,
})
}
func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error {
if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord("", "", req.Address, req.Strategy)
}
return hostRepo.SaveFirewallRecord(&model.Firewall{
Address: req.Address,
Strategy: req.Strategy,
Description: req.Description,
})
}

View file

@ -38,6 +38,7 @@ func Init() {
migrations.AddRemoteDB, migrations.AddRemoteDB,
migrations.UpdateRedisParam, migrations.UpdateRedisParam,
migrations.UpdateCronjobWithDb, migrations.UpdateCronjobWithDb,
migrations.AddTableFirewall,
}) })
if err := m.Migrate(); err != nil { if err := m.Migrate(); err != nil {
global.LOG.Error(err) global.LOG.Error(err)

View file

@ -570,3 +570,13 @@ var UpdateCronjobWithDb = &gormigrate.Migration{
return nil return nil
}, },
} }
var AddTableFirewall = &gormigrate.Migration{
ID: "20230814-add-table-firewall",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.Firewall{}); err != nil {
return err
}
return nil
},
}

View file

@ -33,6 +33,7 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
hostRouter.POST("/firewall/batch", baseApi.BatchOperateRule) hostRouter.POST("/firewall/batch", baseApi.BatchOperateRule)
hostRouter.POST("/firewall/update/port", baseApi.UpdatePortRule) hostRouter.POST("/firewall/update/port", baseApi.UpdatePortRule)
hostRouter.POST("/firewall/update/addr", baseApi.UpdateAddrRule) hostRouter.POST("/firewall/update/addr", baseApi.UpdateAddrRule)
hostRouter.POST("/firewall/update/description", baseApi.UpdateFirewallDescription)
hostRouter.GET("/ssh/conf", baseApi.LoadSSHConf) hostRouter.GET("/ssh/conf", baseApi.LoadSSHConf)
hostRouter.POST("/ssh/search", baseApi.GetSSHInfo) hostRouter.POST("/ssh/search", baseApi.GetSSHInfo)

View file

@ -7,8 +7,9 @@ type FireInfo struct {
Protocol string `json:"protocol"` // tcp udp tcp/udp Protocol string `json:"protocol"` // tcp udp tcp/udp
Strategy string `json:"strategy"` // accept drop Strategy string `json:"strategy"` // accept drop
APPName string `json:"appName"` APPName string `json:"appName"`
IsUsed bool `json:"isUsed"` IsUsed bool `json:"isUsed"`
Description string `json:"description"`
} }
type Forward struct { type Forward struct {

View file

@ -6906,6 +6906,39 @@ const docTemplate = `{
} }
} }
}, },
"/hosts/firewall/update/description": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "更新防火墙描述",
"consumes": [
"application/json"
],
"tags": [
"Firewall"
],
"summary": "Update rule description",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.UpdateFirewallDescription"
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/hosts/firewall/update/port": { "/hosts/firewall/update/port": {
"post": { "post": {
"security": [ "security": [
@ -11517,6 +11550,9 @@ const docTemplate = `{
"address": { "address": {
"type": "string" "type": "string"
}, },
"description": {
"type": "string"
},
"operation": { "operation": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -13610,6 +13646,9 @@ const docTemplate = `{
"address": { "address": {
"type": "string" "type": "string"
}, },
"description": {
"type": "string"
},
"operation": { "operation": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -14469,6 +14508,33 @@ const docTemplate = `{
} }
} }
}, },
"dto.UpdateFirewallDescription": {
"type": "object",
"required": [
"strategy"
],
"properties": {
"address": {
"type": "string"
},
"description": {
"type": "string"
},
"port": {
"type": "string"
},
"protocol": {
"type": "string"
},
"strategy": {
"type": "string",
"enum": [
"accept",
"drop"
]
}
}
},
"dto.Upgrade": { "dto.Upgrade": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -6899,6 +6899,39 @@
} }
} }
}, },
"/hosts/firewall/update/description": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "更新防火墙描述",
"consumes": [
"application/json"
],
"tags": [
"Firewall"
],
"summary": "Update rule description",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.UpdateFirewallDescription"
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/hosts/firewall/update/port": { "/hosts/firewall/update/port": {
"post": { "post": {
"security": [ "security": [
@ -11510,6 +11543,9 @@
"address": { "address": {
"type": "string" "type": "string"
}, },
"description": {
"type": "string"
},
"operation": { "operation": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -13603,6 +13639,9 @@
"address": { "address": {
"type": "string" "type": "string"
}, },
"description": {
"type": "string"
},
"operation": { "operation": {
"type": "string", "type": "string",
"enum": [ "enum": [
@ -14462,6 +14501,33 @@
} }
} }
}, },
"dto.UpdateFirewallDescription": {
"type": "object",
"required": [
"strategy"
],
"properties": {
"address": {
"type": "string"
},
"description": {
"type": "string"
},
"port": {
"type": "string"
},
"protocol": {
"type": "string"
},
"strategy": {
"type": "string",
"enum": [
"accept",
"drop"
]
}
}
},
"dto.Upgrade": { "dto.Upgrade": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -4,6 +4,8 @@ definitions:
properties: properties:
address: address:
type: string type: string
description:
type: string
operation: operation:
enum: enum:
- add - add
@ -1409,6 +1411,8 @@ definitions:
properties: properties:
address: address:
type: string type: string
description:
type: string
operation: operation:
enum: enum:
- add - add
@ -1988,6 +1992,24 @@ definitions:
required: required:
- id - id
type: object type: object
dto.UpdateFirewallDescription:
properties:
address:
type: string
description:
type: string
port:
type: string
protocol:
type: string
strategy:
enum:
- accept
- drop
type: string
required:
- strategy
type: object
dto.Upgrade: dto.Upgrade:
properties: properties:
version: version:
@ -8251,6 +8273,26 @@ paths:
summary: Create group summary: Create group
tags: tags:
- Firewall - Firewall
/hosts/firewall/update/description:
post:
consumes:
- application/json
description: 更新防火墙描述
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.UpdateFirewallDescription'
responses:
"200":
description: OK
security:
- ApiKeyAuth: []
summary: Update rule description
tags:
- Firewall
/hosts/firewall/update/port: /hosts/firewall/update/port:
post: post:
consumes: consumes:

View file

@ -77,6 +77,14 @@ export namespace Host {
strategy: string; strategy: string;
appName: string; appName: string;
isUsed: boolean; isUsed: boolean;
description: string;
}
export interface UpdateDescription {
address: string;
port: string;
protocol: string;
strategy: string;
description: string;
} }
export interface RulePort { export interface RulePort {
operation: string; operation: string;
@ -85,11 +93,13 @@ export namespace Host {
source: string; source: string;
protocol: string; protocol: string;
strategy: string; strategy: string;
description: string;
} }
export interface RuleIP { export interface RuleIP {
operation: string; operation: string;
address: string; address: string;
strategy: string; strategy: string;
description: string;
} }
export interface UpdatePortRule { export interface UpdatePortRule {
oldRule: RulePort; oldRule: RulePort;

View file

@ -90,6 +90,9 @@ export const updatePortRule = (params: Host.UpdatePortRule) => {
export const updateAddrRule = (params: Host.UpdateAddrRule) => { export const updateAddrRule = (params: Host.UpdateAddrRule) => {
return http.post(`/hosts/firewall/update/addr`, params); return http.post(`/hosts/firewall/update/addr`, params);
}; };
export const updateFirewallDescription = (params: Host.UpdateDescription) => {
return http.post(`/hosts/firewall/update/description`, params);
};
export const batchOperateRule = (params: Host.BatchRule) => { export const batchOperateRule = (params: Host.BatchRule) => {
return http.post(`/hosts/firewall/batch`, params); return http.post(`/hosts/firewall/batch`, params);
}; };

View file

@ -74,6 +74,21 @@
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column
:min-width="150"
:label="$t('commons.table.description')"
prop="description"
>
<template #default="{ row }">
<fu-read-write-switch
:data="row.description"
v-model="row.edit"
@change="onChange(row)"
>
<el-input v-model="row.description" @blur="row.edit = false" />
</fu-read-write-switch>
</template>
</el-table-column>
<fu-table-operations <fu-table-operations
width="200px" width="200px"
:buttons="buttons" :buttons="buttons"
@ -118,7 +133,7 @@ import FireRouter from '@/views/host/firewall/index.vue';
import TableSetting from '@/components/table-setting/index.vue'; import TableSetting from '@/components/table-setting/index.vue';
import FireStatus from '@/views/host/firewall/status/index.vue'; import FireStatus from '@/views/host/firewall/status/index.vue';
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { batchOperateRule, searchFireRule, updateAddrRule } from '@/api/modules/host'; import { batchOperateRule, searchFireRule, updateAddrRule, updateFirewallDescription } 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';
@ -184,6 +199,13 @@ const toDoc = () => {
window.open('https://1panel.cn/docs/user_manual/hosts/firewall/', '_blank'); window.open('https://1panel.cn/docs/user_manual/hosts/firewall/', '_blank');
}; };
const onChange = async (info: any) => {
if (!info.edit) {
await updateFirewallDescription(info);
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
}
};
const onChangeStatus = async (row: Host.RuleInfo, status: string) => { const onChangeStatus = async (row: Host.RuleInfo, status: string) => {
let operation = let operation =
status === 'accept' status === 'accept'
@ -198,11 +220,13 @@ const onChangeStatus = async (row: Host.RuleInfo, status: string) => {
operation: 'remove', operation: 'remove',
address: row.address, address: row.address,
strategy: row.strategy, strategy: row.strategy,
description: row.description,
}, },
newRule: { newRule: {
operation: 'add', operation: 'add',
address: row.address, address: row.address,
strategy: status, strategy: status,
description: row.description,
}, },
}; };
loading.value = true; loading.value = true;

View file

@ -24,6 +24,9 @@
<el-radio label="drop">{{ $t('firewall.deny') }}</el-radio> <el-radio label="drop">{{ $t('firewall.deny') }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.table.description')" prop="description">
<el-input clearable v-model.trim="dialogData.rowData!.description" />
</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>

View file

@ -105,6 +105,21 @@
<span v-else>{{ $t('firewall.allIP') }}</span> <span v-else>{{ $t('firewall.allIP') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column
:min-width="150"
:label="$t('commons.table.description')"
prop="description"
>
<template #default="{ row }">
<fu-read-write-switch
:data="row.description"
v-model="row.edit"
@change="onChange(row)"
>
<el-input v-model="row.description" @blur="row.edit = false" />
</fu-read-write-switch>
</template>
</el-table-column>
<fu-table-operations <fu-table-operations
width="200px" width="200px"
:buttons="buttons" :buttons="buttons"
@ -150,7 +165,7 @@ 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 FireStatus from '@/views/host/firewall/status/index.vue'; import FireStatus from '@/views/host/firewall/status/index.vue';
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { batchOperateRule, searchFireRule, updatePortRule } from '@/api/modules/host'; import { batchOperateRule, searchFireRule, updateFirewallDescription, updatePortRule } 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';
@ -239,6 +254,7 @@ const onChangeStatus = async (row: Host.RuleInfo, status: string) => {
source: '', source: '',
protocol: row.protocol, protocol: row.protocol,
strategy: row.strategy, strategy: row.strategy,
description: row.description,
}, },
newRule: { newRule: {
operation: 'add', operation: 'add',
@ -247,6 +263,7 @@ const onChangeStatus = async (row: Host.RuleInfo, status: string) => {
source: '', source: '',
protocol: row.protocol, protocol: row.protocol,
strategy: status, strategy: status,
description: row.description,
}, },
}; };
loading.value = true; loading.value = true;
@ -262,6 +279,13 @@ const onChangeStatus = async (row: Host.RuleInfo, status: string) => {
}); });
}; };
const onChange = async (info: any) => {
if (!info.edit) {
await updateFirewallDescription(info);
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
}
};
const onDelete = async (row: Host.RuleInfo | null) => { const onDelete = async (row: Host.RuleInfo | 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'),

View file

@ -49,6 +49,9 @@
<el-radio label="drop">{{ $t('firewall.drop') }}</el-radio> <el-radio label="drop">{{ $t('firewall.drop') }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.table.description')" prop="description">
<el-input clearable v-model.trim="dialogData.rowData!.description" />
</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>