1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 08:19:15 +08:00

feat: 防火墙列表增加状态、策略筛选项 (#2121)

Refs #1859
This commit is contained in:
ssongliu 2023-08-30 14:56:11 +08:00 committed by GitHub
parent 529a7e6ea6
commit 9cecd66f3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 118 additions and 53 deletions

View File

@ -38,6 +38,10 @@ func (b *BaseApi) SearchFirewallRule(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return return
} }
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
total, list, err := firewallService.SearchWithPage(req) total, list, err := firewallService.SearchWithPage(req)
if err != nil { if err != nil {

View File

@ -9,8 +9,10 @@ type FirewallBaseInfo struct {
type RuleSearch struct { type RuleSearch struct {
PageInfo PageInfo
Info string `json:"info"` Info string `json:"info"`
Type string `json:"type" validate:"required"` Status string `json:"status"`
Strategy string `json:"strategy"`
Type string `json:"type" validate:"required"`
} }
type FirewallOperation struct { type FirewallOperation struct {
@ -28,6 +30,7 @@ type PortRuleOperate struct {
} }
type UpdateFirewallDescription struct { type UpdateFirewallDescription struct {
Type string `json:"type"`
Address string `json:"address"` Address string `json:"address"`
Port string `json:"port"` Port string `json:"port"`
Protocol string `json:"protocol"` Protocol string `json:"protocol"`

View File

@ -3,6 +3,7 @@ package model
type Firewall struct { type Firewall struct {
BaseModel BaseModel
Type string `gorm:"type:varchar(64);not null" json:"type"`
Port string `gorm:"type:varchar(64);not null" json:"port"` Port string `gorm:"type:varchar(64);not null" json:"port"`
Protocol string `gorm:"type:varchar(64);not null" json:"protocol"` Protocol string `gorm:"type:varchar(64);not null" json:"protocol"`
Address string `gorm:"type:varchar(64);not null" json:"address"` Address string `gorm:"type:varchar(64);not null" json:"address"`

View File

@ -24,7 +24,7 @@ type IHostRepo interface {
ListFirewallRecord() ([]model.Firewall, error) ListFirewallRecord() ([]model.Firewall, error)
SaveFirewallRecord(firewall *model.Firewall) error SaveFirewallRecord(firewall *model.Firewall) error
DeleteFirewallRecordByID(id uint) error DeleteFirewallRecordByID(id uint) error
DeleteFirewallRecord(port, protocol, address, strategy string) error DeleteFirewallRecord(fType, port, protocol, address, strategy string) error
} }
func NewIHostRepo() IHostRepo { func NewIHostRepo() IHostRepo {
@ -136,9 +136,16 @@ func (h *HostRepo) SaveFirewallRecord(firewall *model.Firewall) error {
return global.DB.Save(firewall).Error return global.DB.Save(firewall).Error
} }
var data model.Firewall 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 firewall.Type == "port" {
if data.ID != 0 { _ = global.DB.Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", "port", firewall.Port, firewall.Protocol, firewall.Address, firewall.Strategy).First(&data)
firewall.ID = data.ID if data.ID != 0 {
firewall.ID = data.ID
}
} else {
_ = global.DB.Where("type = ? AND address = ? AND strategy = ?", "address", firewall.Address, firewall.Strategy).First(&data)
if data.ID != 0 {
firewall.ID = data.ID
}
} }
return global.DB.Save(firewall).Error return global.DB.Save(firewall).Error
} }
@ -147,6 +154,6 @@ func (h *HostRepo) DeleteFirewallRecordByID(id uint) error {
return global.DB.Where("id = ?", id).Delete(&model.Firewall{}).Error return global.DB.Where("id = ?", id).Delete(&model.Firewall{}).Error
} }
func (h *HostRepo) DeleteFirewallRecord(port, protocol, address, strategy string) error { func (h *HostRepo) DeleteFirewallRecord(fType, 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 return global.DB.Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", fType, port, protocol, address, strategy).Delete(&model.Firewall{}).Error
} }

View File

@ -104,20 +104,57 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
datas = addrs datas = addrs
} }
} }
total, start, end := len(datas), (req.Page-1)*req.PageSize, req.Page*req.PageSize
var datasFilterStatus []fireClient.FireInfo
if len(req.Status) != 0 {
for _, data := range datas {
portItem, _ := strconv.Atoi(data.Port)
if req.Status == "free" && !common.ScanPort(portItem) {
datasFilterStatus = append(datasFilterStatus, data)
}
if req.Status == "used" && common.ScanPort(portItem) {
datasFilterStatus = append(datasFilterStatus, data)
}
}
} else {
datasFilterStatus = datas
}
var datasFilterStrategy []fireClient.FireInfo
if len(req.Strategy) != 0 {
for _, data := range datasFilterStatus {
if req.Strategy == data.Strategy {
datasFilterStrategy = append(datasFilterStrategy, data)
}
}
} else {
datasFilterStrategy = datasFilterStatus
}
total, start, end := len(datasFilterStrategy), (req.Page-1)*req.PageSize, req.Page*req.PageSize
if start > total { if start > total {
backDatas = make([]fireClient.FireInfo, 0) backDatas = make([]fireClient.FireInfo, 0)
} else { } else {
if end >= total { if end >= total {
end = total end = total
} }
backDatas = datas[start:end] backDatas = datasFilterStrategy[start:end]
} }
datasFromDB, _ := hostRepo.ListFirewallRecord() datasFromDB, _ := hostRepo.ListFirewallRecord()
for i := 0; i < len(backDatas); i++ { for i := 0; i < len(backDatas); i++ {
for _, des := range datasFromDB { 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 { if req.Type != des.Type {
continue
}
if backDatas[i].Port == des.Port &&
req.Type == "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 == "address" && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.Address {
backDatas[i].Description = des.Description backDatas[i].Description = des.Description
break break
} }
@ -488,10 +525,11 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er
func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error { func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error {
if req.Operation == "remove" { if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord(req.Port, req.Protocol, req.Address, req.Strategy) return hostRepo.DeleteFirewallRecord("port", req.Port, req.Protocol, req.Address, req.Strategy)
} }
return hostRepo.SaveFirewallRecord(&model.Firewall{ return hostRepo.SaveFirewallRecord(&model.Firewall{
Type: "port",
Port: req.Port, Port: req.Port,
Protocol: req.Protocol, Protocol: req.Protocol,
Address: req.Address, Address: req.Address,
@ -502,9 +540,10 @@ func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error {
func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error { func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error {
if req.Operation == "remove" { if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord("", "", req.Address, req.Strategy) return hostRepo.DeleteFirewallRecord("address", "", "", req.Address, req.Strategy)
} }
return hostRepo.SaveFirewallRecord(&model.Firewall{ return hostRepo.SaveFirewallRecord(&model.Firewall{
Type: "address",
Address: req.Address, Address: req.Address,
Strategy: req.Strategy, Strategy: req.Strategy,
Description: req.Description, Description: req.Description,

View File

@ -572,14 +572,12 @@ var UpdateCronjobWithDb = &gormigrate.Migration{
} }
var AddTableFirewall = &gormigrate.Migration{ var AddTableFirewall = &gormigrate.Migration{
ID: "20230825-add-table-firewall", ID: "20230828-add-table-firewall",
Migrate: func(tx *gorm.DB) error { Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.Firewall{}, model.SnapshotStatus{}, &model.Cronjob{}); err != nil { if err := tx.AutoMigrate(&model.Firewall{}, model.SnapshotStatus{}, &model.Cronjob{}); err != nil {
return err return err
} }
if err := tx.Exec("alter table remote_dbs rename to databases;").Error; err != nil { _ = tx.Exec("alter table remote_dbs rename to databases;").Error
return err
}
return nil return nil
}, },
} }

View File

@ -66,6 +66,8 @@ export namespace Host {
pingStatus: string; pingStatus: string;
} }
export interface RuleSearch extends ReqPage { export interface RuleSearch extends ReqPage {
status: string;
strategy: string;
info: string; info: string;
type: string; type: string;
} }

View File

@ -140,9 +140,7 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('commons.table.description')" prop="description"> <el-table-column :label="$t('commons.table.description')" prop="description">
<template #default="{ row }"> <template #default="{ row }">
<fu-read-write-switch :data="row.description" v-model="row.edit" @change="onChange(row)"> <fu-input-rw-switch v-model="row.description" @blur="onChange(row)" />
<el-input v-model="row.description" @blur="row.edit = false" />
</fu-read-write-switch>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -382,10 +380,8 @@ const goRouter = async () => {
}; };
const onChange = async (info: any) => { const onChange = async (info: any) => {
if (!info.edit) { await updateMysqlDescription({ id: info.id, description: info.description });
await updateMysqlDescription({ id: info.id, description: info.description }); MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
}
}; };
const goDashboard = async () => { const goDashboard = async () => {

View File

@ -45,6 +45,16 @@
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
<template #search>
<div class="flx-align-center">
<el-select v-model="searchStrategy" @change="search()" clearable>
<template #prefix>{{ $t('firewall.strategy') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<el-option :label="$t('firewall.allow')" value="accept"></el-option>
<el-option :label="$t('firewall.deny')" value="drop"></el-option>
</el-select>
</div>
</template>
<template #main> <template #main>
<ComplexTable <ComplexTable
:pagination-config="paginationConfig" :pagination-config="paginationConfig"
@ -80,13 +90,7 @@
prop="description" prop="description"
> >
<template #default="{ row }"> <template #default="{ row }">
<fu-read-write-switch <fu-input-rw-switch v-model="row.description" @blur="onChange(row)" />
: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> </template>
</el-table-column> </el-table-column>
<fu-table-operations <fu-table-operations
@ -143,6 +147,7 @@ const loading = ref();
const activeTag = ref('address'); const activeTag = ref('address');
const selects = ref<any>([]); const selects = ref<any>([]);
const searchName = ref(); const searchName = ref();
const searchStrategy = ref('');
const fireName = ref(); const fireName = ref();
const maskShow = ref(true); const maskShow = ref(true);
@ -165,6 +170,8 @@ const search = async () => {
} }
let params = { let params = {
type: activeTag.value, type: activeTag.value,
status: '',
strategy: searchStrategy.value,
info: searchName.value, info: searchName.value,
page: paginationConfig.currentPage, page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize, pageSize: paginationConfig.pageSize,
@ -200,10 +207,9 @@ const toDoc = () => {
}; };
const onChange = async (info: any) => { const onChange = async (info: any) => {
if (!info.edit) { info.type = 'address';
await updateFirewallDescription(info); await updateFirewallDescription(info);
MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
}
}; };
const onChangeStatus = async (row: Host.RuleInfo, status: string) => { const onChangeStatus = async (row: Host.RuleInfo, status: string) => {

View File

@ -35,6 +35,22 @@
</template> </template>
</el-alert> </el-alert>
</template> </template>
<template #search>
<div class="flx-align-center">
<el-select v-model="searchStatus" @change="search()" clearable>
<template #prefix>{{ $t('commons.table.status') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<el-option :label="$t('firewall.unUsed')" value="free"></el-option>
<el-option :label="$t('firewall.used')" value="used"></el-option>
</el-select>
<el-select v-model="searchStrategy" style="margin-left: 10px" @change="search()" clearable>
<template #prefix>{{ $t('firewall.strategy') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<el-option :label="$t('firewall.accept')" value="accept"></el-option>
<el-option :label="$t('firewall.drop')" value="drop"></el-option>
</el-select>
</div>
</template>
<template #toolbar> <template #toolbar>
<el-row> <el-row>
<el-col :span="16"> <el-col :span="16">
@ -110,13 +126,7 @@
prop="description" prop="description"
> >
<template #default="{ row }"> <template #default="{ row }">
<fu-read-write-switch <fu-input-rw-switch v-model="row.description" @blur="onChange(row)" />
: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> </template>
</el-table-column> </el-table-column>
<fu-table-operations <fu-table-operations
@ -175,6 +185,8 @@ const loading = ref();
const activeTag = ref('port'); const activeTag = ref('port');
const selects = ref<any>([]); const selects = ref<any>([]);
const searchName = ref(); const searchName = ref();
const searchStatus = ref('');
const searchStrategy = ref('');
const maskShow = ref(true); const maskShow = ref(true);
const fireStatus = ref('running'); const fireStatus = ref('running');
@ -197,6 +209,8 @@ const search = async () => {
} }
let params = { let params = {
type: activeTag.value, type: activeTag.value,
status: searchStatus.value,
strategy: searchStrategy.value,
info: searchName.value, info: searchName.value,
page: paginationConfig.currentPage, page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize, pageSize: paginationConfig.pageSize,
@ -279,10 +293,9 @@ const onChangeStatus = async (row: Host.RuleInfo, status: string) => {
}; };
const onChange = async (info: any) => { const onChange = async (info: any) => {
if (!info.edit) { info.type = 'port';
await updateFirewallDescription(info); await updateFirewallDescription(info);
MsgSuccess(i18n.global.t('commons.msg.operationSuccess')); MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
}
}; };
const onDelete = async (row: Host.RuleInfo | null) => { const onDelete = async (row: Host.RuleInfo | null) => {

View File

@ -74,9 +74,7 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('commons.table.description')" prop="description"> <el-table-column :label="$t('commons.table.description')" prop="description">
<template #default="{ row }"> <template #default="{ row }">
<fu-read-write-switch :data="row.description" v-model="row.edit" @change="onChange(row)"> <fu-input-rw-switch v-model="row.description" @blur="onChange(row)" />
<el-input v-model="row.description" @blur="row.edit = false" />
</fu-read-write-switch>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -205,10 +203,8 @@ const handleClose = () => {
}; };
const onChange = async (info: any) => { const onChange = async (info: any) => {
if (!info.edit) { await updateSnapshotDescription({ id: info.id, description: info.description });
await updateSnapshotDescription({ id: info.id, description: info.description }); MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
}
}; };
const submitAddSnapshot = (formEl: FormInstance | undefined) => { const submitAddSnapshot = (formEl: FormInstance | undefined) => {