fix: root case-scoped dashboard widgets at cases instead of alerts - #1115
fix: root case-scoped dashboard widgets at cases instead of alerts#1115Scharxi wants to merge 1 commit into
Conversation
Every custom dashboard widget query was rooted at `alerts` (_BASE_TABLE = 'alerts'), reaching `cases` and case-scoped child tables (case_tasks, case_notes, case_assets, ...) via outerjoin(Cases, Alert.cases). A case with 0 merged alerts never produced a base row, so it - and everything joined through it - never appeared. A case with N merged alerts produced N duplicate base rows, so every joined child-table row was counted N times. Reproduces dfir-iris#1112 exactly: 4 cases with 1 task each, merged into 0/2/2/1 alerts, showed a Total Tasks count of 5 instead of 4. Adds _CASE_ROOTED_TABLES, the set of tables reachable from `cases` without needing `alerts` at all (cases itself, case_owner/creator/ reviewer, case_tags/tags, case_assets(+types), case_iocs(+types), case_events, case_notes, case_tasks, review_status, case_state). When every field/group_by/filter/time_column a widget references is in that set, the query is rooted at `cases` directly instead of `alerts` - no fan-out, no invisibility - while every join lambda for those tables was already written to reference only `Cases`, so none of them needed to change. Widgets touching any alert-only table keep the exact original alerts-rooted path, byte-for-byte, so there is no behavior change for the widgets already proven correct. Also generalizes the access-control filter (previously alert-only) and the existing tags/case_tags scoped-subquery filter (previously assumed `cases` was always joined, never the base) to both modes. Adds a regression test creating the exact 4-case/0-2-2-1-alert scenario from the issue and asserting both a Number widget (count) and a Table widget (per-case rows) now reflect the true per-case data instead of the alert-fanout-inflated one.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
hi @Scharxi - thanks a lot for the issues and the PRs! Please note that we are currently migrating to IRIS v3, which not yet published but changes a lot, including a whole new backend and SvelteKit frontend. We'll see how it fits when we go public 🙏 |
Summary
Custom Dashboard widgets on case-scoped child tables (
case_tasks,case_notes,case_assets,case_iocs,case_events, tags, owner/creator/reviewer, review status, case state) now reflect true per-case data, independent of how many alerts happen to be merged into a case.What changed
Every widget query was rooted at
alerts(_BASE_TABLE = 'alerts'), reachingcasesand its child tables viaouterjoin(Cases, Alert.cases):Adds
_CASE_ROOTED_TABLES, the set of tables reachable fromcaseswithout needingalertsat all. When every field/group_by/filter/time_column a widget references is in that set, the query is rooted atcasesdirectly instead ofalerts— no fan-out, no invisibility. Every join lambda for those tables already referenced onlyCases, so none needed to change. Widgets touching any alert-only table keep the exact original alerts-rooted path, byte-for-byte — no behavior change for widgets already proven correct.Also generalizes the access-control filter (previously alert-only) and the existing tags/
case_tagsscoped-subquery filter (previously assumedcaseswas always joined, never the base) to both modes.Adds a regression test creating the exact 4-case / 0-2-2-1-alert scenario from the issue and asserting both a Number widget (count) and a Table widget (per-case rows) reflect true per-case data.
Validation
tests/tests.py::test_custom_dashboard_case_child_table_widgets_are_not_affected_by_merged_alert_count(new).Total Tasksrenders 4 (not 5), theTasks per Casetable shows each case exactly once including the 0-alert case. Cross-checked an alerts-rooted widget (Total Alerts= 5) and the new cases-rooted count (Total Cases= 5) to confirm the untouched path and the new path are both correct side by side.Notes for the reviewer
None — no behavior change for existing alert-rooted widgets; this only changes the query root for widgets that touch exclusively case-scoped tables.
Linked
Fixes #1112
Fixes #1091
Ready for review once out of draft.