Commit Graph

2183 Commits

Author SHA1 Message Date
kolaente 88b534776a fix(kanban): skip upsert when repeating task already in default bucket (#2573)
When a repeating task dropped on the done bucket is already in the
view's default bucket, the upsert would try to UPDATE with an
unchanged bucket_id. MySQL reports 0 affected rows for unchanged
updates, so upsert fell through to INSERT and hit the unique
constraint on (task_id, project_view_id).
2026-04-09 10:45:34 +00:00
kolaente 1e784aa194 fix(tasks): route repeating tasks to default bucket when marked done (#2573) 2026-04-09 10:45:34 +00:00
kolaente 007379cff1 refactor(tasks): add moveTaskToDefaultBuckets helper (#2573) 2026-04-09 10:45:34 +00:00
kolaente 9a8126c111 test(tasks): add failing test for repeating task bucket routing via Task.Update (#2573) 2026-04-09 10:45:34 +00:00
kolaente 3d7bab4497 fix(kanban): route repeating tasks to default bucket when dropped on done (#2573) 2026-04-09 10:45:34 +00:00
kolaente e37b54abca test(kanban): add failing test for repeating task bucket routing on done (#2573) 2026-04-09 10:45:34 +00:00
kolaente 457ffbfe51 test(webhook): assert bad webhook is retried in no-duplicate test
Adds a hit counter to the bad webhook and asserts it is attempted at
least 3 times, proving the watermill retry middleware actually fires
on a failing delivery. We use GreaterOrEqual rather than an exact
count because gochannel resends nacked messages, so a permanently
failing delivery keeps running through retry cycles until the test
times out its wait window.
2026-04-09 09:26:04 +00:00
kolaente ca7f82a5e5 fix(webhook): order matching webhooks by id for deterministic fan-out
Previously WebhookListener.Handle fetched matching webhooks with
Find(&ws) without an explicit ORDER BY, so iteration order depended on
the DB driver. Add ORDER BY id ASC so the fan-out order is stable for
both project- and user-level webhooks, and update the sibling-blocking
regression test to insert webhooks with explicit ids so its ordering
assumption is robust to autoincrement state.
2026-04-09 09:26:04 +00:00
kolaente 85a3b3e469 fix(webhook): return error from delivery listener on nil payload
A nil payload signals data corruption or a version mismatch on the
event bus, not a safe-to-drop condition. Returning an error lets the
watermill retry middleware retry the message and eventually park it in
the poison queue instead of silently acking it.
2026-04-09 09:26:04 +00:00
kolaente bf87796669 test(webhook): handle deleted webhook gracefully between fan-out and delivery 2026-04-09 09:26:04 +00:00
kolaente 2a816f5db5 test(webhook): assert flaky webhook is retried until it succeeds 2026-04-09 09:26:04 +00:00
kolaente b09f50c6e2 test(webhook): assert good webhook delivered once despite sibling retries 2026-04-09 09:26:04 +00:00
kolaente bef58079d7 fix(webhook): dispatch one delivery event per webhook (#2569) 2026-04-09 09:26:04 +00:00
kolaente e5726239d4 feat(webhook): register WebhookDeliveryListener on startup 2026-04-09 09:26:04 +00:00
kolaente eef985011b feat(webhook): add WebhookDeliveryListener for per-webhook delivery 2026-04-09 09:26:04 +00:00
kolaente d89af8ce6d feat(webhook): add WebhookDeliveryEvent for per-webhook fan out 2026-04-09 09:26:04 +00:00
kolaente 38555b1120 test(webhook): add failing test for #2569 sibling webhook blocking
Also clear the example.com fixture webhook (id=1) in the existing
TestTaskUpdateWebhookE2E, since it now errors after sendWebhookPayload
returns non-nil for non-2xx responses.
2026-04-09 09:26:04 +00:00
kolaente 42b0f0ba77 fix(webhook): return error from sendWebhookPayload on non-2xx responses
Previously the HTTP response status was only logged, so retries never
triggered for failing webhooks and downstream fan-out bugs (#2569) were
impossible to exercise via tests. Returning an error lets the watermill
retry middleware do its job.
2026-04-09 09:26:04 +00:00
Rhys McNeill 699c766049 fix: add timeouts to Gravatar, Unsplash, and SSRF-safe HTTP clients 2026-04-09 07:31:08 +00:00
kolaente 17a97cacfa refactor: use per-view IN clause for filter task deletion instead of batching 2026-04-09 07:25:57 +00:00
kolaente bfdcea6bd2 fix: batch delete conditions in filter view cron to avoid SQLite expression depth limit
The filter view cron built an unbounded builder.Or(deleteCond...) tree
that exceeded SQLite's 1000-node expression depth limit when many tasks
needed removal. Delete conditions are now processed in chunks of 500.

Ref: #2550
2026-04-09 07:25:57 +00:00
kolaente 2014343557 fix: catch ErrNeedsFullRecalculation in task creation position conflict resolution
resolvePositionConflictsAfterInsert now falls back to a full position
recalculation when resolveTaskPositionConflicts returns
ErrNeedsFullRecalculation, instead of bubbling the error up as HTTP 500.
This mirrors the existing fallback logic in the CLI repair command.

Ref: #2550
2026-04-09 07:25:57 +00:00
kolaente c5450fb55f fix: update user list test expectations for new fixture user 2026-04-08 09:49:14 +00:00
kolaente 119d7df796 fix: use assert.Empty instead of assert.Equal for empty string check 2026-04-08 09:49:14 +00:00
kolaente a5fb01cc3d fix: reset SSO avatar provider to default when picture claim is removed 2026-04-08 09:49:14 +00:00
kolaente 1065bdd84c test: add tests for SSO avatar provider reset on empty picture URL 2026-04-08 09:49:14 +00:00
kolaente 76790348f7 test: verify background removal preserves project title
Regression test for #2552. Deletes the background of project 35 (owned by
testuser6) and then fetches the project to confirm the title is still
'Test35 with background'.
2026-04-08 09:07:15 +00:00
kolaente d5051c97e4 fix(background): use targeted column update when removing background
Fixes #2552. RemoveProjectBackground was passing a minimal Project struct
(only ID set) through UpdateProject, which always includes 'title' in its
Cols() list. This caused XORM to write the zero-value empty title to the
DB, wiping the real project title. Now uses ClearProjectBackground which
only updates background_file_id and background_blur_hash.
2026-04-08 09:07:15 +00:00
kolaente bf86bee690 feat(models): add ClearProjectBackground for scoped column update 2026-04-08 09:07:15 +00:00
kolaente c166eff95f test: remove obsolete invalid-cache-type test for avatar upload
RememberValue[T] always gob-decodes to the correct type, so the
corrupted-cache recovery path no longer exists.
2026-04-08 08:56:22 +00:00
kolaente 0f54dc43d0 fix: use RememberValue for task attachment preview cache
Migrate task attachment preview caching to RememberValue[[]byte] so it
works correctly with Redis gob-encoded values.
2026-04-08 08:56:22 +00:00
kolaente 59b047f76a fix: register gob types and use RememberValue for avatar and unsplash cache
Register CachedAvatar and Photo with encoding/gob so Redis can properly
deserialize them. Migrate both to use RememberValue[T] which calls
GetWithValue() internally, fixing the broken type assertion when Redis
is the keyvalue backend.

Also removes the recursion-depth fallback in upload.go since
RememberValue eliminates the type mismatch failure mode entirely.
2026-04-08 08:56:22 +00:00
kolaente e2de681b71 feat: add generic RememberValue[T] for type-safe keyvalue caching
RememberValue uses GetWithValue() internally for proper gob-decoding,
which is required when Redis is used as the keyvalue backend.
2026-04-08 08:56:22 +00:00
Frederick [Bot] f528bcc276 chore(i18n): update translations via Crowdin 2026-04-08 01:25:14 +00:00
Frederick [Bot] a0dd7a7270 [skip ci] Updated swagger docs 2026-04-07 15:45:50 +00:00
kolaente bc0bb556ad feat(migration): flatten project hierarchy for single-project imports 2026-04-07 15:20:06 +00:00
kolaente 3437f98dc3 feat(migration): add skip rows option to CSV import
Allow users to skip the first N data rows when importing CSV files.
This is useful when the CSV contains metadata rows before the actual
task data begins. Adds skip_rows to ImportConfig (backend) and a
number input in the parsing options UI (frontend).
2026-04-07 15:20:06 +00:00
Claude f555762def feat(migration): add generic CSV import with column mapping
Add a new CSV migration module that allows users to import tasks from
any CSV file with custom column mapping and parsing options.

Backend changes:
- New CSV migrator module with detection, preview, and import endpoints
- Auto-detection of delimiter, quote character, and date format
- Suggested column mappings based on column name patterns
- Transactional import using InsertFromStructure

Frontend changes:
- New CSV migration UI with two-step flow (upload -> mapping -> import)
- Column mapping selectors for all task attributes
- Live preview showing first 5 tasks with current mapping
- Parsing option controls for delimiter and date format

The CSV migrator creates a parent "Imported from CSV" project with
child projects based on the project column if provided, or a default
"Tasks" project for tasks without a specified project.
2026-04-07 15:20:06 +00:00
Frederick [Bot] 7820bb1ffd [skip ci] Updated swagger docs 2026-04-07 12:22:00 +00:00
kolaente e40877cca1 fix(migration): delete all default buckets when migration provides its own
Previously only the "To-Do" default bucket was deleted, leaving "Doing"
and "Done" as duplicates alongside migration-provided buckets. Now all
default-created buckets are removed when migration data already provides
bucket assignments for all tasks.
2026-04-07 12:05:47 +00:00
kolaente ccf1468884 fix(migration): correct TickTick swagger annotation to PUT 2026-04-07 12:05:47 +00:00
kolaente 1a1fd780ec feat(migration): add WeKan to migration page with logo
Register WeKan in the AvailableMigrators list and add the frontend
migrator entry with the WeKan logo, referenced as "WeKan ®".
2026-04-07 12:05:47 +00:00
kolaente 64aa7a9e75 feat(migration): register WeKan migration routes 2026-04-07 12:05:47 +00:00
kolaente 56ce73738d test(migration): add WeKan migration tests and fixture
Add comprehensive tests for the WeKan conversion function including
edge cases (empty board, orphan cards, color mapping, multiple
checklists, unsupported fields) and a realistic JSON fixture file.
2026-04-07 12:05:47 +00:00
kolaente 4cc7715951 feat(migration): add WeKan board JSON import
Add a file-based migration importer that reads WeKan board JSON exports
and creates Vikunja projects with kanban buckets, tasks, labels,
checklists, and comments.

WeKan lists become kanban buckets. Checklists are converted to HTML
task lists in the description. Card descriptions and comments are
converted from markdown to HTML using goldmark. Label colors are
mapped from WeKan's CSS color names to their actual hex values.
2026-04-07 12:05:47 +00:00
kolaente ac76bce5cd fix: use recursive CTE in accessibleProjectIDsSubquery for inherited project permissions
Resolves #2490. Users with team access on a parent project were not seeing
subtask relations for tasks in child projects because getUserProjectsStatement
does not walk the project hierarchy. The fix wraps the base query in a
recursive CTE that traverses child projects via parent_project_id.
2026-04-05 12:20:35 +00:00
Frederick [Bot] 23d9cbc664 [skip ci] Updated swagger docs 2026-04-05 10:05:20 +00:00
kolaente e9a26b9088 feat: add DELETE /test/all endpoint to truncate all tables 2026-04-05 09:48:09 +00:00
kolaente 6a3dd8b281 feat: add TruncateAllTables function for e2e test isolation 2026-04-05 09:48:09 +00:00
kolaente 6299bea794 fix(mail): guard log calls in GetMailDomain and fix hostname-dependent tests
GetMailDomain called log.Warningf which panics when the logger is not
initialized (e.g. in unit tests). Add log.IsInitialized() guard.

Also fix TestGetThreadID tests that hardcoded "vikunja" as the expected
fallback domain - on CI the os.Hostname() fallback produces a different
value. Tests now dynamically compute the expected domain.
2026-04-03 18:30:39 +00:00