mirror of https://github.com/wg-easy/wg-easy
Browse Source
- Added a "Duplicate Client" button to the ClientCard, allowing users to create a new client based on the settings from existing clients. - The duplicated client will have its own name, private key and ipv4Address and ipv6Address - Added new API endpoint for duplicating clients, which accepts a client ID and creates a new client with the same properties.pull/2551/head
9 changed files with 205 additions and 0 deletions
@ -0,0 +1,8 @@ |
|||||
|
<template> |
||||
|
<ClientCardDuplicateDialog> |
||||
|
<BaseSecondaryButton class="inline-block rounded bg-gray-100 p-2 align-middle transition hover:bg-red-800 hover:text-white dark:bg-neutral-600 dark:text-neutral-300 dark:hover:bg-red-800 dark:hover:text-white" |
||||
|
:title="$t('client.duplicate')"> |
||||
|
<IconsDuplicate class="w-5" /> |
||||
|
</BaseSecondaryButton> |
||||
|
</ClientCardDuplicateDialog> |
||||
|
</template> |
||||
@ -0,0 +1,51 @@ |
|||||
|
<template> |
||||
|
<BaseDialog :trigger-class="triggerClass"> |
||||
|
<template #trigger> |
||||
|
<slot /> |
||||
|
</template> |
||||
|
<template #title> |
||||
|
{{ $t('client.duplicate') }} |
||||
|
</template> |
||||
|
<template #description> |
||||
|
<div class="flex flex-col"> |
||||
|
<FormTextField id="name" v-model="name" :label="$t('client.name')" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template #actions> |
||||
|
<DialogClose as-child> |
||||
|
<BaseSecondaryButton>{{ $t('dialog.cancel') }}</BaseSecondaryButton> |
||||
|
</DialogClose> |
||||
|
<DialogClose as-child> |
||||
|
<BasePrimaryButton @click="duplicateClient"> |
||||
|
{{ $t('client.create') }} |
||||
|
</BasePrimaryButton> |
||||
|
</DialogClose> |
||||
|
</template> |
||||
|
</BaseDialog> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
//const name = ref<string>(''); |
||||
|
//const name = computed(() => `${props.client.name}`); |
||||
|
const clientsStore = useClientsStore(); |
||||
|
|
||||
|
const { t } = useI18n(); |
||||
|
|
||||
|
const props = defineProps<{triggerClass?: string ; name?: string; client: LocalClient}>(); |
||||
|
const name = ref<string>(`${props.client.name}`); |
||||
|
|
||||
|
function duplicateClient() { |
||||
|
return _duplicateClient({ name: name.value}); |
||||
|
} |
||||
|
|
||||
|
const _duplicateClient = useSubmit( |
||||
|
`/api/client/${props.client.id}/duplicate`, |
||||
|
{ |
||||
|
method: 'post', |
||||
|
}, |
||||
|
{ |
||||
|
revert: () => clientsStore.refresh(), |
||||
|
successMsg: t('client.created'), |
||||
|
} |
||||
|
); |
||||
|
</script> |
||||
@ -0,0 +1,8 @@ |
|||||
|
<template> |
||||
|
<DuplicateIcon /> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import DuplicateIcon from '@heroicons/vue/24/outline/esm/DocumentDuplicateIcon'; |
||||
|
</script> |
||||
|
|
||||
@ -0,0 +1,26 @@ |
|||||
|
import { ClientDuplicateSchema, ClientGetSchema } from '#db/repositories/client/types'; |
||||
|
|
||||
|
export default definePermissionEventHandler( |
||||
|
'clients', |
||||
|
'create', |
||||
|
async ({ event, checkPermissions }) => { |
||||
|
const { clientId } = await getValidatedRouterParams( |
||||
|
event, |
||||
|
validateZod(ClientGetSchema, event) |
||||
|
); |
||||
|
|
||||
|
const { name } = await readValidatedBody( |
||||
|
event, |
||||
|
validateZod(ClientDuplicateSchema, event) |
||||
|
); |
||||
|
|
||||
|
const client = await Database.clients.get(clientId); |
||||
|
checkPermissions(client); |
||||
|
|
||||
|
const result = await Database.clients.createFromExistingId({ name, clientId }); |
||||
|
await WireGuard.saveConfig(); |
||||
|
|
||||
|
const newClientId = result[0]!.clientId; |
||||
|
return { success: true, newClientId }; |
||||
|
} |
||||
|
); |
||||
Loading…
Reference in new issue