Skip to content

Api v2 delete event #776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Apr 15, 2025
Merged

Api v2 delete event #776

merged 30 commits into from
Apr 15, 2025

Conversation

c8y3
Copy link
Contributor

@c8y3 c8y3 commented Apr 11, 2025

Implement endpoint DELETE /api/v2/cases/{case_identifier}/events/{identifier} to delete an evidence.

  • tests
  • deprecated POST /case/timeline/events/delete/{event_id}
  • fix: DELETE /api/v2/cases/{case_identifier}/evidences/{identifier} should not delete evidence, when user has no permission to access case
  • deprecated create and update events preload hooks
  • removed the adherence of the event business layer with marshmallow and the schema (moved up in the API)
  • created class Events so as to avoid to duplicate and recreate the EventSchema several times in the code (and at runtime)
  • removed endpoint GET /manage/server/check-updates/modal
  • removed endpoint GET /manage/server/make-update
  • fixed all remaining occurrences and activate ruff rule RET506
  • moved some methods from app.util closer to their use in namespace app.schema.utils

Note: this pull request goes hand in hand with the documentation PR#56 in iris-doc-src.

Summary by CodeRabbit

  • Bug Fixes

    • Improved deletion processes with enhanced access controls and clearer error responses for event and evidence removal.
  • Refactor

    • Streamlined event management and removed outdated server update interfaces for a more reliable experience.
  • Tests

    • Expanded test coverage to ensure consistent behavior during deletion operations and proper access validations.

c8y3 added 30 commits April 11, 2025 09:17
…idence when user has no permission to access case should not delete evidence
… when event case identifier and case_identifier do not match
…ELETE /api/v2/cases/{case_identifier}/events/{identifier}
Copy link

coderabbitai bot commented Apr 11, 2025

Walkthrough

This pull request updates several components of the application. The linter configuration in pyproject.toml has been modified. Two server management routes and their associated templates were removed. The error handling and data loading logic in case timeline routes have been refactored, and event-related functionality has been encapsulated into a new Events class. Additionally, the business logic functions for events have been updated for a parameterized design, and utility functions have been reorganized by moving them to a new schema utilities module while removing legacy implementations. New tests have also been added for event and evidence deletion scenarios.

Changes

File(s) Change Summary
pyproject.toml Updated linting configuration: replaced "UP032" with "RET506" in the select list.
src/app/.../manage_srv_settings_routes.py
src/app/.../manage_make_update.html
src/app/.../modal_server_updates.html
Removed two server management routes and deleted the associated update templates.
src/app/.../case_timeline_routes.py Refactored error handling; added helper method _load to centralize event data loading and validation.
src/app/.../events.py Introduced the Events class with methods for creating, retrieving, updating, and deleting case events; moved identifier match check into the class scope.
src/app/.../evidences.py Adjusted control flow in delete_evidence to perform access checks before deletion.
src/app/business/events.py Updated the signatures of events_create and events_update to work with parameterized inputs; added new events_delete function.
src/app/.../case_events_db.py Modified delete_event to remove the external caseid parameter and use the event’s own case_id attribute.
src/app/.../module_handler.py Replaced local logger variable with an imported logger; added a new function call_deprecated_on_preload_modules_hook for logging deprecation warnings.
src/app/schema/marshables.py Updated import paths from app.util to app/schema/utils for several utility functions.
src/app/schema/utils.py New file added with functions: assert_type_mml, str_to_bool, stream_sha256sum, and file_sha256sum.
src/app/util.py Removed several utility functions (decompress_7z, file_sha256sum, stream_sha256sum, str_to_bool, assert_type_mml) and associated imports.
tests/tests_rest_events.py Added multiple new test methods covering event deletion scenarios with various response expectations (204, 404, 403, 400).
tests/tests_rest_evidences.py Added test to ensure evidence is not removed when the user lacks proper access rights.
ui/src/pages/updates.handler.js Removed update management functions, variables, and document ready logic associated with server updates.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant API as REST Endpoint
    participant E as Events Class
    participant B as Business Logic
    participant DB as Database

    U->>API: Request deletion of event
    API->>E: Call delete(event, case_identifier)
    E->>B: Validate event, permissions, and case match
    B->>DB: Execute deletion query
    DB-->>B: Confirm deletion
    B-->>E: Return success status
    E-->>API: Return 204 No Content response
    API-->>U: Send response (204)
Loading

Poem

I’m a bunny, hopping with glee,
Changes abound, as plain as can be.
Routes removed, and events now neat,
New utils and tests make the code complete.
I nibble on updates with a cheerful beat!
🐇✨ Happy coding in every leap!

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@c8y3 c8y3 linked an issue Apr 11, 2025 that may be closed by this pull request
11 tasks
@whikernel
Copy link
Contributor

