From 55ca06ca3d34e23c1033b1019b473e1ab88bc857 Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 17 Jun 2026 14:25:40 +0200 Subject: [PATCH] fix(export): treat a missing export meta row as no export in the status GetUserDataExportStatus propagated the raw LoadFileMetaByID error when the meta row was gone, so /user/export could 500. The download path already maps that case to ErrUserDataExportDoesNotExist (404); make status consistent by returning nil (no export), matching the documented contract. --- pkg/models/export.go | 5 ++++ pkg/models/export_test.go | 53 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 pkg/models/export_test.go diff --git a/pkg/models/export.go b/pkg/models/export.go index 65d1f2fae..2d9b57651 100644 --- a/pkg/models/export.go +++ b/pkg/models/export.go @@ -438,6 +438,11 @@ func GetUserDataExportStatus(u *user.User) (*UserExportStatus, error) { exportFile := &files.File{ID: u.ExportFileID} if err := exportFile.LoadFileMetaByID(); err != nil { + // A missing meta row means there is no export — mirror the download path + // (404 there) instead of surfacing a 500. + if files.IsErrFileDoesNotExist(err) { + return nil, nil + } return nil, err } diff --git a/pkg/models/export_test.go b/pkg/models/export_test.go new file mode 100644 index 000000000..f2d0fa2fb --- /dev/null +++ b/pkg/models/export_test.go @@ -0,0 +1,53 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-present Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package models + +import ( + "testing" + + "code.vikunja.io/api/pkg/db" + "code.vikunja.io/api/pkg/user" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetUserDataExportStatus(t *testing.T) { + t.Run("no export", func(t *testing.T) { + db.LoadAndAssertFixtures(t) + status, err := GetUserDataExportStatus(&user.User{ID: 15}) + require.NoError(t, err) + assert.Nil(t, status) + }) + + t.Run("with export", func(t *testing.T) { + db.LoadAndAssertFixtures(t) + status, err := GetUserDataExportStatus(&user.User{ID: 1, ExportFileID: 1}) + require.NoError(t, err) + require.NotNil(t, status) + assert.Equal(t, int64(1), status.ID) + }) + + t.Run("export points at a missing file", func(t *testing.T) { + db.LoadAndAssertFixtures(t) + // A dangling ExportFileID must read as "no export" rather than erroring, + // matching the download path which 404s the same case. + status, err := GetUserDataExportStatus(&user.User{ID: 15, ExportFileID: 9999}) + require.NoError(t, err) + assert.Nil(t, status) + }) +}