Merge remote-tracking branch 'origin/release/17.5' into dev

This commit is contained in:
Oliver Günther
2026-06-10 11:29:44 +02:00
20 changed files with 247 additions and 113 deletions
@@ -47,5 +47,7 @@ module Admin::Settings::ProjectReservedIdentifiers
def blank_title = t("admin.reserved_identifiers.empty_heading")
def blank_description = t("admin.reserved_identifiers.empty_body")
def blank_icon = :"check-circle"
def pagination_params = { params: { action: "index" } }
end
end
@@ -140,5 +140,5 @@ See COPYRIGHT and LICENSE files for more details.
<% end %>
<% if paginated? %>
<%= helpers.pagination_links_full rows %>
<%= helpers.pagination_links_full rows, **pagination_params %>
<% end %>
@@ -77,6 +77,8 @@ module OpPrimer
self.class.main_column.include?(column)
end
def pagination_params = {}
def column_title(name)
_, header_options = headers.assoc(name)
header_options&.dig(:caption)
+1 -1
View File
@@ -141,7 +141,7 @@ ENV PGDATA=/var/openproject/pgdata
COPY --from=openproject/gosu /go/bin/gosu /usr/local/bin/gosu
RUN chmod +x /usr/local/bin/gosu && gosu nobody true
COPY --from=openproject/hocuspocus:17.4.0 --chown=$APP_USER:$APP_USER /app /opt/hocuspocus
COPY --from=openproject/hocuspocus:17.5.0 --chown=$APP_USER:$APP_USER /app /opt/hocuspocus
# Keep node/npm in all-in-one for bundled hocuspocus even when BIM support is disabled.
COPY --from=build-base /usr/local/bin/node /usr/local/bin/node
COPY --from=build-base /usr/local/lib/node_modules /usr/local/lib/node_modules
+112 -83
View File
@@ -14,6 +14,10 @@ We released [OpenProject 17.5.0](https://community.openproject.org/versions/2293
## Important feature changes
Take a look at our release video showing the most important features introduced in OpenProject 17.5.0:
![Release video of OpenProject 17.5](https://openproject-docs.s3.eu-central-1.amazonaws.com/videos/OpenProject_17_5_release.mp4)
### Project-based work package identifiers for clearer references and Jira migrations
OpenProject 17.5 introduces **optional project-based work package identifiers in Beta**. Administrators can choose between the **default numerical sequence** and **project-based IDs** for the entire OpenProject instance.
@@ -21,7 +25,7 @@ OpenProject 17.5 introduces **optional project-based work package identifiers in
> [!NOTE]
> The setting can be reverted later. Existing numerical IDs remain valid and continue to resolve to the same work packages throughout the application, including existing URLs, bookmarks, and references.
![OpenProject administration to select either 'Instance-wide numerical sequence (default)' or 'Project-based semantic identifiers'](openproject-17-5-identifiers-setting.png)
![Work package table for version 17.5 with highlighted project-based work package IDs](openproject-community-project-based-ids-highlighted.png)
Project-based work package identifiers are especially useful for organizations migrating from Jira, as [existing Jira issue identifiers can now be preserved in OpenProject](#jira-migrator-support-for-jira-identifiers-due-dates-and-more). Beyond migrations, project-based IDs provide **shorter sequence numbers and clearer project context**, making it easier to recognize, reference, and share work packages across projects, emails, documents, chats, and integrations.
@@ -32,7 +36,7 @@ Switching to project-based work package identifiers is an instance-wide administ
> [!NOTE]
> Historical references remain functional when project identifiers change.
![OpenProject administration to configure project-based work package identifiers and convert project identifiers](openproject-17-5-project-based-identifier.png)
![OpenProject administration to select either 'Instance-wide numerical sequence (default)' or 'Project-based semantic identifiers'](openproject-17-5-identifiers-setting.png)
#### Support across URLs, searches, exports, and integrations
@@ -43,6 +47,8 @@ Existing integrations such as GitHub and GitLab already support the new identifi
> [!NOTE]
> Project-based work package identifiers are still in Beta. While the feature is supported across important areas of OpenProject, **some areas may continue to display numerical identifiers until support for project-based identifiers is fully implemented**. In these cases, numerical identifiers remain fully functional and continue to resolve to the same work packages.
[See our system admin guide for detailed information on how to manage work package identifiers](../../system-admin-guide/manage-work-packages/work-package-identifiers/).
#### Releasing unused numerical identifiers
When switching from the default numerical sequence to project-based work package identifiers, previously reserved numerical identifiers can be released again if they are no longer needed. This helps administrators avoid unnecessary gaps and keep numerical identifiers available if they later revert to the default sequence.
@@ -116,14 +122,6 @@ Instead of sending an email for every small change, OpenProject now consolidates
[Read more about OpenProject's Meetings module](../../user-guide/meetings/).
### Nested groups for organizational structures and inherited permissions
OpenProject 17.5 introduces nested groups to better represent organizational structures such as departments, teams, or business units.
Groups can now contain subgroups, allowing administrators to model hierarchies directly in OpenProject. Permissions and memberships can also be inherited from parent groups, making it easier to manage access rights consistently across larger organizations.
![Mockup showing users and permissions sorted into hierarchical groups](openproject-17-5-nested-groups-mockup.png)
### Allow multi-selection of roles in workflow
OpenProject 17.5 improves workflow administration by allowing administrators to select and configure multiple roles at once in the workflow configuration. This makes it easier and faster to manage workflows across complex role setups and reduces repetitive configuration work for administrators.
@@ -153,10 +151,36 @@ to requests and also can't be added or altered through JavaScript. It's unlikely
should only be used for browser-contexts, where the new header will still be present. Non-browser API-access should use different authentication
methods (e.g. OAuth or API tokens), which are not affected by this change.
### SSRF protection for the SAML integration
In previous releases, we have introduced improved mechanisms to prevent Server-Side Request Forgery (SSRF) for integrations that communicate with external hosts. In this release, we have extended the SSRF protections to SAML.
In most installations, this will not require any changes.
However, if you operate your SAML using internal IP addresses, you may need to add your IP or range to the `OPENPROJECT_SSRF_PROTECTION_IP_ALLOWLIST` configuration. Please see [the configuration guide for SSRF](https://www.openproject.org/docs/installation-and-operations/configuration/ssrf-protection/) for more information.
We'd like to thank GitHub user [@aslantugay](https://github.com/aslantugay) for reporting on the SAML integration still lacking SSRF protection as part of GitHub advisory https://github.com/opf/openproject/security/advisories/GHSA-mq29-cmv3-rcmr.
<!-- Remove this section if empty, add to it in pull requests linking to tickets and provide information -->
<!-- BEGIN SECURITY FIXES AUTOMATED SECTION -->
## Security fixes
### CVE-2026-52779 - Cross-project authorization bypass allows deleting public Calendar and Team Planner queries from unauthorized projects
A cross-project IDOR / authorization context confusion in the Calendar and Team Planner modules allows a user with management permissions in one project to delete public Calendar or Team Planner Queries from another project where they do not have the corresponding management permissions.
This vulnerability was reported as part of the [YesWeHack.com OpenProject Bug Bounty program](https://yeswehack.com/programs/openproject), sponsored by the European Commission.
For more information, please see the [GitHub advisory #GHSA-jrx5-px3f-vfq4](https://github.com/opf/openproject/security/advisories/GHSA-jrx5-px3f-vfq4)
<!-- END SECURITY FIXES AUTOMATED SECTION -->
<!--more-->
@@ -165,124 +189,129 @@ methods (e.g. OAuth or API tokens), which are not affected by this change.
<!-- Warning: Anything within the below lines will be automatically removed by the release script -->
<!-- BEGIN AUTOMATED SECTION -->
- Feature: Track working hours and availabilities for each user in the system \[[#34911](https://community.openproject.org/wp/34911)\]
- Feature: Exclude certain work package types from automated backlog (per project) \[[#71305](https://community.openproject.org/wp/71305)\]
- Feature: Container header (Sprint/Bucket/Inbox) restyling \[[#72945](https://community.openproject.org/wp/72945)\]
- Feature: Restyled work package card in &quot;Backlogs and sprints&quot; view \[[#73089](https://community.openproject.org/wp/73089)\]
- Feature: Bring sprint sharing (SAFe) to corporate plan \[[#74147](https://community.openproject.org/wp/74147)\]
- Feature: Create work package links through # notation in documents / BlockNote \[[#73664](https://community.openproject.org/wp/73664)\]
- Feature: Create a WorkPackageCard component \[[#73968](https://community.openproject.org/wp/73968)\]
- Feature: Extend the SubHeader component to support quick filter components \[[#73972](https://community.openproject.org/wp/73972)\]
- Feature: Jira Migrator imports project-based semantic issue identifiers \[[#72427](https://community.openproject.org/wp/72427)\]
- Feature: Jira Migrator supports due date, estimated hours and remaining hours. \[[#74807](https://community.openproject.org/wp/74807)\]
- Feature: Meeting series: Add monthly scheduling options \[[#61522](https://community.openproject.org/wp/61522)\]
- Feature: Debounce emails for meetings \[[#66645](https://community.openproject.org/wp/66645)\]
- Feature: Primerize Types form configuration page \[[#69524](https://community.openproject.org/wp/69524)\]
- Feature: Sprint goals \[[#71059](https://community.openproject.org/wp/71059)\]
- Feature: Exclude certain work package types from automated backlog (per project) \[[#71305](https://community.openproject.org/wp/71305)\]
- Feature: Expand work package mentions (##, ###) macros inside CKEditor \[[#74641](https://community.openproject.org/wp/74641)\]
- Feature: Allow Custom Fields on UserQuery \[[#74758](https://community.openproject.org/wp/74758)\]
- Feature: Primerize users administration to allow all filters \[[#74763](https://community.openproject.org/wp/74763)\]
- Feature: Workflows UX improvement: Allow multi-selection of roles in workflow \[[#72242](https://community.openproject.org/wp/72242)\]
- Feature: Administration setting for project-based work package identifiers \[[#71633](https://community.openproject.org/wp/71633)\]
- Feature: Background job for converting project-based semantic work package identifiers \[[#71645](https://community.openproject.org/wp/71645)\]
- Feature: Allow nested Groups to show a company org chart \[[#72224](https://community.openproject.org/wp/72224)\]
- Feature: Workflows UX improvement: Allow multi-selection of roles in workflow \[[#72242](https://community.openproject.org/wp/72242)\]
- Feature: Jira Migrator imports project-based semantic work item identifiers \[[#72427](https://community.openproject.org/wp/72427)\]
- Feature: Allow inline Work Package links within text paragraphs \[[#72817](https://community.openproject.org/wp/72817)\]
- Feature: Container header (Sprint/Bucket/Inbox) restyling \[[#72945](https://community.openproject.org/wp/72945)\]
- Feature: Restyled work package card in &quot;Backlogs and sprints&quot; view \[[#73089](https://community.openproject.org/wp/73089)\]
- Feature: Allow inline Work Package links within text paragraphs in the Documents module \[[#72817](https://community.openproject.org/wp/72817)\]
- Feature: Adapt creation of projects through the API for semantic identifiers \[[#73175](https://community.openproject.org/wp/73175)\]
- Feature: Define database model for project-based work package identifiers \[[#73315](https://community.openproject.org/wp/73315)\]
- Feature: Create work package links through # notation in documents / BlockNote \[[#73664](https://community.openproject.org/wp/73664)\]
- Feature: Adapt work package show view for project-based semantic work package identifiers \[[#73716](https://community.openproject.org/wp/73716)\]
- Feature: Adapt work package lists for project-based semantic work package identifiers \[[#73717](https://community.openproject.org/wp/73717)\]
- Feature: Adapt routes for project-based semantic work package identifiers \[[#73756](https://community.openproject.org/wp/73756)\]
- Feature: Search work packages by their identifier \[[#73761](https://community.openproject.org/wp/73761)\]
- Feature: Adapt email notifications for project-based work package identifiers \[[#73827](https://community.openproject.org/wp/73827)\]
- Feature: Create a WorkPackageCard component \[[#73968](https://community.openproject.org/wp/73968)\]
- Feature: Extend the SubHeader component to support quick filter components \[[#73972](https://community.openproject.org/wp/73972)\]
- Feature: Adapt work package link blocks in BlockNote for project-based semantic work package identifiers \[[#74115](https://community.openproject.org/wp/74115)\]
- Feature: Adapt work package links in CKEditor for project-based semantic work package identifiers \[[#74116](https://community.openproject.org/wp/74116)\]
- Feature: Bring sprint sharing (SAFe) to corporate plan \[[#74147](https://community.openproject.org/wp/74147)\]
- Feature: Adapt GitHub and GitLab modules for semantic identifiers \[[#74364](https://community.openproject.org/wp/74364)\]
- Feature: Adapt work package PDF exports for semantic identifiers \[[#74366](https://community.openproject.org/wp/74366)\]
- Feature: Expand work package mentions (##, ###) macros inside CKEditor \[[#74641](https://community.openproject.org/wp/74641)\]
- Feature: Allow Custom Fields on UserQuery \[[#74758](https://community.openproject.org/wp/74758)\]
- Feature: Primerize users administration to allow all filters \[[#74763](https://community.openproject.org/wp/74763)\]
- Feature: Jira Migrator supports due date, estimated hours and remaining hours. \[[#74807](https://community.openproject.org/wp/74807)\]
- Feature: Add better progress indicator to identifier conversion page \[[#74903](https://community.openproject.org/wp/74903)\]
- Feature: Put &quot;Beta&quot; label on the setting for enabling semantic identifiers \[[#74975](https://community.openproject.org/wp/74975)\]
- Feature: Admin panel for releasing old classic project aliases \[[#74992](https://community.openproject.org/wp/74992)\]
- Bugfix: WP table configuration: overflow due to the very long CF label \[[#46005](https://community.openproject.org/wp/46005)\]
- Bugfix: Tooltip on Team planner not entirely visible \[[#48223](https://community.openproject.org/wp/48223)\]
- Bugfix: Work package configuration dialog&#39;s highlighting tab has no space between radio buttons and labels \[[#64359](https://community.openproject.org/wp/64359)\]
- Bugfix: Misalignment of fields in Work estimates and progress when language=DE \[[#65738](https://community.openproject.org/wp/65738)\]
- Bugfix: Wrong calendar week in My time tracking \[[#68272](https://community.openproject.org/wp/68272)\]
- Bugfix: Asterisks on Project attributes displaced \[[#68633](https://community.openproject.org/wp/68633)\]
- Bugfix: Clicking work package tabs triggers page reload and flickering \[[#69210](https://community.openproject.org/wp/69210)\]
- Bugfix: Infinite SAML Seeding Loop Causing Disk Space Exhaustion \[[#69339](https://community.openproject.org/wp/69339)\]
- Bugfix: Mobile - Include project on WP list is missing spacing \[[#69451](https://community.openproject.org/wp/69451)\]
- Bugfix: Roles selectable as &quot;Role given to a non-admin user who creates a project&quot; that lack essential permissions \[[#69496](https://community.openproject.org/wp/69496)\]
- Bugfix: Fix accessibility errors found by ERB Lint \[[#70166](https://community.openproject.org/wp/70166)\]
- Bugfix: BlockNote: Drag and drop of table blocks broken \[[#71900](https://community.openproject.org/wp/71900)\]
- Bugfix: Connection error on successive navigation to and from a document \[[#71901](https://community.openproject.org/wp/71901)\]
- Bugfix: Impossible to search for archived projects, page reverts to active projects list on its own \[[#71971](https://community.openproject.org/wp/71971)\]
- Bugfix: Click position is lost when activating an inline edit field \[[#72837](https://community.openproject.org/wp/72837)\]
- Bugfix: Incorrect confirmation message when deleting a OAuth token \[[#72958](https://community.openproject.org/wp/72958)\]
- Bugfix: Role not created properly when unselecting all permissions \[[#73494](https://community.openproject.org/wp/73494)\]
- Bugfix: POST/PATCH/DELETE requests to APIv3 return unauthorized \[[#73499](https://community.openproject.org/wp/73499)\]
- Bugfix: Copy &amp; Paste Loses Formatting in Documents \[[#73669](https://community.openproject.org/wp/73669)\]
- Bugfix: Not possible to follow link custom field from work package list view \[[#73673](https://community.openproject.org/wp/73673)\]
- Bugfix: Doubled scrollbar on a Board \[[#73714](https://community.openproject.org/wp/73714)\]
- Bugfix: Jira migrator: &quot;An internal error has occurred&quot; \[[#73736](https://community.openproject.org/wp/73736)\]
- Bugfix: Nextcloud integration shows &quot;No connection to Nextcloud&quot; for folders that have &quot;&amp;&quot; in the name \[[#73855](https://community.openproject.org/wp/73855)\]
- Bugfix: Lists of work packages should sort correctly by semantic id \[[#74156](https://community.openproject.org/wp/74156)\]
- Bugfix: Automatically converting project identifiers should not lead to usage of reserved keywords \[[#74161](https://community.openproject.org/wp/74161)\]
- Bugfix: Moving work packages after switching to semantic and back should not lead to errors \[[#74192](https://community.openproject.org/wp/74192)\]
- Bugfix: Cancel occurrence action item is called &#39;Delete&#39; on My Meetings page and Meeting index page &#39;Past&#39; tab \[[#74303](https://community.openproject.org/wp/74303)\]
- Bugfix: User cannot restore a cancelled occurrence if series has a deleted WP on the agenda \[[#74304](https://community.openproject.org/wp/74304)\]
- Bugfix: Show default section more clearly when using the section selector for a meeting with no sections \[[#74321](https://community.openproject.org/wp/74321)\]
- Bugfix: Closed work packages are still considered to be part of the bucket. \[[#74773](https://community.openproject.org/wp/74773)\]
- Bugfix: Inconsistent handling of &quot;Definition of Done&quot; \[[#74796](https://community.openproject.org/wp/74796)\]
- Bugfix: Backlogs: Missing space on mobile \[[#75188](https://community.openproject.org/wp/75188)\]
- Bugfix: Sprint field is sometimes not visible on the wp page \[[#75194](https://community.openproject.org/wp/75194)\]
- Bugfix: Backlog settings tab switching doesn&#39;t persist in url \[[#75239](https://community.openproject.org/wp/75239)\]
- Bugfix: No &quot;Undisclosed&quot; mention for the parent work package on the wp card for a user without permissions to see the parent \[[#75241](https://community.openproject.org/wp/75241)\]
- Bugfix: Incorrect resize behavior for pasted inline-links \[[#74190](https://community.openproject.org/wp/74190)\]
- Bugfix: Inserting &quot;#&quot; inside text removes content after cursor \[[#74325](https://community.openproject.org/wp/74325)\]
- Bugfix: Cards converting to hash links on copy-paste and DnD \[[#74327](https://community.openproject.org/wp/74327)\]
- Bugfix: Сards converting to hash links on copy-paste and DnD \[[#74327](https://community.openproject.org/wp/74327)\]
- Bugfix: Type colors are not applied correctly at the beginning \[[#74330](https://community.openproject.org/wp/74330)\]
- Bugfix: Impossible to open work packages list from the sidebar after visiting team planner \[[#74331](https://community.openproject.org/wp/74331)\]
- Bugfix: Inconsistent contrast for type colors when switching themes \[[#74332](https://community.openproject.org/wp/74332)\]
- Bugfix: Dropdown option order changes depending on selected item \[[#74333](https://community.openproject.org/wp/74333)\]
- Bugfix: Inconsistent inline chip heights in text flow \[[#74341](https://community.openproject.org/wp/74341)\]
- Bugfix: User can only delete a past occurrence \[[#74363](https://community.openproject.org/wp/74363)\]
- Bugfix: Inconsistent inline-link heights in text flow \[[#74341](https://community.openproject.org/wp/74341)\]
- Bugfix: Inline work package chip has no visual highlight when selected \[[#74385](https://community.openproject.org/wp/74385)\]
- Bugfix: Arrow-down selection for link work package block prevented by tooltip \[[#74393](https://community.openproject.org/wp/74393)\]
- Bugfix: Wrong cursor placement after inserting links to Work Packages in BlockNote \[[#74397](https://community.openproject.org/wp/74397)\]
- Bugfix: Copy/paste of a single block(chip) does not work \[[#74538](https://community.openproject.org/wp/74538)\]
- Bugfix: Roles select panel button should be &quot;Apply&quot; \[[#74560](https://community.openproject.org/wp/74560)\]
- Bugfix: Use memory more efficiently \[[#74579](https://community.openproject.org/wp/74579)\]
- Bugfix: After migration job is complete save button is visible and clicking it triggers a 404 \[[#74623](https://community.openproject.org/wp/74623)\]
- Bugfix: Improve size menu and remove L+XL blocks \[[#74651](https://community.openproject.org/wp/74651)\]
- Bugfix: Admin page for semantic IDs: grammatical issue \[[#74681](https://community.openproject.org/wp/74681)\]
- Bugfix: Semantic ids: semantic identifier mismatch for new-1 \[[#74692](https://community.openproject.org/wp/74692)\]
- Bugfix: Click position is lost when activating an inline edit field \[[#72837](https://community.openproject.org/wp/72837)\]
- Bugfix: Doubled scrollbar on a Board \[[#73714](https://community.openproject.org/wp/73714)\]
- Bugfix: Quick filters don&#39;t react good to medium screen sizes \[[#74832](https://community.openproject.org/wp/74832)\]
- Bugfix: Hide pagination buttons when they are disabled \[[#75258](https://community.openproject.org/wp/75258)\]
- Bugfix: Horizontal ellipsis button misaligned when text expanded on Permissions Report/Workflows pages \[[#75275](https://community.openproject.org/wp/75275)\]
- Bugfix: Jira Migrator: misalignement between the status badge and the import name \[[#72840](https://community.openproject.org/wp/72840)\]
- Bugfix: Imprecise error for unallowed IP when testing Jira connection \[[#75031](https://community.openproject.org/wp/75031)\]
- Bugfix: Imprecise error for SSL errors when testing Jira connection \[[#75032](https://community.openproject.org/wp/75032)\]
- Bugfix: Jira Migrator cannot import a user with non-alphanumeric characters in their name \[[#75238](https://community.openproject.org/wp/75238)\]
- Bugfix: Jira Migrator stops the import for non-existing user in user mention \[[#75248](https://community.openproject.org/wp/75248)\]
- Bugfix: Remove extra space in Jira Migrator backup warning dialog \[[#75353](https://community.openproject.org/wp/75353)\]
- Bugfix: Jira Migrator does not scope issues between import runs. \[[#75355](https://community.openproject.org/wp/75355)\]
- Bugfix: Jira Migrator shows 0 issues info if server does not include the data in serverInfo endpoint \[[#75380](https://community.openproject.org/wp/75380)\]
- Bugfix: Jira Migrator gives unhelpful error message if user email is blank \[[#75381](https://community.openproject.org/wp/75381)\]
- Bugfix: No way to find jira import run history page \[[#75382](https://community.openproject.org/wp/75382)\]
- Bugfix: Enabled rate limiting on Jira instance breaks projects selector. \[[#75391](https://community.openproject.org/wp/75391)\]
- Bugfix: Wrong wording on import page in admin \[[#75422](https://community.openproject.org/wp/75422)\]
- Bugfix: Jira Migrator: Do not disable the new configuration button if the instance is not switched to semantic identifiers \[[#75674](https://community.openproject.org/wp/75674)\]
- Bugfix: Cancel occurence action item is called &#39;Delete&#39; on My Meetings page and Meeting index page &#39;Past&#39; tab \[[#74303](https://community.openproject.org/wp/74303)\]
- Bugfix: User cannot restore a cancelled occurrence if series has a deleted WP on the agenda \[[#74304](https://community.openproject.org/wp/74304)\]
- Bugfix: Show default section more clearly when using the section selector for a meeting with no sections \[[#74321](https://community.openproject.org/wp/74321)\]
- Bugfix: Meetings endpoint /api/v3/recurring\_meetings/:id/occurrences/:start\_time/init is not properly authorized \[[#75449](https://community.openproject.org/wp/75449)\]
- Bugfix: ActiveRecord::InvalidForeignKey on RecurringMeetingsController#end\_series \[[#75463](https://community.openproject.org/wp/75463)\]
- Bugfix: Work package configuration dialog&#39;s highlighting tab has no space between radio buttons and labels \[[#64359](https://community.openproject.org/wp/64359)\]
- Bugfix: Log time modal dropdown&#39;s bottom border is indistignuishable from the modal&#39;s bottom border \[[#65523](https://community.openproject.org/wp/65523)\]
- Bugfix: Wrong calendar week in My time tracking \[[#68272](https://community.openproject.org/wp/68272)\]
- Bugfix: Asterisks on Project attributes displaced \[[#68633](https://community.openproject.org/wp/68633)\]
- Bugfix: \[Meetings\] Exception raised while trying to update Stale Object \[[#68703](https://community.openproject.org/wp/68703)\]
- Bugfix: Clicking work package tabs triggers page reload and flickering \[[#69210](https://community.openproject.org/wp/69210)\]
- Bugfix: Mobile - Include project on WP list is missing spacing \[[#69451](https://community.openproject.org/wp/69451)\]
- Bugfix: Roles selectable as &quot;Role given to a non-admin user who creates a project&quot; that lack essential permissions \[[#69496](https://community.openproject.org/wp/69496)\]
- Bugfix: Text overflow in Baseline modal banner \[[#69526](https://community.openproject.org/wp/69526)\]
- Bugfix: Fix accessibility errors found by ERB Lint \[[#70166](https://community.openproject.org/wp/70166)\]
- Bugfix: Role not created properly when unselecting all permissions \[[#73494](https://community.openproject.org/wp/73494)\]
- Bugfix: POST/PATCH/DELETE requests to APIv3 return unauthorized \[[#73499](https://community.openproject.org/wp/73499)\]
- Bugfix: &quot;Upgrade&quot; button label should not be underlined \[[#73570](https://community.openproject.org/wp/73570)\]
- Bugfix: Not possible to filter for blocked users in time and cost report \[[#73660](https://community.openproject.org/wp/73660)\]
- Bugfix: Not possible to follow link custom field from work package list view \[[#73673](https://community.openproject.org/wp/73673)\]
- Bugfix: Black font in dark mode on wp description \[[#74697](https://community.openproject.org/wp/74697)\]
- Bugfix: Admin page for semantic IDs: long ids cause overflow \[[#74730](https://community.openproject.org/wp/74730)\]
- Bugfix: Add upcoming/past filter to meetings index page filters \[[#74743](https://community.openproject.org/wp/74743)\]
- Bugfix: Redirect to /login is missing the URL query params \[[#74778](https://community.openproject.org/wp/74778)\]
- Bugfix: Missing space between user avatar and name \[[#74853](https://community.openproject.org/wp/74853)\]
- Bugfix: LDAP seeding via OPENPROJECT\_SEED\_LDAP\_\* uses a different (and self-contradictory) key convention than the rest of the env-var settings \[[#75361](https://community.openproject.org/wp/75361)\]
- Bugfix: Incorrect confirmation message when deleting a OAuth token \[[#72958](https://community.openproject.org/wp/72958)\]
- Bugfix: Roles select panel button should be &quot;Apply&quot; \[[#74560](https://community.openproject.org/wp/74560)\]
- Bugfix: Nextcloud integration shows &quot;No connection to Nextcloud&quot; for folders that have &quot;&amp;&quot; in the name \[[#73855](https://community.openproject.org/wp/73855)\]
- Bugfix: Shared work package not showing images of comments \[[#69056](https://community.openproject.org/wp/69056)\]
- Bugfix: Lists of work packages should sort correctly by semantic id \[[#74156](https://community.openproject.org/wp/74156)\]
- Bugfix: Automatically converting project identifiers should not lead to usage of reserved keywords \[[#74161](https://community.openproject.org/wp/74161)\]
- Bugfix: Moving work packages after switching to semantic and back should not lead to errors \[[#74192](https://community.openproject.org/wp/74192)\]
- Bugfix: After migration job is complete save button is visible and clicking it triggers a 404 \[[#74623](https://community.openproject.org/wp/74623)\]
- Bugfix: Admin page for semantic IDs: grammatical issue \[[#74681](https://community.openproject.org/wp/74681)\]
- Bugfix: Admin page for semantic IDs: long ids cause overflow \[[#74730](https://community.openproject.org/wp/74730)\]
- Bugfix: Numeric ID still in the URL of the link opened from the email notification \[[#74760](https://community.openproject.org/wp/74760)\]
- Bugfix: Numeric ID in the email notification after adding watchers \[[#74762](https://community.openproject.org/wp/74762)\]
- Bugfix: Closed work packages are still considered to be part of the bucket. \[[#74773](https://community.openproject.org/wp/74773)\]
- Bugfix: Redirect to /login is missing the URL query params \[[#74778](https://community.openproject.org/wp/74778)\]
- Bugfix: Inconsistent handling of &quot;Definition of Done&quot; \[[#74796](https://community.openproject.org/wp/74796)\]
- Bugfix: Spanish (ES) localization mixes formal and informal second-person forms \[[#74817](https://community.openproject.org/wp/74817)\]
- Bugfix: Numeric ID copied instead of semantic ID in &quot;Copy work package ID&quot; on Backlogs page \[[#74826](https://community.openproject.org/wp/74826)\]
- Bugfix: Search with ID doesn&#39;t work in work package table configuration if work package belongs to another project \[[#74830](https://community.openproject.org/wp/74830)\]
- Bugfix: Quick filters don&#39;t react good to medium screen sizes \[[#74832](https://community.openproject.org/wp/74832)\]
- Bugfix: Numeric ID in URL of the wp link when opened from search results \[[#74834](https://community.openproject.org/wp/74834)\]
- Bugfix: Semantic ID is not shown in search results in different places \[[#74844](https://community.openproject.org/wp/74844)\]
- Bugfix: Missing space between user avatar and name \[[#74853](https://community.openproject.org/wp/74853)\]
- Bugfix: Numeric ID instead of semantic one in the spent time calendar \[[#74900](https://community.openproject.org/wp/74900)\]
- Bugfix: Numeric ID instead of semantic one on the Activity page \[[#74912](https://community.openproject.org/wp/74912)\]
- Bugfix: Numeric ID instead of semantic one in Roadmap \[[#74913](https://community.openproject.org/wp/74913)\]
- Bugfix: Numeric ID instead of semantic one in bulk edit work packages \[[#74926](https://community.openproject.org/wp/74926)\]
- Bugfix: Unable to change a parent on bulk edit of work packages with semantic ID \[[#74927](https://community.openproject.org/wp/74927)\]
- Bugfix: Numeric ID instead of semantic one on the error message on bulk edit \[[#74928](https://community.openproject.org/wp/74928)\]
- Bugfix: Show type of field beside the attribute \[[#74931](https://community.openproject.org/wp/74931)\]
- Bugfix: Numeric ID instead of semantic one on the table of related work packages \[[#74942](https://community.openproject.org/wp/74942)\]
- Bugfix: Numeric ID instead of semantic one on the Time and costs report \[[#74943](https://community.openproject.org/wp/74943)\]
- Bugfix: Numeric ID instead of semantic one on the wp delete confirmation dialogue \[[#74944](https://community.openproject.org/wp/74944)\]
- Bugfix: All-numeric project identifiers are not properly handled in classic mode \[[#74993](https://community.openproject.org/wp/74993)\]
- Bugfix: Fix markdown generation in Hocuspocus and manual copy to clipboard \[[#75024](https://community.openproject.org/wp/75024)\]
- Bugfix: Imprecise error for unallowed IP when testing Jira connection \[[#75031](https://community.openproject.org/wp/75031)\]
- Bugfix: Imprecise error for SSL errors when testing Jira connection \[[#75032](https://community.openproject.org/wp/75032)\]
- Bugfix: Impossible to go back with single click from the user profile to the users list when a filter is added \[[#75179](https://community.openproject.org/wp/75179)\]
- Bugfix: Numeric ID visible in edit mode in links with # \[[#75180](https://community.openproject.org/wp/75180)\]
- Bugfix: Backlogs: Missing space on mobile \[[#75188](https://community.openproject.org/wp/75188)\]
- Bugfix: No tooltip for priority on the wp cards on the backlogs \[[#75240](https://community.openproject.org/wp/75240)\]
- Bugfix: No &quot;Undisclosed&quot; mention for the parent work package on the wp card for a user without permissions to see the parent \[[#75241](https://community.openproject.org/wp/75241)\]
- Feature: Provide project templates within new OpenProject instances \[[#72778](https://community.openproject.org/wp/72778)\]
- Bugfix: Inconsistent naming on admin page \[[#75362](https://community.openproject.org/wp/75362)\]
- Bugfix: Reserved project identifiers: UI fails silently with 404 console error when acting on a deleted project \[[#75483](https://community.openproject.org/wp/75483)\]
- Bugfix: workPackageValue:ID:attribute macros failing with semantic IDs \[[#75574](https://community.openproject.org/wp/75574)\]
- Bugfix: Numeric ID showing in Github tab on work packages without links to PRs \[[#75636](https://community.openproject.org/wp/75636)\]
<!-- END AUTOMATED SECTION -->
<!-- Warning: Anything above this line will be automatically removed by the release script -->
Binary file not shown.

After

Width:  |  Height:  |  Size: 452 KiB

+7
View File
@@ -13,6 +13,13 @@ Stay up to date and get an overview of the new features included in the releases
<!--- New release notes are generated below. Do not remove comment. -->
<!--- RELEASE MARKER -->
## 17.5.0
Release date: 2026-06-10
[Release Notes](17-5-0/)
## 17.3.4
Release date: 2026-06-08
+4 -4
View File
@@ -12,7 +12,7 @@
"@blocknote/server-util": "^0.51.3",
"@hocuspocus/extension-logger": "^3.4.4",
"@hocuspocus/server": "^3.4.0",
"op-blocknote-extensions": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.1/op-blocknote-extensions-0.1.1.tgz",
"op-blocknote-extensions": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.2/op-blocknote-extensions-0.1.2.tgz",
"tsx": "^4.21.0"
},
"devDependencies": {
@@ -4245,9 +4245,9 @@
"license": "MIT"
},
"node_modules/op-blocknote-extensions": {
"version": "0.1.1",
"resolved": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.1/op-blocknote-extensions-0.1.1.tgz",
"integrity": "sha512-4VO5Qf51Z8WQGD24AYhNmGHGGwnfnB3q8KwL48hWTifZq/9IL5rKpwKB+QkxvVUCaT8iwFYwB6QPzGgLJKRVFA==",
"version": "0.1.2",
"resolved": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.2/op-blocknote-extensions-0.1.2.tgz",
"integrity": "sha512-6uGRJ2SlIVq0LwNnb8KZXhX09fvwXzrkrtsoRVZUrZKKsRFCVd15bgOu/3DyOCvwztXj4h+6VP2N6PkzeCBpUA==",
"dependencies": {
"@primer/octicons-react": "^19.20.0",
"i18next": "^25.6.3",
@@ -26,7 +26,7 @@
"@blocknote/server-util": "^0.51.3",
"@hocuspocus/extension-logger": "^3.4.4",
"@hocuspocus/server": "^3.4.0",
"op-blocknote-extensions": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.1/op-blocknote-extensions-0.1.1.tgz",
"op-blocknote-extensions": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.2/op-blocknote-extensions-0.1.2.tgz",
"tsx": "^4.21.0"
},
"devDependencies": {
+4 -4
View File
@@ -106,7 +106,7 @@
"ng2-dragula": "^6.0.0",
"ngx-cookie-service": "^21.3.1",
"observable-array": "0.0.4",
"op-blocknote-extensions": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.1/op-blocknote-extensions-0.1.1.tgz",
"op-blocknote-extensions": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.2/op-blocknote-extensions-0.1.2.tgz",
"openapi-explorer": "^2.4.799",
"pako": "^2.0.3",
"qr-creator": "^1.0.0",
@@ -17516,9 +17516,9 @@
}
},
"node_modules/op-blocknote-extensions": {
"version": "0.1.1",
"resolved": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.1/op-blocknote-extensions-0.1.1.tgz",
"integrity": "sha512-4VO5Qf51Z8WQGD24AYhNmGHGGwnfnB3q8KwL48hWTifZq/9IL5rKpwKB+QkxvVUCaT8iwFYwB6QPzGgLJKRVFA==",
"version": "0.1.2",
"resolved": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.2/op-blocknote-extensions-0.1.2.tgz",
"integrity": "sha512-6uGRJ2SlIVq0LwNnb8KZXhX09fvwXzrkrtsoRVZUrZKKsRFCVd15bgOu/3DyOCvwztXj4h+6VP2N6PkzeCBpUA==",
"dependencies": {
"@primer/octicons-react": "^19.20.0",
"i18next": "^25.6.3",
+1 -1
View File
@@ -153,7 +153,7 @@
"ng2-dragula": "^6.0.0",
"ngx-cookie-service": "^21.3.1",
"observable-array": "0.0.4",
"op-blocknote-extensions": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.1/op-blocknote-extensions-0.1.1.tgz",
"op-blocknote-extensions": "https://github.com/opf/op-blocknote-extensions/releases/download/v0.1.2/op-blocknote-extensions-0.1.2.tgz",
"openapi-explorer": "^2.4.799",
"pako": "^2.0.3",
"qr-creator": "^1.0.0",
@@ -62,6 +62,9 @@ import { FrameElement } from '@hotwired/turbo';
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
import { UrlParamsService } from 'core-app/core/navigation/url-params.service';
import { IanBellService } from 'core-app/features/in-app-notifications/bell/state/ian-bell.service';
import { WP_ID_URL_PATTERN } from 'core-app/shared/helpers/work-package-id-pattern';
const DETAILS_URL_PATTERN = new RegExp(`/details/(${WP_ID_URL_PATTERN})(?:/|$)`);
export interface INotificationPageQueryParameters {
filter?:string|null;
@@ -192,7 +195,7 @@ export class IanCenterService extends UntilDestroyedMixin {
public selectedNotification:INotification;
selectedWorkPackage$ = this.urlParams.pathMatching$(/\/details\/(\d+)/);
selectedWorkPackage$ = this.urlParams.pathMatching$(DETAILS_URL_PATTERN);
constructor() {
super();
+33 -7
View File
@@ -36,15 +36,20 @@ module OpenProject
class << self
delegate :delete, :clear, to: Cache
def fetch(*, **)
ciphertext = Cache.fetch(*, **) { token_encryptor.encrypt_and_sign(yield) }
token_encryptor.decrypt_and_verify(ciphertext)
# Rubocop wants to convert this to ... but we need the first positional args
# for the delete case.
# rubocop:disable Style/ArgumentsForwarding
def fetch(*, **, &)
fetch_and_decrypt(*, **, &)
rescue ActiveSupport::MessageEncryptor::InvalidMessage
# Drop values that can't be read, ensuring the cache heals from unreadable values
# Drop the unreadable value and recompute once. The recompute is a guaranteed
# cache miss, so the second attempt returns the freshly computed plaintext
# without decrypting. If it still raises, the error propagates rather than
# looping, since this second attempt is not rescued.
delete(*)
retry
fetch_and_decrypt(*, **, &)
end
# rubocop:enable Style/ArgumentsForwarding
def read(name, **)
ciphertext = Cache.read(name, **)
@@ -64,10 +69,31 @@ module OpenProject
private
# Reads the cached ciphertext and decrypts it, computing and storing an
# encrypted value on a cache miss. On a miss we already hold the plaintext,
# so we return it directly instead of decrypting what we just encrypted.
def fetch_and_decrypt(*, **)
recomputed = false
value = nil
ciphertext = Cache.fetch(*, **) do
recomputed = true
value = yield
token_encryptor.encrypt_and_sign(value)
end
return value if recomputed
token_encryptor.decrypt_and_verify(ciphertext)
end
def token_encryptor
@token_encryptor ||= begin
key = Rails.application.key_generator.generate_key("op-cache:confidential-values:v1", 32)
ActiveSupport::MessageEncryptor.new(key, cipher: "aes-256-gcm", serializer: YAML)
# MessagePack avoids YAML's alias emission (which broke decryption for hashes
# that reuse the same object for multiple keys, e.g. Saml::Provider#to_h) and,
# unlike :message_pack_allow_marshal, never falls back to Marshal on load.
ActiveSupport::MessageEncryptor.new(key, cipher: "aes-256-gcm", serializer: :message_pack)
end
end
end
@@ -78,7 +78,7 @@ module Bim
end
def direct_upload_finished # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity
attachment_id = attachment_id_from_key(request.params[:key])
attachment_id = session[:pending_ifc_model_attachment_id]
unless callback_context_valid?(attachment_id)
fail_direct_upload
return
@@ -264,10 +264,6 @@ module Bim
actual_payload == expected_payload
end
def attachment_id_from_key(key)
key.to_s.match(%r{\Auploads/[^/]+/file/(\d+)/[^/]+\z})&.captures&.first
end
def fail_direct_upload
flash[:error] = t("bim.error_direct_upload_failed")
redirect_to action: :new
@@ -56,7 +56,7 @@
end
component.with_row(py: 0) do
helpers.pagination_links_full(documents)
helpers.pagination_links_full(documents, params: { action: "index" })
end
end
else
@@ -214,6 +214,22 @@ RSpec.describe DocumentsController do
end
end
describe "#search", with_settings: { per_page_options: "1 5 10" } do
let!(:document2) { create(:document, title: "Second Document", project:, type: document_type) }
it "returns a turbo_stream response" do
get :search, params: { project_id: project.identifier, per_page: 1 }, format: :turbo_stream
expect(response).to have_http_status(:ok)
end
it "renders pagination links that target the index action, not the search action" do
get :search, params: { project_id: project.identifier, per_page: 1 }, format: :turbo_stream
expect(response.body).not_to include("#{search_project_documents_path(project)}?")
end
end
describe "#render_avatars" do
let(:user) { create(:user, member_with_permissions: { project => [:view_documents] }) }
let!(:non_member) { create(:user) }
@@ -64,6 +64,6 @@ export class TabIssueComponent implements OnInit {
}
public getEmptyText() {
return this.I18n.t('js.gitlab_integration.tab_issue.empty',{ wp_id: this.workPackage.id });
return this.I18n.t('js.gitlab_integration.tab_issue.empty', { wp_id: this.workPackage.displayId });
}
}
+2 -2
View File
@@ -7,8 +7,8 @@ name: OpenProject
applicationSuite: openDesk
url: 'https://github.com/opf/openproject'
roadmap: 'https://www.openproject.org/roadmap'
releaseDate: '2026-06-08'
softwareVersion: '17.4.1'
releaseDate: '2026-06-10'
softwareVersion: '17.5.0'
developmentStatus: stable
softwareType: standalone/web
logo: 'publiccode_logo.svg'
@@ -73,13 +73,31 @@ RSpec.describe Admin::Settings::ProjectReservedIdentifiersController do
end
end
describe "GET #search", with_settings: { work_packages_identifier: "classic" } do
describe "GET #search", with_settings: { work_packages_identifier: "classic", per_page_options: "1 5 10" } do
render_views
it "responds with turbo stream" do
get :search, format: :turbo_stream
expect(response).to have_http_status(:ok)
expect(response.media_type).to eq("text/vnd.turbo-stream.html")
end
context "with multiple reserved slugs triggering pagination" do
let!(:project1) { create(:project, identifier: "proj-a") }
let!(:project2) { create(:project, identifier: "proj-b") }
before do
FriendlyId::Slug.create!(sluggable: project1, slug: "old-a")
FriendlyId::Slug.create!(sluggable: project2, slug: "old-b")
end
it "renders pagination links that target the index action, not the search action (regression #STC-811)" do
get :search, params: { per_page: 1 }, format: :turbo_stream
expect(response.body).not_to include("#{search_admin_settings_project_reserved_identifiers_path}?")
end
end
context "with a reserved slug" do
let!(:project) { create(:project, identifier: "current-id") }
@@ -96,5 +96,40 @@ RSpec.describe OpenProject::ConfidentialCache do
expect(OpenProject::Cache.read(cache_key)).not_to be_nil
end
it "raises instead of looping when the value stays unreadable across a retry" do
# Simulate a value that remains an unreadable cache hit even after delete/retry.
allow(OpenProject::Cache).to receive(:fetch).and_return("some clear text")
expect { described_class.fetch(cache_key) { "value" } }
.to raise_error(ActiveSupport::MessageEncryptor::InvalidMessage)
end
end
# Regression: a hash that reuses the same object for two keys was rejected on load
# which the strict read-side load rejected, raising InvalidMessage on every decrypt and
# sending #fetch into an endless delete/retry loop.
describe "with symbol keys and shared object references" do
let(:shared) { "https://idp.example.com/slo" }
let(:value) do
{
my_provider: {
name: :my_provider,
idp_slo_service_url: shared,
idp_slo_target_url: shared
}
}
end
it "roundtrips via #write and #read" do
described_class.write(cache_key, value)
expect(described_class.read(cache_key)).to eq(value)
end
it "decrypts the cached value on a subsequent #fetch without recomputing" do
expect(described_class.fetch(cache_key) { value }).to eq(value)
expect(described_class.fetch(cache_key) { raise "should not recompute" }).to eq(value)
end
end
end