mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 22:18:07 +08:00
feat: 完成 firewalld 与 ufw 列表显示
This commit is contained in:
parent
d5f446d7cf
commit
c9d36d84f7
@ -54,19 +54,6 @@ 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 req.Protocol == "tcp/udp" {
|
|
||||||
req.Protocol = "tcp"
|
|
||||||
if err := firewallService.OperatePortRule(req); err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
req.Protocol = "udp"
|
|
||||||
if err := firewallService.OperatePortRule(req); err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
helper.SuccessWithData(c, nil)
|
|
||||||
}
|
|
||||||
if err := firewallService.OperatePortRule(req); err != nil {
|
if err := firewallService.OperatePortRule(req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
|
@ -9,7 +9,7 @@ type PortRuleOperate struct {
|
|||||||
Operation string `json:"operation" validate:"required,oneof=add remove"`
|
Operation string `json:"operation" validate:"required,oneof=add remove"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Port string `json:"port" validate:"required"`
|
Port string `json:"port" validate:"required"`
|
||||||
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/upd"`
|
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,16 +59,17 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if req.Protocol == "tcp/udp" {
|
||||||
var fireInfo fireClient.FireInfo
|
req.Protocol = "tcp"
|
||||||
if err := copier.Copy(&fireInfo, &req); err != nil {
|
if err := u.createPort(client, req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Protocol = "udp"
|
||||||
|
}
|
||||||
|
if err := u.createPort(client, req); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return client.Reload()
|
||||||
if len(fireInfo.Address) != 0 || fireInfo.Strategy == "drop" {
|
|
||||||
return client.RichRules(fireInfo, req.Operation)
|
|
||||||
}
|
|
||||||
return client.Port(fireInfo, req.Operation)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate) error {
|
func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate) error {
|
||||||
@ -81,5 +82,20 @@ 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
|
||||||
}
|
}
|
||||||
return client.RichRules(fireInfo, req.Operation)
|
if err := client.RichRules(fireInfo, req.Operation); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return client.Reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *FirewallService) createPort(client firewall.FirewallClient, req dto.PortRuleOperate) error {
|
||||||
|
var fireInfo fireClient.FireInfo
|
||||||
|
if err := copier.Copy(&fireInfo, &req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fireInfo.Address) != 0 || fireInfo.Strategy == "drop" {
|
||||||
|
return client.RichRules(fireInfo, req.Operation)
|
||||||
|
}
|
||||||
|
return client.Port(fireInfo, req.Operation)
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,10 @@ type FirewallClient interface {
|
|||||||
|
|
||||||
func NewFirewallClient() (FirewallClient, error) {
|
func NewFirewallClient() (FirewallClient, error) {
|
||||||
// if _, err := os.Stat("/usr/sbin/firewalld"); err == nil {
|
// if _, err := os.Stat("/usr/sbin/firewalld"); err == nil {
|
||||||
return client.NewFirewalld()
|
// return client.NewFirewalld()
|
||||||
// }
|
// }
|
||||||
// if _, err := os.Stat("/usr/sbin/ufw"); err == nil {
|
// if _, err := os.Stat("/usr/sbin/ufw"); err == nil {
|
||||||
// return client.NewUfw()
|
return client.NewUfw()
|
||||||
// }
|
// }
|
||||||
// return nil, errors.New("no such type")
|
// return nil, errors.New("no such type")
|
||||||
}
|
}
|
||||||
|
@ -111,9 +111,6 @@ func (f *Firewall) Port(port FireInfo, operation string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s port failed, err: %s", operation, stdout)
|
return fmt.Errorf("%s port failed, err: %s", operation, stdout)
|
||||||
}
|
}
|
||||||
if err := f.Reload(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,9 +131,6 @@ func (f *Firewall) RichRules(rule FireInfo, operation string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s rich rules failed, err: %s", operation, stdout)
|
return fmt.Errorf("%s rich rules failed, err: %s", operation, stdout)
|
||||||
}
|
}
|
||||||
if err := f.Reload(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,9 +144,6 @@ func (f *Firewall) PortForward(info Forward, operation string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s port forward failed, err: %s", operation, stdout)
|
return fmt.Errorf("%s port forward failed, err: %s", operation, stdout)
|
||||||
}
|
}
|
||||||
if err := f.Reload(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ type FireInfo struct {
|
|||||||
Family string `json:"family"` // ipv4 ipv6
|
Family string `json:"family"` // ipv4 ipv6
|
||||||
Address string `json:"address"` // Anywhere
|
Address string `json:"address"` // Anywhere
|
||||||
Port string `json:"port"`
|
Port string `json:"port"`
|
||||||
Protocol string `json:"protocol"` // tcp udp tcp/upd
|
Protocol string `json:"protocol"` // tcp udp tcp/udp
|
||||||
Strategy string `json:"strategy"` // accept drop
|
Strategy string `json:"strategy"` // accept drop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func (f *Ufw) ListPort() ([]FireInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
portInfos := strings.Split(strings.ReplaceAll(stdout, "\n", ""), " ")
|
portInfos := strings.Split(stdout, "\n")
|
||||||
var datas []FireInfo
|
var datas []FireInfo
|
||||||
isStart := false
|
isStart := false
|
||||||
for _, line := range portInfos {
|
for _, line := range portInfos {
|
||||||
@ -73,7 +73,7 @@ func (f *Ufw) ListPort() ([]FireInfo, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
itemFire := f.loadInfo(line, "port")
|
itemFire := f.loadInfo(line, "port")
|
||||||
if len(itemFire.Address) != 0 {
|
if len(itemFire.Port) != 0 {
|
||||||
datas = append(datas, itemFire)
|
datas = append(datas, itemFire)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ func (f *Ufw) ListAddress() ([]FireInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
portInfos := strings.Split(strings.ReplaceAll(stdout, "\n", ""), " ")
|
portInfos := strings.Split(stdout, "\n")
|
||||||
var datas []FireInfo
|
var datas []FireInfo
|
||||||
isStart := false
|
isStart := false
|
||||||
for _, line := range portInfos {
|
for _, line := range portInfos {
|
||||||
@ -96,8 +96,11 @@ func (f *Ufw) ListAddress() ([]FireInfo, error) {
|
|||||||
if !isStart {
|
if !isStart {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(line, " IN") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
itemFire := f.loadInfo(line, "address")
|
itemFire := f.loadInfo(line, "address")
|
||||||
if len(itemFire.Address) != 0 {
|
if len(itemFire.Port) == 0 {
|
||||||
datas = append(datas, itemFire)
|
datas = append(datas, itemFire)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,7 +169,7 @@ func (f *Ufw) loadInfo(line string, fireType string) FireInfo {
|
|||||||
if len(fields) < 4 {
|
if len(fields) < 4 {
|
||||||
return itemInfo
|
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[2] == "ALLOW" {
|
||||||
itemInfo.Strategy = "accept"
|
itemInfo.Strategy = "accept"
|
||||||
|
@ -5,23 +5,8 @@
|
|||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="20">
|
<el-col :span="20">
|
||||||
<el-button
|
<el-button type="primary" @click="onOpenDialog('create')">
|
||||||
class="tag-button"
|
{{ $t('commons.button.create') }} {{ $t('firewall.ipRule') }}
|
||||||
:class="activeTag === 'port' ? '' : 'no-active'"
|
|
||||||
@click="changeTag('port')"
|
|
||||||
:type="activeTag === 'port' ? 'primary' : ''"
|
|
||||||
:plain="activeTag !== 'port'"
|
|
||||||
>
|
|
||||||
{{ $t('firewall.portRule') }}
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
class="tag-button"
|
|
||||||
:class="activeTag === 'ip' ? '' : 'no-active'"
|
|
||||||
@click="changeTag('ip')"
|
|
||||||
:type="activeTag === 'ip' ? 'primary' : ''"
|
|
||||||
:plain="activeTag !== 'ip'"
|
|
||||||
>
|
|
||||||
{{ $t('firewall.ipRule') }}
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -34,35 +19,47 @@
|
|||||||
:data="data"
|
:data="data"
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" fix />
|
<el-table-column type="selection" fix />
|
||||||
<el-table-column :label="$t('firewall.protocol')" :min-width="90" prop="protocol" />
|
|
||||||
<el-table-column :label="$t('firewall.port')" :min-width="120" prop="port" />
|
|
||||||
<el-table-column :min-width="80" :label="$t('firewall.strategy')" prop="strategy">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-tag v-if="row.strategy === 'accept'" type="success">{{ $t('firewall.accept') }}</el-tag>
|
|
||||||
<el-tag v-if="row.strategy === 'drop'" type="danger">{{ $t('firewall.drop') }}</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column :min-width="80" :label="$t('firewall.address')" prop="address">
|
<el-table-column :min-width="80" :label="$t('firewall.address')" prop="address">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="row.address && row.address !== 'Anywhere'">{{ row.address }}</span>
|
<span v-if="row.address && row.address !== 'Anywhere'">{{ row.address }}</span>
|
||||||
<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="80" :label="$t('firewall.strategy')" prop="strategy">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag v-if="row.strategy === 'accept'" type="success">{{ $t('firewall.accept') }}</el-tag>
|
||||||
|
<el-tag v-if="row.strategy === 'drop'" type="danger">{{ $t('firewall.drop') }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<fu-table-operations
|
||||||
|
width="200px"
|
||||||
|
:buttons="buttons"
|
||||||
|
:ellipsis="10"
|
||||||
|
:label="$t('commons.table.operate')"
|
||||||
|
fix
|
||||||
|
/>
|
||||||
</ComplexTable>
|
</ComplexTable>
|
||||||
</template>
|
</template>
|
||||||
</LayoutContent>
|
</LayoutContent>
|
||||||
|
|
||||||
|
<OperatrDialog @search="search" ref="dialogRef" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<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 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 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 { searchFireRule } from '@/api/modules/host';
|
import { operateIPRule, searchFireRule } from '@/api/modules/host';
|
||||||
|
import { Host } from '@/api/interface/host';
|
||||||
|
import { ElMessageBox } from 'element-plus';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import { MsgSuccess } from '@/utils/message';
|
||||||
|
|
||||||
const loading = ref();
|
const loading = ref();
|
||||||
const activeTag = ref('port');
|
const activeTag = ref('address');
|
||||||
const selects = ref<any>([]);
|
const selects = ref<any>([]);
|
||||||
|
|
||||||
const data = ref();
|
const data = ref();
|
||||||
@ -91,10 +88,53 @@ const search = async () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeTag = async (type: string) => {
|
const dialogRef = ref();
|
||||||
activeTag.value = type;
|
const onOpenDialog = async (
|
||||||
|
title: string,
|
||||||
|
rowData: Partial<Host.RuleIP> = {
|
||||||
|
strategy: 'accept',
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
let params = {
|
||||||
|
title,
|
||||||
|
rowData: { ...rowData },
|
||||||
|
};
|
||||||
|
dialogRef.value!.acceptParams(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onDelete = async (row: Host.RuleInfo | 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,
|
||||||
|
};
|
||||||
|
loading.value = true;
|
||||||
|
await operateIPRule(params)
|
||||||
|
.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
search();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttons = [
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.delete'),
|
||||||
|
click: (row: Host.RuleInfo) => {
|
||||||
|
onDelete(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
search();
|
search();
|
||||||
});
|
});
|
||||||
|
97
frontend/src/views/host/firewall/ip/operate/index.vue
Normal file
97
frontend/src/views/host/firewall/ip/operate/index.vue
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
||||||
|
<template #header>
|
||||||
|
<DrawerHeader :header="$t('firewall.ipRule')" :back="handleClose" />
|
||||||
|
</template>
|
||||||
|
<div v-loading="loading">
|
||||||
|
<el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules">
|
||||||
|
<el-row type="flex" justify="center">
|
||||||
|
<el-col :span="22">
|
||||||
|
<el-form-item :label="$t('firewall.address')" prop="address">
|
||||||
|
<el-input
|
||||||
|
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||||
|
type="textarea"
|
||||||
|
clearable
|
||||||
|
v-model="dialogData.rowData!.address"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('firewall.strategy')" prop="strategy">
|
||||||
|
<el-radio-group v-model="dialogData.rowData!.strategy">
|
||||||
|
<el-radio label="accept">{{ $t('firewall.accept') }}</el-radio>
|
||||||
|
<el-radio label="drop">{{ $t('firewall.drop') }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit(formRef)">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
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';
|
||||||
|
|
||||||
|
const loading = ref();
|
||||||
|
|
||||||
|
interface DialogProps {
|
||||||
|
title: string;
|
||||||
|
rowData?: Host.RulePort;
|
||||||
|
getTableList?: () => Promise<any>;
|
||||||
|
}
|
||||||
|
const title = ref<string>('');
|
||||||
|
const drawerVisiable = ref(false);
|
||||||
|
const dialogData = ref<DialogProps>({
|
||||||
|
title: '',
|
||||||
|
});
|
||||||
|
const acceptParams = (params: DialogProps): void => {
|
||||||
|
dialogData.value = params;
|
||||||
|
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
||||||
|
drawerVisiable.value = true;
|
||||||
|
};
|
||||||
|
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
drawerVisiable.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
address: [Rules.requiredInput],
|
||||||
|
});
|
||||||
|
|
||||||
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
|
const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate(async (valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
acceptParams,
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,114 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
|
||||||
<template #header>
|
|
||||||
<DrawerHeader :header="$t('firewall.portRule')" :back="handleClose" />
|
|
||||||
</template>
|
|
||||||
<el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules">
|
|
||||||
<el-row type="flex" justify="center">
|
|
||||||
<el-col :span="22">
|
|
||||||
<el-form-item :label="$t('firewall.protocol')" prop="protocol">
|
|
||||||
<el-select style="width: 100%" v-model="dialogData.rowData!.protocol">
|
|
||||||
<el-option value="tcp" label="tcp" />
|
|
||||||
<el-option value="udp" label="udp" />
|
|
||||||
<el-option value="tcp/udp" label="tcp/udp" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('firewall.port')" prop="port">
|
|
||||||
<el-input clearable v-model.trim="dialogData.rowData!.port" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('firewall.source')" prop="source">
|
|
||||||
<el-radio-group v-model="dialogData.rowData!.source">
|
|
||||||
<el-radio label="anyWhere">{{ $t('firewall.anyWhere') }}</el-radio>
|
|
||||||
<el-radio label="address">{{ $t('firewall.address') }}</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('firewall.address')"
|
|
||||||
v-if="dialogData.rowData!.source === 'address'"
|
|
||||||
prop="address"
|
|
||||||
>
|
|
||||||
<el-input v-model="dialogData.rowData!.address" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('firewall.strategy')" prop="strategy">
|
|
||||||
<el-radio-group v-model="dialogData.rowData!.strategy">
|
|
||||||
<el-radio label="accept">{{ $t('firewall.accept') }}</el-radio>
|
|
||||||
<el-radio label="drop">{{ $t('firewall.drop') }}</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
|
||||||
<el-button type="primary" @click="onSubmit(formRef)">
|
|
||||||
{{ $t('commons.button.confirm') }}
|
|
||||||
</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { reactive, ref } from 'vue';
|
|
||||||
import { Rules } from '@/global/form-rules';
|
|
||||||
import i18n from '@/lang';
|
|
||||||
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 { operatePortRule } from '@/api/modules/host';
|
|
||||||
|
|
||||||
interface DialogProps {
|
|
||||||
title: string;
|
|
||||||
rowData?: Host.RulePort;
|
|
||||||
getTableList?: () => Promise<any>;
|
|
||||||
}
|
|
||||||
const title = ref<string>('');
|
|
||||||
const drawerVisiable = ref(false);
|
|
||||||
const dialogData = ref<DialogProps>({
|
|
||||||
title: '',
|
|
||||||
});
|
|
||||||
const acceptParams = (params: DialogProps): void => {
|
|
||||||
dialogData.value = params;
|
|
||||||
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
|
||||||
drawerVisiable.value = true;
|
|
||||||
};
|
|
||||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
drawerVisiable.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const rules = reactive({
|
|
||||||
protocol: [Rules.requiredSelect],
|
|
||||||
port: [Rules.requiredInput],
|
|
||||||
address: [Rules.requiredInput],
|
|
||||||
});
|
|
||||||
|
|
||||||
type FormInstance = InstanceType<typeof ElForm>;
|
|
||||||
const formRef = ref<FormInstance>();
|
|
||||||
|
|
||||||
const onSubmit = async (formEl: FormInstance | undefined) => {
|
|
||||||
if (!formEl) return;
|
|
||||||
formEl.validate(async (valid) => {
|
|
||||||
if (!valid) return;
|
|
||||||
if (!dialogData.value.rowData) return;
|
|
||||||
if (dialogData.value.title === 'create') {
|
|
||||||
await operatePortRule(dialogData.value.rowData);
|
|
||||||
}
|
|
||||||
|
|
||||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
|
||||||
emit('search');
|
|
||||||
drawerVisiable.value = false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
acceptParams,
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -51,7 +51,7 @@
|
|||||||
<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 OperatrDialog from '@/views/host/firewall/port/create/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 { operatePortRule, searchFireRule } from '@/api/modules/host';
|
||||||
@ -120,9 +120,16 @@ const onDelete = async (row: Host.RuleInfo | null) => {
|
|||||||
protocol: row.protocol,
|
protocol: row.protocol,
|
||||||
strategy: row.strategy,
|
strategy: row.strategy,
|
||||||
};
|
};
|
||||||
await operatePortRule(params);
|
loading.value = true;
|
||||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
await operatePortRule(params)
|
||||||
search();
|
.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
search();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
118
frontend/src/views/host/firewall/port/operate/index.vue
Normal file
118
frontend/src/views/host/firewall/port/operate/index.vue
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
<template>
|
||||||
|
<el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
||||||
|
<template #header>
|
||||||
|
<DrawerHeader :header="$t('firewall.portRule')" :back="handleClose" />
|
||||||
|
</template>
|
||||||
|
<div v-loading="loading">
|
||||||
|
<el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules">
|
||||||
|
<el-row type="flex" justify="center">
|
||||||
|
<el-col :span="22">
|
||||||
|
<el-form-item :label="$t('firewall.protocol')" prop="protocol">
|
||||||
|
<el-select style="width: 100%" v-model="dialogData.rowData!.protocol">
|
||||||
|
<el-option value="tcp" label="tcp" />
|
||||||
|
<el-option value="udp" label="udp" />
|
||||||
|
<el-option value="tcp/udp" label="tcp/udp" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="$t('firewall.port')" prop="port">
|
||||||
|
<el-input clearable v-model.trim="dialogData.rowData!.port" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="$t('firewall.source')" prop="source">
|
||||||
|
<el-radio-group v-model="dialogData.rowData!.source">
|
||||||
|
<el-radio label="anyWhere">{{ $t('firewall.anyWhere') }}</el-radio>
|
||||||
|
<el-radio label="address">{{ $t('firewall.address') }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('firewall.address')"
|
||||||
|
v-if="dialogData.rowData!.source === 'address'"
|
||||||
|
prop="address"
|
||||||
|
>
|
||||||
|
<el-input v-model="dialogData.rowData!.address" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="$t('firewall.strategy')" prop="strategy">
|
||||||
|
<el-radio-group v-model="dialogData.rowData!.strategy">
|
||||||
|
<el-radio label="accept">{{ $t('firewall.accept') }}</el-radio>
|
||||||
|
<el-radio label="drop">{{ $t('firewall.drop') }}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="onSubmit(formRef)">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
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 { operatePortRule } from '@/api/modules/host';
|
||||||
|
|
||||||
|
const loading = ref();
|
||||||
|
|
||||||
|
interface DialogProps {
|
||||||
|
title: string;
|
||||||
|
rowData?: Host.RulePort;
|
||||||
|
getTableList?: () => Promise<any>;
|
||||||
|
}
|
||||||
|
const title = ref<string>('');
|
||||||
|
const drawerVisiable = ref(false);
|
||||||
|
const dialogData = ref<DialogProps>({
|
||||||
|
title: '',
|
||||||
|
});
|
||||||
|
const acceptParams = (params: DialogProps): void => {
|
||||||
|
dialogData.value = params;
|
||||||
|
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
||||||
|
drawerVisiable.value = true;
|
||||||
|
};
|
||||||
|
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
drawerVisiable.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
protocol: [Rules.requiredSelect],
|
||||||
|
port: [Rules.requiredInput],
|
||||||
|
address: [Rules.requiredInput],
|
||||||
|
});
|
||||||
|
|
||||||
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
|
const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate(async (valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
loading.value = true;
|
||||||
|
dialogData.value.rowData.operation = 'add';
|
||||||
|
if (!dialogData.value.rowData) return;
|
||||||
|
await operatePortRule(dialogData.value.rowData);
|
||||||
|
loading.value = false;
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
emit('search');
|
||||||
|
drawerVisiable.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
acceptParams,
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
x
Reference in New Issue
Block a user