@coderabbitai review

Copy link

coderabbitai bot commented Apr 14, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@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: 3

🧹 Nitpick comments (5)
source/app/schema/utils.py (1)

34-49: Consider combining nested if checks.
You can simplify the nested checks for max_len, max_val, and min_val into a single condition per block. For example:

- if max_len:
-     if len(input_var) > max_len:
+ if max_len and len(input_var) > max_len:
    raise ValidationError('Invalid data - max length exceeded',
                          field_name=field_name if field_name else 'type')
🧰 Tools
🪛 Ruff (0.8.2)

35-36: Use a single if statement instead of nested if statements

Combine if statements using and

(SIM102)


40-41: Use a single if statement instead of nested if statements

(SIM102)


45-46: Use a single if statement instead of nested if statements

(SIM102)

source/app/business/events.py (3)

53-53: Use direct assignment instead of setattr.

- setattr(event, 'event_category_id', event_category_id)
+ event.event_category_id = event_category_id

This avoids the overhead of setattr for a single known field.

🧰 Tools
🪛 Ruff (0.8.2)

53-53: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)


65-65: Use direct assignment instead of setattr.

- setattr(event, 'event_category_id', event_category_id)
+ event.event_category_id = event_category_id
🧰 Tools
🪛 Ruff (0.8.2)

65-65: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)


88-88: Direct assignment is more conventional than setattr.

- setattr(event, 'event_category_id', event_category_id)
+ event.event_category_id = event_category_id
🧰 Tools
🪛 Ruff (0.8.2)

88-88: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)

source/app/blueprints/rest/v2/case_objects/events.py (1)

55-59: Consider moving date validation inside the schema.
Although calling validate_date externally works, placing date validation within the Marshmallow schema can further encapsulate data validation processes and reduce coupling.

 def _load(self, request_data, **kwargs):
-    event = self._schema.load(request_data, **kwargs)
-    event.event_date, event.event_date_wtz = self._schema.validate_date(request_data.get(u'event_date'),
-                                                                        request_data.get(u'event_tz'))
+    event = self._schema.load(request_data, **kwargs)  # The schema handles all date validation
     return event
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e6373c and 11384c3.

📒 Files selected for processing (16)
  • pyproject.toml (1 hunks)
  • source/app/blueprints/pages/manage/manage_srv_settings_routes.py (0 hunks)
  • source/app/blueprints/pages/manage/templates/manage_make_update.html (0 hunks)
  • source/app/blueprints/pages/manage/templates/modal_server_updates.html (0 hunks)
  • source/app/blueprints/rest/case/case_timeline_routes.py (12 hunks)
  • source/app/blueprints/rest/v2/case_objects/events.py (2 hunks)
  • source/app/blueprints/rest/v2/case_objects/evidences.py (1 hunks)
  • source/app/business/events.py (3 hunks)
  • source/app/datamgmt/case/case_events_db.py (2 hunks)
  • source/app/iris_engine/module_handler/module_handler.py (19 hunks)
  • source/app/schema/marshables.py (1 hunks)
  • source/app/schema/utils.py (1 hunks)
  • source/app/util.py (0 hunks)
  • tests/tests_rest_events.py (1 hunks)
  • tests/tests_rest_evidences.py (1 hunks)
  • ui/src/pages/updates.handler.js (0 hunks)
💤 Files with no reviewable changes (5)
  • source/app/blueprints/pages/manage/templates/manage_make_update.html
  • source/app/blueprints/pages/manage/templates/modal_server_updates.html
  • source/app/util.py
  • source/app/blueprints/pages/manage/manage_srv_settings_routes.py
  • ui/src/pages/updates.handler.js
🧰 Additional context used
🧬 Code Graph Analysis (7)
source/app/blueprints/rest/v2/case_objects/evidences.py (1)
source/app/business/evidences.py (1)
  • evidences_delete (86-90)
source/app/datamgmt/case/case_events_db.py (3)
source/app/blueprints/rest/v2/case_objects/events.py (2)
  • delete_event (179-180)
  • delete (136-152)
source/app/models/models.py (2)
  • CaseEventsAssets (280-290)
  • CaseEventsIoc (293-303)
source/app/datamgmt/states.py (1)
  • update_timeline_state (86-87)
source/app/iris_engine/module_handler/module_handler.py (1)
source/app/models/models.py (2)
  • IrisModuleHook (877-891)
  • IrisHook (869-874)
tests/tests_rest_evidences.py (2)
tests/iris.py (2)
  • create_dummy_case (72-80)
  • create_dummy_user (69-70)
