Skip to content

feat: Disallow new cypher rule if query yields no results (BED-7739)#2835

Open
dcairnsspecterops wants to merge 8 commits into
mainfrom
BED-7739-disable-save-query-if-no-results
Open

feat: Disallow new cypher rule if query yields no results (BED-7739)#2835
dcairnsspecterops wants to merge 8 commits into
mainfrom
BED-7739-disable-save-query-if-no-results

Conversation

@dcairnsspecterops
Copy link
Copy Markdown
Contributor

@dcairnsspecterops dcairnsspecterops commented May 28, 2026

Description

Describe your changes in detail

Motivation and Context

Resolves <TICKET_OR_ISSUE_NUMBER>

Why is this change required? What problem does it solve?

How Has This Been Tested?

Please describe in detail how you tested your changes.
Include details of your testing environment, and the tests you ran to
see how your change affects other areas of the code, etc.

Screenshots (optional):

Types of changes

  • Chore (a change that does not modify the application functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Database Migrations

Checklist:

Summary by CodeRabbit

  • New Features
    • Cypher editor validation added to rule forms—queries must return at least one result before saving.
    • Real-time validation updates and visual error styling in the Cypher editor.
  • Bug Fixes
    • Form submission blocked when Cypher validation fails to prevent invalid creates/updates.
    • Users now receive a notification when Cypher queries produce no results.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 07a7b508-94ff-460f-90d2-2a6c91cd0b1e

📥 Commits

Reviewing files that changed from the base of the PR and between 7e117ac and b8a7ea7.

📒 Files selected for processing (4)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/PrivilegeZonesCypherEditor/PrivilegeZonesCypherEditor.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/RuleForm.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/SeedSelectionPreview.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/rule-form-utils.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/PrivilegeZonesCypherEditor/PrivilegeZonesCypherEditor.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/RuleForm.tsx

📝 Walkthrough

Walkthrough

Cypher editor validation is added to the privilege zones rule form: a cypherEditorInvalid flag is tracked in form state and context, SeedSelectionPreview auto-detects empty Cypher results and toggles the flag (with a notification), submission is blocked when invalid, and the editor shows an error border when invalid.

Changes

Cypher Editor Validation Flow

Layer / File(s) Summary
State type and context definition
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/types.ts, packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/RuleFormContext.tsx
RuleFormState gains cypherEditorInvalid: boolean. RuleFormContext interface and initialValue are updated to include and initialize the flag to false.
Validation utilities and message
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/rule-form-utils.ts
Adds shared emptyFunction no-op and CYPHER_MUST_HAVE_RESULTS notification message constant.
Form state management and submission validation
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/RuleForm.tsx
RuleForm reducer handles set-cypher-editor-validation and includes cypherEditorInvalid in initial state; onSubmit blocks create/patch when cypherEditorInvalid is true and emits CYPHER_MUST_HAVE_RESULTS. RuleFormContext.Provider exposes cypherEditorInvalid.
Automatic validation from Cypher results
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/SeedSelectionPreview.tsx
SeedSelectionPreview adds a useEffect that inspects fetched preview results and dispatches set-cypher-editor-validation; it emits CYPHER_MUST_HAVE_RESULTS when the results are empty and the flag was not set.
Validation state visual feedback
packages/javascript/bh-shared-ui/src/views/PrivilegeZones/PrivilegeZonesCypherEditor/PrivilegeZonesCypherEditor.tsx
Editor reads cypherEditorInvalid from context and conditionally applies border-error border-2 classes; also imports shared emptyFunction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

user interface

Suggested reviewers

  • TheNando
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete with placeholder text and unfilled sections. Critical details like actual motivation, testing procedures, and change type are missing or unspecified. Fill in all required sections: provide specific motivation, describe testing approach, specify change type, and confirm checklist items are completed.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: preventing new Cypher rules from being saved if the query returns no results, and includes the associated ticket number (BED-7739).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch BED-7739-disable-save-query-if-no-results

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the user interface A pull request containing changes affecting the UI code. label May 28, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/RuleForm.tsx`:
- Around line 281-291: The onSubmit handler currently shows a notification when
cypherEditorInvalid is true but continues to call handlePatchRule or
handleCreateRule; update the onSubmit callback (the const onSubmit:
SubmitHandler<RuleFormInputs> using cypherEditorInvalid, addNotification,
handleCreateRule, handlePatchRule, ruleId) to return early after
addNotification(CYPHER_MUST_HAVE_RESULTS) when cypherEditorInvalid is true so
that neither handlePatchRule nor handleCreateRule run for invalid Cypher.

In
`@packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/SeedSelectionPreview.tsx`:
- Around line 63-74: The effect currently treats any fetch completion
(sampleResultsFetched) as a trigger and may mark cypherEditorInvalid for
non-Cypher rules or failed requests; update the guard so it only runs when the
preview is for a Cypher rule and the sample results successfully returned.
Concretely, add a rule-type check (e.g., ruleType === 'cypher') and replace or
augment sampleResultsFetched with an explicit success flag (e.g.,
sampleResultsStatus === 'success' or !sampleResultsError) before computing
cypherQueryIsEmpty and dispatching CYPHER_MUST_HAVE_RESULTS; keep references to
directObjects, expandedObjects, cypherEditorInvalid, dispatch, addNotification
and CYPHER_MUST_HAVE_RESULTS when applying the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: ecc1adaa-4232-41af-ac21-7c8e7090a7bb

📥 Commits

Reviewing files that changed from the base of the PR and between ccb3ed5 and 7e117ac.

📒 Files selected for processing (6)
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/PrivilegeZonesCypherEditor/PrivilegeZonesCypherEditor.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/RuleForm.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/RuleFormContext.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/SeedSelectionPreview.tsx
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/rule-form-utils.ts
  • packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/types.ts

Comment on lines +281 to +291
const onSubmit: SubmitHandler<RuleFormInputs> = useCallback(() => {
if (cypherEditorInvalid) {
addNotification(CYPHER_MUST_HAVE_RESULTS);
}

if (ruleId !== '') {
handlePatchRule();
} else {
handleCreateRule();
}
}, [cypherEditorInvalid, addNotification, handleCreateRule, handlePatchRule, ruleId]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Stop submission when Cypher validation fails.

Line [282]-Line [290] still runs handlePatchRule/handleCreateRule after showing the notification, so invalid Cypher can still be saved.

Proposed fix
 const onSubmit: SubmitHandler<RuleFormInputs> = useCallback(() => {
     if (cypherEditorInvalid) {
         addNotification(CYPHER_MUST_HAVE_RESULTS);
+        return;
     }

     if (ruleId !== '') {
         handlePatchRule();
     } else {
         handleCreateRule();
     }
 }, [cypherEditorInvalid, addNotification, handleCreateRule, handlePatchRule, ruleId]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/RuleForm.tsx`
around lines 281 - 291, The onSubmit handler currently shows a notification when
cypherEditorInvalid is true but continues to call handlePatchRule or
handleCreateRule; update the onSubmit callback (the const onSubmit:
SubmitHandler<RuleFormInputs> using cypherEditorInvalid, addNotification,
handleCreateRule, handlePatchRule, ruleId) to return early after
addNotification(CYPHER_MUST_HAVE_RESULTS) when cypherEditorInvalid is true so
that neither handlePatchRule nor handleCreateRule run for invalid Cypher.

Comment on lines +63 to +74
useEffect(() => {
const emptyResults = directObjects?.length === 0 && expandedObjects?.length === 0;
const undefinedResults = !directObjects && !expandedObjects;
const cypherQueryIsEmpty = sampleResultsFetched && (emptyResults || undefinedResults);

if (cypherQueryIsEmpty && !cypherEditorInvalid) {
addNotification(CYPHER_MUST_HAVE_RESULTS);
dispatch({ type: 'set-cypher-editor-validation', cypherEditorInvalid: true });
} else if (!cypherQueryIsEmpty && cypherEditorInvalid) {
dispatch({ type: 'set-cypher-editor-validation', cypherEditorInvalid: false });
}
}, [directObjects, expandedObjects, cypherEditorInvalid, dispatch, sampleResultsFetched, addNotification]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Gate invalid-state updates to successful Cypher previews only.

Line [66]-Line [73] uses isFetched and no rule-type guard, so request failures or non-Cypher previews can incorrectly set cypherEditorInvalid and trigger the Cypher-specific toast.

Proposed fix
-    const { data: sampleResults, isFetched: sampleResultsFetched } = useQuery({
+    const { data: sampleResults, isSuccess: sampleResultsSuccess } = useQuery({
         queryKey: ['privilege-zones', 'preview-selectors', ruleType, seeds, expansion],
         queryFn: async ({ signal }) => {
             return apiClient
                 .assetGroupTagsPreviewSelectors({ seeds, expansion }, { signal })
                 .then((res) => res.data.data['members']);
         },
         retry: false,
         refetchOnWindowFocus: false,
         enabled: seeds.length > 0,
     });

@@
     useEffect(() => {
-        const emptyResults = directObjects?.length === 0 && expandedObjects?.length === 0;
-        const undefinedResults = !directObjects && !expandedObjects;
-        const cypherQueryIsEmpty = sampleResultsFetched && (emptyResults || undefinedResults);
+        const shouldValidateCypher = ruleType === SeedTypeCypher && sampleResultsSuccess;
+        if (!shouldValidateCypher) {
+            if (cypherEditorInvalid) {
+                dispatch({ type: 'set-cypher-editor-validation', cypherEditorInvalid: false });
+            }
+            return;
+        }
+
+        const cypherQueryIsEmpty = (sampleResults?.length ?? 0) === 0;

         if (cypherQueryIsEmpty && !cypherEditorInvalid) {
             addNotification(CYPHER_MUST_HAVE_RESULTS);
             dispatch({ type: 'set-cypher-editor-validation', cypherEditorInvalid: true });
         } else if (!cypherQueryIsEmpty && cypherEditorInvalid) {
             dispatch({ type: 'set-cypher-editor-validation', cypherEditorInvalid: false });
         }
-    }, [directObjects, expandedObjects, cypherEditorInvalid, dispatch, sampleResultsFetched, addNotification]);
+    }, [ruleType, sampleResults, sampleResultsSuccess, cypherEditorInvalid, dispatch, addNotification]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/javascript/bh-shared-ui/src/views/PrivilegeZones/Save/RuleForm/SeedSelectionPreview.tsx`
around lines 63 - 74, The effect currently treats any fetch completion
(sampleResultsFetched) as a trigger and may mark cypherEditorInvalid for
non-Cypher rules or failed requests; update the guard so it only runs when the
preview is for a Cypher rule and the sample results successfully returned.
Concretely, add a rule-type check (e.g., ruleType === 'cypher') and replace or
augment sampleResultsFetched with an explicit success flag (e.g.,
sampleResultsStatus === 'success' or !sampleResultsError) before computing
cypherQueryIsEmpty and dispatching CYPHER_MUST_HAVE_RESULTS; keep references to
directObjects, expandedObjects, cypherEditorInvalid, dispatch, addNotification
and CYPHER_MUST_HAVE_RESULTS when applying the change.

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

Labels

user interface A pull request containing changes affecting the UI code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant