Skip to content

Resolve project parent before other fields in updateProject - #7262

Merged
nscuro merged 2 commits into
DependencyTrack:mainfrom
adityaanikam:fix-project-collection-classifier-flush-order-7241
Sep 15, 2026
Merged

nscuro merged 2 commits into
DependencyTrack:mainfrom
adityaanikam:fix-project-collection-classifier-flush-order-7241

Conversation

@adityaanikam

@adityaanikam adityaanikam commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

Description

ProjectQueryManager.updateProject sets the new classifier on the persistent project, then resolves the new parent (if any) via a getObjectByUuid call, and only clears collectionLogic afterward. getObjectByUuid runs a query, and DataNucleus flushes pending dirty state before any query executes. If a request converts a collection project back to a regular one (clearing collectionLogic, setting a classifier) while also carrying a parent, that flush writes a row with both classifier and collectionLogic non-null, violating the PROJECT_COLLECTION_CLASSIFIER_check database constraint and surfacing as an uncaught 500 instead of the expected 200.

This is the same class of hazard already documented and guarded a few lines below for collectionTag (resolveTags is deliberately called before collectionLogic is set, for the same reason) — parent resolution just wasn't given the same treatment.

This PR moves parent resolution to the very start of updateProject, before any field is set on the persistent object, so the query runs while it's still clean and nothing flushes prematurely. No other ordering changes.

Scope note: hasActiveChild (raw SQL) and getLatestProjectVersion (JDOQL), used by the isActive/isLatest branches, run queries in the same position in the method and have the same latent hazard. Neither is exercised by the reported issue or the added test, so I left them alone to keep this change scoped to what's reported and verified — flagging here in case a maintainer wants a follow-up.

Addressed Issue

fixes #7241

Additional Details

Added shouldConvertCollectionProjectBackToRegularWithParent to ProjectResourceTest, reproducing the exact reported request shape: a collection project's classifier is set, collectionLogic is omitted (cleared), and a parent is included in the same POST /api/v1/project body. Verified it fails with the original 500 when the fix is reverted (with the test kept), and passes with the fix applied.

Checklist

  • I have read and understand the contributing guidelines
  • This PR fixes a defect, and I have provided tests to verify that the fix is effective
  • This PR implements an enhancement, and I have provided tests to verify that it works as intended
  • This PR introduces changes to the database model, and I have updated the migration changelog accordingly
  • This PR introduces new or alters existing behavior, and I have updated the documentation accordingly
  • This PR is a substantial change (per the ADR criteria), and I have added an ADR under docs/adr/

getObjectByUuid, used to resolve the new parent, triggers a query. Any
JDO query flushes dirty state first, so if the parent block ran after
setClassifier but before setCollectionLogic cleared it, converting a
collection project back to a regular one while also changing its
parent flushed a row with both fields set, violating
PROJECT_COLLECTION_CLASSIFIER_check and surfacing as an uncaught 500.

The same hazard is already handled a few lines below for the
collection tag, which is resolved before collectionLogic is set for
exactly this reason. Moving parent resolution to the top of the
method, before any field is touched, applies the same fix: the query
now runs while the object is still clean, so nothing is flushed early.

Added a test reproducing the reported request shape: converting a
collection project back to a regular one, with a classifier and a
parent in the same request. Reverting the fix reproduces the original
500.

hasActiveChild and getLatestProjectVersion also run queries between
setClassifier and setCollectionLogic, for the isActive and isLatest
branches respectively. Same hazard, not exercised by the reported
case or by the added test, and not changed here to keep this fix
scoped to what was reported and verified.

Signed-off-by: adityaanikam <adityanikam9502@gmail.com>
@owasp-dt-bot

owasp-dt-bot commented Sep 8, 2026 •

Copy link
Copy Markdown

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@codacy-production

codacy-production Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Coverage 92.86% diff coverage · +0.01% coverage variation

Metric Results
Coverage variation ✅ +0.01% coverage variation (-1.00%)
Diff coverage ✅ 92.86% diff coverage (70.00%)

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (dc76b56) 44448 38824 87.35%
Head commit (e7ddb2e) 44448 (+0) 38827 (+3) 87.35% (+0.01%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#7262) 14 13 92.86%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@nscuro nscuro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good. Please resolve the lint failure, then this is good to merge.

@nscuro nscuro added this to the 5.2 milestone Sep 14, 2026
@nscuro nscuro added defect Something isn't working backport/5.1.1 labels Sep 14, 2026
The Lint Java check failed on the test added in the previous commit:
one assertion was longer than palantir-java-format allows. This only
rewraps that line.

Signed-off-by: adityaanikam <adityanikam9502@gmail.com>
@nscuro
nscuro merged commit 8f399b6 into DependencyTrack:main Sep 15, 2026
22 checks passed
nscuro pushed a commit that referenced this pull request Sep 20, 2026
* Resolve project parent before other fields in updateProject

getObjectByUuid, used to resolve the new parent, triggers a query. Any
JDO query flushes dirty state first, so if the parent block ran after
setClassifier but before setCollectionLogic cleared it, converting a
collection project back to a regular one while also changing its
parent flushed a row with both fields set, violating
PROJECT_COLLECTION_CLASSIFIER_check and surfacing as an uncaught 500.

The same hazard is already handled a few lines below for the
collection tag, which is resolved before collectionLogic is set for
exactly this reason. Moving parent resolution to the top of the
method, before any field is touched, applies the same fix: the query
now runs while the object is still clean, so nothing is flushed early.

Added a test reproducing the reported request shape: converting a
collection project back to a regular one, with a classifier and a
parent in the same request. Reverting the fix reproduces the original
500.

hasActiveChild and getLatestProjectVersion also run queries between
setClassifier and setCollectionLogic, for the isActive and isLatest
branches respectively. Same hazard, not exercised by the reported
case or by the added test, and not changed here to keep this fix
scoped to what was reported and verified.

Signed-off-by: adityaanikam <adityanikam9502@gmail.com>

* Apply Spotless formatting to ProjectResourceTest

The Lint Java check failed on the test added in the previous commit:
one assertion was longer than palantir-java-format allows. This only
rewraps that line.

Signed-off-by: adityaanikam <adityanikam9502@gmail.com>

---------

Signed-off-by: adityaanikam <adityanikam9502@gmail.com>
(cherry picked from commit 8f399b6)
Signed-off-by: nscuro <nscuro@protonmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

defect Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTP 500 when converting a collection project back to a regular project, if the request body carries parent

3 participants