source/app/blueprints/rest/v2/case_objects/events.py (3)
  • create (61-84)
  • delete (136-152)
  • get (86-102)
source/app/business/events.py (3)
source/app/datamgmt/case/case_events_db.py (1)
  • delete_event (354-384)
source/app/iris_engine/utils/tracker.py (1)
  • track_activity (30-66)
source/app/iris_engine/utils/collab.py (1)
  • collab_notify (6-15)
source/app/blueprints/rest/case/case_timeline_routes.py (5)
source/app/business/events.py (1)
  • events_delete (106-111)
source/app/iris_engine/module_handler/module_handler.py (1)
  • call_deprecated_on_preload_modules_hook (584-587)
source/app/blueprints/rest/endpoints.py (1)
  • endpoint_deprecated (76-86)
source/app/blueprints/responses.py (1)
  • response_error (48-54)
source/app/schema/marshables.py (2)
  • EventSchema (1132-1284)
  • validate_date (1159-1185)
source/app/blueprints/rest/v2/case_objects/events.py (5)
source/app/business/events.py (1)
  • events_delete (106-111)
source/app/schema/marshables.py (2)
  • EventSchema (1132-1284)
  • validate_date (1159-1185)
source/app/business/cases.py (1)
  • cases_exists (71-72)
source/app/iris_engine/access_control/utils.py (1)
  • ac_fast_check_current_user_has_case_access (320-321)
source/app/models/authorization.py (1)
  • CaseAccessLevel (38-45)
🪛 Ruff (0.8.2)
source/app/iris_engine/module_handler/module_handler.py

468-468: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

source/app/schema/utils.py

35-36: Use a single if statement instead of nested if statements

Combine if statements using and

(SIM102)


40-41: Use a single if statement instead of nested if statements

(SIM102)


45-46: Use a single if statement instead of nested if statements

(SIM102)

source/app/business/events.py

53-53: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)


65-65: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)


88-88: Do not call setattr with a constant attribute value. It is not any safer than normal property access.

Replace setattr with assignment

(B010)

🔇 Additional comments (51)
source/app/blueprints/rest/v2/case_objects/evidences.py (1)

141-142: Proper security check implementation.

The evidences_delete call is now correctly positioned after the access control checks, which ensures that evidence will only be deleted when the user has appropriate access to the case. This prevents unauthorized deletion of evidence and aligns with the principle of complete authorization before performing sensitive operations.

tests/tests_rest_evidences.py (1)

303-313: Good test case for unauthorized evidence deletion.

This test appropriately verifies that evidence remains intact when a user without permissions attempts to delete it. It complements the fix in the delete_evidence function, ensuring that unauthorized deletion attempts are properly blocked while still returning an appropriate response code.

source/app/datamgmt/case/case_events_db.py (4)

354-356: Good refactoring of parameter passing.

The function now extracts the case ID from the event object rather than requiring it as a separate parameter. This makes the interface more consistent and less prone to errors where mismatched case IDs might be provided.


358-361: Updated query to use case_identifier from event.

The filtering condition now correctly uses the case_identifier variable extracted from the event object, maintaining consistency with the function signature change.


363-366: Updated query to use case_identifier from event.

Similar to the previous segment, this filtering condition is now correctly using the case_identifier variable from the event.


382-382: Updated parameter passing to match refactored function signature.

The call to update_timeline_state now correctly passes the case_identifier extracted from the event, completing the refactoring of the function parameter signature.

source/app/iris_engine/module_handler/module_handler.py (2)

31-31: Standardized logger import.

Replacing the local logger variable with a direct import from app.logger improves code consistency and maintainability.


584-588: Added helper function for deprecated hooks.

This new function properly handles deprecated hooks by adding a warning log while maintaining backward compatibility. This is a good approach for phasing out deprecated functionality.

source/app/schema/marshables.py (1)

96-99: Reorganized imports look good.
These imports from app.schema.utils are consistent with the new modular structure. No concerns here.

source/app/blueprints/rest/case/case_timeline_routes.py (15)

24-24: Improved explicit import for ValidationError.
This direct import from marshmallow.exceptions is clear and standard.


77-78: Added imports for new event-deletion logic.
Bringing in events_delete and call_deprecated_on_preload_modules_hook aligns with the refactoring.


160-160: Proper exception handling.
Catching ValidationError here is a clean approach for reporting data issues.


629-629: Great use of deprecation decorator.
Using @endpoint_deprecated properly guides clients to the new DELETE API route.


639-639: Refined event deletion call.
The switch to events_delete centralizes the deletion logic in the business layer.


