diff --git a/dashboard/src/components/app/Backups.vue b/dashboard/src/components/app/Backups.vue index 5c0bca28e..723618ca7 100644 --- a/dashboard/src/components/app/Backups.vue +++ b/dashboard/src/components/app/Backups.vue @@ -7,9 +7,13 @@ const t = i18n.t; import { ref, watch, onMounted, useTemplateRef } from 'vue'; import { Icon, Button, Switch, Checkbox, FormGroup, TextInput, TableView, ButtonGroup, Dialog } from 'pankow'; import { prettyLongDate } from 'pankow/utils'; +import { SECRET_PLACEHOLDER } from '../../constants.js'; +import { download } from '../../utils.js'; import AppsModel from '../../models/AppsModel.js'; +import BackupsModel from '../../models/BackupsModel.js'; const appsModel = AppsModel.create(); +const backupsModel = BackupsModel.create(); const props = defineProps([ 'app' ]); @@ -88,6 +92,32 @@ function getDownloadLink(backup) { return `${origin}/api/v1/apps/${props.app.id}/backups/${backup.id}/download?access_token=${accessToken}`; } +async function onDownloadConfig(backup) { + const [error, backupConfig] = await backupsModel.getConfig(); + if (error) return console.error(error); + + // secrets and tokens already come with placeholder characters we remove them + const tmp = { + remotePath: backup.remotePath, + encrypted: !!backupConfig.password // we add this just to help the import UI + }; + + Object.keys(backupConfig).forEach(k => { + const v = backupConfig[k]; + if (v && typeof v === 'object') { // to hide mountOptions.password and the likes + tmp[k] = {}; + Object.keys(v).forEach(function (j) { + if (v[j] !== SECRET_PLACEHOLDER) tmp[k][j] = v[j]; + }); + } else { + if (backupConfig[k] !== SECRET_PLACEHOLDER) tmp[k] = v; + } + }); + + const filename = `${props.app.fqdn}-backup-config-${(new Date(backup.creationTime)).toISOString().split('T')[0]}.json`; + download(filename, JSON.stringify(tmp, null, 4)); +} + async function refresh() { const [error, result] = await appsModel.backups(props.app.id); if (error) return console.error(error);