diff --git a/dashboard/src/components/AppImportDialog.vue b/dashboard/src/components/AppImportDialog.vue index 9a4cb55b8..f32fb2593 100644 --- a/dashboard/src/components/AppImportDialog.vue +++ b/dashboard/src/components/AppImportDialog.vue @@ -2,7 +2,7 @@ import { ref, useTemplateRef } from 'vue'; import { Dialog, FormGroup, TextInput, PasswordInput, Checkbox } from '@cloudron/pankow'; -import { s3like } from '../utils.js'; +import { s3like, mountlike } from '../utils.js'; import BackupProviderForm from './BackupProviderForm.vue'; import AppsModel from '../models/AppsModel.js'; import { REGIONS_CONTABO, REGIONS_VULTR, REGIONS_IONOS, REGIONS_OVH, REGIONS_LINODE, REGIONS_SCALEWAY, REGIONS_WASABI } from '../constants.js'; @@ -31,80 +31,102 @@ async function onSubmit() { busy.value = true; let backupPath = remotePath.value; - const backupConfig = {}; + const config = {}; // only set provider specific fields, this will clear them in the db if (s3like(provider.value)) { - backupConfig.bucket = providerConfig.value.bucket; - backupConfig.prefix = providerConfig.value.prefix; - backupConfig.accessKeyId = providerConfig.value.accessKeyId; - backupConfig.secretAccessKey = providerConfig.value.secretAccessKey; + config.bucket = providerConfig.value.bucket; + config.prefix = providerConfig.value.prefix; + config.accessKeyId = providerConfig.value.accessKeyId; + config.secretAccessKey = providerConfig.value.secretAccessKey; - if (providerConfig.value.endpoint) backupConfig.endpoint = providerConfig.value.endpoint; + if (providerConfig.value.endpoint) config.endpoint = providerConfig.value.endpoint; if (provider.value === 's3') { - if (providerConfig.value.region) backupConfig.region = providerConfig.value.region; - delete backupConfig.endpoint; + if (providerConfig.value.region) config.region = providerConfig.value.region; + delete config.endpoint; } else if (provider.value === 'minio' || provider.value === 's3-v4-compat') { - backupConfig.region = providerConfig.value.region || 'us-east-1'; - backupConfig.acceptSelfSignedCerts = !!providerConfig.value.acceptSelfSignedCerts; - backupConfig.s3ForcePathStyle = true; // might want to expose this in the UI + config.region = providerConfig.value.region || 'us-east-1'; + config.acceptSelfSignedCerts = !!providerConfig.value.acceptSelfSignedCerts; + config.s3ForcePathStyle = true; // might want to expose this in the UI } else if (provider.value === 'exoscale-sos') { - backupConfig.region = 'us-east-1'; - backupConfig.signatureVersion = 'v4'; + config.region = 'us-east-1'; + config.signatureVersion = 'v4'; } else if (provider.value === 'wasabi') { - backupConfig.region = REGIONS_WASABI.find(function (x) { return x.value === backupConfig.endpoint; }).region; - backupConfig.signatureVersion = 'v4'; + config.region = REGIONS_WASABI.find(function (x) { return x.value === config.endpoint; }).region; + config.signatureVersion = 'v4'; } else if (provider.value === 'scaleway-objectstorage') { - backupConfig.region = REGIONS_SCALEWAY.find(function (x) { return x.value === backupConfig.endpoint; }).region; - backupConfig.signatureVersion = 'v4'; + config.region = REGIONS_SCALEWAY.find(function (x) { return x.value === config.endpoint; }).region; + config.signatureVersion = 'v4'; } else if (provider.value === 'linode-objectstorage') { - backupConfig.region = REGIONS_LINODE.find(function (x) { return x.value === backupConfig.endpoint; }).region; - backupConfig.signatureVersion = 'v4'; + config.region = REGIONS_LINODE.find(function (x) { return x.value === config.endpoint; }).region; + config.signatureVersion = 'v4'; } else if (provider.value === 'ovh-objectstorage') { - backupConfig.region = REGIONS_OVH.find(function (x) { return x.value === backupConfig.endpoint; }).region; - backupConfig.signatureVersion = 'v4'; + config.region = REGIONS_OVH.find(function (x) { return x.value === config.endpoint; }).region; + config.signatureVersion = 'v4'; } else if (provider.value === 'ionos-objectstorage') { - backupConfig.region = REGIONS_IONOS.find(function (x) { return x.value === backupConfig.endpoint; }).region; - backupConfig.signatureVersion = 'v4'; + config.region = REGIONS_IONOS.find(function (x) { return x.value === config.endpoint; }).region; + config.signatureVersion = 'v4'; } else if (provider.value === 'vultr-objectstorage') { - backupConfig.region = REGIONS_VULTR.find(function (x) { return x.value === backupConfig.endpoint; }).region; - backupConfig.signatureVersion = 'v4'; + config.region = REGIONS_VULTR.find(function (x) { return x.value === config.endpoint; }).region; + config.signatureVersion = 'v4'; } else if (provider.value === 'contabo-objectstorage') { - backupConfig.region = REGIONS_CONTABO.find(function (x) { return x.value === backupConfig.endpoint; }).region; - backupConfig.signatureVersion = 'v4'; - backupConfig.s3ForcePathStyle = true; // https://docs.contabo.com/docs/products/Object-Storage/technical-description (no virtual buckets) + config.region = REGIONS_CONTABO.find(function (x) { return x.value === config.endpoint; }).region; + config.signatureVersion = 'v4'; + config.s3ForcePathStyle = true; // https://docs.contabo.com/docs/products/Object-Storage/technical-description (no virtual buckets) } else if (provider.value === 'upcloud-objectstorage') { const m = /^.*\.(.*)\.upcloudobjects.com$/.exec(providerConfig.value.endpoint); - backupConfig.region = m ? m[1] : 'us-east-1'; // let it fail in validation phase if m is not valid - backupConfig.signatureVersion = 'v4'; + config.region = m ? m[1] : 'us-east-1'; // let it fail in validation phase if m is not valid + config.signatureVersion = 'v4'; } else if (provider.value === 'digitalocean-spaces') { - backupConfig.region = 'us-east-1'; + config.region = 'us-east-1'; } else if (provider.value === 'hetzner-objectstorage') { - backupConfig.region = 'us-east-1'; - backupConfig.signatureVersion = 'v4'; + config.region = 'us-east-1'; + config.signatureVersion = 'v4'; + } + } else if (mountlike(provider.value)) { + config.prefix = providerConfig.value.prefix; + config.noHardlinks = !providerConfig.value.useHardlinks; + config.mountOptions = {}; + + if (provider.value === 'sshfs' || provider.value === 'cifs' || provider.value === 'nfs') { + config.mountOptions.host = providerConfig.value.mountOptionHost; + config.mountOptions.remoteDir = providerConfig.value.mountOptionRemoteDir; + + if (provider.value === 'cifs') { + config.mountOptions.username = providerConfig.value.mountOptionUsername; + config.mountOptions.password = providerConfig.value.mountOptionPassword; + config.mountOptions.seal = !!providerConfig.value.mountOptionSeal; + config.preserveAttributes = !!providerConfig.value.preserveAttributes; + } else if (provider.value === 'sshfs') { + config.mountOptions.user = providerConfig.value.mountOptionUser; + config.mountOptions.port = parseInt(providerConfig.value.mountOptionPort); + config.mountOptions.privateKey = providerConfig.value.mountOptionPrivateKey; + config.preserveAttributes = true; + } + } else if (provider.value === 'ext4' || provider.value === 'xfs') { + config.mountOptions.diskPath = providerConfig.value.mountOptionDiskPath; + config.preserveAttributes = true; + } else if (provider.value === 'mountpoint') { + config.mountPoint = providerConfig.value.mountPoint; + config.chown = !!providerConfig.value.chown; + config.preserveAttributes = !!providerConfig.value.preserveAttributes; } - } else if (provider.value === 'gcs') { - backupConfig.bucket = providerConfig.value.bucket; - backupConfig.prefix = providerConfig.value.prefix; - backupConfig.projectId = providerConfig.value.projectId; - backupConfig.credentials = providerConfig.value.credentials; - } else if (provider.value === 'sshfs' || provider.value === 'cifs' || provider.value === 'nfs' || provider.value === 'ext4' || provider.value === 'xfs') { - backupConfig.mountOptions = providerConfig.value.mountOptions; - backupConfig.prefix = providerConfig.value.prefix; - } else if (provider.value === 'mountpoint') { - backupConfig.prefix = providerConfig.value.prefix; - backupConfig.mountPoint = providerConfig.value.mountPoint; } else if (provider.value === 'filesystem') { const parts = remotePath.value.split('/'); backupPath = parts.pop() || parts.pop(); // removes any trailing slash. this is basename() - backupConfig.backupDir = parts.join('/'); // this is dirname() + config.backupDir = parts.join('/'); // this is dirname() + } else if (provider.value === 'gcs') { + config.bucket = providerConfig.value.bucket; + config.prefix = providerConfig.value.prefix; + config.projectId = providerConfig.value.projectId; + config.credentials = providerConfig.value.credentials; } const data = { format: format.value, provider: provider.value, - config: backupConfig, + config: config, remotePath: backupPath }; @@ -176,12 +198,27 @@ function onBackupConfigChanged(event) { provider.value = data.provider; remotePath.value = data.remotePath; - providerConfig.value = data.config; format.value = data.format; encrypted.value = !!data.encrypted; encryptionPasswordHint.value = data.encryptionPasswordHint || ''; encryptionPassword.value = ''; encryptedFilenames.value = data.encryptedFilenames; + + // translate for BackupProviderForm flattened object + providerConfig.value = {}; + providerConfig.value.useHardlinks = !data.config.noHardlinks; + providerConfig.value.prefix = data.config.prefix; + providerConfig.value.chown = !!data.config.chown; + providerConfig.value.preserveAttributes = data.config.preserveAttributes; + providerConfig.value.mountOptionHost = data.config.mountOptions.host; + providerConfig.value.mountOptionPort = data.config.mountOptions.port; + providerConfig.value.mountOptionRemoteDir = data.config.mountOptions.remoteDir; + providerConfig.value.mountOptionSeal = !!data.config.mountOptions.seal; + providerConfig.value.mountOptionDiskPath = data.config.mountOptions.diskPath; + providerConfig.value.mountOptionUser = data.config.mountOptions.user; + providerConfig.value.mountOptionUsername = data.config.mountOptions.username; + providerConfig.value.mountOptionPassword = data.config.mountOptions.password; + providerConfig.value.mountOptionPrivateKey = ''; }; reader.readAsText(event.target.files[0]); diff --git a/dashboard/src/views/RestoreView.vue b/dashboard/src/views/RestoreView.vue index 0060c8c33..901093cdd 100644 --- a/dashboard/src/views/RestoreView.vue +++ b/dashboard/src/views/RestoreView.vue @@ -191,7 +191,7 @@ async function onSubmit() { config.noHardlinks = !providerConfig.value.useHardlinks; config.mountOptions = {}; - if (provider.value === 'cifs' || provider.value === 'sshfs' || provider.value === 'nfs') { + if (provider.value === 'sshfs' || provider.value === 'cifs' || provider.value === 'nfs') { config.mountOptions.host = providerConfig.value.mountOptionHost; config.mountOptions.remoteDir = providerConfig.value.mountOptionRemoteDir;