693-694: Preload hook invoked before update.
No issues found. The call to a deprecated hook is explicitly signaled.


695-701: Extracted event fields and invoked _load.
Assigning event_id and then calling _load keeps the logic consistent. Looks good.


702-702: Updated event via the new events_update function.
Centralizing update logic in the business layer fosters maintainability.


714-715: Better error feedback for Marshmallow ValidationError.
Using e.get_message() and e.get_data() clarifies the issue for the client.


726-727: Preload hook invoked before create.
Matches the pattern used in update. No concerns.


728-728: _load used to parse the event data.
Good approach for consistent data loading.


730-734: Pulling relevant fields from request_data.
Straightforward retrieval of event parameters.


735-735: Creating event via events_create in the business layer.
This is consistent with the new architecture.


809-809: Catching ValidationError for duplication scenario.
Still consistent with the other flows; no issues.


1009-1015: Helper _load function fosters code reuse.
This centralized approach to schema validation ensures consistency across create and update flows.

source/app/business/events.py (11)

33-34: Importing the new delete function.
Centralizing deletion logic through delete_event is a good dependency injection.


39-39: Enhanced events_create signature.
This explicit approach clarifies which parameters are handled, improving readability.


51-51: Saving event category upon creation.
Makes sense to keep category logic at the business layer.


67-67: Post-creation module hook.
No issues spotted. The event is passed to external hooks for further processing.


80-80: Refined signature for events_update.
Similarly clarifies what parameters are used for updating.


81-84: Committed changes quickly after partial updates.
No problem, though consider batching if performance is a concern.


86-86: Category saving for an update.
Ensures category is maintained or changed properly.


90-99: Updating event assets & IOCs.
Catching and raising BusinessProcessingError for failures is clear.


100-100: Post-update module hook.
Consistent approach to external integration.


102-103: Track changes with an activity entry.
Fine approach for logging updated events.


106-112: New events_delete function centralizes removal logic.
Covers deletion steps, calls module hook, notifies collaborators, and tracks activity.

source/app/blueprints/rest/v2/case_objects/events.py (9)

21-21: New imports look good and consistent.
No issues found with the introduced imports for ValidationError, response_api_deleted, events_delete, and call_deprecated_on_preload_modules_hook.

Also applies to: 26-26, 33-33, 42-42


45-49: Encapsulating event logic in Events class is a solid design choice.
The introduction of this class centralizes event logic, improving maintainability and readability.


51-53: Error handling for mismatched case identifiers is correct.
Raising BusinessProcessingError here is consistent with the rest of the codebase, and the 400 error is handled properly in higher-level exception handling.


61-86: Overall create method implementation is robust.

  • Properly checks case existence and access.
  • Uses hooks for data pre-processing.
  • Raises ValidationError with a clear message.

No further concerns here.


87-103: get method gracefully handles missing or restricted events.
The checks for case existence, user access, and event mismatch are consistent and thorough.


104-135: update method logic is well-structured.

  • Good use of try blocks for business logic.
  • The updates follow the same pattern as creation, ensuring consistency.

136-153: delete method is properly secured and straightforward.

  • Checks existence and access before calling events_delete.
  • Returns a 204-equivalent response (response_api_deleted()).

155-156: Instantiation and blueprint creation are appropriate.
No issues with the blueprint registration or the events = Events() assignment.


161-162: Route definitions align with the new class-based logic.
The mapping of HTTP verbs to class methods is cleanly handled.

Also applies to: 168-169, 172-175, 177-179, 180-181

tests/tests_rest_events.py (7)

362-362: Good addition of new test cases for deletion scenarios.
This improves overall coverage and ensures correct API behavior for event deletion.


363-372: test_delete_event_should_return_204
Correctly validates that a successful deletion returns a 204 status code.


373-383: test_get_event_should_return_404_after_it_has_been_deleted
Adequately confirms that a deleted event cannot be retrieved.


384-393: test_delete_event_should_return_404_when_case_does_not_exist
Ensures proper handling of invalid case identifiers.


394-398: test_delete_event_should_return_404_when_the_event_does_not_exist
Verifies that deleting a non-existent event responds with 404, as expected.


399-410: test_delete_event_should_return_403_when_user_has_no_permission_to_access_case
Checks that the API enforces access control, which is crucial for data security.


411-420: test_delete_event_should_return_400_when_case_identifier_does_not_match_event_case
Confirms correct handling when the case identifier is mismatched, aligning with _check_event_and_case_identifier_match().

@whikernel whikernel merged commit 278b0e3 into develop Apr 15, 2025
18 checks passed
@whikernel whikernel deleted the api_v2_delete_event branch April 15, 2025 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

API v2 delete event
2 participants