Skip to content

Conversation

@monsieurswag
Copy link
Contributor

@monsieurswag monsieurswag commented Oct 29, 2025

Summary by CodeRabbit

  • New Features

    • Browse and retrieve subdomains from folder views.
    • Folder selection in forms now adapts based on context/origin (shows relevant subfolders).
    • Modal and form components propagate an optional origin parameter to enable context-aware behavior.
  • Refactor

    • Harmonized folder/subfolder path and retrieval behavior across backend and frontend for consistent results.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 29, 2025

Walkthrough

Adds a folder "subdomains" API action, enforces keyword-only parameters for folder path/subfolder methods, and updates frontend forms to use the new subdomains endpoint and propagate an optional origin prop.

Changes

Cohort / File(s) Change Summary
Folder model signatures
backend/iam/models.py
get_sub_folders() now yields a generator and requires include_self as a keyword-only parameter; get_folder_full_path() changed to require keyword-only include_root.
RiskScenario model
backend/core/models.py
RiskScenario.get_folder_full_path(...) signature updated to require include_root as a keyword-only parameter; delegates to assessment path method.
FolderViewSet API
backend/core/views.py
Added subdomains(self, request, pk) action: fetch folder by pk, enforce view_folder RBAC, collect sub-folders (including self), serialize and return them.
Frontend: applied control form
frontend/src/lib/components/Forms/ModelForm/AppliedControlPolicyForm.svelte
Added origin prop; folder AutocompleteSelect endpoint switched to dynamic domainOptionEndpoint using folders/${initialData.folder}/subdomains/ when origin === 'requirement-assessments'; removed hidden prop on folder field.
Frontend: component prop forwarding
frontend/src/lib/components/Forms/ModelForm.svelte, frontend/src/lib/components/Modals/CreateModal.svelte
Added optional `origin?: string
Frontend: route usage
frontend/src/routes/(app)/(third-party)/requirement-assessments/[id=uuid]/edit/+page.svelte
When opening add-applied-controls modal, pass origin: 'requirement-assessments' to CreateModal.
Frontend: params/fields
frontend/src/params/fields.ts
Initialize the fields Set with a predefined 'subdomains' entry in addition to keys from listViewFields.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as FolderViewSet
    participant RBAC
    participant Folder as FolderModel
    participant Serializer

    Client->>API: GET /folders/{pk}/subdomains/
    API->>API: retrieve Folder(pk)
    API->>RBAC: check view_folder permission
    alt permission denied
        RBAC-->>Client: 403 Forbidden
    else permission granted
        RBAC-->>API: OK
        API->>Folder: get_sub_folders(include_self=True)
        Folder-->>API: yields folders (generator)
        API->>Serializer: serialize folder list
        Serializer-->>Client: 200 OK (JSON)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Attention areas:
    • RBAC permission pattern in subdomains() to ensure consistency with other view actions
    • Call sites across the codebase for get_sub_folders() / get_folder_full_path() to update callers to keyword-only usage
    • Frontend: ensure safe handling when initialData.folder is missing or null and endpoint string construction is resilient

Possibly related PRs

Suggested labels

High Value

Suggested reviewers

  • eric-intuitem
  • ab-smith

Poem

🐰 I hopped through folders, neat and spry,
Found subdomains beneath the sky,
Args made strict, endpoints aligned,
I passed my props and left none behind. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: allowing users to choose the domain of applied controls created from requirement assessments (audits), which is reflected throughout the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/choose_domain_for_controls_created_from_audits

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 95550dc and 754d113.

📒 Files selected for processing (5)
  • backend/core/models.py (1 hunks)
  • backend/core/views.py (1 hunks)
  • frontend/src/lib/components/Forms/ModelForm.svelte (3 hunks)
  • frontend/src/lib/components/Forms/ModelForm/AppliedControlPolicyForm.svelte (4 hunks)
  • frontend/src/routes/(app)/(third-party)/requirement-assessments/[id=uuid]/edit/+page.svelte (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/core/views.py
🧰 Additional context used
🧬 Code graph analysis (1)
backend/core/models.py (1)
backend/iam/models.py (3)
  • get_folder_full_path (147-155)
  • get_folder_full_path (336-340)
  • Folder (68-321)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: test (3.12)
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: build_enterprise_frontend
  • GitHub Check: build_community_frontend
  • GitHub Check: build (3.12)
  • GitHub Check: Analyze (python)
🔇 Additional comments (5)
frontend/src/routes/(app)/(third-party)/requirement-assessments/[id=uuid]/edit/+page.svelte (1)

88-88: LGTM!

The addition of origin: 'requirement-assessments' correctly provides context to the modal, enabling the subdomain-based folder endpoint selection in downstream components.

frontend/src/lib/components/Forms/ModelForm.svelte (1)

96-96: LGTM!

The origin prop is properly typed, defaulted, and threaded through to AppliedControlsPoliciesForm. The implementation is clean and consistent.

Also applies to: 117-117, 379-379

frontend/src/lib/components/Forms/ModelForm/AppliedControlPolicyForm.svelte (2)

28-28: LGTM!

The origin prop is properly declared and defaulted, following the pattern established in parent components.

Also applies to: 41-41


448-448: Using derived endpoint is correct, but depends on fixing the undefined folder issue.

The switch from a hardcoded endpoint to domainOptionEndpoint is the right approach for dynamic behavior. However, ensure the critical issue at lines 80-84 is resolved to prevent invalid API calls.

backend/core/models.py (1)

4890-4891: Verification complete—no issues found.

All call sites use keyword arguments or rely on the default, confirming the kw-only signature change is safe. RiskAssessment inherits get_folder_full_path from FolderMixin (via Assessment), so delegation is valid. The change maintains consistency with Folder and FolderMixin signatures.


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.

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

3628-3647: Optimize subdomains for N+1 avoidance and deterministic ordering

  • Serializer likely triggers extra queries (path/parent_folder/labels). Prefetch and order for stable output.
  • Optional: use get_object_or_404 for brevity without changing RBAC behavior.

Apply:

 @action(detail=True, methods=["get"])
 def subdomains(self, request, pk):
     """
     Returns a list composed of the given domain and all its subdomains
     """
-    instance = Folder.objects.filter(pk=pk).first()
-    if not instance:
-        return Response(status=status.HTTP_404_NOT_FOUND)
+    instance = get_object_or_404(Folder, pk=pk)

     if not RoleAssignment.is_access_allowed(
         user=request.user,
         perm=Permission.objects.get(codename="view_folder"),
         folder=instance,
     ):
         return Response(status=status.HTTP_403_FORBIDDEN)

-    subfolders = list(instance.get_sub_folders(include_self=True))
-    serializer = FolderReadSerializer(subfolders, many=True)
+    subfolder_ids = [f.id for f in instance.get_sub_folders(include_self=True)]
+    subfolders_qs = (
+        Folder.objects
+        .filter(id__in=subfolder_ids)
+        .select_related("parent_folder")
+        .prefetch_related("filtering_labels")
+        .order_by(Lower("name"))
+    )
+    serializer = FolderReadSerializer(subfolders_qs, many=True)
     return Response(serializer.data)
backend/iam/models.py (2)

336-341: FolderMixin.get_folder_full_path parity and return shape

LGTM and consistent with Folder.get_folder_full_path. Minor: consider mirroring the docstring here for clarity, and add a small test covering include_root True/False.

Do you want a tiny pytest to lock behavior for include_root?


125-133: Clarify generator behavior and include_self semantics

Docstring says "list" but the method yields a generator in depth‑first (pre‑order). Update the docstring to state it yields and to document include_self semantics; callers in the repo iterate/convert to list and do not rely on list indexing/len.

File: backend/iam/models.py (around lines 125–139)

-    def get_sub_folders(
-        self, *, include_self: bool = False
-    ) -> Generator[Self, None, None]:
-        """Return the list of subfolders"""
+    def get_sub_folders(
+        self, *, include_self: bool = False
+    ) -> Generator[Self, None, None]:
+        """Yield subfolders in depth-first order (pre-order).
+        Set include_self=True to yield the folder itself first.
+        """
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e9aabf2 and 4f400ac.

📒 Files selected for processing (5)
  • backend/core/models.py (1 hunks)
  • backend/core/views.py (1 hunks)
  • backend/iam/models.py (3 hunks)
  • frontend/src/lib/components/Forms/ModelForm/AppliedControlPolicyForm.svelte (1 hunks)
  • frontend/src/params/fields.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
backend/core/views.py (2)
backend/iam/models.py (4)
  • Folder (68-321)
  • RoleAssignment (812-1099)
  • is_access_allowed (842-862)
  • get_sub_folders (125-138)
backend/core/serializers.py (1)
  • FolderReadSerializer (1253-1262)
backend/core/models.py (1)
backend/iam/models.py (3)
  • get_folder_full_path (147-155)
  • get_folder_full_path (336-340)
  • Folder (68-321)
backend/iam/models.py (1)
backend/core/models.py (1)
  • get_folder_full_path (4792-4793)
🔇 Additional comments (4)
frontend/src/params/fields.ts (1)

15-17: LGTM! Clear initialization for subdomain route support.

The Set initialization with 'subdomains' properly supports the new endpoint pattern. The inline comment effectively explains the purpose.

frontend/src/lib/components/Forms/ModelForm/AppliedControlPolicyForm.svelte (1)

346-346: Confirm removal of content_type filters is intentional by verifying against feature requirements.

The current subdomains endpoint returns all subfolder types (DOMAIN, ENCLAVE, ROOT) without filtering. The previous implementation filtered to only DOMAIN (DO) and ROOT (GL) types. Verify this change aligns with the intended behavior for the Applied Control Policy form—specifically, whether all subfolder types should be selectable or only specific ones.

backend/iam/models.py (1)

147-156: No compatibility issue found—all existing calls already use keyword arguments or defaults.

Verification confirmed that all four actual calls to get_folder_full_path() in the codebase either pass include_root as a keyword argument or rely on the default. There are zero positional callers like get_folder_full_path(True) that would break with this signature.

backend/core/models.py (1)

4792-4793: Keyword-only alignment verified—no positional calls found

Search across the codebase confirmed all existing calls to get_folder_full_path() use either no arguments or keyword arguments. The delegation in RiskScenario.get_folder_full_path() correctly forwards the parameter as a keyword argument (include_root=include_root). No runtime breakage risk.

@monsieurswag monsieurswag marked this pull request as draft October 29, 2025 16:01
@monsieurswag monsieurswag marked this pull request as ready for review October 31, 2025 10:06
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f400ac and 95550dc.

📒 Files selected for processing (4)
  • frontend/src/lib/components/Forms/ModelForm.svelte (3 hunks)
  • frontend/src/lib/components/Forms/ModelForm/AppliedControlPolicyForm.svelte (4 hunks)
  • frontend/src/lib/components/Modals/CreateModal.svelte (3 hunks)
  • frontend/src/routes/(app)/(third-party)/requirement-assessments/[id=uuid]/edit/+page.svelte (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: enterprise-startup-docker-compose-test
  • GitHub Check: test (3.12)
  • GitHub Check: build_community_frontend
  • GitHub Check: enterprise-startup-functional-test (3.12)
  • GitHub Check: build_enterprise_frontend
  • GitHub Check: startup-docker-compose-test
  • GitHub Check: startup-functional-test (3.12)
  • GitHub Check: build (3.12)
🔇 Additional comments (7)
frontend/src/routes/(app)/(third-party)/requirement-assessments/[id=uuid]/edit/+page.svelte (1)

70-90: LGTM! Origin parameter correctly identifies the requirement-assessments context.

The addition of origin: 'requirement-assessments' properly propagates context to the modal form, enabling origin-specific endpoint selection downstream.

frontend/src/lib/components/Modals/CreateModal.svelte (2)

18-53: LGTM! Origin prop correctly defined and defaulted.

The optional origin prop with a sensible null default enables context-aware form behavior without breaking existing usage.


81-99: LGTM! Origin properly forwarded to ModelForm.

The prop is correctly threaded to the child component for downstream consumption.

frontend/src/lib/components/Forms/ModelForm/AppliedControlPolicyForm.svelte (2)

19-39: LGTM! Origin prop correctly defined.

The prop signature and default value are consistent with the parent components.


352-360: LGTM! Dynamic endpoint correctly wired to AutocompleteSelect.

The domainOptionEndpoint properly replaces the static endpoint, enabling context-aware domain selection.

frontend/src/lib/components/Forms/ModelForm.svelte (2)

90-130: LGTM! Origin prop correctly integrated.

The prop is properly typed, defaulted, and consistent with the component hierarchy.


364-375: LGTM! Origin correctly forwarded to AppliedControlsPoliciesForm.

The prop propagation completes the flow from the requirement-assessments page to the nested form component.

Copy link
Collaborator

@nas-tabchiche nas-tabchiche left a comment

Choose a reason for hiding this comment

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

The scope_folder_id url parameter should be enough to address this.
I am quite confident something like

<AutocompleteSelect
	{form}
	optionsEndpoint="folders?content_type=DO&content_type=GL"
	optionsDetailedUrlParameters={[
		origin === 'requirement-assessments' ? ['scope_folder_id', initialData.folder] : ['', undefined]
	]}
	field="folder"
	pathField="path"
	cacheLock={cacheLocks['folder']}
	bind:cachedValue={formDataCache['folder']}
	label={m.domain()}
/>

would work the same as the proposed implementation

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.

3 participants