From 7c08a10621cb9eb08b7c60ad666f41ebb8047632 Mon Sep 17 00:00:00 2001 From: Dillard Blom Date: Thu, 8 Oct 2026 00:40:48 +0200 Subject: [PATCH 1/8] Locations: ask for password confirmation before adding addTarget requires a recent password confirmation, but the form never asked for one. Within 30 minutes of logging in that went unnoticed; after that, adding a location failed with a bare 403. --- CHANGELOG.md | 6 ++++++ src/components/Locations.vue | 1 + 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8e3938..d6af94c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ the app store accepts a `-beta` suffix, but Nextcloud servers then only offer th beta/daily update channel, which would hide the app from most admins. The stability stage is instead carried by the app description, the git tag, the release, and this file. +## [Unreleased] + +### Fixed +- Adding a backup location in the web interface failed with "Request failed with status code 403" + when the login was more than 30 minutes old: the form did not ask for password confirmation. + ## [0.9.1-beta.2] - 2026-10-07 Second beta, the first release in the Nextcloud app store (signed). diff --git a/src/components/Locations.vue b/src/components/Locations.vue index 1b23cf3..2131c7c 100644 --- a/src/components/Locations.vue +++ b/src/components/Locations.vue @@ -104,6 +104,7 @@ async function add() { busy.value = true error.value = '' try { + await confirmPassword() await api.addTarget({ name: form.name, backend: backend.value.id, auth: auth.value.id, options: form.options, path: form.path, maxGb: form.maxGb === '' ? null : Number(form.maxGb) }) adding.value = false From 972a52e66596cbc73d2d425433ddef6e403d2e24 Mon Sep 17 00:00:00 2001 From: Dillard Blom Date: Wed, 7 Oct 2026 23:56:28 +0200 Subject: [PATCH 2/8] Settings: align the tabs with the sections The tabs had no inline margin, so they sat against the edge while every NcSettingsSection is inset by 7 grid baselines. --- CHANGELOG.md | 2 ++ src/AdminSettings.vue | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6af94c..4bad4d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ instead carried by the app description, the git tag, the release, and this file. ### Fixed - Adding a backup location in the web interface failed with "Request failed with status code 403" when the login was more than 30 minutes old: the form did not ask for password confirmation. +- Settings page: the "Backup and restore" / "Settings" tabs line up with the sections below them. +- Backups: the runs table scrolls horizontally on narrow screens instead of running off the page. ## [0.9.1-beta.2] - 2026-10-07 diff --git a/src/AdminSettings.vue b/src/AdminSettings.vue index 9f0b458..c66dcf7 100644 --- a/src/AdminSettings.vue +++ b/src/AdminSettings.vue @@ -82,6 +82,7 @@ onBeforeUnmount(() => clearTimeout(timer)) .ngb-tabs { display: flex; gap: 8px; - margin: 0 0 12px; + /* Same inline margin as NcSettingsSection, so the tabs line up with the section content */ + margin: 0 calc(var(--default-grid-baseline) * 7) 12px; } From 695d972785ab6e14a78a08d16bf9bbd9ea1a74e0 Mon Sep 17 00:00:00 2001 From: Dillard Blom Date: Wed, 7 Oct 2026 23:56:28 +0200 Subject: [PATCH 3/8] Backups: let the runs table scroll on narrow screens The table could not shrink below its content width and ran off the page, cutting off the last columns; wrap it in an overflow-x container. --- src/components/Backups.vue | 51 ++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/components/Backups.vue b/src/components/Backups.vue index 9baf14f..3a09a28 100644 --- a/src/components/Backups.vue +++ b/src/components/Backups.vue @@ -30,30 +30,32 @@ - - - - - - - - - - - - - - - - - - - - - - - -
{{ t('ng_backup', 'Started') }}{{ t('ng_backup', 'Location') }}{{ t('ng_backup', 'Kind') }}{{ t('ng_backup', 'Restore point') }}{{ t('ng_backup', 'Status') }}{{ t('ng_backup', 'Files') }}{{ t('ng_backup', 'Uploaded') }}
{{ new Date(run.startedAt * 1000).toLocaleString() }}{{ targetName(run.targetId) }}{{ run.kind }}{{ run.snapshot ? new Date(run.snapshot.createdAt * 1000).toLocaleString() + (run.snapshot.label ? ' – ' + run.snapshot.label : '') : '' }}{{ run.status }}{{ run.status === 'running' ? ' (' + run.phase + ')' : '' }}{{ run.error ? ': ' + run.error : '' }}{{ run.stats?.files?.files ?? run.stats?.restored ?? '' }}{{ run.stats?.files ? formatSize(run.stats.files.uploaded) : '' }}
+
+ + + + + + + + + + + + + + + + + + + + + + + +
{{ t('ng_backup', 'Started') }}{{ t('ng_backup', 'Location') }}{{ t('ng_backup', 'Kind') }}{{ t('ng_backup', 'Restore point') }}{{ t('ng_backup', 'Status') }}{{ t('ng_backup', 'Files') }}{{ t('ng_backup', 'Uploaded') }}
{{ new Date(run.startedAt * 1000).toLocaleString() }}{{ targetName(run.targetId) }}{{ run.kind }}{{ run.snapshot ? new Date(run.snapshot.createdAt * 1000).toLocaleString() + (run.snapshot.label ? ' – ' + run.snapshot.label : '') : '' }}{{ run.status }}{{ run.status === 'running' ? ' (' + run.phase + ')' : '' }}{{ run.error ? ': ' + run.error : '' }}{{ run.stats?.files?.files ?? run.stats?.restored ?? '' }}{{ run.stats?.files ? formatSize(run.stats.files.uploaded) : '' }}
+
@@ -126,6 +128,7 @@ async function saveSchedule() {