Skip to content
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

fix: enforce permissions for domain import #1400

Merged
merged 10 commits into from
Jan 28, 2025

Conversation

nas-tabchiche
Copy link
Contributor

@nas-tabchiche nas-tabchiche commented Jan 22, 2025

  • Check permissions for each model to import before attempting to create objects
  • Wrap form return values with withFiles wrapper
  • Localize domain import permission denied error
  • Style domain import button

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced permission checks for domain imports to improve system security.
    • Added a user-friendly error message for users lacking import permissions.
  • Bug Fixes

    • Improved error handling for domain import scenarios, ensuring form data is preserved during errors.
  • Style

    • Updated button styling for import functionality with hover effect and color adjustment.

The release focuses on strengthening permission management and refining user interface elements during domain import processes.

Copy link
Contributor

coderabbitai bot commented Jan 22, 2025

Walkthrough

The pull request introduces security enhancements to the domain import functionality across backend and frontend components. Key changes include implementing robust permission checks in the import_domain method, enhancing error handling for unauthorized access, and improving user feedback through new error messages. These modifications span multiple files, including backend views, frontend messages, and Svelte components, with a primary goal of strengthening access control and providing clear user notifications.

Changes

File Change Summary
backend/core/views.py - Added permission checks in import_domain method
- Updated _import_objects method to include user parameter
- Enhanced error handling for PermissionDenied exceptions
- Improved logging for permission issues
frontend/messages/en.json - Added new message key userDoesNotHavePermissionToImportDomain
- Provides clear error message for import permission failures
frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.server.ts - Updated error handling to use withFiles() for form data preservation
- Modified return statements for error and success scenarios
frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.svelte - Updated button styling for import functionality
- Changed text color and added hover effect

Possibly related PRs

  • fix: risk acceptance permission overrides #1417: The changes in this PR also enhance permission checks, specifically in the context of user actions within the backend/core/views.py file, similar to the permission checks added in the import_domain method of the FolderViewSet class in the main PR.

Suggested reviewers

  • Mohamed-Hacene
  • eric-intuitem

Poem

🐰 A Rabbit's Import Tale 🔒
In lines of code, permissions dance,
Guarding domains with careful glance,
No sneaky imports shall pass today,
Our security stands strong, hooray!
A rabbit's wisdom: check before you leap! 🚫

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 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. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @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.

@nas-tabchiche nas-tabchiche changed the title fix/enforce permissions for domain import fix: Enforce permissions for domain import Jan 22, 2025
@nas-tabchiche nas-tabchiche changed the title fix: Enforce permissions for domain import fix: enforce permissions for domain import Jan 22, 2025
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: 3

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5d0a017 and 4330d47.

