240 Commits

Author SHA1 Message Date
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 61cd01b784 Add associated_visible_resource to properly handle undisclosed work packages 2026-05-26 07:09:59 +02:00
Oliver Günther 7ae5604869 Merge pull request #23070 from opf/fix/relation-visible-scope
The performance decreased because of a combination of calls that were supposed to increase performance. 

We have a mechanism in place which automatically eager loads models needed in the element representers when a collection of them is rendered. This is to avoid N+1 queries of course. But, if eager loading is  combined with e.g., a LIMIT, which we do because we paginate, rails automatically falls back to issuing two instead of just one SQL statement. Which makes sense as otherwise LEFT JOINS might mess with the result set. 

But Rails does so in a somewhat simple fashion. It uses the first query to get the DISTINCT ids. The second is used to load the values (without a limit). But instead of removing all WHERE statements in the second SQL statement and then apply just the one for the ids, it keeps the original WHERE statement and applies the one for the ids on top. The problem with that is that the database trips on that (I didn't check the why) and uses a less than optimal query plan. 

That was the problem here as well. The first query remained reasonable quick (300ms) but the second one took 25s. 

The fix is to split the two statements by hand in the representer whenever eager loading is defined. The first query has all the filters but no eager loading and fetches the ids. The second takes the ids, and with eager loading included loads the data. Et voila, second query takes 10ms.   

That at least works for relations, work_packages and projects. But there are other representers that also seem to have custom behaviour. I'm looking into whether they can be easily adapted.
2026-05-07 15:44:13 +02:00
Jan Sandbrink f9d8bc6614 Introduce SubclassResponsibility error
This error is intended for cases when a method is
intentionally not implemented, because the module/class defining
it expects a subclass (or class including the module) to implement
the method.

This is intended to distinguish it from other cases, such as:
* feature not implemented yet
* edge case of a method call not yet supported

Notably it avoids the misuse of the Ruby-defined NotImplementedError,
which is only intended for much more specific scenarios:

> Raised when a feature is not implemented on the current platform. For example, methods depending on the fsync or fork system calls may raise this exception [...]

Also see https://docs.ruby-lang.org/en/master/NotImplementedError.html
2026-03-27 08:14:56 +01:00
ulferts a1032a55a2 move placeholder functionality to backend schema 2026-02-05 17:04:08 +01:00
Christophe Bliard 5292033e1b Avoid deprecation warnings for time and cost entries representers
They both use `work_package` and `work_package_id` to render links,
which generates verbose deprecation warnings. They are filling up logs.

Force usage of `entity` and `entity_id` instead in the api representers
to reduce the burden.
2025-12-02 10:21:16 +01:00
ulferts 7653fbf66b workspace references in representers and auxilliary endpoints 2025-11-25 16:47:59 +01:00
Jan Sandbrink a82257ac66 Automatically pre- and eager-load collections
Index endpoints will automatically discover and use
the `to_eager_load` and `to_preload` declarations of their
representers. This takes away the possibility of forgetting
to add those to the scope.

I found a few endpoint that didn't use them, when other endpoints
rendering the same collection did.

Interestingly the SCM integration modules consistently declared
those methods but never used them.
2025-11-10 16:16:05 +01:00
Jan Sandbrink 51c2c89cb0 Preload entities when rendering time entries
We were previously eager-loading work packages, but
when time entries were refactored to have a polymorphic association
to "entities", eager loading was not possible anymore and the eagerload
was removed without replacement (see eb4a1d7138).

However, preloading is a viable alternative for polymorphic associations,
so we use that now instead. Docs around the "to_eager_load" and the newly
added "to_preload" method have been added to clarify the purpose of these two
methods.
2025-10-24 14:47:00 +02:00
Jan Sandbrink 2d0d20713d Extract checking for selection into result method
Adding this method to the result makes it available to any
component involved in the SqlWalker implementation, so it
should be more reusable.

The code that's calculating the actual SELECT SQL statements is
not making use of the new helper, so some duplication still exists,
but hopefully we'll not deduplicate more than the current state.
2025-10-21 16:14:30 +02:00
Jan Sandbrink 9e18edf54a Only count total when necessary
It's easily possible that the selects do not
require the calculation of the total number of elements.
However, since we resolve the number of total elements ahead
of constructing the complex SQL query, there's no way for the
database to optimize this out. Thus we have to manually skip
the total calculation if we do not need to perform it.
2025-10-21 14:53:17 +02:00
Jan Sandbrink 599d94242d Do not issue SQL count for number of elements on current page
We will be rendering the elements on the current page anyways,
so it's unavoidable that we load them. By forcing us through to_a.size,
we make sure that the elements are loaded first and then only count how
many elements have been loaded. Since AR caches the result, the relation
will not be loaded twice.

Previously we had a useless SQL count query, which can be tremendously
slower than the actual loading of elements. In the case of time entries
for a larger database, the COUNT took ~1.5 seconds, when the loading
of those same elements only took ~20ms. I don't hope that this ratio
is generalizable to all collection API endpoints, but it's definitely
a nice speed boost.
2025-10-16 16:26:02 +02:00
Tobias Dillmann ceee1e8382 [#64530] API renders formula for calculated values 2025-09-14 17:34:39 +02:00
Jan Sandbrink 1587c2f233 Validate _links in API requests
Respond with a proper HTTP 400 response
for some cases of invalid _links formatting
in write requests to the API.
2025-08-18 09:03:47 +02:00
Jan Sandbrink 886e824f62 Merge pull request #19740 from opf/concurrent-group-member-updates
Replace user_ids param with (add|remove|replace)_user_ids
2025-08-11 14:34:08 +02:00
Eric Schubert 59c51d1993 [#60672] fix sql representer
- add exception for "total only"
- add unit tests
2025-08-06 14:46:00 +02:00
Eric Schubert 17aea283f6 [#60672] fix select total for project with no wps
- https://community.openproject.org/work_packages/60672
- short circuit projection if count is 0
2025-08-05 17:11:17 +02:00
Jan Sandbrink 706fb7c645 Replace user_ids param with (add|remove|replace)_user_ids
Previously it was always necessary to provide a full list of users when calling the service.
Now it's also possible to provide a delta that should be achieved.

This allows to simplify calls to the service, when only the delta is known (e.g. "add this user").
It also makes those calls safer, since the internals of the Groups::UpdateService are already locked
through an advisory lock (via BaseContracted), thus concurrent changes to group memberships are serialized
properly inside the service. However, previous implementations would have read the current members of a group
outside of the service scope, where race conditions could have occured.
2025-07-31 09:32:26 +02:00
Tobias Dillmann 6fa35010a5 [#62982] frontend UI decides about displaying a leadingIcon 2025-06-03 17:46:41 +02:00
Tobias Dillmann 8e62fd5b4b display project phase in work package table
make group by for project phase definitions work

group by with leading phase icon

undo unnecessary changes
2025-06-03 17:46:33 +02:00
Oliver Günther e27db03fb0 Ensure existing keys have translations 2025-02-25 10:47:21 +01:00
Alexander Brandon Coles 7a5124522c Fix typo in user_format: s/coma/comma/ 2025-02-14 07:27:08 -03:00
Andreas Pfohl 3bdfc8d7e5 [59920] Fixed by_project_index_resource_spec 2024-12-20 09:57:56 +01:00
Andreas Pfohl 7314758e32 [59920] Fixed group_by for single and multiselct hierarchy custom field 2024-12-19 11:00:57 +01:00
Andreas Pfohl 151dbff551 [59174] Fixed group row name rendering 2024-12-05 10:59:39 +01:00
Ivan Kuchin d971aa0bc8 fix copyright years for files which got them from 4bf7a26eb1 2024-08-16 19:27:44 +02:00
Ivan Kuchin 4911b8a149 remove years from copyrights (except for COPYRIGHT file) 2024-07-31 15:02:49 +02:00
Ivan Kuchin fa5d03eae0 rubocop safe autocorrect all except Rails/WhereRange 2024-05-30 19:54:08 +02:00
ulferts 3b2121f733 Revert "Merge remote-tracking branch 'origin/release/13.4' into dev"
This reverts commit 40b2bbeb09, reversing
changes made to b4c6cb17cc.
2024-03-21 11:31:17 +01:00
Ivan Kuchin 7787e457a3 Revert "Merge branch 'dev' into release/13.4"
This reverts commit a901541269, reversing
changes made to e573ca00b7.
2024-03-20 20:19:08 +01:00
Ivan Kuchin 9e4934cd0a change quotes using rubocop --only Style/StringLiterals,Style/QuotedSymbols -a 2024-03-20 18:05:22 +01:00
Christophe Bliard c795874f7f Update copyright year for 2024
command used: `rg -l 'Copyright \(C\) 2012-202\d the OpenProject' | xargs -n 100 sed -i -r 's/Copyright \(C\) 2012-202. the OpenProject/Copyright (C) 2012-2024 the OpenProject/'`
2024-01-02 16:23:54 +01:00
ulferts 8742bcb805 introduce cache_if option for custom field injector
Using the config option, the project representer can hide all custom field values (link, property, embedded)
if the user does not have the necessary permission (:view_project)
2023-12-06 17:16:49 +01:00
Klaus Zanders d67c29253e Get rid of current_user_allowed_to method in the API 2023-10-30 11:50:56 +01:00
Eric Schubert cebc82f7de Merge branch 'dev' into implementation/48044-use-location-picker-modal-to-insert-project-folder-name 2023-05-26 10:37:26 +02:00
Dombi Attila c86cf5be01 [#48248] Work package in query without timestamps have cached timestamps url parameter
https://community.openproject.org/work_packages/48248
2023-05-25 09:44:30 +03:00
Eric Schubert 41385cc658 [#48044] added api specifications for project storages endpoints 2023-05-24 16:18:55 +02:00
ulferts 6e17dce314 mark the link of members in the group representer uncacheable
That link should be guarded by a permission check but that permission check short circuited if the cache is used.
2023-05-11 15:35:09 +02:00
Christophe Bliard 9e865b4f7b lint: Run rubocop safe autocorrect
Command is `rubocop --safe --autocorrect app lib lib_static modules spec`
2023-03-09 10:25:57 +01:00
Sebastian Fiedlschuster a24a06fefa baseline api: refactoring nomenclature in collection representer
`query` refers to the `Query` object. `query_params` refers to a hash of query parameters.

https://github.com/opf/openproject/pull/11783#discussion_r1116731624
2023-02-27 23:03:21 +01:00
Christophe Bliard 33a591b49d refactor: Improve readability with explicit parameter names 2023-01-23 09:31:23 +01:00
Christophe Bliard 21a696ef9b Update copyright information for 2023 2022-12-30 15:51:26 +01:00
ulferts 2321701f7f move property name conversion for writability check
This way, the conversion occurs where the name is determined and representation logic does not mix with business logic.
2022-12-02 17:09:33 +01:00
ulferts 7b4db84609 return empty array instead of null
`_embedded/elements` should always have an array, even if it is empty to not trip up clients.
2022-11-23 12:06:06 +01:00
Dombi Attila e8867d16c4 Merge branch 'dev' into implementation/43677-extend-notification-representer-to-include-the-date-lines 2022-10-28 17:39:24 +03:00
Christophe Bliard 75f272504a Change NotificationSettings duration units to days
Days are easier to work with than hours when building SQL requests.

Also change "everyday" value for overdue from 0 to 1, for consistency
with the other values.
2022-10-28 15:53:20 +02:00
ulferts 3c8d0001f0 add details to notification representer 2022-10-21 13:44:31 +02:00
Dombi Attila 40688d6304 Create a duration_property helper in the API::Decorators::DateProperty 2022-10-18 13:24:57 +03:00
ulferts 4200b38617 autofix new rubocop cops 2022-08-02 18:02:45 +02:00
ulferts 71e6f28df5 reduce count calls in collection representer
will_paginated, when actually fetching the records will do an SQL count on top of the fetching. We don`t need that
in our offset paginated represters since those implement their own counts.

And if the per_page is 0, we don`t even have to try to fetch any objects so we can use `none` to avoid the database
roundtrip.
2022-06-21 18:20:52 +02:00