Browse Source

Update allowed Ips from xwvike/allowed-ips

- Fix dark mode
  - adjust style to fit wg-easy theme
  - added check for valid ipv4
  - added js helper to jump on next input when '.' pressed
  - rm allowed ip from New client create for simplicity
pull/997/head
jcosmao 2 years ago
committed by Julien COSMAO
parent
commit
82dbe6fc48
No known key found for this signature in database GPG Key ID: 69153421048939E2
  1. 4
      README.md
  2. 8
      src/lib/Server.js
  3. 24
      src/lib/WireGuard.js
  4. 8
      src/www/css/app.css
  5. 157
      src/www/index.html
  6. 4
      src/www/js/api.js
  7. 14
      src/www/js/app.js
  8. 10
      src/www/js/i18n.js

4
README.md

@ -109,12 +109,12 @@ These options can be configured by setting environment variables using `-e KEY="
| `WG_HOST` | - | `vpn.myserver.com` | The public hostname of your VPN server. | | `WG_HOST` | - | `vpn.myserver.com` | The public hostname of your VPN server. |
| `WG_DEVICE` | `eth0` | `ens6f0` | Ethernet device the wireguard traffic should be forwarded through. | | `WG_DEVICE` | `eth0` | `ens6f0` | Ethernet device the wireguard traffic should be forwarded through. |
| `WG_PORT` | `51820` | `12345` | The public UDP port of your VPN server. WireGuard will listen on that (othwise default) inside the Docker container. | | `WG_PORT` | `51820` | `12345` | The public UDP port of your VPN server. WireGuard will listen on that (othwise default) inside the Docker container. |
| `WG_CONFIG_PORT`| `51820` | `12345` | The UDP port used on [Home Assistant Plugin](https://github.com/adriy-be/homeassistant-addons-jdeath/tree/main/wgeasy) | `WG_CONFIG_PORT`| `51820` | `12345` | The UDP port used on [Home Assistant Plugin](https://github.com/adriy-be/homeassistant-addons-jdeath/tree/main/wgeasy)
| `WG_MTU` | `null` | `1420` | The MTU the clients will use. Server uses default WG MTU. | | `WG_MTU` | `null` | `1420` | The MTU the clients will use. Server uses default WG MTU. |
| `WG_PERSISTENT_KEEPALIVE` | `0` | `25` | Value in seconds to keep the "connection" open. If this value is 0, then connections won't be kept alive. | | `WG_PERSISTENT_KEEPALIVE` | `0` | `25` | Value in seconds to keep the "connection" open. If this value is 0, then connections won't be kept alive. |
| `WG_DEFAULT_ADDRESS` | `10.8.0.x` | `10.6.0.x` | Clients IP address range. | | `WG_DEFAULT_ADDRESS` | `10.8.0.x` | `10.6.0.x` | Clients IP address range. |
| `WG_DEFAULT_DNS` | `1.1.1.1` | `8.8.8.8, 8.8.4.4` | DNS server clients will use. If set to blank value, clients will not use any DNS. | | `WG_DEFAULT_DNS` | `1.1.1.1` | `8.8.8.8, 8.8.4.4` | DNS server clients will use. If set to blank value, clients will not use any DNS. |
| `WG_ALLOWED_IPS` | `0.0.0.0/0, ::/0` | `192.168.15.0/24, 10.0.1.0/24` | Allowed IPs clients will use. | | `WG_ALLOWED_IPS` | `0.0.0.0/0, ::/0` | `192.168.15.0/24, 10.0.1.0/24` | Allowed IPs clients will use. It specify which destination address will be routed to wireguard interface. |
| `WG_PRE_UP` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L19) for the default value. | | `WG_PRE_UP` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L19) for the default value. |
| `WG_POST_UP` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L20) for the default value. | | `WG_POST_UP` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L20) for the default value. |
| `WG_PRE_DOWN` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L27) for the default value. | | `WG_PRE_DOWN` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L27) for the default value. |

8
src/lib/Server.js

@ -191,8 +191,8 @@ module.exports = class Server {
return config; return config;
})) }))
.post('/api/wireguard/client', defineEventHandler(async (event) => { .post('/api/wireguard/client', defineEventHandler(async (event) => {
const { name, allowedIps } = await readBody(event); const { name } = await readBody(event);
await WireGuard.createClient({ name, allowedIps }); await WireGuard.createClient({ name });
return { success: true }; return { success: true };
})) }))
.delete('/api/wireguard/client/:clientId', defineEventHandler(async (event) => { .delete('/api/wireguard/client/:clientId', defineEventHandler(async (event) => {
@ -234,7 +234,7 @@ module.exports = class Server {
await WireGuard.updateClientAddress({ clientId, address }); await WireGuard.updateClientAddress({ clientId, address });
return { success: true }; return { success: true };
})) }))
.put('/api/wireguard/client/:clientId/allowedips', defineEventHandler(async (event) => { .put('/api/wireguard/client/:clientId/allowedIPs', defineEventHandler(async (event) => {
const clientId = getRouterParam(event, 'clientId'); const clientId = getRouterParam(event, 'clientId');
if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') { if (clientId === '__proto__' || clientId === 'constructor' || clientId === 'prototype') {
throw createError({ status: 403 }); throw createError({ status: 403 });
@ -242,7 +242,7 @@ module.exports = class Server {
const { allowedIPs } = await readBody(event); const { allowedIPs } = await readBody(event);
await WireGuard.updateClientAllowedIPs({ clientId, allowedIPs }); await WireGuard.updateClientAllowedIPs({ clientId, allowedIPs });
return { success: true }; return { success: true };
})) }));
const safePathJoin = (base, target) => { const safePathJoin = (base, target) => {
// Manage web root (edge case) // Manage web root (edge case)

24
src/lib/WireGuard.js

@ -117,7 +117,7 @@ PostDown = ${WG_POST_DOWN}
} }
allowedIPs = allowedIPs.substring(1); allowedIPs = allowedIPs.substring(1);
} else { } else {
allowedIPs = client.address; allowedIPs = `${client.address}/32`;
} }
result += ` result += `
@ -235,7 +235,7 @@ Endpoint = ${WG_HOST}:${WG_CONFIG_PORT}`;
}); });
} }
async createClient({ name, allowedIps }) { async createClient({ name }) {
if (!name) { if (!name) {
throw new Error('Missing: Name'); throw new Error('Missing: Name');
} }
@ -248,20 +248,16 @@ Endpoint = ${WG_HOST}:${WG_CONFIG_PORT}`;
}); });
const preSharedKey = await Util.exec('wg genpsk'); const preSharedKey = await Util.exec('wg genpsk');
// Calculate next IP
let address; let address;
if (allowedIps) { for (let i = 2; i < 255; i++) {
address = allowedIps; const client = Object.values(config.clients).find((client) => {
} else { return client.address.includes(WG_DEFAULT_ADDRESS.replace('x', i));
// Calculate next IP });
for (let i = 2; i < 255; i++) {
const client = Object.values(config.clients).find((client) => {
return client.address.includes(WG_DEFAULT_ADDRESS.replace('x', i));
});
if (!client) { if (!client) {
address = `${WG_DEFAULT_ADDRESS.replace('x', i)}`; address = `${WG_DEFAULT_ADDRESS.replace('x', i)}`;
break; break;
}
} }
} }

8
src/www/css/app.css

@ -843,6 +843,10 @@ video {
height: 2rem; height: 2rem;
} }
.h-9 {
height: 2.25rem;
}
.min-h-5 { .min-h-5 {
min-height: 1.25rem; min-height: 1.25rem;
} }
@ -887,6 +891,10 @@ video {
width: 2rem; width: 2rem;
} }
.w-9 {
width: 2.25rem;
}
.w-fit { .w-fit {
width: -moz-fit-content; width: -moz-fit-content;
width: fit-content; width: fit-content;

157
src/www/index.html

@ -112,7 +112,7 @@
<span class="max-md:hidden text-sm">{{$t("backup")}}</span> <span class="max-md:hidden text-sm">{{$t("backup")}}</span>
</a> </a>
<!-- New client --> <!-- New client -->
<button @click="clientCreate = true; clientCreateName = ''; clientCreateAllowedIps = '';" <button @click="clientCreate = true; clientCreateName = '';"
class="hover:bg-red-800 hover:border-red-800 hover:text-white text-gray-700 dark:text-neutral-200 border-2 border-gray-100 dark:border-neutral-600 py-2 px-4 rounded inline-flex items-center transition"> class="hover:bg-red-800 hover:border-red-800 hover:text-white text-gray-700 dark:text-neutral-200 border-2 border-gray-100 dark:border-neutral-600 py-2 px-4 rounded inline-flex items-center transition">
<svg class="w-4 mr-2" inline xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" <svg class="w-4 mr-2" inline xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke="currentColor"> stroke="currentColor">
@ -308,7 +308,7 @@
<!-- AllowedIPs --> <!-- AllowedIPs -->
<button <button
class="align-middle bg-gray-100 dark:bg-neutral-600 dark:text-neutral-300 hover:bg-red-800 dark:hover:bg-red-800 hover:text-white dark:hover:text-white p-2 rounded transition" class="align-middle bg-gray-100 dark:bg-neutral-600 dark:text-neutral-300 hover:bg-red-800 dark:hover:bg-red-800 hover:text-white dark:hover:text-white p-2 rounded transition"
title="Edit Allowed IPs" @click="clientEditAllowedIPs = client"> :title="$t('editAllowedIPs')" @click="clientEditAllowedIPs = client">
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 icon icon-tabler icon-tabler-list" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <svg xmlns="http://www.w3.org/2000/svg" class="w-5 icon icon-tabler icon-tabler-list" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M9 6l11 0" /> <path d="M9 6l11 0" />
@ -467,12 +467,6 @@
type="text" v-model.trim="clientCreateName" :placeholder="$t('name')" /> type="text" v-model.trim="clientCreateName" :placeholder="$t('name')" />
</p> </p>
</div> </div>
<div class="mt-2">
<p class="text-sm text-gray-500">
<input class="rounded p-2 border-2 dark:bg-neutral-700 dark:text-neutral-200 border-gray-100 dark:border-neutral-600 focus:border-gray-200 focus:dark:border-neutral-500 dark:placeholder:text-neutral-400 outline-none w-full"
type="text" v-model.trim="clientCreateAllowedIps" placeholder="Allowed IPs (optional)" />
</p>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -562,80 +556,101 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<!--edit allowedIPs dialog--> <!-- Allowed Ips -->
<div v-if="clientEditAllowedIPs" class="fixed z-10 inset-0 overflow-y-auto"> <div v-if="clientEditAllowedIPs" class="fixed z-10 inset-0 overflow-y-auto">
<div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> <div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true"> <div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 dark:bg-black opacity-75 dark:opacity-50"></div> <div class="absolute inset-0 bg-gray-500 dark:bg-black opacity-75 dark:opacity-50"></div>
</div> </div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div <!-- This element is to trick the browser into centering the modal contents. -->
class="inline-block align-bottom bg-white dark:bg-neutral-700 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg w-full" <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
role="dialog" aria-modal="true" aria-labelledby="modal-headline"> <div class="inline-block align-bottom bg-white dark:bg-neutral-700 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg w-full"
<div class="bg-white dark:bg-neutral-700 px-4 pt-5 pb-4 sm:p-6 sm:pb-4"> role="dialog" aria-modal="true" aria-labelledby="modal-headline">
<div class="sm:flex sm:items-start"> <div class="bg-white dark:bg-neutral-700 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full text-white bg-red-800 sm:mx-0 sm:h-10 sm:w-10"> <div class="sm:flex sm:items-start">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-topology-star" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-800 sm:mx-0 sm:h-10 sm:w-10">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> <svg class="h-6 w-6 text-white" inline xmlns="http://www.w3.org/2000/svg"
<path d="M8 18a2 2 0 1 0 -4 0a2 2 0 0 0 4 0z" /> fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path d="M20 6a2 2 0 1 0 -4 0a2 2 0 0 0 4 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
<path d="M8 6a2 2 0 1 0 -4 0a2 2 0 0 0 4 0z" /> d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
<path d="M20 18a2 2 0 1 0 -4 0a2 2 0 0 0 4 0z" /> </svg>
<path d="M14 12a2 2 0 1 0 -4 0a2 2 0 0 0 4 0z" /> </div>
<path d="M7.5 7.5l3 3" /> <div class="flex-grow mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<path d="M7.5 16.5l3 -3" /> <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-neutral-200" id="modal-headline">
<path d="M13.5 13.5l3 3" /> {{$t("allowedIPs")}}
<path d="M16.5 7.5l-3 3" /> </h3>
</svg> <!-- Ip address input -->
</div> <div class="w-full flex items-center mt-3">
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div class="rounded p-1 border-2 dark:bg-neutral-700 dark:text-neutral-200 border-gray-100 dark:border-neutral-600 focus:border-gray-200 focus:dark:border-neutral-500 dark:placeholder:text-neutral-400 outline-none">
<h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-neutral-200" id="modal-headline"> <input maxlength="3" v-model.number="userInputIP[0]" placeholder="10" @keydown="handleKeyDown($event, '.', 'ip1')" class="w-8 text-center outline-none border-none bg-transparent"/>
Edit AllowedIPs <sub class="text-neutral-400"></sub>
</h3> <input maxlength="3" v-model.number="userInputIP[1]" placeholder="0" ref="ip1" @keydown="handleKeyDown($event, '.', 'ip2')" class="w-8 text-center outline-none border-none bg-transparent"/>
<div class="mt-2 flex items-center flex-col"> <sub class="text-neutral-400"></sub>
<div class="w-full min-h-5 flex flex-wrap"> <input maxlength="3" v-model.number="userInputIP[2]" placeholder="0" ref="ip2" @keydown="handleKeyDown($event, '.', 'ip3')" class="w-8 text-center outline-none border-none bg-transparent"/>
<div :class="[item.address!==clientEditAllowedIPs.address?'pr-8':'']" class="bg-white text-gray-700 relative h-8 tracking-widest border-2 border-gray-100 text-sm items-center rounded p-1 mb-2 mr-2 px-2 cursor-pointer flex w-fit" v-for="(item,index) in clientEditAllowedIPs.allowedIPs"> <sub class="text-neutral-400"></sub>
{{item.address+'/'+item.cidr}} <input maxlength="3" v-model.number="userInputIP[3]" placeholder="0" ref="ip3" @keydown="handleKeyDown($event, '/', 'ip4')" class="w-8 text-center outline-none border-none bg-transparent"/>
<div v-if="item.address!==clientEditAllowedIPs.address" style="width:calc(2rem - 4px);height:calc(2rem - 4px)" class="hover:bg-red-800 hover:text-white rounded top-0 right-0 w-8 h-8 flex justify-center items-center absolute"> <span class="text-neutral-400">/</span>
<svg @click="removeIP(index)" xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-x" width="15" height="15" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <input maxlength="2" v-model.number="userInputIP[4]" placeholder="8" ref="ip4" class="w-8 text-center outline-none border-none bg-transparent"/>
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" /></svg>
</div>
</div>
</div>
<div class="w-full flex items-center">
<div class="h-8 text-gray-700 w-fit text-sm bg-white border-2 border-gray-100 rounded flex items-center px-2">
<input maxlength="3" v-model.number="userInputIP[0]" class="w-8 text-center outline-none border-none bg-transparent"/><span></span>
<input maxlength="3" v-model.number="userInputIP[1]" class="w-8 text-center outline-none border-none bg-transparent"/><span></span>
<input maxlength="3" v-model.number="userInputIP[2]" class="w-8 text-center outline-none border-none bg-transparent"/><span></span>
<input maxlength="3" v-model.number="userInputIP[3]" class="w-8 text-center outline-none border-none bg-transparent"/><span>/</span>
<input maxlength="2" v-model.number="userInputIP[4]" class="w-8 text-center outline-none border-none bg-transparent"/>
</div> </div>
<div @click="addNewIP" class="w-8 h-8 rounded bg-white hover:border-red-800 hover:bg-red-800 hover:text-white text-gray-700 border-2 border-gray-100 cursor-pointer ml-2 flex justify-center items-center"> <!-- Ip address add -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-plus" width="18" height="18" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <button v-if="userInputIP.length == 5" @click="addNewIP"
class="w-9 h-9 rounded p-1 ml-2 bg-red-800 text-base font-medium text-white hover:bg-red-700 hover:border-red-700 dark:text-neutral-200 dark:border-neutral-600 cursor-pointer flex justify-center items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-plus"
width="18" height="18" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M12 5l0 14" />
<path d="M5 12l14 0" />
</svg>
</button>
<button v-else
class="w-9 h-9 rounded ml-2 bg-gray-200 dark:bg-neutral-400 text-white dark:text-neutral-300 border-gray-100 dark:border-neutral-600 dark:bg-neutral-500 flex justify-center items-center cursor-not-allowed">
<svg
xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-plus"
width="18" height="18" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M12 5l0 14" /> <path d="M12 5l0 14" />
<path d="M5 12l14 0" /></svg> <path d="M5 12l14 0" />
</svg>
</button>
</div>
<!-- Allowed ips inline display -->
<div class="mt-5">
<div class="w-full min-h-5 flex flex-wrap">
<div :class="[item.address!==clientEditAllowedIPs.address?'pr-8':'']" v-for="(item,index) in clientEditAllowedIPs.allowedIPs"
class="rounded p-1 border-2 mt-2 mb-2 mr-2 px-2 dark:bg-neutral-700 dark:text-neutral-200 border-gray-100 dark:border-neutral-600 focus:border-gray-200 focus:dark:border-neutral-500 relative h-8 tracking-widest text-sm items-center cursor-pointer flex w-fit">
{{item.address+'/'+item.cidr}}
<div v-if="item.address!==clientEditAllowedIPs.address" style="width:calc(2rem - 4px);height:calc(2rem - 4px)"
class="rounded top-0 right-0 w-8 h-8 bg-red-800 hover:bg-red-700 text-white hover:text-white hover:border-red-700 dark:text-neutral-200 dark:border-neutral-600 flex justify-center items-center absolute">
<svg @click="removeIP(index)" xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-x"
width="15" height="15" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> <div class="bg-gray-50 dark:bg-neutral-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<div class="bg-gray-50 dark:bg-neutral-600 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse"> <button type="button" @click="updateClientAllowedIPs(clientEditAllowedIPs); clientEditAllowedIPs = null"
<button type="button" @click="updateClientAllowedIPs(clientEditAllowedIPs); clientEditAllowedIPs = null" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-800 text-base font-medium text-white hover:bg-red-700 focus:outline-none sm:ml-3 sm:w-auto sm:text-sm">
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 dark:bg-red-600 text-base font-medium text-white dark:text-white hover:bg-red-700 dark:hover:bg-red-700 focus:outline-none sm:ml-3 sm:w-auto sm:text-sm"> {{$t("update")}}
Save </button>
</button> <button type="button" @click="clientEditAllowedIPs = null"
<button type="button" @click="clientEditAllowedIPs = null" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-neutral-500 shadow-sm px-4 py-2 bg-white dark:bg-neutral-500 text-base font-medium text-gray-700 dark:text-neutral-50 hover:bg-gray-50 dark:hover:bg-neutral-600 dark:hover:border-neutral-600 focus:outline-none sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-neutral-500 shadow-sm px-4 py-2 bg-white dark:bg-neutral-500 text-base font-medium text-gray-700 dark:text-neutral-50 hover:bg-gray-50 dark:hover:bg-neutral-600 dark:hover:border-neutral-600 focus:outline-none sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"> {{$t("cancel")}}
Cancel </button>
</button> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- End Allowed Ips -->
</div> </div>
<div v-if="authenticated === false"> <div v-if="authenticated === false">

4
src/www/js/api.js

@ -93,11 +93,11 @@ class API {
}))); })));
} }
async createClient({ name, allowedIps }) { async createClient({ name }) {
return this.call({ return this.call({
method: 'post', method: 'post',
path: '/wireguard/client', path: '/wireguard/client',
body: { name, allowedIps }, body: { name },
}); });
} }

14
src/www/js/app.js

@ -59,13 +59,12 @@ new Vue({
clientDelete: null, clientDelete: null,
clientCreate: null, clientCreate: null,
clientCreateName: '', clientCreateName: '',
clientCreateAllowedIps: '',
clientEditName: null, clientEditName: null,
clientEditNameId: null, clientEditNameId: null,
clientEditAddress: null, clientEditAddress: null,
clientEditAddressId: null, clientEditAddressId: null,
clientEditAllowedIPs: null, clientEditAllowedIPs: null,
userInputIP: [0, 0, 0, 0, 0], userInputIP: [],
qrcode: null, qrcode: null,
currentRelease: null, currentRelease: null,
@ -271,10 +270,9 @@ new Vue({
}, },
createClient() { createClient() {
const name = this.clientCreateName; const name = this.clientCreateName;
const allowedIps = this.clientCreateAllowedIps;
if (!name) return; if (!name) return;
this.api.createClient({ name, allowedIps }) this.api.createClient({ name })
.catch((err) => alert(err.message || err.toString())) .catch((err) => alert(err.message || err.toString()))
.finally(() => this.refresh().catch(console.error)); .finally(() => this.refresh().catch(console.error));
}, },
@ -324,13 +322,19 @@ new Vue({
.catch((err) => alert(err.message || err.toString())) .catch((err) => alert(err.message || err.toString()))
.finally(() => this.refresh().catch(console.error)); .finally(() => this.refresh().catch(console.error));
}, },
handleKeyDown(event, key, nextInputRef) {
if (event.key === key) {
event.preventDefault();
this.$refs[nextInputRef].focus();
}
},
addNewIP() { addNewIP() {
const address = this.userInputIP.slice(0, 4).join('.'); const address = this.userInputIP.slice(0, 4).join('.');
const allowedIPs = [...this.clientEditAllowedIPs.allowedIPs]; const allowedIPs = [...this.clientEditAllowedIPs.allowedIPs];
const obj = { type: 'ipv4', address, cidr: this.userInputIP[4] }; const obj = { type: 'ipv4', address, cidr: this.userInputIP[4] };
allowedIPs.push(obj); allowedIPs.push(obj);
this.clientEditAllowedIPs.allowedIPs = allowedIPs; this.clientEditAllowedIPs.allowedIPs = allowedIPs;
this.userInputIP = [0, 0, 0, 0, 0]; this.userInputIP = [];
}, },
removeIP(index) { removeIP(index) {
const allowedIPs = [...this.clientEditAllowedIPs.allowedIPs]; const allowedIPs = [...this.clientEditAllowedIPs.allowedIPs];

10
src/www/js/i18n.js

@ -34,6 +34,8 @@ const messages = { // eslint-disable-line no-unused-vars
backup: 'Backup', backup: 'Backup',
titleRestoreConfig: 'Restore your configuration', titleRestoreConfig: 'Restore your configuration',
titleBackupConfig: 'Backup your configuration', titleBackupConfig: 'Backup your configuration',
editAllowedIPs: 'Edit server AllowedIPs parameter',
allowedIPs: 'Server AllowedIPs',
}, },
ua: { ua: {
name: 'Ім`я', name: 'Ім`я',
@ -174,14 +176,14 @@ const messages = { // eslint-disable-line no-unused-vars
fr: { // github.com/clem3109 fr: { // github.com/clem3109
name: 'Nom', name: 'Nom',
password: 'Mot de passe', password: 'Mot de passe',
signIn: 'Se Connecter', signIn: 'Se connecter',
logout: 'Se déconnecter', logout: 'Se déconnecter',
updateAvailable: 'Une mise à jour est disponible !', updateAvailable: 'Une mise à jour est disponible !',
update: 'Mise à jour', update: 'Mise à jour',
clients: 'Clients', clients: 'Clients',
new: 'Nouveau', new: 'Nouveau',
deleteClient: 'Supprimer ce client', deleteClient: 'Supprimer ce client',
deleteDialog1: 'Êtes-vous que vous voulez supprimer', deleteDialog1: 'Êtes-vous sûr de vouloir supprimer ?',
deleteDialog2: 'Cette action ne peut pas être annulée.', deleteDialog2: 'Cette action ne peut pas être annulée.',
cancel: 'Annuler', cancel: 'Annuler',
create: 'Créer', create: 'Créer',
@ -193,7 +195,7 @@ const messages = { // eslint-disable-line no-unused-vars
disableClient: 'Désactiver ce client', disableClient: 'Désactiver ce client',
enableClient: 'Activer ce client', enableClient: 'Activer ce client',
noClients: 'Aucun client pour le moment.', noClients: 'Aucun client pour le moment.',
showQR: 'Afficher le code à réponse rapide (QR Code)', showQR: 'Afficher le QR Code',
downloadConfig: 'Télécharger la configuration', downloadConfig: 'Télécharger la configuration',
madeBy: 'Développé par', madeBy: 'Développé par',
donate: 'Soutenir', donate: 'Soutenir',
@ -201,6 +203,8 @@ const messages = { // eslint-disable-line no-unused-vars
backup: 'Sauvegarder', backup: 'Sauvegarder',
titleRestoreConfig: 'Restaurer votre configuration', titleRestoreConfig: 'Restaurer votre configuration',
titleBackupConfig: 'Sauvegarder votre configuration', titleBackupConfig: 'Sauvegarder votre configuration',
editAllowedIPs: 'Editer le paramètre AllowedIPs du serveur',
allowedIPs: 'Serveur AllowedIPs',
}, },
de: { // github.com/florian-asche de: { // github.com/florian-asche
name: 'Name', name: 'Name',

Loading…
Cancel
Save