Allow add/edit domains for most providers

This commit is contained in:
Johannes Zellner
2025-01-29 16:29:21 +01:00
parent 60140087a5
commit d12e8cbe97
3 changed files with 219 additions and 50 deletions

View File

@@ -1,8 +1,15 @@
<script setup>
const API_ORIGIN = import.meta.env.VITE_API_ORIGIN ? import.meta.env.VITE_API_ORIGIN : window.location.origin;
import { ref, useTemplateRef } from 'vue';
import { Dialog, TextInput, FormGroup, Checkbox } from 'pankow';
import { ENDPOINTS_OVH } from '../constants.js';
import DomainsModel from '../models/DomainsModel.js';
const emit = defineEmits([ 'success' ]);
const domainsModel = DomainsModel.create(API_ORIGIN, localStorage.token);
// currently, validation of wildcard with various provider is done server side
const tlsProviders = [
@@ -41,7 +48,7 @@ const domainProviders = [
const dialog = useTemplateRef('dialog');
const busy = ref(false);
const error = ref('');
const errorMessage = ref('');
const editing = ref(false);
const domain = ref('');
const zoneName = ref('');
@@ -52,7 +59,7 @@ const showAdvanced = ref(false);
const accessKeyId = ref('');
const secretAccessKey = ref('');
const digitalOceanToken = ref('');
const gandiTokenType = ref('');
const gandiTokenType = ref('ApiKey');
const gandiApiKey = ref('');
const godaddyApiKey = ref('');
const godaddyApiSecret = ref('');
@@ -103,58 +110,166 @@ function checkValidity() {
}
const form = useTemplateRef('form');
function onSubmit() {
async function onSubmit() {
if (!form.value.reportValidity()) return;
console.log('all good?')
busy.value = true;
errorMessage.value = '';
const config = {};
if (provider.value === 'route53') {
config.accessKeyId = accessKeyId.value;
config.secretAccessKey = secretAccessKey.value;
} else if (provider.value === 'gcdns') {
// TODO
// try {
// var serviceAccountKey = JSON.parse($scope.domainConfigure.gcdnsKey.content);
// config.projectId = serviceAccountKey.project_id;
// config.credentials = {
// client_email: serviceAccountKey.client_email,
// private_key: serviceAccountKey.private_key
// };
// if (!config.projectId || !config.credentials || !config.credentials.client_email || !config.credentials.private_key) {
// throw new Error('One or more fields are missing in the JSON');
// }
// } catch (e) {
// $scope.domainConfigure.error = 'Cannot parse Google Service Account Key: ' + e.message;
// $scope.domainConfigure.busy = false;
// return;
// }
} else if (provider.value === 'digitalocean') {
config.token = digitalOceanToken.value;
} else if (provider.value === 'linode') {
config.token = linodeToken.value;
} else if (provider.value === 'bunny') {
config.accessKey = bunnyAccessKey.value;
} else if (provider.value === 'dnsimple') {
config.accessToken = dnsimpleAccessToken.value;
} else if (provider.value === 'hetzner') {
config.token = hetznerToken.value;
} else if (provider.value === 'vultr') {
config.token = vultrToken.value;
} else if (provider.value === 'desec') {
config.token = deSecToken.value;
} else if (provider.value === 'gandi') {
config.token = gandiApiKey.value;
config.tokenType = gandiTokenType.value;
} else if (provider.value === 'godaddy') {
config.apiKey = godaddyApiKey.value;
config.apiSecret = godaddyApiSecret.value;
} else if (provider.value === 'cloudflare') {
config.token = cloudflareToken.value;
config.email = cloudflareEmail.value;
config.tokenType = cloudflareTokenType.value;
config.defaultProxyStatus = cloudflareDefaultProxyStatus.value;
} else if (provider.value === 'namecom') {
config.token = nameComToken.value;
config.username = nameComUsername.value;
} else if (provider.value === 'namecheap') {
config.token = namecheapApiKey.value;
config.username = namecheapUsername.value;
} else if (provider.value === 'inwx') {
config.username = inwxUsername.value;
config.password = inwxPassword.value;
} else if (provider.value === 'netcup') {
config.customerNumber = netcupCustomerNumber.value;
config.apiKey = netcupApiKey.value;
config.apiPassword = netcupApiPassword.value;
} else if (provider.value === 'ovh') {
config.endpoint = ovhEndpoint.value;
config.consumerKey = ovhConsumerKey.value;
config.appKey = ovhAppKey.value;
config.appSecret = ovhAppSecret.value;
} else if (provider.value === 'porkbun') {
config.apikey = porkbunApikey.value;
config.secretapikey = porkbunSecretapikey.value;
}
const tlsConfig = {
provider: tlsProvider.value,
wildcard: false
};
// UI uses -wildcard providers, API uses wildcard flag
if (tlsConfig.provider.indexOf('-wildcard') !== -1) {
tlsConfig.provider = tlsConfig.provider.replace('-wildcard', '');
tlsConfig.wildcard = true;
}
const func = editing.value ? domainsModel.update : domainsModel.add;
const [error] = await func(domain.value, zoneName.value, provider.value, config, null, tlsConfig);
if (error) {
errorMessage.value = error.body ? error.body.message : 'Internal error';
busy.value = false;
return console.error(error);
}
emit('success');
dialog.value.close();
busy.value = false;
}
defineExpose({
open(d) {
console.log(d);
d = d || {};
d = d || { config: {}, tlsConfig: {}};
busy.value = false;
error.value = '';
showAdvanced.value = false;
errorMessage.value = '';
editing.value = !!d.domain;
domain.value = d.domain || '';
zoneName.value = d.zoneName || '';
provider.value = d.provider || '';
tlsProvider.value = d.tlsProvider || 'letsencrypt-prod-wildcard';
tlsProvider.value = d.tlsConfig.provider || 'letsencrypt-prod-wildcard';
accessKeyId.value = d.accessKeyId || '';
secretAccessKey.value = d.secretAccessKey || '';
digitalOceanToken.value = d.digitalOceanToken || '';
gandiTokenType.value = d.gandiTokenType || '';
gandiApiKey.value = d.gandiApiKey || '';
godaddyApiKey.value = d.godaddyApiKey || '';
godaddyApiSecret.value = d.godaddyApiSecret || '';
netcupCustomerNumber.value = d.netcupCustomerNumber || '';
netcupApiKey.value = d.netcupApiKey || '';
netcupApiPassword.value = d.netcupApiPassword || '';
ovhEndpoint.value = d.ovhEndpoint || '';
ovhConsumerKey.value = d.ovhConsumerKey || '';
ovhAppKey.value = d.ovhAppKey || '';
ovhAppSecret.value = d.ovhAppSecret || '';
porkbunSecretapikey.value = d.porkbunSecretapikey || '';
porkbunApikey.value = d.porkbunApikey || '';
cloudflareTokenType.value = d.cloudflareTokenType || 'ApiToken';
cloudflareToken.value = d.cloudflareToken || '';
cloudflareEmail.value = d.cloudflareEmail || '';
cloudflareDefaultProxyStatus.value = d.cloudflareDefaultProxyStatus || false;
linodeToken.value = d.linodeToken || '';
bunnyAccessKey.value = d.bunnyAccessKey || '';
dnsimpleAccessToken.value = d.dnsimpleAccessToken || '';
hetznerToken.value = d.hetznerToken || '';
vultrToken.value = d.vultrToken || '';
deSecToken.value = d.deSecToken || '';
nameComUsername.value = d.nameComUsername || '';
nameComToken.value = d.nameComToken || '';
namecheapUsername.value = d.namecheapUsername || '';
namecheapApiKey.value = d.namecheapApiKey || '';
inwxUsername.value = d.inwxUsername || '';
inwxPassword.value = d.inwxPassword || '';
// TODO
// $scope.domainConfigure.gcdnsKey.keyFileName = '';
// $scope.domainConfigure.gcdnsKey.content = '';
// if (domain.provider === 'gcdns') {
// $scope.domainConfigure.gcdnsKey.keyFileName = domain.config.credentials && domain.config.credentials.client_email;
// $scope.domainConfigure.gcdnsKey.content = JSON.stringify({
// project_id: domain.config.projectId,
// client_email: domain.config.credentials.client_email,
// private_key: domain.config.credentials.private_key
// });
// }
accessKeyId.value = (d.provider === 'route53' && d.config.accessKeyId) || '';
secretAccessKey.value = (d.provider === 'route53' && d.config.secretAccessKey) || '';
digitalOceanToken.value = (d.provider === 'digitalocean' && d.config.token) || '';
gandiTokenType.value = (d.provider === 'gandi' && d.config.tokenType) || 'ApiKey';
gandiApiKey.value = (d.provider === 'gandi' && d.config.token) || '';
godaddyApiKey.value = (d.provider === 'godaddy' && d.config.apiKey) || '';
godaddyApiSecret.value = (d.provider === 'godaddy' && d.config.apiSecret) || '';
netcupCustomerNumber.value = (d.provider === 'netcup' && d.config.customerNumber) || '';
netcupApiKey.value = (d.provider === 'netcup' && d.config.apiKey) || '';
netcupApiPassword.value = (d.provider === 'netcup' && d.config.apiPassword) || '';
ovhEndpoint.value = (d.provider === 'ovh' && d.config.endpoint) || '';
ovhConsumerKey.value = (d.provider === 'ovh' && d.config.consumerKey) || '';
ovhAppKey.value = (d.provider === 'ovh' && d.config.appKey) || '';
ovhAppSecret.value = (d.provider === 'ovh' && d.config.appSecret) || '';
porkbunSecretapikey.value = (d.provider === 'porkbun' && d.config.secretapikey) || '';
porkbunApikey.value = (d.provider === 'porkbun' && d.config.apikey) || '';
cloudflareTokenType.value = (d.provider === 'cloudflare' && d.config.tokenType) || 'ApiToken';
cloudflareToken.value = (d.provider === 'cloudflare' && d.config.token) || '';
cloudflareEmail.value = (d.provider === 'cloudflare' && d.config.email) || '';
cloudflareDefaultProxyStatus.value = d.provider === 'cloudflare' ? d.config.defaultProxyStatus : false;
linodeToken.value = (d.provider === 'linode' && d.config.token) || '';
bunnyAccessKey.value = (d.provider === 'bunny' && d.config.accessKey) || '';
dnsimpleAccessToken.value = (d.provider === 'dnsimple' && d.config.accessToken) || '';
hetznerToken.value = (d.provider === 'hetzner' && d.config.token) || '';
vultrToken.value = (d.provider === 'vultr' && d.config.token) || '';
deSecToken.value = (d.provider === 'desec' && d.config.token) || '';
nameComUsername.value = (d.provider === 'namecom' && d.config.username) || '';
nameComToken.value = (d.provider === 'namecom' && d.config.token) || '';
namecheapUsername.value = (d.provider === 'namecheap' && d.config.username) || '';
namecheapApiKey.value = (d.provider === 'namecheap' && d.config.token) || '';
inwxUsername.value = (d.provider === 'inwx' && d.config.username) || '';
inwxPassword.value = (d.provider === 'inwx' && d.config.password) || '';
dialog.value.open();
}
@@ -165,23 +280,25 @@ defineExpose({
<template>
<Dialog ref="dialog"
:title="editing ? $t('domains.domainDialog.editTitle', { domain: domain }) : $t('domains.domainDialog.addTitle')"
:confirm-loading="busy"
:modal="busy"
:confirm-busy="busy"
:confirm-active="isFormValid"
:confirm-label="$t('main.dialog.save')"
:reject-label="$t('main.dialog.cancel')"
:reject-label="busy ? null : $t('main.dialog.cancel')"
:reject-active="!busy"
reject-style="secondary"
@confirm="onSubmit()"
>
<p v-show="!editing" v-html="$t('domains.domainDialog.addDescription')"></p>
<p class="text-danger" v-show="errorMessage">{{ errorMessage }}</p>
<form ref="form" @submit.prevent="onSubmit()" autocomplete="off" @input="checkValidity()">
<fieldset>
<fieldset :disabled="busy">
<input style="display: none;" type="submit" :disabled="busy"/>
<p class="has-error text-center" v-show="error">{{ error }}</p>
<FormGroup>
<label for="domainInput">{{ $t('domains.domainDialog.domain') }}</label>
<TextInput id="domainInput" v-model="domain" placeholder="example.com" required />
<TextInput id="domainInput" v-model="domain" placeholder="example.com" :readonly="editing ? true : undefined" required />
</FormGroup>
<FormGroup>