wg-gen-web/ui/src/components/Server.vue

268 lines
11 KiB
Vue

<template>
<v-container v-if="server">
<v-row>
<v-col cols="12">
<v-card dark>
<v-list-item>
<v-list-item-content>
<v-list-item-title class="headline">Server's interface configuration</v-list-item-title>
</v-list-item-content>
</v-list-item>
<div class="d-flex flex-no-wrap justify-space-between">
<v-col cols="12">
<v-text-field
v-model="server.publicKey"
label="Public key"
disabled
/>
<v-text-field
v-model="server.listenPort"
type="number"
:rules="[
v => !!v || 'Listen port is required',
]"
label="Listen port"
required
/>
<v-combobox
v-model="server.address"
chips
hint="Write IPv4 or IPv6 CIDR and hit enter"
label="Server interface addresses"
multiple
dark
>
<template v-slot:selection="{ attrs, item, select, selected }">
<v-chip
v-bind="attrs"
:input-value="selected"
close
@click="select"
@click:close="server.address.splice(server.address.indexOf(item), 1)"
>
<strong>{{ item }}</strong>&nbsp;
</v-chip>
</template>
</v-combobox>
</v-col>
</div>
</v-card>
</v-col>
<v-col cols="12">
<v-card dark>
<v-list-item>
<v-list-item-content>
<v-list-item-title class="headline">Client's global configuration</v-list-item-title>
</v-list-item-content>
</v-list-item>
<div class="d-flex flex-no-wrap justify-space-between">
<v-col cols="12">
<v-text-field
v-model="server.endpoint"
label="Public endpoint for clients to connect to"
:rules="[
v => !!v || 'Public endpoint for clients to connect to is required',
]"
required
/>
<v-combobox
v-model="server.dns"
chips
hint="Write IPv4 or IPv6 address and hit enter"
label="DNS servers for clients"
multiple
dark
>
<template v-slot:selection="{ attrs, item, select, selected }">
<v-chip
v-bind="attrs"
:input-value="selected"
close
@click="select"
@click:close="server.dns.splice(server.dns.indexOf(item), 1)"
>
<strong>{{ item }}</strong>&nbsp;
</v-chip>
</template>
</v-combobox>
<v-combobox
v-model="server.allowedips"
chips
hint="Write IPv4 or IPv6 address and hit enter"
label="Default Allowed IPs for clients"
multiple
dark
>
<template v-slot:selection="{ attrs, item, select, selected }">
<v-chip
v-bind="attrs"
:input-value="selected"
close
@click="select"
@click:close="server.allowedips.splice(server.allowedips.indexOf(item), 1)"
>
<strong>{{ item }}</strong>&nbsp;
</v-chip>
</template>
</v-combobox>
<v-text-field
type="number"
v-model="server.mtu"
label="Define global MTU"
hint="Leave at 0 and let wg-quick take care of MTU"
/>
<v-text-field
type="number"
v-model="server.persistentKeepalive"
label="Persistent keepalive"
hint="Leave at 0 if you dont want to specify persistent keepalive"
/>
</v-col>
</div>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-card dark>
<v-list-item>
<v-list-item-content>
<v-list-item-title class="headline">Interface configuration hooks</v-list-item-title>
</v-list-item-content>
</v-list-item>
<div class="d-flex flex-no-wrap justify-space-between">
<v-col cols="12">
<v-text-field
v-model="server.preUp"
label="PreUp: script snippets which will be executed by bash before setting up the interface"
/>
<v-text-field
v-model="server.postUp"
label="PostUp: script snippets which will be executed by bash after setting up the interface"
/>
<v-text-field
v-model="server.preDown"
label="PreDown: script snippets which will be executed by bash before setting down the interface"
/>
<v-text-field
v-model="server.postDown "
label="PostDown : script snippets which will be executed by bash after setting down the interface"
/>
</v-col>
</div>
</v-card>
</v-col>
</v-row>
<v-row>
<v-divider dark/>
<v-btn
class="ma-2"
color="success"
:href="`${apiBaseUrl}/server/config`"
>
Download server configuration
<v-icon right dark>mdi-cloud-download-outline</v-icon>
</v-btn>
<v-spacer></v-spacer>
<v-btn
class="ma-2"
color="warning"
@click="updateServer"
>
Update server configuration
<v-icon right dark>mdi-update</v-icon>
</v-btn>
<v-divider dark/>
</v-row>
<Notification v-bind:notification="notification"/>
</v-container>
</template>
<script>
import {API_BASE_URL, ApiService} from "../services/ApiService";
import Notification from '../components/Notification'
export default {
name: 'Server',
components: {
Notification
},
data: () => ({
api: null,
server: null,
apiBaseUrl: API_BASE_URL,
notification: {
show: false,
color: '',
text: '',
},
}),
mounted () {
this.api = new ApiService();
this.getServer()
},
methods: {
getServer() {
this.api.get('/server').then((res) => {
this.server = res;
}).catch((e) => {
this.notify('error', e.response.status + ' ' + e.response.statusText);
});
},
updateServer () {
// convert int values
this.server.listenPort = parseInt(this.server.listenPort, 10);
this.server.persistentKeepalive = parseInt(this.server.persistentKeepalive, 10);
this.server.mtu = parseInt(this.server.mtu, 10);
// check server addresses
if (this.server.address.length < 1) {
this.notify('error', 'Please provide at least one valid CIDR address for server interface');
return;
}
for (let i = 0; i < this.server.address.length; i++){
if (this.$isCidr(this.server.address[i]) === 0) {
this.notify('error', `Invalid CIDR detected, please correct ${this.server.address[i]} before submitting`);
return
}
}
// check DNS correct
for (let i = 0; i < this.server.dns.length; i++){
if (this.$isCidr(this.server.dns[i] + '/32') === 0) {
this.notify('error', `Invalid IP detected, please correct ${this.server.dns[i]} before submitting`);
return
}
}
// check client AllowedIPs
if (this.server.allowedips.length < 1) {
this.notify('error', 'Please provide at least one valid CIDR address for client allowed IPs');
return;
}
for (let i = 0; i < this.server.allowedips.length; i++){
if (this.$isCidr(this.server.allowedips[i]) === 0) {
this.notify('error', 'Invalid CIDR detected, please correct before submitting');
return
}
}
this.api.patch('/server', this.server).then((res) => {
this.notify('success', "Server successfully updated");
this.server = res;
}).catch((e) => {
this.notify('error', e.response.status + ' ' + e.response.statusText);
});
},
notify(color, msg) {
this.notification.show = true;
this.notification.color = color;
this.notification.text = msg;
}
}
};
</script>