Files
cloudron-box/dashboard/src/components/Firewall.vue
2025-03-28 17:51:39 +01:00

179 lines
5.9 KiB
Vue

<script setup>
import { ref, onMounted, useTemplateRef, computed } from 'vue';
import { Dialog, Button, FormGroup } from 'pankow';
import Section from '../components/Section.vue';
import SettingsItem from '../components/SettingsItem.vue';
import NetworkModel from '../models/NetworkModel.js';
const networkModel = NetworkModel.create();
const blocklistLength = ref(0);
const blocklist = ref('');
const blocklistDialog = useTemplateRef('blocklistDialog');
const editBlocklistError = ref('');
const editBlocklistBusy = ref(false);
const editBlocklist = ref('');
const isBlocklistValid = computed(() => {
return true;
});
async function refreshBlocklist() {
const [error, result] = await networkModel.getBlocklist();
if (error) return console.error(error);
blocklist.value = result;
blocklistLength.value = result.split('\n').filter(function (l) { return l.length !== 0 && l[0] !== '#'; }).length;
}
function onBlocklistConfigure() {
editBlocklistBusy.value = false;
editBlocklistError.value = '';
editBlocklist.value = blocklist.value;
blocklistDialog.value.open();
}
async function onBlocklistSubmit() {
if (!isBlocklistValid.value) return;
editBlocklistBusy.value = true;
const [error] = await networkModel.setBlocklist(editBlocklist.value);
if (error) {
editBlocklistBusy.value = false;
editBlocklistError.value = error.body ? error.body.message : 'Internal error';
return;
}
await refreshBlocklist();
blocklistDialog.value.close();
editBlocklistBusy.value = false;
}
const trustedIpsLength = ref(0);
const trustedIps = ref('');
const trustedIpsDialog = useTemplateRef('trustedIpsDialog');
const editTrustedIpsError = ref('');
const editTrustedIpsBusy = ref(false);
const editTrustedIps = ref('');
const isTrustedIpsValid = computed(() => {
return true;
});
function onTrustedIpsConfigure() {
editTrustedIpsError.value = '';
editTrustedIpsBusy.value = false;
editTrustedIps.value = trustedIps.value;
trustedIpsDialog.value.open();
}
async function onTrustedIpsSubmit() {
if (!isTrustedIpsValid.value) return;
editTrustedIpsBusy.value = true;
const [error] = await networkModel.setTrustedIps(editTrustedIps.value);
if (error) {
editTrustedIpsBusy.value = false;
editTrustedIpsError.value = error.body ? error.body.message : 'Internal error';
return;
}
await refreshTrustedIps();
trustedIpsDialog.value.close();
editTrustedIpsBusy.value = false;
}
async function refreshTrustedIps() {
const [error, result] = await networkModel.getTrustedIps();
if (error) return console.error(error);
trustedIps.value = result;
trustedIpsLength.value = result.split('\n').filter(function (l) { return l.length !== 0 && l[0] !== '#'; }).length;
}
onMounted(async () => {
await refreshBlocklist();
await refreshTrustedIps();
});
</script>
<template>
<div>
<Dialog ref="blocklistDialog"
:title="$t('network.firewall.configure.title')"
:confirm-label="$t('main.dialog.save')"
:confirm-busy="editBlocklistBusy"
:confirm-active="!editBlocklistBusy && isBlocklistValid"
:reject-label="$t('main.dialog.cancel')"
reject-style="secondary"
@confirm="onBlocklistSubmit()"
>
<div>
<p class="small">{{ $t('network.firewall.configure.description') }}</p>
<form novalidate @submit.prevent="onBlocklistSubmit()" autocomplete="off">
<fieldset :disabled="editBlocklistBusy">
<input style="display: none" type="submit" :disabled="editBlocklistBusy || !isBlocklistValid"/>
<FormGroup>
<label for="blocklistInput">{{ $t('network.firewall.blockedIpRanges') }}</label>
<div class="has-error" v-show="editBlocklistError">{{ editBlocklistError }}</div>
<textarea id="blocklistInput" v-model="editBlocklist" :placeholder="$t('network.firewall.configure.blocklistPlaceholder')" rows="4"></textarea>
</FormGroup>
</fieldset>
</form>
</div>
</Dialog>
<Dialog ref="trustedIpsDialog"
:title="$t('network.trustedIps.title')"
:confirm-label="$t('main.dialog.save')"
:confirm-busy="editTrustedIpsBusy"
:confirm-active="!editTrustedIpsBusy && isTrustedIpsValid"
:reject-label="$t('main.dialog.cancel')"
reject-style="secondary"
@confirm="onTrustedIpsSubmit()"
>
<div>
<p class="small">{{ $t('network.trustedIps.description') }}</p>
<form novalidate @submit.prevent="onTrustedIpsSubmit()" autocomplete="off">
<fieldset :disabled="editTrustedIpsBusy">
<input style="display: none;" type="submit" :disabled="editTrustedIpsBusy || !isTrustedIpsValid"/>
<FormGroup>
<label for="">{{ $t('network.trustedIpRanges') }}</label>
<div class="has-error" v-show="editTrustedIpsError">{{ editTrustedIpsError }}</div>
<textarea v-model="editTrustedIps" :placeholder="$t('network.firewall.configure.blocklistPlaceholder')" rows="4"></textarea>
</FormGroup>
</fieldset>
</form>
</div>
</Dialog>
<Section :title="$t('network.firewall.title')" :padding="false">
<SettingsItem>
<FormGroup>
<label>{{ $t('network.firewall.blockedIpRanges') }}</label>
<div>{{ $t('network.firewall.blocklist', { blockCount: blocklistLength }) }}</div>
</FormGroup>
<div style="display: flex; align-items: center">
<Button tool plain @click="onBlocklistConfigure()">{{ $t('main.dialog.edit') }}</Button>
</div>
</SettingsItem>
<SettingsItem>
<FormGroup>
<label>{{ $t('network.trustedIpRanges') }}</label>
<div>{{ $t('network.trustedIps.summary', { trustCount: trustedIpsLength }) }}</div>
</FormGroup>
<div style="display: flex; align-items: center">
<Button tool plain @click="onTrustedIpsConfigure()">{{ $t('main.dialog.edit') }}</Button>
</div>
</SettingsItem>
</Section>
</div>
</template>