Commit Graph
14958 Commits
Author SHA1 Message Date
kolaente d49e587928 fix(projects): reload projects when the api recalculated positions
The api renumbers all sibling positions when they drift too close together but
only returns the updated project. The store kept stale positions for the
siblings, so navigating to one of them pulled in its recalculated position and
made it jump to a different spot in the sidebar.
2026-08-18 14:28:37 +02:00
kolaente 57493ef81e fix(projects): make position healing include the moved project
recalculateProjectPositions ran before the new position was written, so the
moved project kept its tiny position while all its siblings were renumbered.
Every further move to the top then triggered another recalculation, and root
projects with a NULL parent_project_id were never healed at all.
2026-08-18 14:28:37 +02:00
kolaente 62f3e2f76b fix(ratelimit): give session renewal its own budget
The refresh-token and OAuth token endpoints shared the 10 requests/minute
floor that protects login, register and password reset. Access tokens live
for 10 minutes, so every client renews its session several times an hour --
and behind a reverse proxy `service.ipextractionmethod` defaults to `direct`,
which keys all of them to the proxy's address. Routine renewals therefore
used up the login budget, and users got "Too many requests" when signing in.
This hit the desktop app hardest: it exchanges its authorization code on the
very same endpoint it refreshes tokens on.

Renewal now has a separate limiter with its own `ratelimit.tokenrefreshlimit`
setting, defaulting to 60 requests/minute. Both limits stay enforced.
2026-08-18 14:01:06 +02:00
kolaente bb6318b1a5 fix(ratelimit): namespace each limiter's counters by prefix
Every limiter got its own store, but the redis store derives its keys from
a prefix that was identical everywhere. With `ratelimit.store: redis` the
unauthenticated floor and the global limiter therefore decremented the same
counter, so one budget silently applied to all of them.
2026-08-18 14:01:06 +02:00
Nick Manosandkolaente 358d043fb9 fix: expose pkg/config and viper to yaegi plugins
The plugin docs show yaegi plugins reading Vikunja configuration via
pkg/config and github.com/spf13/viper, but neither package was registered
in the yaegi symbol table. Plugins importing them failed to load at the
import itself.

Add both packages to yaegiSymbolPackages and commit the generated symbol
files so interpreted plugins can read configuration as documented.

Fixes #3500.
2026-08-18 13:29:23 +02:00
kolaente 26cb3c9b57 fix(frontend): don't overlap project color with drag handle on touch capable desktops
The sidebar drag handle and the project color bubble share the same 1rem box and
swap on hover. Two rules forced both of them visible at once whenever the
`is-touch` body class was set, which `is-touch-device` sets for anything exposing
touch events — including a desktop with a touchscreen. Those machines report
`pointer: fine`, so the coarse-pointer rule that hides the handle didn't apply and
the grip icon was painted on top of the color dot permanently.

Key the overrides off `(pointer: coarse)` instead, matching how the handle is
already hidden there and how ProjectList/ProjectKanban detect touch.