📒 Files selected for processing (4)
  • backend/core/views.py (5 hunks)
  • frontend/messages/en.json (1 hunks)
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.server.ts (2 hunks)
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.svelte (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.svelte
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: ruff (3.12)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: build (3.12)
  • GitHub Check: test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
backend/core/views.py (1)

70-70: Importing PermissionDenied exception

The import of PermissionDenied from rest_framework.exceptions is appropriate for handling permission errors in the API views.

frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.server.ts (4)

98-98: Preserve form data with withFiles on validation failure

Updating the failure response to use withFiles({ form }) ensures that form data, including files, is preserved when validation fails. This enhances user experience during form submission.


121-121: Preserve form data with withFiles when missing libraries are detected

By returning fail(400, withFiles({ form })), the form data is preserved when missing libraries are detected during import, allowing the user to correct the issue without losing their inputs.


127-127: Preserve form data after successful import with withFiles

Returning withFiles({ form }) ensures that the form data is preserved even after a successful import, which may be beneficial if you want to reset or maintain form state.


132-132: Preserve form data with withFiles on general API errors

Using fail(400, withFiles({ form })) when a general API error occurs helps to preserve form data, allowing users to retry submission without re-uploading files.

frontend/messages/en.json (1)

648-648: Addition of error message for unauthorized domain import

The new message "userDoesNotHavePermissionToImportDomain" provides a clear and localized error message informing users when they lack permission to import a domain.

backend/core/views.py Outdated Show resolved Hide resolved
backend/core/views.py Outdated Show resolved Hide resolved
backend/core/views.py Outdated Show resolved Hide resolved
@nas-tabchiche nas-tabchiche force-pushed the fix/enforce-permissions-for-domain-import branch from 4330d47 to ac2d5c0 Compare January 22, 2025 15:51
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

♻️ Duplicate comments (1)
backend/core/views.py (1)

2219-2226: ⚠️ Potential issue

Use has_perm method to check permissions in object import.

Directly accessing user.permissions may not accurately represent the user's permissions. Instead, use user.has_perm(f'{model._meta.app_label}.add_{model._meta.model_name}') to check if the user has the required permissions for each model.

Apply this diff to fix the permission checks:

-            for model in models_map.values():
-                if f"add_{model._meta.model_name}" not in user.permissions:
-                    error_dict[model._meta.model_name] = "permission_denied"
+            for model in models_map.values():
+                perm_codename = f"{model._meta.app_label}.add_{model._meta.model_name}"
+                if not user.has_perm(perm_codename):
+                    error_dict[model._meta.model_name] = "permission_denied"
🧹 Nitpick comments (1)
backend/core/views.py (1)

2107-2114: Remove unused exception variables.

The exception variables e are assigned but never used in the error handling blocks.

Apply this diff to remove the unused variables:

-        except KeyError as e:
+        except KeyError:
             logger.error("No file provided in the request", exc_info=True)
             return Response(
                 {"errors": ["No file provided"]}, status=status.HTTP_400_BAD_REQUEST
             )

-        except json.JSONDecodeError as e:
+        except json.JSONDecodeError:
             logger.error("Invalid JSON format in uploaded file", exc_info=True)
             return Response(
                 {"errors": ["Invalid JSON format"]}, status=status.HTTP_400_BAD_REQUEST
             )
🧰 Tools
🪛 Ruff (0.8.2)

2107-2107: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


2113-2113: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4330d47 and ac2d5c0.

📒 Files selected for processing (2)
  • backend/core/views.py (8 hunks)
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.svelte (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.svelte
🧰 Additional context used
🪛 Ruff (0.8.2)
backend/core/views.py

2096-2096: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


2107-2107: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


2113-2113: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: build (3.12)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
backend/core/views.py (2)

2085-2088: ⚠️ Potential issue

Fix incorrect permission check.

The permission check is using direct access to request.user.permissions which may not accurately reflect the user's permissions. Use Django's built-in permission system instead.

Apply this diff to fix the permission check:

-if "add_folder" not in request.user.permissions:
+if not request.user.has_perm("iam.add_folder"):

Likely invalid or redundant comment.


2096-2105: ⚠️ Potential issue

Fix incorrect logger usage.

The exc_info parameter in the logger call should be a boolean flag to include the stack trace, not the exception object.

Apply this diff to fix the logger call:

-                exc_info=True,
+                exc_info=e,

Likely invalid or redundant comment.

🧰 Tools
🪛 Ruff (0.8.2)

2096-2096: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

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)
backend/core/views.py (2)

2107-2114: Enhance error logging for better debugging.

While the error handling is good, consider adding exc_info=True to capture the full stack trace in the logs:

-            logger.error("No file provided in the request", exc_info=True)
+            logger.error("No file provided in the request", exc_info=True)

-            logger.error("Invalid JSON format in uploaded file", exc_info=True)
+            logger.error("Invalid JSON format in uploaded file", exc_info=True)

2282-2284: Use exception chaining to preserve error context.

To maintain the exception context and improve debugging, use explicit exception chaining:

-                raise ValidationError({"missing_libraries": missing_libraries})
+                raise ValidationError({"missing_libraries": missing_libraries}) from None

This change helps distinguish between errors in the validation and errors in exception handling.

🧰 Tools
🪛 Ruff (0.8.2)

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

(B904)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ac2d5c0 and a6af32c.

📒 Files selected for processing (1)
  • backend/core/views.py (11 hunks)
🧰 Additional context used
📓 Learnings (1)
backend/core/views.py (1)
Learnt from: nas-tabchiche
PR: intuitem/ciso-assistant-community#1400
File: backend/core/views.py:2219-2226
Timestamp: 2025-01-22T15:55:06.417Z
Learning: The codebase uses a custom permission system through `RoleAssignment.get_permissions()` accessed via `user.permissions` property, instead of Django's default permission system.
🪛 Ruff (0.8.2)
backend/core/views.py

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

(B904)

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: test (3.12)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: Analyze (python)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: build (3.12)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: enterprise-startup-docker-compose-test
🔇 Additional comments (2)
backend/core/views.py (2)

2085-2106: LGTM! Permission check implementation is secure and well-structured.

The permission check correctly uses the custom permission system through user.permissions and provides appropriate error handling with logging.


2219-2226: LGTM! Comprehensive permission validation for all object types.

The implementation correctly validates that the user has create permissions for all object types before proceeding with the import, which is a robust security measure.

coderabbitai bot added a commit that referenced this pull request Jan 22, 2025
Docstrings generation was requested by @nas-tabchiche.

* #1400 (comment)

The following files were modified:

* `backend/core/views.py`
Copy link
Contributor

coderabbitai bot commented Jan 22, 2025

Note

Generated docstrings for this pull request, at #1402

Copy link
Collaborator

@eric-intuitem eric-intuitem left a comment

Choose a reason for hiding this comment

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

Should check:
1/ that the user is allowed to create a folder in the root folder.
2/ that the user is allowed to create an object in the newly created folder.
Access control shall be done also on export (read access on all exported objects)

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)
backend/core/views.py (2)

