mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-07-16 14:52:35 -05:00
iOS Reminders (and other RFC 6578 clients) never learned about tasks deleted on the Vikunja side: caldav-go answers unknown REPORT types with 412, which makes iOS silently stop syncing, and deleted tasks left no protocol-level trace a client could observe. Intercept sync-collection REPORTs before caldav-go sees them and answer per RFC 6578: tasks changed since the sync token as 200 entries and deleted tasks as 404 entries. Deletion records come from task soft-deletes, which are kept for 30 days before being purged. Token edge cases: delta comparisons are inclusive because tokens have second granularity (re-reported items keep their etag, so clients skip the download), and tokens older than the soft-delete retention answer 403 + valid-sync-token to force a full resync instead of a delta that would silently miss purged deletions.
52 lines
1.9 KiB
Go
52 lines
1.9 KiB
Go
// 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 <https://www.gnu.org/licenses/>.
|
|
|
|
package models
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"code.vikunja.io/api/pkg/db"
|
|
"code.vikunja.io/api/pkg/files"
|
|
)
|
|
|
|
func TestDeleteExpiredTasks(t *testing.T) {
|
|
// Task 51 was soft-deleted at this time in the fixtures
|
|
deletedAt := time.Date(2018, 12, 1, 1, 12, 4, 0, time.UTC)
|
|
|
|
t.Run("older than the retention period", func(t *testing.T) {
|
|
db.LoadAndAssertFixtures(t)
|
|
files.InitTestFileFixtures(t)
|
|
|
|
deleteExpiredTasks(deletedAt.Add(TaskDeleteRetention + 24*time.Hour))
|
|
|
|
db.AssertMissing(t, "tasks", map[string]interface{}{"id": 51})
|
|
db.AssertMissing(t, "task_reminders", map[string]interface{}{"task_id": 51})
|
|
db.AssertMissing(t, "label_tasks", map[string]interface{}{"task_id": 51})
|
|
db.AssertMissing(t, "subscriptions", map[string]interface{}{"entity_id": 51, "entity_type": SubscriptionEntityTask})
|
|
})
|
|
|
|
t.Run("newer than the retention period", func(t *testing.T) {
|
|
db.LoadAndAssertFixtures(t)
|
|
|
|
deleteExpiredTasks(deletedAt.Add(TaskDeleteRetention - 24*time.Hour))
|
|
|
|
db.AssertExists(t, "tasks", map[string]interface{}{"id": 51}, false)
|
|
db.AssertExists(t, "task_reminders", map[string]interface{}{"task_id": 51}, false)
|
|
})
|
|
}
|