3465 Commits
Author SHA1 Message Date
kolaente 0b749163dc [skip ci] Updated yaegi symbols 2026-11-05 16:08:13 +01:00
kolaente fa6d9941fd fix(projects): only respread positions of projects the user can write
Moving a project to a position below 0.1 respread the positions of all
sibling projects on the instance. It now only touches the siblings the
user can write, plus the moved project itself.
2026-11-05 15:42:45 +01:00
kolaente 0ca8618a5c fix(link-shares): hide creator emails in the share list
Share creators are now loaded through the same helper as other user
listings, which blanks email addresses.
2026-11-05 15:42:45 +01:00
kolaente 8f9b9aba68 feat(migration): index the columns that reference stored files
Adds indexes on task_attachments.file_id, users.avatar_file_id,
users.export_file_id, projects.background_file_id and
migration_status.upload_file_id.
2026-11-05 15:42:45 +01:00
kolaente 8ee689add4 fix(backgrounds): clear backgrounds that point at files used elsewhere
A migration clears the background of projects whose background file is
also a task attachment, an avatar, a data export, a pending import upload
or another project's background. Of projects sharing a file, the oldest
keeps it.

The Unsplash and upload providers now remove the old background through
DeleteBackgroundFileIfExists.
2026-11-05 15:42:45 +01:00
kolaente 70451f4e4a fix(projects): never take the background from a project create request
The background of a new project is only ever set by the background
endpoints. Duplicating a project now hands the source background to the
copy step explicitly instead of relying on the field surviving creation.
2026-11-05 15:42:45 +01:00
kolaente 050c587ceb fix(user): only take username, name and language when creating a bot
Every other field of a new bot is set by the server.
2026-11-05 15:42:45 +01:00
kolaente b36581bcc1 fix(routes): only bind JSON, form and multipart request bodies
Form and multipart only bind fields with an explicit form tag. Other
content types are answered with 415, or 400 (2004) on v1 CRUD routes.
2026-11-05 15:42:45 +01:00
kolaente e693d3c273 fix(caldav): answer task validation errors with 403 instead of 500 2026-11-05 15:42:45 +01:00
kolaente 27ec08bb03 fix(images): limit the side length of decoded images
Images longer than MaxSide (65535) pixels on either side are now rejected
before decoding, like images over the pixel limit.

Attachments with such images are still stored; only their preview is not
generated. Project backgrounds and avatars reject them with the existing
image too large error.
2026-11-05 15:42:45 +01:00
kolaente e3acf407fb fix(export): export related tasks as references
The user data export embedded every related task in full, repeating its
description once per relation. Related tasks are now exported as id and
project id only, since every related task is part of the export anyway.

The importer resolves such references across all imported projects and
creates relations once every project exists, so relations between
projects survive the round trip instead of duplicating the related task.
Exports with the full related task shape import as before.
2026-11-05 15:42:45 +01:00
kolaente 1f79a8e01a fix(migration): reject repeated csv column mappings, cap labels per row
- Reject a config that maps a column more than once, already when the
  import is started or previewed.
- Import repeated labels of a row once and reject rows with more than
  MaxLabelsPerTask (100) labels.
- Count items while converting rows so a file over the import item limit
  fails before the whole structure is built.