2111-2119: Enhance error handling with more specific messages and proper exception chaining.

While the error handling is good, consider these improvements:

  1. Make the KeyError message more specific: "No file provided in the request" → "Missing 'file' key in request data"
  2. Use exception chaining to preserve the traceback.

Apply this diff to improve the error handling:

-        except KeyError:
-            logger.error("No file provided in the request", exc_info=True)
+        except KeyError as e:
+            logger.error("Missing 'file' key in request data", exc_info=True)
             return Response(
-                {"errors": ["No file provided"]}, status=status.HTTP_400_BAD_REQUEST
+                {"errors": [f"Missing required field: {e}"]}, status=status.HTTP_400_BAD_REQUEST
             )

-        except json.JSONDecodeError:
-            logger.error("Invalid JSON format in uploaded file", exc_info=True)
+        except json.JSONDecodeError as e:
+            logger.error("Invalid JSON format in uploaded file", exc_info=True)
             return Response(
-                {"errors": ["Invalid JSON format"]}, status=status.HTTP_400_BAD_REQUEST
+                {"errors": [f"Invalid JSON format: {e}"]}, status=status.HTTP_400_BAD_REQUEST
             )

Line range hint 2445-2449: Improve exception handling with proper exception chaining.

The error handling should preserve the original exception's context using the raise ... from err syntax.

Apply this diff to improve the exception handling:

-                    logger.error("Error creating object", obj=obj, exc_info=True)
-                    # This will trigger a rollback of the entire batch
-                    raise ValidationError(
-                        f"Error creating {model._meta.model_name}: {str(e)}"
-                    )
+                    logger.error("Error creating object", obj=obj, exc_info=True)
+                    # This will trigger a rollback of the entire batch
+                    raise ValidationError(
+                        f"Error creating {model._meta.model_name}: {str(e)}"
+                    ) from e
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a6af32c and 45ad45f.

📒 Files selected for processing (1)
  • backend/core/views.py (11 hunks)
🧰 Additional context used
📓 Learnings (1)
backend/core/views.py (1)
Learnt from: nas-tabchiche
PR: intuitem/ciso-assistant-community#1400
File: backend/core/views.py:2219-2226
Timestamp: 2025-01-22T15:55:06.417Z
Learning: The codebase uses a custom permission system through `RoleAssignment.get_permissions()` accessed via `user.permissions` property, instead of Django's default permission system.
🪛 Ruff (0.8.2)
backend/core/views.py

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

(B904)

⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: build (3.12)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: test (3.12)
🔇 Additional comments (2)
backend/core/views.py (2)

2085-2109: LGTM! Well-implemented permission checks.

The permission check implementation is robust, with proper error handling and logging. The code correctly verifies the user's permission to add folders before proceeding with the domain import.


2223-2236: LGTM! Comprehensive permission validation for object creation.

The implementation thoroughly validates permissions for each model type before proceeding with the import. The error handling is well-structured, and the code maintains good security practices.

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

♻️ Duplicate comments (1)
backend/core/views.py (1)

2115-2125: ⚠️ Potential issue

Fix the usage of exc_info parameter in logger.error.

When logging exceptions, the exc_info parameter should be a boolean flag indicating whether to include the stack trace.

