Commit Graph

14417 Commits

Author SHA1 Message Date
kolaente 46b07a019c refactor(user): extract shared account orchestration into models/user/shared for v1+v2
Pull the business logic out of the v1 current-user account/settings handlers
into reusable functions so both v1 and the upcoming v2 handlers call one
implementation. No behavior change — the v1 handlers keep their HTTP-layer
quirks (input binding, validation, error mapping); only orchestration moves.

Homes are forced by the import graph:
- shared.GetAuthProviderName  (new pkg/routes/api/shared, above openid+user so it
                              can combine both without a cycle; routes-only helper)
- user.ChangeUserEmail        (CheckUserCredentials + UpdateEmail, both in user)
- models.ChangeUserPassword   (needs models.DeleteAllUserSessions; user can't import models)
- models.UpdateUserGeneralSettings / UpdateUserAvatarProvider
                              (need avatar.FlushAllCaches; user can't import avatar)

The general settings get a single shared wire struct, models.UserGeneralSettings
(tagged for both swaggo/govalidator and Huma): it is the update request body and
the nested settings on GET /user for v1 (replacing v1's UserSettings) and v2.
ExtraSettingsLinks is readOnly — populated from the user on read, ignored on
write. A dedicated struct is required because user.User's settings fields are
json:"-" so they don't leak when it is embedded in other responses.
2026-06-11 07:02:31 +00:00
kolaente 154a96674d fix(notifications): strip remote images from notification emails
User-controlled fields rendered into notification emails (task title via the
conversational header, comment and description bodies) were sanitized with a
bluemonday UGCPolicy that permits remote <img> sources. An attacker with write
access to a shared project could therefore inject an external image that acts
as a tracking pixel in a subscriber's inbox, leaking email-open time and IP.

Restrict notification-email images to inline data URIs (used by avatars) by
adding a RewriteSrc hook that blanks any non-data image src. The policy was
duplicated in three places, so extract it into newNotificationSanitizer.

Refs GHSA-2vr2-r3qw-rjvq
2026-06-11 06:53:37 +00:00
kolaente b8894ac1c1 feat(api/v2): add user account-deletion flow on /api/v2 2026-06-10 19:15:05 +00:00
kolaente a610ccbbac feat(api/v2): add user webhooks on /api/v2
Port the per-user webhook endpoints (/user/settings/webhooks) from /api/v1 to
the Huma-backed /api/v2: list, available events, create, update, delete. They
are the project-less sibling of the project webhooks (#2858) and share the
webhooks.enabled gate, checked inside the registrar.

Webhook.ReadAll is extended to serve the user-level list (scoped to the
authenticated user) so the v2 list handler can go through handler.DoReadAll like
the project list; the project branch is unchanged. Credentials are masked on
read via the model's existing maskCredentials, matching #2858.
2026-06-10 19:12:41 +00:00
kolaente 190fab8e6d feat(api/v2): add TOTP 2FA on /api/v2
Ports the current-user TOTP (2FA) endpoints from /api/v1 to the Huma-backed
/api/v2: get status, enroll, enable, and disable. Each is a custom,
current-user-scoped handler that resolves the authenticated user and refuses
non-local (OIDC/LDAP) accounts, preserving v1's local-account-only guard.

The image/jpeg QR-code endpoint is intentionally not ported here; it is a
binary-streaming route deferred to a later wave.
2026-06-10 17:58:16 +00:00
kolaente 4afcfa4441 docs(api/v2): tag TOTP fields for the v2 schema 2026-06-10 17:58:16 +00:00
kolaente a562f69f02 feat(api/v2): add CalDAV tokens on /api/v2 2026-06-10 17:55:52 +00:00
kolaente da3bf0e7cd docs(api/v2): tag CalDAV token fields for the v2 schema 2026-06-10 17:55:52 +00:00
kolaente e271f75cad feat(init): use the hierarchical fuzzy picker for project selection
Replaces the flat numbered project list during 'veans init' with the interactive picker. --project <id> still bypasses it; non-TTY stdin fails cleanly asking for --project.
2026-06-10 13:51:46 +02:00
kolaente 3462e24ec7 feat(picker): add hierarchical fuzzy project picker
Interactive bubbletea picker that renders projects as an indented tree (siblings by position then title, orphans re-parented to root) and fuzzy-filters as you type, keeping matched rows' ancestors visible as dimmed context. Pure tree/flatten logic is split from the TUI and unit-tested.
2026-06-10 13:51:46 +02:00
kolaente a221a15ec3 feat(client): add parent_project_id and position to Project wire type
The init project picker needs the parent/child relationship and sibling ordering to render projects hierarchically like the web sidebar.
2026-06-10 13:51:46 +02:00
kolaente a1621fec37 feat(api/v2): add task attachments on /api/v2 2026-06-10 10:22:39 +00:00
kolaente dc935f263c docs(api/v2): tag task attachment fields for the v2 schema 2026-06-10 10:22:39 +00:00
kolaente cec74717fc refactor(task-attachment): share upload+download via pkg/web/files for v1+v2 2026-06-10 10:22:39 +00:00
kolaente 5cdc785b49 fix(api/v2): return ErrProjectDoesNotExist for unknown project identifiers 2026-06-10 10:12:09 +00:00
kolaente 0a879e56a8 feat(api/v2): add task CRUD on /api/v2 2026-06-10 10:12:09 +00:00
kolaente 4316554b27 docs(api/v2): tag task fields for the v2 schema 2026-06-10 10:12:09 +00:00
kolaente 328de89c0b feat(api/v2): add bulk label replacement on /api/v2 2026-06-10 11:56:05 +02:00
kolaente 0e0ececa2d docs(api/v2): tag bulk label fields for the v2 schema 2026-06-10 11:56:05 +02:00
kolaente 25a294d7bc feat(api/v2): add task position updates on /api/v2 2026-06-10 11:55:51 +02:00
kolaente a6a073329f docs(api/v2): tag task position fields for the v2 schema 2026-06-10 11:55:51 +02:00
kolaente e16d120236 fix(time-tracking): cap smart-fill start at now so the range is never inverted
Smart-fill set the From time to the configured default start (09:00) when there
was no recent entry to continue from. Before that time of day the default lands
in the future, after the To time of now, producing an inverted range the backend
rejects (end_time before start_time). The save then failed silently and the
entry never appeared.

This surfaced as a flaky time-tracking e2e suite: the smart-fill specs failed
only when CI happened to run before 09:00 UTC.
2026-06-10 11:47:47 +02:00
renovate[bot] 6d505e360b chore(deps): update dev-dependencies to v40.10.3 2026-06-10 11:47:27 +02:00
Frederick [Bot] 8502c541a6 chore(i18n): update translations via Crowdin 2026-06-10 00:33:40 +00:00
Frederick [Bot] 12f290905a [skip ci] Updated swagger docs 2026-06-09 23:32:10 +00:00
kolaente 1e82c62ff7 feat(api/v2): add reactions on /api/v2 2026-06-09 21:34:22 +00:00
kolaente f5e7e9ddde docs(api/v2): tag reaction fields for the v2 schema 2026-06-09 21:34:22 +00:00
kolaente 2e02fe11ac feat(api/v2): add task relations on /api/v2 2026-06-09 20:42:00 +00:00
kolaente da76d393d9 docs(api/v2): tag task relation fields for the v2 schema 2026-06-09 20:42:00 +00:00
kolaente 5c960fccd5 feat(api/v2): add bulk task updates on /api/v2 2026-06-09 20:13:02 +00:00
kolaente 711545e9f2 docs(api/v2): tag bulk task fields for the v2 schema 2026-06-09 20:13:02 +00:00
kolaente 1aa9493bc3 feat(api/v2): add project duplication on /api/v2 2026-06-09 20:11:43 +00:00
kolaente d5bcbe39b4 docs(api/v2): tag project duplication fields for the v2 schema 2026-06-09 20:11:43 +00:00
kolaente 51e5c86f69 feat(api/v2): add kanban task-bucket moves on /api/v2 2026-06-09 20:01:20 +00:00
kolaente 9eca20fe43 docs(api/v2): tag task bucket fields for the v2 schema 2026-06-09 20:01:20 +00:00
kolaente aa144b9a39 feat(api/v2): add task read-status marking on /api/v2 2026-06-09 19:50:58 +00:00
kolaente bf2a65dcaf feat(api/v2): add bulk assignee replacement on /api/v2 2026-06-09 19:42:16 +00:00
kolaente 732cd115a5 docs(api/v2): tag bulk assignee fields for the v2 schema 2026-06-09 19:42:16 +00:00
renovate[bot] cb0d24dae1 chore(deps): update dev-dependencies to v8.61.0 2026-06-09 11:47:14 +00:00
Claude c9c2c58c16 feat(labels): let bot owners manage labels created by their bots
Bot owners inherit read/update/delete permission on labels created by
bots they own, mirroring the bot-owner branch already used by API tokens
(see api_tokens_permissions.go). Without this, a label a bot creates is
permanently locked to that bot and the human owner cannot maintain it.

https://claude.ai/code/session_016x6mUPJuuQEeXpHY814iLh
2026-06-09 11:40:04 +00:00
kolaente e1512b6b53
chore(deps): update devenv 2026-06-09 10:54:20 +02:00
Frederick [Bot] df6a56b195 chore(i18n): update translations via Crowdin 2026-06-09 00:26:57 +00:00
Frederick [Bot] 9e181bfc55 [skip ci] Updated swagger docs 2026-06-08 14:15:20 +00:00
kolaente 00bbdbf95b refactor(time-tracking): drop the now-redundant duration clamp in the entry list 2026-06-08 13:54:09 +00:00
kolaente 0bd7f956f5 fix(time-tracking): reject inverted time-entry intervals 2026-06-08 13:54:09 +00:00
kolaente 4390af4773 test(time-tracking): add end-to-end coverage 2026-06-08 13:54:09 +00:00
kolaente 2d334e56c7 i18n(time-tracking): add the time-tracking UI strings 2026-06-08 13:54:09 +00:00
kolaente 7c021dd663 feat(time-tracking): configure the smart-fill start time in settings 2026-06-08 13:54:09 +00:00
kolaente e948b191b0 feat(time-tracking): add the time-tracking view 2026-06-08 13:54:09 +00:00
kolaente 2ef898e89d feat(time-tracking): add the task-detail time-tracking section 2026-06-08 13:54:09 +00:00