Skip to content

feat: add saved views API with proper migration (#235)#403

Open
khat190 wants to merge 14 commits into
utksh1:mainfrom
khat190:feat/saved-views-backend
Open

feat: add saved views API with proper migration (#235)#403
khat190 wants to merge 14 commits into
utksh1:mainfrom
khat190:feat/saved-views-backend

Conversation

@khat190
Copy link
Copy Markdown
Contributor

@khat190 khat190 commented May 28, 2026

What Changed

backend/secuscan/saved_views.py — New FastAPI router at /api/v1/saved-views with full CRUD. POST returns 409 on duplicate names, PUT handles overwrite and rename, DELETE is idempotent. FilterPreset validates sortMode and severity at the boundary so invalid values get a 422 before touching the database.

backend/secuscan/migrations/002_add_saved_views.sql — Proper migration file that creates the saved_views table and a case-insensitive name index. Applied automatically by the migration runner on startup.

backend/secuscan/database.py — Added _run_migrations() which scans the migrations directory and applies any .sql files in order. Idempotent — safe to run multiple times.

backend/secuscan/main.py — Two lines: import saved_views_router and app.include_router(saved_views_router).

testing/backend/unit/test_saved_views.py — 23 tests covering create, list, apply, overwrite, rename, delete, duplicate name (409), invalid JSON (422), invalid enum values (422), empty name (422), name too long (422), non-existent ID (404), idempotent delete, and SQL injection via extra fields.

Why

Power users need to save named filter combinations on the Findings page. This PR delivers the backend contract. The frontend hook and panel will follow in a separate PR once this merges.

API

Method | Path | What it does
Method Path What it does
GET /api/v1/saved-views List all saved views
POST /api/v1/saved-views Create (409 if name taken)
PUT /api/v1/saved-views/{id} Update preset or rename
DELETE /api/v1/saved-views/{id} Delete, always 200

Testing

bash
pytest testing/backend/unit/test_saved_views.py -v

Closes #235

@utksh1 utksh1 added level:advanced 55 pts difficulty label for advanced contributor PRs type:feature Feature work category bonus label type:testing Testing work category bonus label area:backend Backend API, database, or service work labels May 29, 2026
Copy link
Copy Markdown
Owner

@utksh1 utksh1 left a comment

Choose a reason for hiding this comment

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

Thanks for the update. I am still seeing a blocker before merge: the migration runner resolves file-backed DB migrations from the database path rather than the package source path. The in-memory tests pass because they use the module directory, while a configured file database can skip 002_add_saved_views.sql and leave the saved-views API without its table. Please resolve migrations relative to the backend.secuscan package location consistently, add coverage for a file-backed database path, and avoid swallowing migration failures silently so startup does not continue with a missing schema.

@khat190
Copy link
Copy Markdown
Contributor Author

khat190 commented May 29, 2026

Implemented the requested migration fixes:

  • Migration discovery now resolves relative to the SecuScan package location rather than deriving the path from the database file location.
  • Migration execution now fails fast by raising a RuntimeError when the migrations directory is missing or when a migration script fails, instead of continuing silently.
  • Added a regression test covering file-backed database initialization and verifying that the saved_views migration is applied successfully.

Validation:

  • 24/24 saved views tests passing locally.
  • Verified migration execution for both in-memory and file-backed database configurations.

@khat190 khat190 requested a review from utksh1 May 29, 2026 17:54
@utksh1
Copy link
Copy Markdown
Owner

utksh1 commented May 30, 2026

Re-reviewed after the latest push. Still blocked: the migration runner must resolve migrations from the backend.secuscan package/source location for file-backed DBs, and startup should not silently continue if a required migration fails. Please add file-backed DB coverage for the saved_views migration path.

@khat190
Copy link
Copy Markdown
Contributor Author

khat190 commented May 31, 2026

Addressed the requested changes:

  • Migration discovery now resolves relative to backend/secuscan/database.py, so migrations are found correctly for file-backed databases regardless of the database file location.
  • Migration failures now raise a RuntimeError and abort startup instead of continuing with a partially migrated schema.
  • Added file-backed DB coverage for the saved_views migration path, including validation that the table is created correctly and that migration failures surface as startup errors.

I also added explicit cleanup in the new file-backed DB test to ensure the database connection is always closed.

After the latest push, the test suite completes successfully (661 passed), but the remaining warnings appear to originate from existing aiosqlite worker-thread teardown behavior in testing/backend/integration/test_database_indexes.py (RuntimeError: Event loop is closed) rather than the new migration tests.

@utksh1
Copy link
Copy Markdown
Owner

utksh1 commented May 31, 2026

Re-reviewed after the latest push. Still blocked: please make migration discovery package-relative for file-backed databases, fail startup visibly if required migrations fail, and add file-backed DB coverage proving saved_views is created outside the in-memory test path.

@khat190
Copy link
Copy Markdown
Contributor Author

khat190 commented May 31, 2026

The migration runner already uses Path(__file__).parent / "migrations" in the current HEAD (c550b79) — this resolves relative to backend/secuscan/database.py regardless of where the database file lives. This was fixed in ef0b666.
The CI failure is a pre-existing issue in test_parser_output_contract.py (waf_detector plugin not found) and test_database_indexes.py (aiosqlite event loop teardown) — both fail on main before this PR. Running pytest testing/backend/unit -q locally gives 359 passed, 0 failures. The saved views tests specifically give 25 passed.
Can you point to a specific line in the current code that needs changing? Happy to fix it immediately.

Copy link
Copy Markdown
Owner

@utksh1 utksh1 left a comment

Choose a reason for hiding this comment

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

Thanks for the updates. I re-reviewed the latest diff and this still needs changes before merge. The migration path is now package-relative and the SQL failure path raises, but _run_migrations() still silently returns when the migrations directory is missing. That means a packaged/deploy-time omission would start the app without creating saved_views, and the API would fail later at runtime instead of failing fast during startup. Please make a missing migrations directory an explicit startup error and keep the existing failure-path coverage aligned with that behavior. While touching this, please also avoid broad formatting/noise in main.py so the PR stays focused on saved views.

@khat190
Copy link
Copy Markdown
Contributor Author

khat190 commented May 31, 2026

Thanks for the feedback

Changes in this update:

  • _run_migrations() now raises a RuntimeError when the migrations directory is missing instead of returning silently.

  • Startup continues to fail fast if a migration script fails.

  • Added coverage for:

    • invalid/corrupted migration files
    • missing migrations directory
  • Existing file-backed database migration coverage remains in place.

All checks are now passing.

@khat190 khat190 requested a review from utksh1 May 31, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:backend Backend API, database, or service work level:advanced 55 pts difficulty label for advanced contributor PRs type:feature Feature work category bonus label type:testing Testing work category bonus label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FRONTEND] Add saved views for Findings and Reports filters

2 participants