- Walk mappings sorted by column so a row only visits the cells it has.
2026-11-05 15:42:45 +01:00
kolaente 8725e89725 refactor(utils): share rune-safe string truncation 2026-11-05 15:42:45 +01:00
kolaente 462a76a466 fix(migration): cap planka names copied into every task and comment
Custom field, group and user names are repeated per value or comment, so one long name multiplied the description size.
2026-11-05 15:42:45 +01:00
kolaente deeee79834 fix(migration): import repeated planka lists and cards only once
Lists, cards, checklists and attachments are looked up by id while
converting a board, so a repeated id imported the whole group once per
copy. Keep the first entry of each id and stop the conversion as soon as
the import item limit is exceeded instead of after building everything.
2026-11-05 15:42:45 +01:00
kolaente a3f3e9baaf fix(caldav): answer rejected bodies on unreadable projects with 404
Body checks now run after the read check, so a project the user can't
read answers like a missing one whatever the body.
2026-11-05 15:42:45 +01:00
kolaente 8efd16c2a3 fix(caldav): answer requested props and multiget hrefs once
Updates caldav-go, which answered every property in <prop> as often as it
was listed, rendering its value again each time, and passed repeated
multiget hrefs to storage again. It now answers each property and href
once and rejects requests for more than 200 properties.
2026-11-05 15:42:45 +01:00
kolaente fbedeae73e fix(caldav): render a resource's content once per request
A multistatus response asks for a resource's iCal content once per
requested property. It is now rendered once per resource and request.
2026-11-05 15:42:45 +01:00
kolaente daa4676e94 fix(caldav): only parse calendar bodies for PUT after access checks
Task bodies sent to a collection URL are now only parsed for PUT and
after the read check.

Calendar bodies are also limited in size (1 MiB) and in parameters per
property (100) before golang-ical sees them. Violations are answered with
413/400.
2026-11-05 15:42:45 +01:00
kolaente c6f18e405c fix(caldav): build iCalendar output linearly, cap reminders and titles
Every VALARM repeats the task title and the output was built with string
concatenation, so rendering cost grew quadratically with the number of
reminders. Build it with a strings.Builder instead.

Tasks may now have at most MaxRemindersPerTask (100) reminders and a
title of at most MaxTaskTitleLength (1000) characters, checked through
v1, v2 and CalDAV. On update the reminder limit only applies when the
count grows and the title limit only when the title changes, so existing
tasks stay editable.
2026-11-05 15:42:45 +01:00
kolaente 62a6cf1a17 fix(richtext): flatten quotes and lists nested deeper than ten levels
Markdown repeats every level's prefix on each line, so output grew with depth times lines.
2026-11-05 15:42:45 +01:00
kolaente 5ca6dbf3b1 fix(richtext): render markdown tables with minimal cell padding
Aligned padding pads every cell to its column's widest cell, so output grows with rows x widest cell.
2026-11-05 15:42:45 +01:00
kolaente 46279ab3c5 fix(richtext): bound the cells tables expand to during conversion
Rowspan/colspan and short-row padding make both converters materialize
far more cells than the input contains. HTML to markdown now renders
tables past MaxTableCells as plain rows, so stored descriptions still
read fine. Markdown to HTML rejects such input, which the v2 API reports
as invalid data.
2026-11-05 15:42:45 +01:00
kolaente d73b5e4963 fix(migration): mask credentials in urls of failed migration errors
Request urls are masked before a failed migration is logged or reported.
2026-11-05 15:42:45 +01:00
kolaente 886ce004c2 feat(migration): add a helper to mask credentials in error urls 2026-11-05 15:42:45 +01:00
kolaente 9fdd7f212e fix(tasks): keep the deleting user's data out of the task deleted event
The event no longer carries the deleting user's related tasks, favorite
and subscription.
2026-11-05 15:42:45 +01:00
kolaente b728feb9e8 fix(reminders): limit overdue task events to the recipient's projects 2026-11-05 15:42:45 +01:00
kolaente 111e332379 fix(filters): limit business day offsets in date math
The business day offsets in the date values of a task or time entry
filter may now add up to at most MaxDatemathBusinessDays (10000). Larger
filters are rejected with the invalid filter value error before any value
is evaluated. The frontend date math parser applies the same limit.
2026-11-05 15:42:45 +01:00
kolaente dcf98317ca fix(user): build the TOTP replay key from the normalized passcode
Trim the passcode once, require exactly six digits and use the trimmed
code for both the check and the single-use key.
2026-11-05 15:42:45 +01:00
kolaente a8501c28e5 fix(mcp): hint at listing all actions when find_action matches nothing
An empty find_action result looked identical to "not authorized", so
agents guessing a wrong resource prefix (task_relations instead of
tasks_relations) concluded their token lacked permission.

Refs #4342
2026-11-05 13:34:47 +01:00
kolaenteandTink b2c1686d11 feat(auth): preview verified OIDC accounts and reject unavailable identities 2026-11-05 12:44:50 +01:00
kolaenteandTink a405f9be3f chore(plugins): regenerate the yaegi symbols for the identity endpoints 2026-11-05 12:44:50 +01:00
kolaenteandTink 859b5c5255 feat(user): notify users when an OIDC identity is linked 2026-11-05 12:44:50 +01:00
kolaenteandTink f0625e6d1c feat(api): add reauthenticated OIDC identity management endpoints 2026-11-05 12:44:50 +01:00
kolaenteandTink c661314940 feat(models): add errors for linking user identities 2026-11-05 12:44:50 +01:00
kolaenteandTink 68feffefc3 test(openid): count code exchanges in the mock IdP 2026-11-05 12:44:50 +01:00
kolaenteandTink 934ced938e feat(auth): persist linked OIDC identities and authenticate local accounts 2026-11-05 12:44:49 +01:00
kolaenteandTink 5a3ef8e565 refactor(openid): extract issuer to provider lookup from the admin user view
FindProviderByIssuer is the lookup linked identities will use to resolve
their provider; the admin user view switches to it.
2026-11-05 12:44:49 +01:00
kolaenteandTink 833feb90ed test(openid): pin callback login behaviour with a signing mock IdP
Adds a mock OpenID provider issuing signed ID tokens so AuthenticateCallback
can be tested end to end, and pins the current behaviour for OIDC-created
users (email/name/avatar/team sync, disabled user refused). The proxy test
reuses the same mock instead of its inline copy.
2026-11-05 12:44:49 +01:00
kolaenteandTink 61f8af603f refactor(user): share password and TOTP reauthentication 2026-11-05 12:44:49 +01:00
Frederick [Bot] a0dca3108f [skip ci] Updated yaegi symbols 2026-11-05 11:08:00 +00:00
kolaente bab08e90c7 fix(tasks): lock views before tasks and recheck restores
Address PR Swarm lock-order decision across task writes, restoration, and project/user purges. Reject moves discovered after view locks without acquiring views out of order.
2026-11-05 11:29:33 +01:00
kolaente 37de71b15d fix(db): use read committed transactions
Address the PR Swarm snapshot finding with connection defaults for MySQL, MariaDB and PostgreSQL.
2026-11-05 11:29:33 +01:00
kolaente 5174bda98d style(tasks): format literals and trim comments
Address pr-swarm finding: follow the repository one-field-per-line convention in changed literals.
2026-11-05 11:29:33 +01:00
kolaente f5421cb272 fix(projects): archive duplicates after copying attachments
Address pr-swarm finding: keep the destination writable while populating an archived project duplicate.
2026-11-05 11:29:33 +01:00
kolaente 0472f02cd0 fix(tasks): recheck child writes and relation endpoints under row locks
Covers comments, attachments, labels, assignees, relations, reactions and task duplication. Assignee access is now checked against the project the task is in after the lock.
2026-11-05 11:29:33 +01:00
kolaente 97518e71ce fix(tasks): recheck write permission and view fit under the row lock for bucket and position moves
A task moved into another project between the check and the write would otherwise get a bucket or position in a view of its old project.
2026-11-05 11:29:33 +01:00
kolaente c8bdd3f87b fix(tasks): recheck write permission under the row lock before deleting a task 2026-11-05 11:29:33 +01:00
kolaente 1179b21227 refactor(tasks): extract locked write-permission recheck into lockTaskForWrite
The locked re-read now also drops the stale memoized task so later reads in the same session see the row the lock returned.
2026-11-05 11:29:33 +01:00
Frederick [Bot] 79115623b2 chore(i18n): update translations via Crowdin 2026-11-05 00:06:32 +00:00