Skip to content

Conversation

@rtpt-romankarwacik
Copy link

@rtpt-romankarwacik rtpt-romankarwacik commented Nov 26, 2025

Description

This pull requests adds an option for database management to delete HasSession edges. The pull request has been created using GitHub Copilot.
#853

Motivation and Context

When analyzing sessions the current state is very important. Currently, when ingesting new sessions, the old ones are not deleted. This resolves #853

How Has This Been Tested?

I tested it with dummy data from the UI, where i queried all sessions after insertion, and after deletion.

Screenshots (optional):

Screenshot From 2025-11-26 10-54-00

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist:

Summary by CodeRabbit

Release Notes

  • New Features
    • Added option to delete HasSession relationship edges during database cleanup operations.
    • New checkbox in Database Management interface to control HasSession edge deletion.
    • Extended database wipe functionality to support selective HasSession edge removal with audit logging.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link

github-actions bot commented Nov 26, 2025

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

Walkthrough

This PR adds a new optional feature to the database wipe endpoint that allows selective deletion of HasSession relationship edges. It extends the API schema, backend deletion logic, React UI, and JavaScript client library with a new deleteHasSessionEdges boolean flag.

Changes

Cohort / File(s) Summary
Backend API Enhancement
cmd/api/src/api/v2/database_wipe.go
Added DeleteHasSessionEdges boolean field to DatabaseWipe payload, extended empty-request detection to include the field, implemented deleteHasSessionEdges() method to locate and delete HasSession relationships via graph batch API with audit logging, and expanded imports for graph schema and operations.
React UI Update
cmd/ui/src/views/DatabaseManagement/DatabaseManagement.tsx
Added state management for deleteHasSessionEdges boolean, introduced new FormControlLabel with Checkbox UI component for HasSession edge deletion option, integrated the flag into mutation payload, and extended no-selection detection logic.
OpenAPI Documentation
packages/go/openapi/doc/openapi.json, packages/go/openapi/src/paths/data-quality.clear-database.yaml
Extended request body schema with new deleteHasSessionEdges boolean field and updated operation descriptions to reference HasSession relationship edges as deletable data.
JavaScript Client Library
packages/javascript/js-client-library/src/requests.ts
Added optional deleteHasSessionEdges?: boolean property to ClearDatabaseRequest interface.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as DatabaseManagement UI
    participant API as Backend API
    participant Graph as Graph Database
    participant Audit as Audit Log

    User->>UI: Checks "Delete HasSession" checkbox
    User->>UI: Submits database wipe request
    
    UI->>API: POST /api/v2/clear-database<br/>{deleteHasSessionEdges: true, ...}
    
    rect rgb(200, 220, 255)
    Note over API,Graph: HasSession Deletion Flow (if enabled)
    API->>Graph: Query all (Computer)-[HasSession]->(User)
    Graph-->>API: Return HasSession edges
    API->>Graph: Batch delete HasSession edges
    Graph-->>API: Deletion complete
    API->>Audit: Log HasSession deletion success/failure
    end
    
    API-->>UI: Success response
    UI->>User: Display confirmation
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify that the deleteHasSessionEdges() method correctly queries and deletes HasSession edges using graph batch API.
  • Confirm audit logging captures success and failure states appropriately.
  • Review UI permission handling to ensure the checkbox respects user permissions.
  • Validate that the new field is correctly propagated through the mutation lifecycle and reset on successful deletion.
  • Ensure OpenAPI schema changes match the implementation and client library definitions.

Possibly related PRs

Suggested labels

enhancement, user interface

Suggested reviewers

  • brandonshearin
  • cweidenkeller

Poem

🐰 A wipe that's wise, a choice so fine,
Sessions deleted—when the stars align!
No more old logins cluttering the way,
HasSession edges vanish, hip hooray! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The description covers the main feature but is missing test validation confirmation despite indicating tests were performed; contributing prerequisites are only partially completed. Confirm that tests were added and passed in the checklist; also ensure all contributing prerequisites (assignment, labels, issue association) are fully completed.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main feature addition: enabling deletion of HasSession edges during database management operations.
Linked Issues check ✅ Passed The PR successfully implements the feature requested in issue #853: adds deleteHasSessionEdges option to both API endpoint and UI for selective deletion of HasSession edges.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked issue #853; modifications span API schema, backend logic, UI components, and client library—all supporting the HasSession edge deletion feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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.

@rtpt-romankarwacik
Copy link
Author

I have read the CLA Document and I hereby sign the CLA

Copy link
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: 0

🧹 Nitpick comments (2)
cmd/api/src/api/v2/database_wipe.go (1)

251-276: Consider using a streaming pattern for better scalability.

The current implementation uses ops.FetchRelationships which loads all HasSession relationships into memory at once. For environments with many session edges, this could cause high memory consumption or OOM issues.

