ux: token Proxmox en deux champs séparés (ID + Secret)
Install.vue et Settings.vue : remplace le champ unique "PVEAPIToken=..." par deux inputs distincts — Token ID (ex: enzo@pam!panel) et Secret (uuid). L'assemblage PVEAPIToken=ID=Secret se fait côté frontend avant envoi. Plus besoin de connaître le format interne. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d55ecdcd97
commit
233f690214
4 changed files with 48 additions and 20 deletions
|
|
@ -33,8 +33,9 @@
|
|||
"sshSuccess": "SSH connection successful!",
|
||||
"sshFailed": "SSH connection failed",
|
||||
"proxmoxUrl": "Proxmox URL",
|
||||
"proxmoxToken": "Proxmox API token",
|
||||
"proxmoxTokenHint": "Format: PVEAPIToken=user{'@'}realm!tokenid=secret",
|
||||
"proxmoxTokenId": "Token ID",
|
||||
"proxmoxTokenSecret": "Token secret",
|
||||
"proxmoxTokenHint": "Token ID: enzo{'@'}pam!panel — Secret: UUID generated by Proxmox",
|
||||
"back": "Back",
|
||||
"next": "Next",
|
||||
"finish": "Complete installation",
|
||||
|
|
@ -115,7 +116,9 @@
|
|||
"sshUsername": "SSH username",
|
||||
"sshPassword": "SSH password",
|
||||
"proxmoxUrl": "Proxmox URL",
|
||||
"proxmoxToken": "Proxmox API token",
|
||||
"proxmoxTokenId": "Proxmox Token ID",
|
||||
"proxmoxTokenIdPlaceholder": "enzo@pam!panel",
|
||||
"proxmoxTokenSecret": "Token secret",
|
||||
"secretPlaceholder": "Leave empty to keep current value",
|
||||
"darkMode": "Dark mode",
|
||||
"sidebarPosition": "Sidebar position",
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@
|
|||
"sshSuccess": "Connexion SSH réussie !",
|
||||
"sshFailed": "Connexion SSH échouée",
|
||||
"proxmoxUrl": "URL Proxmox",
|
||||
"proxmoxToken": "Token API Proxmox",
|
||||
"proxmoxTokenHint": "Format : PVEAPIToken=user{'@'}realm!tokenid=secret",
|
||||
"proxmoxTokenId": "Token ID",
|
||||
"proxmoxTokenSecret": "Secret du token",
|
||||
"proxmoxTokenHint": "Token ID : enzo{'@'}pam!panel — Secret : uuid généré par Proxmox",
|
||||
"back": "Retour",
|
||||
"next": "Suivant",
|
||||
"finish": "Terminer l'installation",
|
||||
|
|
@ -115,7 +116,9 @@
|
|||
"sshUsername": "Utilisateur SSH",
|
||||
"sshPassword": "Mot de passe SSH",
|
||||
"proxmoxUrl": "URL Proxmox",
|
||||
"proxmoxToken": "Token API Proxmox",
|
||||
"proxmoxTokenId": "Token ID Proxmox",
|
||||
"proxmoxTokenIdPlaceholder": "enzo@pam!panel",
|
||||
"proxmoxTokenSecret": "Secret du token",
|
||||
"secretPlaceholder": "Laisser vide pour ne pas modifier",
|
||||
"darkMode": "Mode sombre",
|
||||
"sidebarPosition": "Position de la sidebar",
|
||||
|
|
|
|||
|
|
@ -98,8 +98,12 @@
|
|||
<input v-model="form.proxmoxUrl" class="neu-input" placeholder="https://10.0.0.1:8006" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ t('install.proxmoxToken') }}</label>
|
||||
<input v-model="form.proxmoxToken" class="neu-input" placeholder="PVEAPIToken=enzo@pam!panel=xxxx" />
|
||||
<label>{{ t('install.proxmoxTokenId') }}</label>
|
||||
<input v-model="form.proxmoxTokenId" class="neu-input" placeholder="enzo@pam!panel" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ t('install.proxmoxTokenSecret') }}</label>
|
||||
<input v-model="form.proxmoxTokenSecret" type="password" class="neu-input" placeholder="ed57ea62-cadc-4ddd-..." />
|
||||
<small>{{ t('install.proxmoxTokenHint') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -187,7 +191,8 @@ const form = ref({
|
|||
sshUsername: 'enzo',
|
||||
sshPassword: '',
|
||||
proxmoxUrl: 'https://10.0.0.1:8006',
|
||||
proxmoxToken: '',
|
||||
proxmoxTokenId: '',
|
||||
proxmoxTokenSecret: '',
|
||||
})
|
||||
|
||||
const canProceed = computed(() => {
|
||||
|
|
@ -264,7 +269,9 @@ async function finalize() {
|
|||
ssh_username: form.value.sshUsername,
|
||||
ssh_password: form.value.sshPassword,
|
||||
proxmox_url: form.value.proxmoxUrl,
|
||||
proxmox_token: form.value.proxmoxToken,
|
||||
proxmox_token: (form.value.proxmoxTokenId && form.value.proxmoxTokenSecret)
|
||||
? `PVEAPIToken=${form.value.proxmoxTokenId}=${form.value.proxmoxTokenSecret}`
|
||||
: '',
|
||||
}),
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -64,8 +64,12 @@
|
|||
<input v-model="settings.proxmox_url" class="neu-input" placeholder="https://10.0.0.1:8006" />
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>{{ t('settings.proxmoxToken') }}</label>
|
||||
<input v-model="secrets.proxmox_token" type="password" class="neu-input" :placeholder="t('settings.secretPlaceholder')" autocomplete="new-password" />
|
||||
<label>{{ t('settings.proxmoxTokenId') }}</label>
|
||||
<input v-model="secrets.proxmox_token_id" class="neu-input" :placeholder="t('settings.proxmoxTokenIdPlaceholder')" autocomplete="off" />
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label>{{ t('settings.proxmoxTokenSecret') }}</label>
|
||||
<input v-model="secrets.proxmox_token_secret" type="password" class="neu-input" :placeholder="t('settings.secretPlaceholder')" autocomplete="new-password" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -184,7 +188,8 @@ const settings = ref({
|
|||
// Champs sensibles — write-only, jamais retournés par l'API
|
||||
const secrets = ref({
|
||||
ssh_password: '',
|
||||
proxmox_token: '',
|
||||
proxmox_token_id: '',
|
||||
proxmox_token_secret: '',
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
|
|
@ -225,13 +230,22 @@ async function saveSettings() {
|
|||
saving.value = true
|
||||
saveSuccess.value = false
|
||||
|
||||
const allEntries: [string, string][] = [
|
||||
...Object.entries(settings.value),
|
||||
// Secrets : envoyés seulement si non-vides (le backend ignore les valeurs vides)
|
||||
...Object.entries(secrets.value).filter(([, v]) => v !== ''),
|
||||
]
|
||||
const entries: [string, string][] = [...Object.entries(settings.value)]
|
||||
|
||||
for (const [key, value] of allEntries) {
|
||||
// Mot de passe SSH — envoyé seulement si non-vide
|
||||
if (secrets.value.ssh_password) {
|
||||
entries.push(['ssh_password', secrets.value.ssh_password])
|
||||
}
|
||||
|
||||
// Token Proxmox — assemblé si les deux champs sont remplis
|
||||
if (secrets.value.proxmox_token_id && secrets.value.proxmox_token_secret) {
|
||||
entries.push([
|
||||
'proxmox_token',
|
||||
`PVEAPIToken=${secrets.value.proxmox_token_id}=${secrets.value.proxmox_token_secret}`,
|
||||
])
|
||||
}
|
||||
|
||||
for (const [key, value] of entries) {
|
||||
await fetch(`/api/settings/${key}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
|
|
@ -244,7 +258,8 @@ async function saveSettings() {
|
|||
|
||||
// Vider les champs secrets après sauvegarde
|
||||
secrets.value.ssh_password = ''
|
||||
secrets.value.proxmox_token = ''
|
||||
secrets.value.proxmox_token_id = ''
|
||||
secrets.value.proxmox_token_secret = ''
|
||||
|
||||
saving.value = false
|
||||
saveSuccess.value = true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue