Commit Graph

8595 Commits

Author SHA1 Message Date
Dombi Attila 5a14af6e0d Merge pull request #23630 from opf/task/op-19483-introduce-bundler-cooldown
[OP-19483] Introduce Bundler cooldown
2026-06-11 10:47:57 +03:00
Oliver Günther f389bb1c9b Merge pull request #23629 from opf/fix/meeting-backlog-section
Expose the backlog section visibly through the meetings API, ensuring it appears
2026-06-10 14:06:40 +02:00
Oliver Günther cd5ceba958 Allow embed_links to be parameterized, controlling which elements should be embedded 2026-06-10 13:43:06 +02:00
Oliver Günther d851d25524 Merge remote-tracking branch 'origin/release/17.5' into dev 2026-06-10 11:29:44 +02:00
Oliver Günther dc4cd9a6b4 Bumped version to 17.5.1
[ci skip]
2026-06-10 07:53:08 +02:00
Dombi Attila 90d54206a4 Add cooldown to the module Gemfiles too 2026-06-09 17:06:34 +03:00
OpenProject Actions CI 24be36fce6 Merge branch 'release/17.4' into release/17.5 2026-06-09 05:55:31 +00:00
Oliver Günther 7bf32598ed Also use message_pack for ConfidentialCache
YAML default coder uses aliases which break on safe_load
2026-06-09 07:54:33 +02:00
Oliver Günther 1451d2c3c4 Bumped version to 17.4.2
[ci skip]
2026-06-08 10:04:34 +02:00
Jan Sandbrink 5689a105a0 Work around SSRF issue
Ingredients needed for the issue to occur are:

* an allowed IPv4 range
* a checked IPv6 address
* the checked address must be wrapped in HTTPX::Resolver::Entry

This leads to a failure in checking address inclusion by IPAddr.
2026-06-08 08:15:38 +02:00
Henriette Darge 396de9362f [74625] Make project hierarchy collapsable in the global project selector (#23137)
* Use new async FilterableTreeView for global project selector

* Remove replaced angular component

* Fine tune sorting and expansion state of the new project selector

* Update primer to 0.86.1

* Add workspace information and filter results hierarchy information to project selector

* Include review feedback: Harmonize I18n keys, fix visible scope, use guarded local storage

* Add a turboFrame in the project select overlay to only load the projects when it is actually opened

* Restore BIM tab styles which were broken for a while already but the new project selector changes made it so bad that the test broke because the plus icon was overlapping the checkbox

* Clarify spec expectation
2026-06-08 08:14:47 +02:00
Marcello Rocha 81e5726838 [OP#73293] Creates POST /api/v3/wiki_page_links endpoint (#23529)
* Remove the `render_author` method as it is unnecessary
* Add the necessary paths, clarify the param to wiki_provider path
* Rework the representers, merge upstream changes to the create contract
* Remove unnecessary mixin and make everything read-only
* Create Endpoint for POST /api/v3/wiki_page_links
* Incorporates @Kharonus feedback in testing multiple page link creation
2026-06-04 10:06:13 +02:00
Jan Sandbrink 663dc3f182 Merge pull request #23480 from opf/httpx-ssrf-filter
Add SSRF filter for HTTPX
2026-06-04 07:19:42 +02:00
Jan Sandbrink 294611cc59 Add SSRF filter for HTTPX
Filtering in front of HTTPX calls is less secure, because it's vulnerable to
DNS rebinding. In addition to that it's also duplicate work, because all affected
callsites would have to make sure to "remember" SSRF filtering.

This SSRF filter is inspired by the original HTTPX SSRF Filter, but using our custom
IP address matcher that allows to configure safe IP addresses or ranges.
2026-06-03 09:56:48 +02:00
OpenProject Actions CI 523ef39065 Merge branch 'release/17.5' into dev 2026-06-01 14:42:29 +00:00
Oliver Günther 64422d3c63 Merge remote-tracking branch 'origin/release/17.4' into release/17.5 2026-06-01 13:57:42 +02:00
Oliver Günther 38ab5af1ff Merge remote-tracking branch 'origin/release/17.3' into release/17.4 2026-06-01 13:57:33 +02:00
Oliver Günther 9ed3392dae Better whitelisting of allowed macros and data-attributes 2026-06-01 13:57:18 +02:00
OpenProject Actions CI b2f72fd486 Merge branch 'release/17.5' into dev 2026-05-30 04:49:04 +00:00
Tom Hykel 1a22f59d21 Merge pull request #23367 from opf/fix/74942-numeric-id-instead-of-semantic-one-on-th
[#74942] fix(ui): Support semantic identifiers on related work packages table
2026-05-29 13:10:37 +02:00
Oliver Günther b5350cccf7 Add rack-attack throttler for all logins
We have a built-in bruteforce protection for built-in users. When users
are being created from LDAP on-the-fly, these limits cannot apply, as we
do not have a user object yet.

Instead, we can provide a more generous throttler to block attempts
2026-05-29 12:33:28 +02:00
Oliver Günther 4565b53957 Extract and use charset to properly serve inline text attachments (#23432)
* Extract and use charset to properly encode attachments

* Add the content type for external URLs

* Be more cautious when parsing charset from `file`
2026-05-29 10:51:37 +02:00
Oliver Günther a852d46cb6 Be more cautious when parsing charset from file 2026-05-29 10:30:07 +02:00
Oliver Günther 5330745e69 Add the content type for external URLs 2026-05-29 10:26:43 +02:00
Oliver Günther 6f63faeed1 Extract and use charset to properly encode attachments 2026-05-29 10:26:43 +02:00
Ivan Kuchin f6e073f0a1 [#74769] Remove portfolio_models feature flag
https://community.openproject.org/wp/74769
2026-05-28 13:53:08 +02:00
Henriette Darge 599b6fab1b Pass class option to non-linkable instances as well 2026-05-28 13:02:42 +02:00
OpenProject Actions CI 49b802ca02 Merge branch 'release/17.5' into dev 2026-05-28 08:51:09 +00:00
Kabiru Mwenja ab32cab495 Merge pull request #23337 from opf/bug/74762-numeric-id-in-the-email-notification-after-adding-watchers
bug/74762 Numeric ID in the email notification after adding watchers
2026-05-28 11:38:02 +03:00
OpenProject Actions CI eb6717f81e Merge branch 'release/17.5' into dev 2026-05-27 14:11:35 +00:00
Tomas Hykel cee98d16bb fix(ui): Numeric ID instead of semantic one on the table of related work packages (WP #74942) 2026-05-27 15:03:40 +02:00
Kabiru Mwenja 3036e852a9 Tighten render_mode and mail formatting helper docstrings
Strip a forward-looking aside about future external surfaces in RenderMode;
the invariant is that external surfaces need both absolute URLs and static
rendering. Replace "in practice" with "a coupled set" to drop the soft
hedge.

Drop the lead "wrappers around format_text" sentence on MailFormattingHelper
since the module body already shows the wrapping; the WHY (channel pinning,
extension/helper name parity) is the part worth documenting.
2026-05-27 13:22:56 +03:00
Kabiru Mwenja 499d7820a2 Add render_mode flag and MailFormattingHelper
`format_text` accepts `render_mode:` (`:in_app_html`, `:external_html`,
`:external_text`), which resolves the `only_path`, `static_html` and
`plain_text` context flags as a set. External surfaces (mailer HTML
body, future RSS/PDF/webhook) need absolute URLs and static rendering
together; pinning the trio at the public API keeps callers from
forgetting one. Explicit primitive kwargs still override.

`MailFormattingHelper` exposes `format_mail_html` and `format_mail_text`
thin wrappers around `format_text(render_mode:)`. The `_html` / `_text`
suffix matches the `.html.erb` / `.text.erb` template extension so
caller intent stays visible in the view, with no introspection of
`formats`.

The five WorkPackageMailer view sites use the helpers; `_work_package_details`,
`mentioned.html`, `mentioned.text`, `watcher_changed.html`, `watcher_changed.text`
drop the `static_html:`/`only_path:`/`plain_text:` boilerplate.
2026-05-27 13:04:26 +03:00
Oliver Günther 4cc9faef4f Consistently use OpenProject::SqlSanitization instead of forwarding to sanitize_sql_array 2026-05-27 10:08:16 +02:00
Oliver Günther 4724150e3d Avoid quote_string in favor of bindings where possible 2026-05-27 10:08:16 +02:00
Kabiru Mwenja f5957d800f Collapse plain-text formatter into a context option
Same pattern as the static-HTML collapse: the `markdown_as_text` format
symbol was a thin subclass setting a context flag and swapping the filter
list. Replace it with `plain_text: true` on the existing rich formatter,
which now picks between `RICH_FILTERS` and `TEXT_FILTERS` constants based
on the flag. `static_html:` and `plain_text:` now sit as peer options on
one format.

Rename the `as_text` context key to `plain_text` for symmetry with
`static_html`. Update both mailer `.text.erb` views and the two handler
predicates that branch on the flag.
2026-05-26 22:10:29 +03:00
Kabiru Mwenja c607b36b8e Rename with_hash_prefix to format_display_id 2026-05-26 22:10:07 +03:00
OpenProject Actions CI a147cf2168 Merge branch 'release/17.5' into dev 2026-05-26 13:14:53 +00:00
Kabiru Mwenja 94c13c11fa Collapse static-HTML formatter into a context option
The static-HTML pipeline differs from the rich pipeline only by a
context flag - both share the same filter chain. The dedicated
`Markdown::StaticHtmlFormatter` and `:markdown_as_static_html`
format symbol were pure boilerplate around that one-line override.

Callers now pass `format: :rich, static_html: true` and the matchers
read `context[:static_html]` directly.
2026-05-26 14:50:59 +03:00
Kabiru Mwenja 2ca379fe37 Trim verbose comments
Strip explanatory paragraphs and cross-reference jargon
("Mirrors X", "Shared with Y", etc.) from comments introduced
on this branch. Keep only the WHY — the parts of the design
intent that aren't already evident from method names and
short bodies. Pre-existing comments on methods this branch
didn't author stay as-is.
2026-05-26 14:32:37 +03:00
Kabiru Mwenja 989dbf9da8 Name the preload-required predicate
Compress the "do we need to load WP records?" condition into
`preload_required?(context)` so the call site reads as intent rather
than a tangle of two unrelated signals. The reasoning (semantic mode
needs row lookup; static-HTML output needs type/subject for the
anchor) moves to a comment on the predicate, where it belongs.
2026-05-26 14:24:03 +03:00
Kabiru Mwenja e70b9ab21c Tighten mention pipeline: helper extraction, principal preload, coverage
Lift the static-anchor label composition out of LinkHandlers and into
a small Helpers::StaticMacroLabel module so the envelope path
(MentionFilter) and the text-reference path (LinkHandlers) share one
shape — same module called from both, no cross-class reach-through.

Batch the User and Group mention preloads alongside the existing WP
preload so a note with N principals costs one SELECT per type rather
than N. Class lookup now reads from indexed hashes; visibility-gating
stays where it was (at the find for principals, separate from the
label for WPs).

Rename SemanticIdentifier.format → with_hash_prefix; the prior name
was broad enough to invite misuse for arbitrary work-package values.
Override StaticHtmlFormatter#filters explicitly so a future filter
appearing in Formatter#filters is a deliberate decision to apply to
mailer-side rendering, not an automatic one.

Spec coverage: classic-mode quickinfo and inaccessible-WP paths
(symmetric with the existing semantic-mode contexts), a principal
preload N+1 guard, and an anonymous current_user smoke test that
confirms the static-HTML pipeline doesn't raise when invoked without
an authenticated viewer.
2026-05-26 14:24:02 +03:00
Kabiru Mwenja 666069e126 Cleanup unneeded comments, touch up syntax 2026-05-26 14:19:24 +03:00
Kabiru Mwenja e269fddffc Extract shared static-macro label composition
Reviewer feedback on cd122f867cc: the `parts << status / type / label`
block was duplicated between the regex-driven (`WorkPackages` link
handler) and envelope-driven (`MentionFilter`) static paths, with no
guard against silent desynchronisation. Centralise the composition on
the link handler and document why the two callers pass different
labels — the regex path preserves the alias-as-matched, the envelope
path normalises to the WP's current formatted_id.
2026-05-26 14:19:24 +03:00
Kabiru Mwenja ee4c9aee59 Render WP quickinfo macros as static HTML in mailer notes
The `##N` and `###N` work-package macros emit JS-hydrated
`<opce-macro-wp-quickinfo>` custom elements, which mail clients
collapse to empty bullets. Introduce a `:markdown_as_static_html`
format that shares the rich filter chain but signals
`context[:as_static_html]` so the matcher and `MentionFilter` emit a
server-rendered anchor — formatted_id, type name, subject, and (for
`###`) status name — closely mirroring the in-app widget once
flattened.

Mailer HTML templates (`mentioned`, `watcher_changed`,
`_work_package_details`) opt into the new format. Invisible WPs still
render as plain-text labels, matching the cross-project visibility
policy.

`ResourceLinksMatcher.build_cache` and
`MentionFilter#preload_work_package_mentions` eager-load `:type` and
`:status` only when `:as_static_html` is set, leaving the default web
path's two-SELECT shape untouched. Classic-mode preload now also runs
under `:as_static_html` so the link handler can resolve type/subject
for `##`/`###`.

Renames the internal flag `context[:plain_text]` to `context[:as_text]`
to restore symmetry with the user-facing `:markdown_as_text` format.
2026-05-26 14:19:23 +03:00
Kabiru Mwenja a54dd3dc0b Rename :plain_text format to :markdown_as_text
The format runs the full markdown pipeline and then collapses the DOM
to text — it has nothing to do with the existing `:plain` format,
which strips markdown entirely. Moves the formatter under the Markdown
namespace next to the rich-output formatter whose pipeline it mirrors,
and renames the symbol so the relationship is legible from the
formatter_for case clause.
2026-05-26 14:19:11 +03:00
Kabiru Mwenja 5d8929a7c3 Resolve invisible WP mentions to their current formatted_id
The mention filter previously dropped to the envelope's stored text
when the recipient lacked view permission on the referenced work
package, which left stale identifiers in mailer bodies after a
project rename and diverged from the `#N` text-reference path on
the same render.

Adopts the two-SELECT pattern ResourceLinksMatcher uses for `#N`
references: a single unscoped batched lookup for label resolution
plus a visibility-scoped id pluck for anchor gating. Invisible WPs
render as plain text with the current formatted_id; the per-mention
`WorkPackage.visible.find_by` is gone.
2026-05-26 14:19:11 +03:00
Kabiru Mwenja 8d9aa18ad3 Collapse work-package preload state into one cache value object
Pairs unscoped label resolution and viewer-scoped link gating in a
WorkPackagePreloadCache instead of two RequestStore keys with a
five-method save/restore protocol. Exposes one `current_cache` reader;
consumers ask the cache directly via `fetch` and `visible?`.

Extracts a `text_only?` predicate in the WP link handler so the
`context[:plain_text]` and invisible-WP guards collapse into a single
call site. `SemanticIdentifier.format` renames its parameter to
reflect that the input may or may not be semantic.
2026-05-26 14:19:10 +03:00
Kabiru Mwenja 878048f8e8 Resolve WP labels across visibility boundaries in text macros
The macro preload was visibility-scoped — references to work packages the
recipient cannot see would fall through to the literal `#43` shape, even
when the same reference rendered as `DCP-1` for an author with full view
permission. Notification recipients saw misleading numeric ids for cross-
project references in journal notes.

Splits label resolution from link gating:

- `ResourceLinksMatcher.build_lookup` now does an unscoped fetch for the
  primary identifier and a separate visibility-scoped id pluck. The link
  handler reads `visible_to_current_user?` to decide between a navigable
  anchor and a plain-text label.
- `UpdateAncestorsService#set_journal_note` writes `#display_id` so new
  notes carry the semantic shape at the source; render-time resolution
  heals legacy `#N` content for users with view permission.

Tradeoff: a recipient without view permission now sees the WP's semantic
identifier (e.g. `DCP-1`) as plain text rather than `#43`. The reference's
existence was already disclosed by the stored journal text; the project
identifier is the only new piece of information surfaced, and is not
treated as a secret elsewhere in the system (URLs, exports, API).
2026-05-26 14:18:48 +03:00
Kabiru Mwenja 7c9d15e506 Render WP identifiers per current mode in plain-text mailer notes
The `mentioned` and `watcher_changed` text-mailer bodies surfaced raw
journal markdown — numeric `#42` references stayed numeric in semantic
mode, and `<mention>` envelopes leaked as HTML source.

Introduces `:plain_text` as a sibling format inside the existing Plain
module. The filter chain mirrors the markdown pipeline (markdown,
sanitization, mention, pattern-matcher) and finishes with a new
`PlainTextOutputFilter` that collapses the DOM to text. The
`WorkPackages` link handler and `MentionFilter` get plain-text branches
keyed off `context[:plain_text]` so identifier resolution stays in one
place across rich and plain channels.

Closes https://community.openproject.org/wp/74762
2026-05-26 14:18:17 +03:00