The existing DeleteCollectedGraphData function (referenced in relevant snippets) uses a more scalable streaming approach with ops.StartNewOperation, readers, writers, and channels to process IDs incrementally without loading everything into memory.

Consider refactoring to use the streaming pattern:

 func (s Resources) deleteHasSessionEdges(ctx context.Context, auditEntry *model.AuditEntry) (failure bool) {
-	// Use the graph batch API to find and delete all HasSession relationships
-	if err := s.Graph.BatchOperation(ctx, func(batch graph.Batch) error {
-		targetCriteria := query.Kind(query.Relationship(), ad.HasSession)
-
-		rels, err := ops.FetchRelationships(batch.Relationships().Filter(targetCriteria))
-		if err != nil {
-			return err
-		}
-
-		for _, rel := range rels {
-			if err := batch.DeleteRelationship(rel.ID); err != nil {
-				return err
-			}
-		}
-
-		return nil
-	}); err != nil {
+	operation := ops.StartNewOperation[graph.ID](ops.OperationContext{
+		Parent:     ctx,
+		DB:         s.Graph,
+		NumReaders: 1,
+		NumWriters: 1,
+	})
+
+	operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- graph.ID) error {
+		return tx.Relationships().Filter(
+			query.Kind(query.Relationship(), ad.HasSession),
+		).FetchIDs(func(cursor graph.Cursor[graph.ID]) error {
+			for id := range cursor.Chan() {
+				select {
+				case <-ctx.Done():
+					return ctx.Err()
+				case outC <- id:
+				}
+			}
+			return cursor.Error()
+		})
+	})
+
+	operation.SubmitWriter(func(ctx context.Context, batch graph.Batch, inC <-chan graph.ID) error {
+		for {
+			select {
+			case <-ctx.Done():
+				return ctx.Err()
+			case id, ok := <-inC:
+				if !ok {
+					return nil
+				}
+				if err := batch.DeleteRelationship(id); err != nil {
+					return err
+				}
+			}
+		}
+	})
+
+	if err := operation.Done(); err != nil {
 		slog.ErrorContext(ctx, fmt.Sprintf("%s: %s", "there was an error deleting HasSession edges", err.Error()))
 		s.handleAuditLogForDatabaseWipe(ctx, auditEntry, false, "HasSession edges")
 		return true
 	} else {
 		s.handleAuditLogForDatabaseWipe(ctx, auditEntry, true, "HasSession edges")
 		return false
 	}
 }
packages/go/openapi/doc/openapi.json (1)

13319-13319: Clarify description and align terminology with schema.

  • The description says “custom high value selectors,” but the request body uses deleteAssetGroupSelectors. Consider replacing with “asset group selectors” for consistency and to avoid ambiguity. Also, briefly state that deleteHasSessionEdges deletes only HasSession relationships, not nodes. Adding a small request example would help.

Example (description tweak only):

- Wipes your BloodHound data permanently. Specify the data to delete in the request body. Possible data includes collected graph data, HasSession relationship edges, custom high value selectors, file ingest history, and data quality history.
+ Wipes your BloodHound data permanently. Specify the data to delete in the request body. Possible data includes collected graph data, HasSession relationship edges, asset group selectors, file ingest history, and data quality history.

Optionally add a request example under requestBody.content.application/json.example:

{
  "deleteHasSessionEdges": true
}

Based on learnings, this JSON file is generated; please ensure the change is applied to the YAML under packages/go/openapi/src/schemas and the spec is regenerated.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c58475e and 44783e1.

📒 Files selected for processing (5)
  • cmd/api/src/api/v2/database_wipe.go (4 hunks)
  • cmd/ui/src/views/DatabaseManagement/DatabaseManagement.tsx (8 hunks)
  • packages/go/openapi/doc/openapi.json (2 hunks)
  • packages/go/openapi/src/paths/data-quality.clear-database.yaml (2 hunks)
  • packages/javascript/js-client-library/src/requests.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-09-08T19:01:53.112Z
Learnt from: jvacca-specterops
Repo: SpecterOps/BloodHound PR: 1823
File: packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx:108-148
Timestamp: 2025-09-08T19:01:53.112Z
Learning: In BloodHound's CypherSearch component (packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx), the sharing state reset for sharedIds and isPublic after the two-step permissions update is handled elsewhere in the codebase, so additional state reset callbacks in the updateQueryPermissions function are not needed.

Applied to files:

  • cmd/ui/src/views/DatabaseManagement/DatabaseManagement.tsx
��� Learning: 2025-11-25T22:11:53.509Z
Learnt from: LawsonWillard
Repo: SpecterOps/BloodHound PR: 2107
File: cmd/api/src/database/graphschema.go:86-100
Timestamp: 2025-11-25T22:11:53.509Z
Learning: In cmd/api/src/database/graphschema.go, the CreateSchemaEdgeKind method intentionally does not use AuditableTransaction or audit logging because it would create too much noise in the audit log, unlike CreateGraphSchemaExtension which does use auditing.

Applied to files:

  • cmd/api/src/api/v2/database_wipe.go
📚 Learning: 2025-08-28T16:43:43.961Z
Learnt from: mvlipka
Repo: SpecterOps/BloodHound PR: 1784
File: packages/go/openapi/doc/openapi.json:18008-18029
Timestamp: 2025-08-28T16:43:43.961Z
Learning: In SpecterOps/BloodHound, packages/go/openapi/doc/openapi.json is generated from YAML under packages/go/openapi/src/schemas; edits must be made to the YAML and then the spec regenerated.

Applied to files:

  • packages/go/openapi/doc/openapi.json
📚 Learning: 2025-11-25T18:07:04.522Z
Learnt from: superlinkx
Repo: SpecterOps/BloodHound PR: 2083
File: cmd/api/src/model/graphschema.go:42-53
Timestamp: 2025-11-25T18:07:04.522Z
Learning: In the BloodHound codebase (SpecterOps/BloodHound), database models are moving toward a newer architecture where API validation is handled via `jsonschema` at the handler level, which obviates the need for json validation tags on database models themselves.

Applied to files:

  • packages/go/openapi/doc/openapi.json
🧬 Code graph analysis (1)
cmd/api/src/api/v2/database_wipe.go (2)
cmd/api/src/daemons/datapipe/delete.go (1)
  • DeleteCollectedGraphData (33-113)
packages/go/graphschema/ad/ad.go (2)
  • HasSession (53-53)
  • Relationships (1149-1151)
🔇 Additional comments (5)
packages/go/openapi/src/paths/data-quality.clear-database.yaml (1)

24-25: LGTM! Schema changes are correct and consistent.

The OpenAPI schema updates properly document and expose the new HasSession edge deletion capability. The field naming and structure follow the existing patterns for other deletion options.

Also applies to: 38-39

cmd/api/src/api/v2/database_wipe.go (1)

32-35: LGTM! Integration and validation changes are correct.

The struct field addition, imports, empty-request validation, and main workflow integration all follow the established patterns used by other deletion options in this file.

Also applies to: 41-41, 70-70, 195-200

packages/javascript/js-client-library/src/requests.ts (1)

241-241: LGTM! TypeScript interface update is correct.

The optional field addition properly mirrors the backend API and OpenAPI schema, maintaining type consistency across the stack.

cmd/ui/src/views/DatabaseManagement/DatabaseManagement.tsx (1)

42-42: LGTM! UI implementation is correct and consistent.

The React component changes properly integrate the new HasSession edges deletion option:

  • State management follows the established patterns for other checkboxes
  • The reducer correctly handles initialization, selection, reset, and validation
  • The UI checkbox respects permissions and is appropriately labeled
  • The mutation payload correctly includes the new field

All changes align with the existing implementation patterns in this component.

Also applies to: 59-59, 107-107, 137-137, 177-177, 224-224, 263-263, 371-381

packages/go/openapi/doc/openapi.json (1)

13334-13336: Based on my verification, I have sufficient information to assess the review comment. The key findings are:

  1. Context confirmed: The review is for proposed changes adding deleteHasSessionEdges to the clear-database endpoint—this field does not yet exist in the codebase.

  2. YAML source verified: The source file at packages/go/openapi/src/paths/data-quality.clear-database.yaml currently defines 4 properties without individual descriptions.

  3. Current properties: deleteCollectedGraphData, deleteFileIngestHistory, deleteDataQualityHistory, deleteAssetGroupSelectors

  4. Review concerns are valid:

    • Naming consistency across layers (Go, YAML, UI, JS client) is a legitimate concern
    • Input validation (ensuring at least one flag) is a reasonable schema pattern
    • Adding descriptions to properties follows API documentation best practices
    • Regenerating from YAML (not hand-editing JSON) is the correct process

The review comment is technically sound. However, I can streamline it by removing the overly complex verification script (which searches for typos that don't exist yet) and focusing on the core actionable items.


Verify the new deleteHasSessionEdges field is consistently named across all implementation layers and properly validated in the schema.

  • Field name follows existing camelCase pattern (good). Ensure it matches exactly in: Go request struct/handler, YAML schema, UI form key, and JS client.
  • Add a short description for this property in the YAML schema (other properties currently lack individual descriptions; consider adding for consistency).
  • Consider adding schema validation (e.g., anyOf constraint) to require at least one delete flag to prevent no-op requests.
  • Critical: Update packages/go/openapi/src/paths/data-quality.clear-database.yaml with this field, then regenerate packages/go/openapi/doc/openapi.json per project standards. Do not edit the JSON file directly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant