Commit Graph
49 Commits
Author SHA1 Message Date
kolaenteandTink 8e5839604e feat(api): support structured domain error details 2026-11-04 23:14:28 +01:00
kolaente e1e617fb9b fix(api): treat page=0 as the first page on v1 list endpoints 2026-10-20 15:13:02 +02:00
kolaenteandTink 0e4fe9c8b4 refactor(attachments): split attachment downloads from previews
Prepares serving previews from their own route: a download returns the original, a preview returns a preview or an error.
2026-10-19 20:33:06 +02:00
kolaenteandTink 685c31a1ae refactor(attachments): cut comment noise
Address pr-swarm comment sweep.
2026-10-19 20:33:06 +02:00
kolaenteandTink bdbdd4f46b fix(attachments): only serve stored previews as jpeg or png
Address pr-swarm finding: any sniffed image/* type, including SVG, was served inline without nosniff.
2026-10-19 20:33:06 +02:00
kolaenteandTink b101cbff74 fix(files): open s3 files without requiring a content length
Address pr-swarm finding: Open went through OpenWithSize, which failed on S3-compatible backends that answer without a Content-Length, breaking every original download there.
2026-10-19 20:33:06 +02:00
kolaenteandTink c084ee6144 refactor(attachments): answer a download with either a preview or the original
GetTaskAttachmentForDownload returned the attachment together with
preview bytes, where the file was only opened when the bytes were nil.
It now returns one value that is a preview or the opened original, and
the response writer closes whichever it got. The preview carries its
own mime type, taken from its bytes, instead of the writer assuming
PNG.
2026-10-19 20:33:06 +02:00
kolaenteandTink 796bbec03a refactor(attachments): cut comment noise
Address pr-swarm comment sweep.
2026-10-19 20:33:06 +02:00
kolaenteandTink 9df5213b3d fix(attachments): decode previews from the stream instead of buffering the file
Generating a preview read the whole source into memory before decoding it. It now reads the header from one handle and decodes from a second one, both owned by the generation. The original is only opened when it is actually served, so a cached preview no longer opens the source at all.
2026-10-19 20:33:06 +02:00
kolaente 5b08e0486a test(web): catch ErrorCode-prefixed constants in error code uniqueness check
The regex only matched ErrCode..., so the 1025 and 1026 collisions with ErrorCodeInvalidTimezone and ErrorCodeUsernameReserved went unnoticed.
2026-09-15 18:38:59 +02:00
kolaente c0545eb559 feat(api): redirect historical task indexes on v2
A by-index address that no longer resolves falls back to the alias table
and answers 307 with the task's current address and Cache-Control:
no-store. The fallback requires read access to the project in the URL and
to the target task, using the same 403 body as DoReadOne.
2026-09-11 20:47:11 +02:00
kolaente fe712620f7 perf(db): read handlers and token auth run without a transaction
db.NewSession begins a transaction, so every request holds one pooled
connection for its whole life: across the API's own work and every round
trip in between. At 20,000 simulated users that filled a 192-connection
pool with 170 backends idle in transaction while 13 were active, and the
database sat at 40 % CPU with p99 at 94 ms.

NewReadSession attaches the session memo but does not Begin; each statement
borrows a connection only for itself. Commit and Rollback are no-ops on it,
so DoReadOne, DoReadAll and ValidateAPITokenString keep their shape. A read
path that writes (position healing) now commits per statement.
2026-09-08 21:09:26 +02:00
kolaente fb70c85b23 refactor(web): read source files through an fs.FS in the error code test 2026-09-06 00:12:30 +02:00
kolaente b4e2dc36ff test(web): fail when two packages claim the same world error code 2026-09-06 00:12:30 +02:00
kolaente 79083df2ea fix: unwrap wrapped domain errors in attachment upload results 2026-09-05 12:17:45 +02:00
kolaenteandkolaente e983fa10c7 fix(web): stop logging the full auth object on permission denials
log.Warningf formatted a web.Auth with %v on the create, read, update and
delete denial paths. That holds a *user.User, which has a Password field
carrying the bcrypt hash and no String method, so every denied request wrote
a password hash into the log at warning level. Log the user id instead.
2026-07-29 07:58:17 +00:00
kolaenteandkolaente f388015dda fix: interpolate dynamic values into translated error toasts
Parametrised error translations (invalid api token permission, invalid
timezone, invalid claim data) rendered their placeholders as empty text
because the backend only baked the values into the English message and
the frontend translated the error code without any interpolation params.

Carry the values as i18n_params on error responses, keyed by the
placeholder names of the frontend's error translations, on both v1 and
the v2 problem+json body, and pass them through when translating the
toast. A 14002 toast now reads e.g. "The permission time_entries of
group tasks is invalid." instead of "The permission of group is
invalid."
2026-07-18 13:41:15 +00:00
TinkandGitHub 4425e0d146 fix(attachments): keep blob mime type so pdf previews open inline (#3157) 2026-07-11 18:53:09 +02:00
kolaenteandkolaente 4b92f23329 fix(files): never cache file downloads in v1 or v2
Move the Cache-Control: no-cache header into the shared WriteFileDownload
so every export and attachment download carries it, and add it to the
standalone v1 export download writer too. Downloads must never be cached.
2026-06-17 18:39:38 +00:00
kolaenteandkolaente ca4e747bed refactor(files): extract WriteFileDownload shared by attachment download
Split the generic file-download writer (ServeContent for seekable readers,
manual 304 + io.Copy otherwise) out of WriteAttachmentDownload so other blob
endpoints can reuse it. The attachment writer keeps its preview branch and
cache override and delegates the rest.
2026-06-17 18:39:38 +00:00
kolaenteandkolaente 8bec654595 refactor(background): extract download + unsplash-proxy logic for reuse
Split the HTTP plumbing from the business logic in the v1 project-background
download and Unsplash image proxy handlers so /api/v2 can reuse it without
duplicating it:

- LoadProjectBackgroundForDownload (background/handler) loads the bg file +
  modtime and fires the Unsplash pingback; GetProjectBackground now calls it.
- WriteProjectBackground (web/files) writes v1's exact background wire shape
  (image/jpg, no-cache, stat-modtime Last-Modified, If-Modified-Since 304).
- FetchUnsplashImageByID / FetchUnsplashThumbByID (background/unsplash) return
  the open upstream body for the caller to stream; the v1 proxy handlers now
  call them. A typed ErrUnsplashImageDoesNotExist maps to 404 on both APIs.
- ErrProjectHasNoBackground (models) gives the no-background case a domain
  error; v1 keeps its verbatim 404 message.

v1 responses are unchanged on the wire.
2026-06-17 11:31:50 +00:00
kolaenteandkolaente 9da51f5096 refactor(events): pass context to DispatchPending directly
Every DispatchPending caller either has the request context in scope or
is genuinely request-less, so passing it as a parameter replaces the
stored-context mechanism on the pending queue and satisfies
contextcheck. Also fixes lint findings in the audit package.
2026-06-12 08:56:08 +00:00
kolaenteandkolaente 48f7dafce3 feat(events): carry request metadata onto dispatched event messages
Adds a RequestMeta context bridge so events dispatched during an HTTP
request can be attributed to it: a middleware stashes IP/UA/request-id
on the request context, the generic Do* handlers associate that context
with the transaction key, and DispatchPending/DispatchWithContext copy
the metadata onto the watermill message at publish time. Existing
dispatch call sites are unchanged.
2026-06-12 08:56:08 +00:00
kolaenteandkolaente cec74717fc refactor(task-attachment): share upload+download via pkg/web/files for v1+v2 2026-06-10 10:22:39 +00:00
kolaenteandkolaente 2fc6f033f2 refactor(handler): return domain error for forbidden instead of echo.HTTPError
Keeps the Do* helpers framework-neutral so non-Echo callers (upcoming
Huma /v2 handlers) don't need a translation shim.

Addresses review feedback on #2670.
2026-04-21 09:23:13 +00:00
kolaenteandkolaente 939381fb12 refactor(handler): extract DoDelete from DeleteWeb 2026-04-21 09:23:13 +00:00
kolaenteandkolaente 1f4471c38f refactor(handler): extract DoUpdate from UpdateWeb 2026-04-21 09:23:13 +00:00
kolaenteandkolaente 0e800b4936 refactor(handler): extract DoReadAll from ReadAllWeb 2026-04-21 09:23:13 +00:00
kolaenteandkolaente 9ec5c2672f refactor(handler): extract DoReadOne from ReadOneWeb 2026-04-21 09:23:13 +00:00
kolaenteandkolaente 11c9137080 refactor(handler): extract DoCreate from CreateWeb 2026-04-21 09:23:13 +00:00
kolaente 217a481162 feat(handlers): dispatch pending events after transaction commit
All generic CRUD handlers now call events.DispatchPending(s) after
s.Commit() and events.CleanupPending(s) on rollback paths. This is
preparation for switching model methods from events.Dispatch to
events.DispatchOnCommit.

Refs #2315
2026-03-03 12:46:34 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>kolaente
9a61453e86 fix(deps): update module github.com/labstack/echo/v4 to v5 (#2131)
Closes https://github.com/go-vikunja/vikunja/pull/2133

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: kolaente <k@knt.li>
2026-01-24 20:38:32 +01:00
kolaenteandGitHub 39b4568bc5 refactor: centralize HTTP error handling (#2062)
This changes the error handling to a centralized HTTP error handler in `pkg/routes/error_handler.go` that converts all error types to proper HTTP responses. This simplifies the overall error handling because http handler now only need to return the error instead of calling HandleHTTPError as previously.
It also removes the duplication between handling errors with and without Sentry.

🐰 Hop along, dear errors, no more wrapping today!
We've centralized handlers in a shiny new way,
From scattered to unified, the code flows so clean,
ValidationHTTPError marshals JSON supreme!
Direct propagation hops forward with glee,
A refactor so grand—what a sight to see! 🎉
2026-01-08 10:02:59 +00:00
kolaenteandGitHub 0b3decd869 fix: ensure API consistency for /tasks and empty array responses (#1988)
- Renames the `/tasks/all` endpoint to `/tasks` for consistency with
other collection endpoints like `/projects` and `/labels`
- Returns `[]` instead of `null` for empty pagination results across all
list endpoints
- Updates the frontend service to use the new endpoint path
- Updates API token tests to use the new endpoint path

Fixes #1984
2025-12-15 15:34:13 +00:00
kolaenteandGitHub a81a3ee0e5 feat!: rename right to permission (#1277) 2025-08-13 11:05:05 +02:00
kolaente ca83ad1f98 feat: move to slog for logging 2025-07-21 18:15:39 +02:00
Dominik Pschenitschniandkolaente ef80fa77b4 docs: fix comments in web package 2025-07-02 17:46:21 +02:00
Dominik PschenitschniandGitHub 296577a875 fix: correct license header references (#882)
See originals:
- https://www.gnu.org/licenses/agpl-3.0.txt
- https://www.gnu.org/licenses/gpl-3.0.txt
2025-06-10 12:18:38 +02:00
Dominik Pschenitschniandkolaente 488b15c128 docs(web): fix typos 2025-06-10 12:10:42 +02:00
Marcandkonrad f4a0c0ef31 feat(auth): sso fallback mapping (#3068)
Reviewed-on: https://kolaente.dev/vikunja/vikunja/pulls/3068
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Marc <marc88@free.fr>
Co-committed-by: Marc <marc88@free.fr>
2025-03-02 15:21:09 +00:00
kolaente 5c56d07215 chore(web): always set internal error 2024-09-01 19:37:27 +02:00
kolaente 6fb314b326 chore(web): use logger directly 2024-09-01 19:37:27 +02:00
kolaente 9b01666ec6 chore(web): use web auth factory directly 2024-09-01 19:37:27 +02:00
kolaente bcfd72c645 chore(web): use config directly 2024-08-29 18:41:20 +02:00
kolaente 499f66b7ae chore(web): directly use new db session 2024-08-29 16:31:46 +02:00
kolaente 8e37d5cb76 chore(web): remove redundant use of fmt.Sprintf 2024-08-29 16:28:37 +02:00
kolaente 57ba073874 chore(web): use errors.As instead of type assertion 2024-08-29 16:28:16 +02:00
kolaente 329de3aab3 chore(web): remove unused echo context 2024-08-29 16:20:39 +02:00
kolaente 2063da9eec chore(web): move web handler package to Vikunja 2024-08-29 16:15:28 +02:00