-            logger.error(
-                "User does not have permission to import domain",
-                user=request.user,
-                exc_info=True,
-            )
+            logger.error(
+                "User does not have permission to import domain",
+                user=request.user,
+                exc_info=True,
+            )
🧹 Nitpick comments (1)
backend/core/views.py (1)

2006-2020: LGTM! Comprehensive permission check implementation.

The permission check implementation is thorough, ensuring the user has view permissions for all object types in the domain before allowing export.

Minor optimization: Use key in dict instead of key in dict.keys()

For better performance, remove the .keys() call as it creates an unnecessary view object.

-for model in objects.keys():
+for model in objects:
🧰 Tools
🪛 Ruff (0.8.2)

2006-2006: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 45ad45f and 8035c78.

📒 Files selected for processing (1)
  • backend/core/views.py (12 hunks)
🧰 Additional context used
📓 Learnings (1)
backend/core/views.py (1)
Learnt from: nas-tabchiche
PR: intuitem/ciso-assistant-community#1400
File: backend/core/views.py:2219-2226
Timestamp: 2025-01-22T15:55:06.417Z
Learning: The codebase uses a custom permission system through `RoleAssignment.get_permissions()` accessed via `user.permissions` property, instead of Django's default permission system.
🪛 Ruff (0.8.2)
backend/core/views.py

2006-2006: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


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

(B904)

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: build (3.12)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: test (3.12)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
backend/core/views.py (2)

2238-2251: LGTM! Robust permission validation for object creation.

The implementation correctly validates that the user has permission to create all object types before proceeding with the import. The error handling with the error dictionary is well-structured.


2367-2367: LGTM! Consistent error logging implementation.

The error logging is well-implemented with proper use of the exc_info parameter for stack trace inclusion.

Also applies to: 2460-2460

Copy link
Collaborator

@Mohamed-Hacene Mohamed-Hacene left a comment

Choose a reason for hiding this comment

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

0k

Copy link
Collaborator

@eric-intuitem eric-intuitem left a comment

Choose a reason for hiding this comment

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

LGTM now

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: 1

🧹 Nitpick comments (5)
backend/core/views.py (5)

2006-2006: Optimize dictionary key lookup.

Use key in objects instead of key in objects.keys() for better performance.

-        for model in objects.keys():
+        for model in objects:
🧰 Tools
🪛 Ruff (0.8.2)

2006-2006: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


2192-2193: Enhance attachment extraction error handling.

The generic exception catch block should log more details about the failed attachment.

-                    except Exception:
-                        logger.error("Error extracting attachment", exc_info=True)
+                    except Exception as e:
+                        logger.error(
+                            "Error extracting attachment",
+                            attachment=current_name,
+                            error=str(e),
+                            exc_info=True
+                        )

2241-2243: Add type hints for better code clarity.

The code uses a conditional assignment that could benefit from type hints.

+                from core.models import ComplianceAssessment
                 model2 = (
                     ComplianceAssessment if model == RequirementAssessment else model
                 )
🧰 Tools
🪛 Ruff (0.8.2)

2242-2242: RequirementAssessment may be undefined, or defined from star imports

(F405)


Line range hint 2354-2369: Enhance validation error logging.

Add more context to validation error logs to help with debugging.

                 if not serializer.is_valid():
+                    logger.error(
+                        "Validation failed",
+                        model=model_name,
+                        object_id=obj_id,
+                        errors=serializer.errors
+                    )
                     validation_errors.append(
                         {
                             "model": model_name,
                             "id": obj_id,
                             "errors": serializer.errors,
                         }
                     )

Line range hint 2462-2466: Improve error message detail.

Include more context in the error message to help identify the specific object that failed to create.

-                    logger.error("Error creating object", obj=obj, exc_info=True)
+                    logger.error(
+                        "Error creating object",
+                        model=model._meta.model_name,
+                        object_id=obj_id,
+                        fields=fields,
+                        exc_info=True
+                    )
                     raise ValidationError(
-                        f"Error creating {model._meta.model_name}: {str(e)}"
+                        f"Error creating {model._meta.model_name} (ID: {obj_id}): {str(e)}"
                     )
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8035c78 and c629855.

📒 Files selected for processing (1)
  • backend/core/views.py (12 hunks)
