Feat/vulnerability audit filter query params - #1722
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
a05dea2 to
6591dd5
Compare
nscuro
left a comment
There was a problem hiding this comment.
Can we find a way to massively trim down the changeset of this PR? 30k lines added / 20k removed is way too much for what this PR aims to implement.
6591dd5 to
1777aa9
Compare
|
@nscuro I agree with you—maybe it's too much for a single commit. The thing is, we should also start adding some infrastructure for testing. So I'll move the testing setup to a separate branch. In the long term, the UI tests should give us confidence that changes to the UI don't break other parts of the application. 🙂 |
09d7b9b to
dee9153
Compare
|
Testing with some new test for the existing code was created in the PR for #1722 |
The project had no test runner, so behaviour could only be verified by hand against a running instance. Add Jest with jsdom and @vue/test-utils, exposed as `npm test`, `npm run test-watch` and `npm run test-coverage`. Specs live in `tests/`. Vue SFC compilation is deliberately left out: the code under test is plain JavaScript (mixins and shared modules), so the setup avoids depending on vue-jest. Generated coverage output is excluded from ESLint and Prettier, which would otherwise lint the report. Signed-off-by: duderoot <catalin.patruica@xlab-iq.de>
…ters Filter state lived only in component data, so a filtered view could not be bookmarked, shared or restored with the browser's back button. Sync the filter pills to the URL query string. The mapping lives in filterPillsMixin as a table of codecs, one per filter shape: boolean showKevOnly=true (omitted when off) multi-select severity=critical,high text search textSearch=log4j&textSearchFields=vulnerability_id date range publishDateFrom=2024-01-01&publishDateTo=2024-12-31 numeric range cvssv3From=7&cvssv3To=9.5 A view opts in with `filterUrlSync` and declares a `type` per filter, so the other views sharing this mixin are unaffected. Notes on behaviour: * Values from the URL are validated on the way in. Unknown enum values are dropped, numeric bounds are clamped to the filter's range, and malformed dates are ignored, so a hand-edited URL cannot push junk to the API. * Writes use replace() rather than push(), since refining a filter is not a separate destination to step back through. * Filters restored on load rewrite the table's URL before the table is created, so a bookmark costs one request instead of two. * The two audit tabs share one query string, so a view only owns the query while its tab pane is visible, and leaves parameters it does not recognise untouched. VulnerabilityAudit dropped the query string when switching tabs, because it compared fullPath and pushed a bare path. It now compares path and carries the query along. Signed-off-by: duderoot <catalin.patruica@xlab-iq.de>
This reverts commit 40738c8. Signed-off-by: duderoot <catalin.patruica@xlab-iq.de>
dee9153 to
ee277ed
Compare
Write the query string with history.replaceState() and read it back from window.location.search instead; the debounce that existed only to limit navigations goes with it. Tab ownership becomes the reactive filterUrlSync prop, replacing a .tab-pane.active probe that could report the wrong pane mid-switch and silently revert a filter the user had just applied. Back and forward now restore the pills on both tabs: the entry's own path decides which tab may adopt it, since a cross-tab jump reaches the leaving tab while it still reads as the owner. Both views build their API request from the same codec that writes the address bar, so the URL says what was actually requested. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: duderoot <catalin.patruica@xlab-iq.de>
remove test files since the test infrastructure is not in place yet. Add it back when test runers in place. Signed-off-by: duderoot <catalin.patruica@xlab-iq.de>
|
@nscuro I remove all the test infrastructure and the the test files. The changes now are limited to adding the filter paramaters in the query parameter and make them sync whyle user navigate over the back und forwards buttos of the browser 😃 |
Description
Filters on the Vulnerability Audit page are now reflected in the URL, so a filtered view can be bookmarked, shared with a colleague, or restored with the browser's back button. Previously the filter pills kept their state only in component data, so a URL always pointed at the unfiltered view and any selection was lost on reload.
Opening a URL such as
restores those pills and loads the matching results directly.
The mapping is implemented generically in
filterPillsMixin, but each view opts in explicitly, so only the two Vulnerability Audit tabs are affected by this change.Addressed Issue
Related to #1191, which asks for filter state to be expressible in a link. That issue is about the project findings page (
/projects/:uuid/findings), which does not use this mixin, so this PR does not close it — it introduces the mechanism that would make resolving it a small follow-up.Additional Details
Query parameter format
One parameter per filter, named after the filter itself:
showKevOnly=true(omitted when off)severity=critical,hightextSearch=log4j&textSearchFields=vulnerability_id,component_namepublishDateFrom=2024-01-01&publishDateTo=2024-12-31cvssv3From=7&cvssv3To=9.5Design notes
replace()rather thanpush(). Refining a filter is a change to the current view, not a new destination, so adjusting five filters does not leave five entries to step back through. Leaving the page still behaves normally.data(), before filters are read from the query string, so hydration rewrites it before the table component is created. Otherwise every bookmark would fire an unfiltered request followed immediately by the real one.PolicyViolationAudit,ComponentSearchandWorkflowRunListshare this mixin and are deliberately left unchanged. Extending it to them is a matter of settingfilterUrlSyncand declaring atypeper filter.Drive-by fix
VulnerabilityAudit.vuediscarded the query string when switching tabs, because it comparedfullPath(which includes the query) and then pushed a bare path. It now comparespathand carries the query along. Without this the feature could not survive a tab switch.Tests
This repository had no test runner, so the first commit adds Jest with jsdom and
@vue/test-utils, exposed asnpm test/npm run test-watch/npm run test-coverage, with specs undertests/. Vue SFC compilation is deliberately left out: the code under test is plain JavaScript, so the setup does not depend onvue-jest.The feature is covered by 35 tests spanning encoding, decoding, rejection of untrusted values, back/forward navigation, and the tab-gating rules. Two bugs were found and fixed while writing them: a numeric range could be dropped when a query object round-tripped in memory rather than through a URL, and the decoder rejected non-string scalars.
Verified manually against a Dependency-Track 5.0.0 API server as well: applying each filter type updates the URL, reloading restores every pill, switching tabs preserves state, back/forward works, and "Clear all" empties the query string.
Checklist