241 lines
8.1 KiB
Vue
241 lines
8.1 KiB
Vue
<script setup lang="ts">
|
|
import {onMounted, ref} from 'vue'
|
|
import {createConfigClient} from '../config'
|
|
|
|
// --- Types ---
|
|
// Ils sont maintenant importés ou définis via l'interface du client
|
|
|
|
const configClient = createConfigClient()
|
|
const config = ref<any>({
|
|
servers: [],
|
|
identities: []
|
|
})
|
|
|
|
const loading = ref(false)
|
|
const toast = useToast()
|
|
|
|
const items = [{
|
|
label: 'Serveurs',
|
|
icon: 'i-lucide-server',
|
|
slot: 'servers'
|
|
}, {
|
|
label: 'Identités',
|
|
icon: 'i-lucide-user',
|
|
slot: 'identities'
|
|
}]
|
|
|
|
// --- Methods ---
|
|
|
|
async function fetchConfig() {
|
|
loading.value = true
|
|
try {
|
|
const res = await configClient.get()
|
|
config.value = res
|
|
} catch (error) {
|
|
console.error('Erreur lors de la récupération de la config:', error)
|
|
toast.add({title: 'Erreur', description: 'Impossible de charger la configuration.', color: 'red'})
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
async function saveConfig() {
|
|
loading.value = true
|
|
try {
|
|
await configClient.update(config.value)
|
|
// Re-fetch config to get any auto-generated keys
|
|
await fetchConfig()
|
|
toast.add({title: 'Succès', description: 'Configuration sauvegardée.', color: 'green'})
|
|
} catch (error) {
|
|
console.error('Erreur lors de la sauvegarde de la config:', error)
|
|
toast.add({title: 'Erreur', description: 'Impossible de sauvegarder la configuration.', color: 'red'})
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// async function generateKey(index: number) {
|
|
// try {
|
|
// // Note: generate_ssh_key n'est pas encore dans IConfigClient, on peut l'ajouter si besoin
|
|
// // ou garder un invoke direct si c'est spécifique à Tauri, mais ici on veut de l'abstrait.
|
|
// // Pour le moment on utilise invoke car c'est un utilitaire.
|
|
// const {invoke} from '@tauri-apps/api/core'
|
|
// const key = await invoke<string>('generate_ssh_key')
|
|
// config.value.identities[index].private_key = key
|
|
// toast.add({title: 'Succès', description: 'Clé SSH générée.', color: 'green'})
|
|
// } catch (error) {
|
|
// console.error('Erreur lors de la génération de la clé:', error)
|
|
// toast.add({title: 'Erreur', description: 'Impossible de générer la clé.', color: 'red'})
|
|
// }
|
|
// }
|
|
|
|
function addServer() {
|
|
config.value.servers.push({adresse: '', identity: ''})
|
|
}
|
|
|
|
function removeServer(index: number) {
|
|
config.value.servers.splice(index, 1)
|
|
}
|
|
|
|
function addIdentity() {
|
|
config.value.identities.push({
|
|
id: crypto.randomUUID(),
|
|
username: '',
|
|
private_key: '',
|
|
mode: 'private_key_path'
|
|
})
|
|
}
|
|
|
|
function removeIdentity(index: number) {
|
|
config.value.identities.splice(index, 1)
|
|
}
|
|
|
|
onMounted(() => {
|
|
fetchConfig()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="p-6 max-w-4xl mx-auto overflow-y-auto h-full">
|
|
<div class="flex items-center justify-between mb-6">
|
|
<h1 class="text-2xl font-bold">Configuration</h1>
|
|
<UButton
|
|
icon="i-lucide-save"
|
|
color="primary"
|
|
:loading="loading"
|
|
@click="saveConfig"
|
|
>
|
|
Sauvegarder
|
|
</UButton>
|
|
</div>
|
|
|
|
<UTabs :items="items" class="w-full">
|
|
<template #servers>
|
|
<div class="space-y-4 py-4">
|
|
<div v-for="(server, index) in config.servers" :key="index"
|
|
class="p-4 border border-gray-200 dark:border-gray-800 rounded-lg relative bg-white dark:bg-gray-900 shadow-sm">
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<UFormField label="Adresse du serveur (IP:Port)">
|
|
<UInput v-model="server.adresse" placeholder="ex: 127.0.0.1:50051" class="w-full"/>
|
|
</UFormField>
|
|
|
|
<UFormField label="Identité à utiliser">
|
|
<USelect
|
|
v-model="server.identity"
|
|
:items="config.identities.map(i => ({ label: i.username || i.id, value: i.id }))"
|
|
placeholder="Sélectionner une identité"
|
|
class="w-full"
|
|
/>
|
|
</UFormField>
|
|
</div>
|
|
|
|
<UButton
|
|
icon="i-lucide-trash"
|
|
color="red"
|
|
variant="ghost"
|
|
size="sm"
|
|
class="absolute top-2 right-2"
|
|
@click="removeServer(index)"
|
|
/>
|
|
</div>
|
|
|
|
<UButton
|
|
icon="i-lucide-plus"
|
|
variant="dashed"
|
|
block
|
|
@click="addServer"
|
|
>
|
|
Ajouter un serveur
|
|
</UButton>
|
|
</div>
|
|
</template>
|
|
|
|
<template #identities>
|
|
<div class="space-y-4 py-4">
|
|
<div v-for="(identity, index) in config.identities" :key="identity.id"
|
|
class="p-4 border border-gray-200 dark:border-gray-800 rounded-lg relative bg-white dark:bg-gray-900 shadow-sm">
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<UFormField label="ID d'identité (unique)">
|
|
<UInput v-model="identity.id" placeholder="ex: mon-id" class="w-full"/>
|
|
</UFormField>
|
|
|
|
<UFormField label="Nom d'utilisateur">
|
|
<UInput v-model="identity.username" placeholder="ex: MonPseudo" class="w-full"/>
|
|
</UFormField>
|
|
|
|
<UFormField label="Mode d'authentification" class="md:col-span-2">
|
|
<USelect
|
|
v-model="identity.mode"
|
|
:items="[
|
|
{ label: 'Clé (Fichier)', value: 'private_key_path' },
|
|
{ label: 'Clé (Base64)', value: 'private_key_base64' },
|
|
{ label: 'Login uniquement', value: 'login' }
|
|
]"
|
|
class="w-full"
|
|
/>
|
|
</UFormField>
|
|
|
|
<template v-if="identity.mode === 'private_key_path' || identity.mode === 'private_key_base64'">
|
|
<UFormField :label="identity.mode === 'private_key_path' ? 'Chemin de la clé' : 'Clé privée (Base64)'"
|
|
class="md:col-span-2">
|
|
<div class="space-y-2">
|
|
<UTextarea
|
|
v-model="identity.private_key"
|
|
:placeholder="identity.mode === 'private_key_path' ? 'ex: ~/.ssh/id_rsa' : 'Entrez la clé encodée en base64 (Si vide, une clé sera générée au besoin)'"
|
|
class="w-full"
|
|
/>
|
|
<!-- <UButton-->
|
|
<!-- v-if="identity.mode === 'private_key_base64'"-->
|
|
<!-- icon="i-lucide-key"-->
|
|
<!-- variant="subtle"-->
|
|
<!-- size="xs"-->
|
|
<!-- label="Générer une clé SSH"-->
|
|
<!-- @click="generateKey(index)"-->
|
|
<!-- />-->
|
|
</div>
|
|
</UFormField>
|
|
</template>
|
|
|
|
|
|
<template v-if="identity.token">
|
|
<UFormField label="Jeton JWT (Persistant)" class="md:col-span-2">
|
|
<div class="flex gap-2">
|
|
<UInput v-model="identity.token" readonly class="flex-1 font-mono text-xs"/>
|
|
<UButton
|
|
icon="i-lucide-copy"
|
|
variant="ghost"
|
|
color="neutral"
|
|
@click="() => {
|
|
navigator.clipboard.writeText(identity.token || '')
|
|
toast.add({ title: 'Copié', description: 'Jeton JWT copié dans le presse-papier', color: 'green' })
|
|
}"
|
|
/>
|
|
</div>
|
|
</UFormField>
|
|
</template>
|
|
</div>
|
|
|
|
<UButton
|
|
icon="i-lucide-trash"
|
|
color="red"
|
|
variant="ghost"
|
|
size="sm"
|
|
class="absolute top-2 right-2"
|
|
@click="removeIdentity(index)"
|
|
/>
|
|
</div>
|
|
|
|
<UButton
|
|
icon="i-lucide-plus"
|
|
variant="dashed"
|
|
block
|
|
@click="addIdentity"
|
|
>
|
|
Ajouter une identité
|
|
</UButton>
|
|
</div>
|
|
</template>
|
|
</UTabs>
|
|
</div>
|
|
</template>
|