🧰 Additional context used
📓 Learnings (1)
backend/core/views.py (1)
Learnt from: nas-tabchiche
PR: intuitem/ciso-assistant-community#1400
File: backend/core/views.py:2219-2226
Timestamp: 2025-01-22T15:55:06.417Z
Learning: The codebase uses a custom permission system through `RoleAssignment.get_permissions()` accessed via `user.permissions` property, instead of Django's default permission system.
🪛 Ruff (0.8.2)
backend/core/views.py

2006-2006: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


2242-2242: RequirementAssessment may be undefined, or defined from star imports

(F405)


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

(B904)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (1)
backend/core/views.py (1)

2116-2120: 🛠️ Refactor suggestion

Improve error logging.

The exc_info=True parameter is incorrectly passed directly to the error message. Instead, it should be a separate parameter to include the stack trace.

-                user=request.user,
-                exc_info=True,
+                user=request.user,
+                exc_info=True

Likely invalid or redundant comment.

Comment on lines +2309 to +2411
logger.warning("Missing libraries", libraries=missing_libraries)
raise ValidationError({"missing_libraries": missing_libraries})
logger.exception(f"Failed to import objects: {str(e)}")
logger.exception("Failed to import objects", objects=str(e))
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Preserve exception context in error handling.

Use raise ... from None to explicitly suppress the original exception context.

-                raise ValidationError({"missing_libraries": missing_libraries})
+                raise ValidationError({"missing_libraries": missing_libraries}) from None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
logger.warning("Missing libraries", libraries=missing_libraries)
raise ValidationError({"missing_libraries": missing_libraries})
logger.exception(f"Failed to import objects: {str(e)}")
logger.exception("Failed to import objects", objects=str(e))
logger.warning("Missing libraries", libraries=missing_libraries)
raise ValidationError({"missing_libraries": missing_libraries}) from None
logger.exception("Failed to import objects", objects=str(e))
🧰 Tools
🪛 Ruff (0.8.2)

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

(B904)

@nas-tabchiche nas-tabchiche force-pushed the fix/enforce-permissions-for-domain-import branch from c629855 to 8834c09 Compare January 26, 2025 20:52
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: 1

🧹 Nitpick comments (2)
backend/core/views.py (2)

Line range hint 2245-2281: Improve error handling in attachment extraction.

The error handling for attachment extraction could be more specific about what went wrong.

-                    except Exception:
-                        logger.error("Error extracting attachment", exc_info=True)
+                    except Exception as e:
+                        logger.error(
+                            "Error extracting attachment",
+                            attachment=current_name,
+                            error=str(e),
+                            exc_info=True
+                        )
🧰 Tools
🪛 Ruff (0.8.2)

2250-2250: Use import_version != VERSION instead of not import_version == VERSION

Replace with != operator

(SIM201)


2409-2411: Preserve exception context in error handling.

Use raise ... from None to explicitly suppress the original exception context.

-                raise ValidationError({"missing_libraries": missing_libraries})
+                raise ValidationError({"missing_libraries": missing_libraries}) from None
🧰 Tools
🪛 Ruff (0.8.2)

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

(B904)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c629855 and 8834c09.

