Skip to content

feat: Link to project using name and version#1425

Open
WIStudent wants to merge 3 commits intoDependencyTrack:masterfrom
WIStudent:feat/link-project-by-name-version
Open

feat: Link to project using name and version#1425
WIStudent wants to merge 3 commits intoDependencyTrack:masterfrom
WIStudent:feat/link-project-by-name-version

Conversation

@WIStudent
Copy link

Description

This is another try to implement project links that use name and version and do not require uuid. The previous try at #45 seems to be abandoned.

Addressed Issue

resolves #41

Additional Details

This PR adds two additional vue routes:

projects/:name/:version/*

Its beforeEach navigation guard tries to lookup the uuid of the project using the /v1/project/lookup API endpoint. If a uuid was found, it redirects to projects/:uuid. If not, it redirects to the 404 page.

The /* at the end is used to keep trailing subpaths.

projects/MyProject/1.2.3/ -> projects/:uuid
projects/MyProject/1.2.3/components -> projects/:uuid/components

projects/:name/:version

The projects/:name/:version/* route will not match projects/MyProject/1.2.3 because it does not end with a /. That's why projects/:name/:version will redirect to projects/:name/:version/.

projects/:name/:version -> projects/:name/:version/ -> projects/:uuid

Checklist

Signed-off-by: Tobias Trumm <tobias@tobiastrumm.de>
Copilot AI review requested due to automatic review settings January 19, 2026 15:41
@owasp-dt-bot
Copy link

owasp-dt-bot commented Jan 19, 2026

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

Status Scanner 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.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a feature to allow linking to projects using their name and version instead of requiring the UUID. It adds two new Vue Router routes that perform a lookup of the project UUID via a new API endpoint and redirect to the existing UUID-based project routes.

Changes:

  • Added URL_PROJECT_LOOKUP API endpoint constant for project lookup by name and version
  • Added projects/:name/:version/* route with navigation guard that looks up UUID and redirects to UUID-based routes
  • Added projects/:name/:version route that redirects to the wildcard variant with a trailing slash

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
src/shared/api.json Adds the URL constant for the new project lookup API endpoint
src/router/index.js Implements two new routes to support name/version-based project linking with UUID lookup and redirection logic

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +233 to +239
path: `projects/${result.data.uuid}${trailingPathSegments}`,
replace: true,
});
})
.catch(() => {
next({
name: '404',
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

Query parameters from the original URL are not preserved during the redirect. If the original URL contains query parameters (e.g., for filtering or sorting), they will be lost. Consider preserving them by including query: to.query in the next() object alongside the path.

Suggested change
path: `projects/${result.data.uuid}${trailingPathSegments}`,
replace: true,
});
})
.catch(() => {
next({
name: '404',
path: `projects/${result.data.uuid}${trailingPathSegments}`,
query: to.query,
replace: true,
});
})
.catch(() => {
next({
name: '404',
query: to.query,

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

I don't think this is necessary, neither the 404 page nor the project page seem to use query parameters.

Comment on lines +237 to +241
.catch(() => {
next({
name: '404',
replace: true,
});
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

The error handling catches all errors uniformly, but different error types should potentially be handled differently. For example, a 404 (not found) is different from a 401 (unauthorized) or 500 (server error). Consider checking the error response status to provide more appropriate error handling, especially for authorization errors which might need different treatment than simple "not found" scenarios.

Suggested change
.catch(() => {
next({
name: '404',
replace: true,
});
.catch((error) => {
const status = error && error.response && error.response.status;
if (status === 404) {
next({
name: '404',
replace: true,
});
} else if (status === 401 || status === 403) {
next({
name: 'Login',
replace: true,
});
} else {
// Cancel navigation on unexpected errors to avoid misreporting them as "not found"
next(false);
}

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

I don't think this is necessary, both the project page and the lookup require the VIEW_PORTFOLIO permission. If the user doesn't have it, the global forEach navigation guard will redirect to the login page and the beforeEnter navigation guard in the Project By Name and Version route will not be called.

Comment on lines +220 to +222
const searchParams = new URLSearchParams({
name: to.params.name,
version: to.params.version,
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

Project names and versions may contain special characters that need URL encoding. The current implementation doesn't decode these parameters before sending them to the API. If a project name contains special characters (e.g., spaces, slashes), the URL parameters extracted from to.params will already be decoded by Vue Router, but this should be verified. Additionally, consider validating that the name and version parameters don't contain path separators or other invalid characters that could cause routing issues.

Suggested change
const searchParams = new URLSearchParams({
name: to.params.name,
version: to.params.version,
const decodeParam = (value) => {
if (typeof value !== 'string') {
return '';
}
try {
return decodeURIComponent(value);
} catch (e) {
// If decoding fails (malformed escape sequences), fall back to the original value
return value;
}
};
const isValidSegment = (value) =>
typeof value === 'string' && !/[\\/]/.test(value);
const name = decodeParam(to.params.name);
const version = decodeParam(to.params.version);
if (!isValidSegment(name) || !isValidSegment(version)) {
next({
name: '404',
replace: true,
});
return;
}
const searchParams = new URLSearchParams({
name,
version,

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

Spaces and slashes are not a problem if encoded properly, vue-router will decode this /projects/Test%20%2FABC/0.0.1/ to name Test /ABC and URLSearchParams will encode it correctly.

Comment on lines +233 to +239
path: `projects/${result.data.uuid}${trailingPathSegments}`,
replace: true,
});
})
.catch(() => {
next({
name: '404',
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

URL hash fragments are not preserved during the redirect. If the original URL contains a hash (e.g., for in-page navigation or state), it will be lost. Consider preserving the hash by including hash: to.hash in the next() object alongside the path.

Suggested change
path: `projects/${result.data.uuid}${trailingPathSegments}`,
replace: true,
});
})
.catch(() => {
next({
name: '404',
path: `projects/${result.data.uuid}${trailingPathSegments}`,
hash: to.hash,
replace: true,
});
})
.catch(() => {
next({
name: '404',
hash: to.hash,

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

I don't think this is necessary, neither the 404 page nor the project page seem to use hash fragments.

WIStudent and others added 2 commits March 10, 2026 17:39
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Tobias Trumm <tobias@tobiastrumm.de>
Signed-off-by: Tobias Trumm <tobias@tobiastrumm.de>
@WIStudent WIStudent force-pushed the feat/link-project-by-name-version branch from 0677a1b to 059926f Compare March 10, 2026 17:48
@WIStudent WIStudent requested a review from Copilot March 10, 2026 17:50
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Link to project page by name and version

3 participants