Fixes #3449
2026-08-18 13:15:40 +02:00
TinkandGitHub 6ba14bc2b0 fix(quick-add): reuse existing labels in the desktop quick entry window (#3533) 2026-08-18 11:06:02 +00:00
kolaente 137d740bfa fix(caldav): don't duplicate a task when a client PUTs a stale href
When a client PUT a task to a collection the task no longer lives in, the
project consistency guard made GetResource report it as missing, so the PUT
handler fell through to CreateResource and created a second copy of the task
in that project. iOS Reminders hits this whenever it completes a task it still
believes lives in the old project, which is why the copies all show up as
STATUS:COMPLETED - and stay invisible in the web UI, where done tasks are
hidden by default.

Refuse to create a task whose UID already exists, so the client resyncs and
finds the task under its real collection instead.
2026-08-18 12:55:13 +02:00
kolaente fdb590f0b5 fix(routes): extract the client IP for requests over a unix socket
Requests arriving through a unix socket have no peer IP, Go sets
RemoteAddr to "@" for them. Echo's IP extractors cannot parse that and
bail out before looking at X-Forwarded-For or X-Real-IP, so remote_ip was
always empty and everything keyed on the client IP (http log, rate
limits, audit log, session records) lost it.

Substitute loopback as the peer address in that case - a unix socket peer
is on the same host by definition - so the configured extraction method
works the same as it does over TCP.

Fixes #3529
2026-08-18 12:51:36 +02:00
kolaente 1ace49348f docs(config): clarify realip trust semantics for ipextractionmethod
Echo's X-Real-IP extractor checks the header value against the trusted
ranges, not the peer that sent it, so it cannot report public client IPs.
Say so and point users behind a reverse proxy at xff.
2026-08-18 12:40:29 +02:00
kolaente 08f426fcd5 fix(auth): don't auto-redirect to the OIDC provider when the login URL must stay copyable
The single-provider auto-redirect added in 18ee92f2 fires on every visit to
/login, including the two cases where the login page has to stay put:

- A native client's /oauth/authorize URL is parked in the login hash so it can
  be copied into the browser the user is actually signed in to (#2654). The
  auto-redirect replaced that URL with the provider's before it could be
  copied. Copying the provider URL instead does not work either, because the
  OIDC state lives in the originating browser's localStorage, so finishing the
  flow elsewhere fails the state check.
- Inside the Electron window, login is handed off to the system browser by
  DesktopLogin. Redirecting to the provider in-window stranded the user there.

Move the decision into getAutoRedirectProvider() and cover it with unit tests.

Fixes #3473
2026-08-18 12:17:39 +02:00
renovate[bot]andkolaente 9f03f74693 chore(deps): update dependency fast-uri@3 to v4 2026-08-18 12:02:25 +02:00
renovate[bot]andkolaente 04a77d9c0e fix(deps): update module github.com/mattn/go-sqlite3 to v1.14.50 2026-08-18 11:42:43 +02:00
kolaente e195f848ae fix(editor): join list items on backspace instead of splitting the list
Backspace at the start of a list item used to lift it out of the list, which
split the list in two and left a bare paragraph between the halves. Now the
item merges into the item above, unless it is the first item of its list -
that keeps lifting so there is still a way out of a list.

Fixes #3480
2026-08-18 11:31:29 +02:00
kolaente c7535008cf test(e2e): cover registration flow when email confirmation is required 2026-08-18 11:30:03 +02:00
kolaente 595f4c3edc fix(frontend): show confirmation notice when registration requires email verification
After a successful registration the frontend auto-logs-in. With email
confirmation enabled that login fails with 412 (code 1012), which
surfaced as a raw "Request failed with status code 412" error in the
register form even though the account was created fine. Treat that case
as a success and tell the user to check their inbox instead.
2026-08-18 11:30:03 +02:00
kolaente 3833b34d37 fix(user): keep email confirmation status after registration
The default-project creation triggered by the user-created event wrote the
stale in-memory user back with a full UpdateUser, racing registration and
sometimes resetting the status from "email confirmation required" back to
active. Only update the default_project_id column and keep the returned
user's status in sync with what was persisted.
2026-08-18 11:30:03 +02:00
kolaente 8607fad4a9 fix(webhooks): wrap long target URLs instead of overflowing the table
Webhook target URLs like Discord's contain no break opportunities, so the
cell's min-content width forced the whole table past its container and
pushed the other columns out of view.

Fixes #3456
2026-08-18 10:57:37 +02:00
kolaente d59b2e1f75 fix(frontend): don't duplicate subtasks as top-level rows in saved filter list views
shouldShowTaskInListView() skipped the parent-in-view check for saved
filters, so a subtask expanded for context was rendered nested *and* as
its own top-level row, even when it did not match the filter.

The bypass was a stopgap for #2494 (a matching subtask was invisible when
its parent did not match). That is now handled in the backend by
buildSubtaskRootCondition, which returns such a subtask as a root, so the
frontend check is safe to apply to saved filters too.

Fixes #3462
2026-08-18 10:26:13 +02:00
renovate[bot]andkolaente 8fd0c23421 chore(deps): update dependency js-yaml to v5.3.0 2026-08-18 10:22:43 +02:00
renovate[bot]andkolaente 4fea68e624 fix(deps): update module golang.org/x/net to v0.58.0 2026-08-18 10:21:54 +02:00
kolaente e773ee4683 fix(frontend): keep focus in the multiselect input after selecting an option
Selecting an option unmounts the result list, so focus fell back to the
document body. On the task detail view, subsequent keystrokes were then
picked up by the global task shortcuts, which looked like focus jumping
to the description or assignee field.

Resolves #3464
2026-08-18 10:08:32 +02:00
kolaente 536d7b7dbf fix(notifications): retry subscriber notifications instead of dropping them on error
Since e25295422 the subscriber loops in the comment, assigned, deleted and
project-created listeners logged a failed Notify and moved on. On SQLite the
insert regularly fails with "database is locked" (SQLITE_BUSY_SNAPSHOT: the
listener's deferred transaction cannot upgrade to a write once a sibling
listener has committed), so the notification was silently lost.

Return the error again so the events router retries the handler with a fresh
session, as it did before 2.5.0.

Reported at https://community.vikunja.io/t/notification-problems-since-2-5-0/4750
2026-08-18 09:46:57 +02:00
kolaente 7d91052976 feat: show relative time in api token expiry notifications 2026-08-18 09:44:49 +02:00
renovate[bot]andkolaente c6b6d84ab1 chore(deps): update e18e/action-dependency-diff action to v1.7.1 2026-08-18 09:32:40 +02:00
renovate[bot]andkolaente 9fbce54a5d chore(deps): update dependency js-yaml@4 to v5.3.0 2026-08-18 09:29:16 +02:00
renovate[bot]andkolaente e61c81cc54 fix(deps): update dependency @sentry/vue to v10.70.0 2026-08-17 17:07:21 +02:00
renovate[bot]andkolaente 7247ae69e8 chore(deps): update dependency esbuild to v0.28.2 2026-08-17 16:41:41 +02:00
renovate[bot]andkolaente c95cf786bd fix(deps): update tiptap to v3.30.1 2026-08-17 14:59:14 +02:00
renovate[bot]andkolaente 3acf56bb82 fix(deps): update dependency pinia to v4.0.3 2026-08-17 14:39:11 +02:00
renovate[bot]andkolaente 6df8e84adf chore(deps): update dependency ip-address to v10.5.0 2026-08-17 14:32:46 +02:00
renovate[bot]andkolaente 5c3c127cc1 chore(deps): update dependency undici@6 to v8.10.0 2026-08-17 14:11:19 +02:00
renovate[bot]andkolaente bad120a368 chore(deps): update dependency serialize-javascript to v7.1.0 2026-08-17 14:07:34 +02:00
renovate[bot]andkolaente 55b3d42854 fix(deps): update module github.com/stretchr/testify to v1.12.0 2026-08-17 14:01:37 +02:00
renovate[bot]andkolaente a8ec0d7a9a chore(deps): update dependency rollup-plugin-visualizer to v7.1.1 2026-08-17 13:40:54 +02:00
renovate[bot]andkolaente 976e84efaa fix(deps): update module charm.land/lipgloss/v2 to v2.0.6 2026-08-17 13:34:56 +02:00
renovate[bot]andkolaente af2f735a39 chore(deps): update cachix/install-nix-action action to v31.11.1 2026-08-17 13:31:23 +02:00
renovate[bot]andkolaente 4b27de44e7 fix(deps): update dependency marked to v18.0.9 2026-08-17 12:38:53 +02:00
renovate[bot]andkolaente 70db5bce84 fix(deps): update module golang.org/x/image to v0.45.0 2026-08-17 12:35:09 +02:00
renovate[bot]andkolaente 3ffea20a16 fix(deps): update dependency vue to v3.5.41 2026-08-17 12:21:11 +02:00
renovate[bot]andkolaente 468e50f4f4 chore(deps): update dependency postcss to v8.5.26 2026-08-17 12:18:40 +02:00
renovate[bot]andkolaente 6569148088 chore(deps): update dependency go to v1.26.6 2026-08-17 12:15:01 +02:00
renovate[bot]andkolaente d41f637068 chore(deps): update docker/dockerfile:1 docker digest to ecfaec9 2026-08-17 12:03:41 +02:00
kolaente b6037a2562 chore(deps): update fast-uri to 3.1.5 2026-08-17 11:35:52 +02:00
kolaente a9b7c89bfb chore(deps): update brace-expansion to 5.0.9 in desktop 2026-08-17 11:35:41 +02:00
kolaente 2b22f0661e chore(deps): update brace-expansion to 5.0.9 2026-08-17 11:35:17 +02:00
kolaente c7dc7844f1 chore(deps): update js-yaml to 3.15.1 2026-08-17 11:35:14 +02:00
kolaente 6314285564 chore(deps): update nanoid to 3.3.18 2026-08-17 11:35:06 +02:00
kolaente c901cedf48 chore(deps): drop redundant esbuild devDependency
Nothing imports esbuild directly and the pnpm override already forces
0.28.1 on all transitive copies, so the direct pin had no effect.
2026-08-17 11:26:51 +02:00
dependabot[bot]andkolaente d053ffec29 chore(deps): bump nanoid from 3.3.16 to 6.0.1 in /frontend
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.16 to 6.0.1.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.16...6.0.1)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-version: 6.0.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 11:03:40 +02:00