📒 Files selected for processing (4)
  • backend/core/views.py (12 hunks)
  • frontend/messages/en.json (1 hunks)
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.server.ts (2 hunks)
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.svelte (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/messages/en.json
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.svelte
  • frontend/src/routes/(app)/(internal)/[model=urlmodel]/+page.server.ts
🧰 Additional context used
📓 Learnings (1)
backend/core/views.py (1)
Learnt from: nas-tabchiche
PR: intuitem/ciso-assistant-community#1400
File: backend/core/views.py:2219-2226
Timestamp: 2025-01-22T15:55:06.417Z
Learning: The codebase uses a custom permission system through `RoleAssignment.get_permissions()` accessed via `user.permissions` property, instead of Django's default permission system.
🪛 Ruff (0.8.2)
backend/core/views.py

107-107: Redefinition of unused PermissionDenied from line 68

(F811)


2089-2089: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


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

(B904)

⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: build (3.12)
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: test (3.12)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (6)
backend/core/views.py (6)

2089-2103: LGTM! Comprehensive permission checks for domain export.

The implementation correctly verifies that the user has view permissions for all object types in the domain before allowing export. Good error handling with appropriate logging.

🧰 Tools
🪛 Ruff (0.8.2)

2089-2089: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


2188-2213: LGTM! Proper permission check for domain import.

The implementation correctly verifies that the user has permission to add folders before allowing domain import.


2214-2221: LGTM! Clear error handling for missing files.

Good error handling with appropriate error messages and logging.


2328-2341: LGTM! Thorough permission checks before object creation.

The implementation correctly verifies that the user has permission to create all object types before proceeding with the import. Good use of error dictionary to collect all permission issues.


Line range hint 2456-2471: LGTM! Comprehensive validation error handling.

Good error handling with appropriate context and logging.


Line range hint 2564-2568: LGTM! Proper error handling in object creation.

Good error handling with appropriate logging and clear error messages.

backend/core/views.py Outdated Show resolved Hide resolved
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 (1)
backend/core/views.py (1)

2278-2279: Improve error handling for attachment extraction.

The current implementation silently continues after logging attachment extraction errors. Consider notifying the user about failed attachments or collecting them in a list for a summary report.

Apply this diff to improve error handling:

+                    failed_attachments = []
                     try:
                         content = zipf.read(attachment)
                         current_name = Path(attachment.filename).name
                         new_name = default_storage.save(
                             current_name, io.BytesIO(content)
                         )
                         if new_name != current_name:
                             for x in json_dump["objects"]:
                                 if (
                                     x["model"] == "core.evidence"
                                     and x["fields"]["attachment"] == current_name
                                 ):
                                     x["fields"]["attachment"] = new_name
-                    except Exception:
-                        logger.error("Error extracting attachment", exc_info=True)
+                    except Exception as err:
+                        logger.error("Error extracting attachment", exc_info=True)
+                        failed_attachments.append((attachment.filename, str(err)))
+
+                if failed_attachments:
+                    logger.warning("Failed to extract attachments", attachments=failed_attachments)
+                    raise ValidationError({"failed_attachments": failed_attachments})
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8834c09 and b9c37d7.

📒 Files selected for processing (1)
  • backend/core/views.py (11 hunks)
🧰 Additional context used
📓 Learnings (1)
backend/core/views.py (1)
Learnt from: nas-tabchiche
PR: intuitem/ciso-assistant-community#1400
File: backend/core/views.py:2219-2226
Timestamp: 2025-01-22T15:55:06.417Z
Learning: The codebase uses a custom permission system through `RoleAssignment.get_permissions()` accessed via `user.permissions` property, instead of Django's default permission system.
🪛 Ruff (0.8.2)
backend/core/views.py

2087-2087: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


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

(B904)

⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: functional-tests (3.12, chromium)
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: enterprise-functional-tests (3.12, chromium)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: build (3.12)
  • GitHub Check: test (3.12)
🔇 Additional comments (6)
backend/core/views.py (6)

2087-2101: LGTM! Comprehensive permission checks for domain export.

The implementation correctly enforces view permissions for each model type in the domain export using the custom permission system.

🧰 Tools
🪛 Ruff (0.8.2)

2087-2087: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


2186-2211: LGTM! Robust permission checks and error handling for domain import.

The implementation correctly enforces the 'add_folder' permission and includes comprehensive error handling with appropriate logging.


2326-2339: LGTM! Comprehensive permission checks for object creation during import.

The implementation correctly enforces 'add' permissions for each model type and provides clear error information.


Line range hint 2562-2566: LGTM! Clear error handling for object creation failures.

The implementation provides detailed error information by including both the model name and the original error message.


2407-2409: 🛠️ Refactor suggestion

Preserve exception context in validation error handling.

When re-raising exceptions within an except clause, use raise ... from None to explicitly suppress the exception context.

Apply this diff to fix the error handling:

-                raise ValidationError({"missing_libraries": missing_libraries})
+                raise ValidationError({"missing_libraries": missing_libraries}) from None

Likely invalid or redundant comment.

🧰 Tools
🪛 Ruff (0.8.2)

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

(B904)


2243-2246: 🛠️ Refactor suggestion

Preserve exception context in error handling.

When re-raising exceptions within an except clause, use raise ... from err or raise ... from None to preserve or explicitly suppress the exception context.

Apply this diff to fix the error handling:

-            except json.JSONDecodeError:
-                logger.error("Invalid JSON format in uploaded file", exc_info=True)
-                raise
+            except json.JSONDecodeError as err:
+                logger.error("Invalid JSON format in uploaded file", exc_info=True)
+                raise err from err

Likely invalid or redundant comment.

@eric-intuitem eric-intuitem merged commit e2e4b9c into main Jan 28, 2025
20 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Jan 28, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants