@ -130,7 +130,7 @@
<!-- Show QR -->
< button class = "align-middle bg-gray-100 hover:bg-red-800 hover:text-white p-2 rounded transition"
title="Show QR Code" @click="qrcode = `/api/wireguard/client/${client.id}/qrcode.svg?${Date.now()}` ;">
title="Show QR Code" @click="clientQRShow = client; areClientsHardened().then(harden => {if (!harden) document.getElementById('client-qr-button').click();}) ;">
< svg class = "w-5" xmlns = "http://www.w3.org/2000/svg" fill = "none" viewBox = "0 0 24 24"
stroke="currentColor">
< path stroke-linecap = "round" stroke-linejoin = "round" stroke-width = "2"
@ -138,6 +138,16 @@
< / svg >
< / button >
<!-- Download Config -->
< button class = "align-middle bg-gray-100 hover:bg-red-800 hover:text-white p-2 rounded transition"
title="Download Configuration" @click="clientConfigDownload = client; areClientsHardened().then(harden => {if (!harden) document.getElementById('client-download-button').click();});">
< svg class = "w-5" xmlns = "http://www.w3.org/2000/svg" fill = "none" viewBox = "0 0 24 24"
stroke="currentColor">
< path stroke-linecap = "round" stroke-linejoin = "round" stroke-width = "2"
d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
< / svg >
< / button >
<!-- Address -->
< span class = "group" >
@ -367,6 +377,147 @@
< / div >
< / div >
<!-- Show QR code Dialog -->
< div v-if = "clientQRShow" class = "fixed z-10 inset-0 overflow-y-auto" >
< div class = "flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0" >
<!--
Background overlay, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0"
To: "opacity-100"
Leaving: "ease-in duration-200"
From: "opacity-100"
To: "opacity-0"
-->
< div class = "fixed inset-0 transition-opacity" aria-hidden = "true" >
< div class = "absolute inset-0 bg-gray-500 opacity-75" > < / div >
< / div >
<!-- This element is to trick the browser into centering the modal contents. -->
< span class = "hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden = "true" > ​ < / span >
<!--
Modal panel, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
To: "opacity-100 translate-y-0 sm:scale-100"
Leaving: "ease-in duration-200"
From: "opacity-100 translate-y-0 sm:scale-100"
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
-->
< div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog" aria-modal="true" aria-labelledby="modal-headline">
< div class = "bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4" >
< div class = "sm:flex sm:items-start" >
< div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<!-- Heroicon name: outline/exclamation -->
< svg class = "h-6 w-6 text-red-600" xmlns = "http://www.w3.org/2000/svg" fill = "none" viewBox = "0 0 24 24"
stroke="currentColor" aria-hidden="true">
< path stroke-linecap = "round" stroke-linejoin = "round" stroke-width = "2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
< / svg >
< / div >
< div class = "mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left" >
< h3 class = "text-lg leading-6 font-medium text-gray-900" id = "modal-headline" >
Show Client QR Code
< / h3 >
< div class = "mt-2" >
< p class = "text-sm text-gray-500" >
Are you sure you want to display the QR code for < strong > {{clientQRShow.name}}< / strong > ?
This will trigger a key regeneration and invalidate existing configuration.
< / p >
< / div >
< / div >
< / div >
< / div >
< div class = "bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse" >
< button id = "client-qr-button" type = "button" @ click = "qrcode = `/api/wireguard/client/${clientQRShow.id}/qrcode.svg?${Date.now()}`; clientQRShow = null;"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
Show
< / button >
< button type = "button" @ click = "clientQRShow = null"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
< / button >
< / div >
< / div >
< / div >
< / div >
<!-- Download client config Dialog -->
< div v-if = "clientConfigDownload" class = "fixed z-10 inset-0 overflow-y-auto" >
< div class = "flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0" >
<!--
Background overlay, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0"
To: "opacity-100"
Leaving: "ease-in duration-200"
From: "opacity-100"
To: "opacity-0"
-->
< div class = "fixed inset-0 transition-opacity" aria-hidden = "true" >
< div class = "absolute inset-0 bg-gray-500 opacity-75" > < / div >
< / div >
<!-- This element is to trick the browser into centering the modal contents. -->
< span class = "hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden = "true" > ​ < / span >
<!--
Modal panel, show/hide based on modal state.
Entering: "ease-out duration-300"
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
To: "opacity-100 translate-y-0 sm:scale-100"
Leaving: "ease-in duration-200"
From: "opacity-100 translate-y-0 sm:scale-100"
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
-->
< div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
role="dialog" aria-modal="true" aria-labelledby="modal-headline">
< div class = "bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4" >
< div class = "sm:flex sm:items-start" >
< div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<!-- Heroicon name: outline/exclamation -->
< svg class = "h-6 w-6 text-red-600" xmlns = "http://www.w3.org/2000/svg" fill = "none" viewBox = "0 0 24 24"
stroke="currentColor" aria-hidden="true">
< path stroke-linecap = "round" stroke-linejoin = "round" stroke-width = "2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
< / svg >
< / div >
< div class = "mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left" >
< h3 class = "text-lg leading-6 font-medium text-gray-900" id = "modal-headline" >
Download Client Configuration
< / h3 >
< div class = "mt-2" >
< p class = "text-sm text-gray-500" >
Are you sure you want to download the configuration for < strong > {{clientConfigDownload.name}}< / strong > ?
This will trigger a key regeneration and invalidate existing configuration.
< / p >
< / div >
< / div >
< / div >
< / div >
< div class = "bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse" >
< a id = "client-config-link" href = "" download > < / a >
< button id = "client-download-button" type = "button" @ click = "var link = document.getElementById('client-config-link'); link.href = `/api/wireguard/client/${clientConfigDownload.id}/configuration`; link.click(); clientConfigDownload = null;"
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
Download
< / button >
< button type = "button" @ click = "clientConfigDownload = null"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
< / button >
< / div >
< / div >
< / div >
< / div >
<!-- Delete Dialog -->
< div v-if = "clientDelete" class = "fixed z-10 inset-0 overflow-y-auto" >
< div class = "flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0" >