Skip to content

Conversation

@Boy132
Copy link
Member

@Boy132 Boy132 commented Sep 29, 2025

Closes #1730

Adds dedicated endpoint for exporting eggs as file. Also changes the auth for the application api so admins can access the api with their session. (which previously was exclusive only for the root admin)

@Boy132 Boy132 self-assigned this Sep 29, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 29, 2025

📝 Walkthrough

Walkthrough

Replaces in-panel egg streaming exports with a route-based export endpoint and adds a controller export action and request validator; adds export route; adds Content-Type header for schedule export; tightens application API authorization and middleware admin check; updates tests and helpers for new admin flag.

Changes

Cohort / File(s) Change Summary
Panel: Egg export action refactor
app/Filament/Components/Actions/ExportEggAction.php
Removes server-side streaming and direct EggExporterService usage in the Filament actions; actions now generate a route-based export URL with a format param and close the modal immediately.
Panel: Schedule export header
app/Filament/Components/Actions/ExportScheduleAction.php
Adds Content-Type: application/json header to the streamDownload response.
API: Egg export controller & route
app/Http/Controllers/Api/Application/Eggs/EggController.php, routes/api-application.php
Injects EggExporterService into EggController; adds export(ExportEggRequest $request, Egg $egg) to stream a YAML/JSON download; registers GET /eggs/{egg:id}/export route mapped to this method.
API Requests: Export validator
app/Http/Requests/Api/Application/Eggs/ExportEggRequest.php
Adds new ExportEggRequest (extends GetEggRequest) with rules() validating optional format ∈ {yaml, json}.
Auth: Application middleware role check
app/Http/Middleware/Api/Application/AuthenticateApplicationUser.php
Changes admin gate from isRootAdmin() to isAdmin() for middleware permission check.
Auth: Application API request authorization
app/Http/Requests/Api/Application/ApplicationApiRequest.php
Refactors transient token authorization to permission-based checks; requires root-admin for account-type API key path; retains AdminAcl fallback for other cases.
Tests & Helpers
tests/Traits/Http/RequestMockHelpers.php, tests/Unit/Http/Middleware/Api/Application/AuthenticateUserTest.php
Updates generateRequestUserModel signature to accept (bool $isAdmin, bool $isRootAdmin, array $args = []); updates tests to pass both flags and adds test_root_admin_user.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant UI as Admin Panel (UI)
    participant PanelAction as Export Action
    participant Router as API Router
    participant Req as ExportEggRequest
    participant Ctrl as EggController
    participant Svc as EggExporterService
    participant Resp as StreamedResponse

    UI->>PanelAction: User clicks "Export" (select format)
    PanelAction->>UI: open/close modal ->close() (modal closed immediately)
    PanelAction->>Router: navigate to GET /api/application/eggs/{id}/export?format=...
    Router->>Req: validate request
    Req-->>Router: validated
    Router->>Ctrl: export(request, egg)
    rect rgba(230,245,255,0.6)
    Ctrl->>Svc: generate export content (egg, format)
    Svc-->>Ctrl: stream callback/content
    end
    Ctrl->>Resp: return StreamedResponse (filename, Content-Type)
    Resp-->>UI: file download (streamed)
Loading

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning In addition to preventing UI blocking, the pull request introduces a new export controller endpoint, updates application API authentication logic for admins, adjusts schedule export headers, and alters several middleware tests, which extend beyond the UI unblocking fix specified by the linked issue. Consider splitting the authentication changes and creation of the new export endpoint into separate pull requests or updating the linked issue to reflect these additional objectives, so that each pull request remains focused on a single primary concern and improves clarity during review.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately describes the primary addition of a dedicated endpoint for exporting eggs, matching the main functional change implemented in the pull request.
Linked Issues Check ✅ Passed The pull request modifies the Filament export action to generate a route-based URL and immediately close the export modal, eliminating server-side streaming and thereby preventing the panel from remaining darkened or blocked after exporting an egg, which directly addresses the primary objective of linked issue #1730.
Description Check ✅ Passed The description clearly references closing issue #1730 and outlines both the addition of the dedicated export endpoint and the change to application API authentication, which directly correspond to the implemented changes in the pull request.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/Http/Requests/Api/Application/ApplicationApiRequest.php (1)

51-56: Clarify account-key ACL policy

The current fast-path for root admins using TYPE_ACCOUNT still allows non-root admins to pass via AdminAcl::check(). Decide on the intended policy and implement one of the following:

  • Option A (restrict to root admins): for ApiKey::TYPE_ACCOUNT, only allow when isRootAdmin() and AdminAcl::check() both pass.
  • Option B (remove special-case bypass): drop the root-admin fast-path and rely solely on AdminAcl::check() for all key types.
🧹 Nitpick comments (5)
app/Http/Requests/Api/Application/Eggs/ExportEggRequest.php (1)

7-11: Use enum-based validation to stay in sync with EggFormat

Replace the string list with an enum rule to prevent drift and typos. Also confirm a sane default is applied when format is null.

-        return [
-            'format' => 'nullable|string|in:yaml,json',
-        ];
+        return [
+            'format' => ['nullable', \Illuminate\Validation\Rule::enum(\App\Enums\EggFormat::class)],
+        ];

Add (outside this hunk):

use App\Enums\EggFormat;
use Illuminate\Validation\Rule;
app/Http/Requests/Api/Application/ApplicationApiRequest.php (1)

44-48: Verify ability naming and required combo for READ

Using “viewList {resource}” AND “view {resource}” for READ is stricter than typical. Confirm these ability names exist and align with User::can() semantics (space vs dot notation) to avoid false 403s on session-based requests. If only viewing a single resource, consider mapping READ to “view {resource}” and letting list endpoints check “viewList {resource}”.

app/Http/Controllers/Api/Application/Eggs/EggController.php (3)

63-64: Use explicit MIME types and add nosniff (recommended).

Some clients expect application/x-yaml for YAML. Also add X-Content-Type-Options=nosniff. Optional, but improves compatibility and security.

Apply this diff:

-        }, 'egg-' . $egg->getKebabName() . '.' . $format->value, [
-            'Content-Type' => 'application/' . $format->value,
-        ]);
+        }, 'egg-' . $egg->getKebabName() . '.' . $format->value, (function () use ($format) {
+            $contentType = match ($format) {
+                EggFormat::JSON => 'application/json',
+                EggFormat::YAML => 'application/x-yaml',
+            };
+            return [
+                'Content-Type' => $contentType,
+                'X-Content-Type-Options' => 'nosniff',
+            ];
+        })());

58-58: Optional: support Accept header as a fallback.

If no format query is provided, consider deriving format from Accept (application/json vs application/x-yaml) before defaulting to YAML. Keeps it HTTP-native for API consumers.


60-62: Avoid re-querying the egg in the service (micro-optimization).

Exporter re-fetches the egg by ID; since you already have the model, consider updating the service to accept Egg (or overload) to drop one DB hit. Low priority.

Based on relevant code snippet for EggExporterService::handle.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec5fd32 and e7b899b.

📒 Files selected for processing (7)
  • app/Filament/Components/Actions/ExportEggAction.php (1 hunks)
  • app/Filament/Components/Actions/ExportScheduleAction.php (1 hunks)
  • app/Http/Controllers/Api/Application/Eggs/EggController.php (2 hunks)
  • app/Http/Middleware/Api/Application/AuthenticateApplicationUser.php (1 hunks)
  • app/Http/Requests/Api/Application/ApplicationApiRequest.php (1 hunks)
  • app/Http/Requests/Api/Application/Eggs/ExportEggRequest.php (1 hunks)
  • routes/api-application.php (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
app/Http/Requests/Api/Application/Eggs/ExportEggRequest.php (1)
app/Http/Requests/Api/Application/Eggs/GetEggRequest.php (1)
  • GetEggRequest (9-14)
routes/api-application.php (1)
app/Http/Controllers/Api/Application/Eggs/EggController.php (1)
  • EggController (15-66)
app/Http/Controllers/Api/Application/Eggs/EggController.php (4)
app/Http/Controllers/Api/Application/ApplicationApiController.php (1)
  • ApplicationApiController (14-81)
app/Http/Requests/Api/Application/Eggs/ExportEggRequest.php (1)
  • ExportEggRequest (5-13)
app/Models/Egg.php (2)
  • Egg (60-328)
  • getKebabName (324-327)
app/Services/Eggs/Sharing/EggExporterService.php (1)
  • EggExporterService (12-99)
app/Http/Requests/Api/Application/ApplicationApiRequest.php (3)
app/Services/Acl/Api/AdminAcl.php (1)
  • AdminAcl (7-39)
app/Models/ApiKey.php (2)
  • user (148-151)
  • ApiKey (56-234)
app/Models/User.php (2)
  • can (358-371)
  • isRootAdmin (380-383)
app/Http/Middleware/Api/Application/AuthenticateApplicationUser.php (1)
app/Models/User.php (1)
  • isAdmin (385-388)
app/Filament/Components/Actions/ExportEggAction.php (1)
app/Models/Egg.php (1)
  • Egg (60-328)
🔇 Additional comments (7)
app/Filament/Components/Actions/ExportEggAction.php (1)

43-48: Route-based download + close modal looks good and should avoid the overlay issue

Opening in a new tab and closing the modal should resolve #1730’s darkened panel behavior.

Please confirm:

  • Response headers set Content-Type and Content-Disposition correctly (per format).
  • Filename uses Egg::getKebabName() or equivalent and matches expectations.
  • Manual test following issue #1730 steps no longer reproduces the overlay.
app/Http/Middleware/Api/Application/AuthenticateApplicationUser.php (1)

20-22: Unable to locate middleware alias—manual verification needed
Could not find the routeMiddleware entry for AuthenticateApplicationUser in app/Http/Kernel.php; please confirm the alias mapping and audit all routes that use this middleware.

routes/api-application.php (1)

104-104: New egg export route looks good; confirm middleware/auth behavior.

LGTM adding GET /eggs/{egg:id}/export. Please confirm it inherits the same application API middleware and that the new “admin session access” change allows authorized admins (not only root) to hit this route, matching the PR goal.

app/Http/Controllers/Api/Application/Eggs/EggController.php (4)

5-13: Imports updated appropriately.
No issues with the added dependencies.


17-21: Constructor DI is clean.
Injecting EggExporterService via ctor keeps the controller lean.


56-62: Export endpoint implementation is correct and aligns with the new route.
Validation via ExportEggRequest + EggFormat fallback to YAML is solid.


56-65: Verify UI regression fix (panel overlay) end-to-end.

This route-based download should prevent the Filament action overlay. Please confirm the front-end now triggers a direct file download without leaving the page darkened, per issue #1730.

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

🧹 Nitpick comments (1)
tests/Traits/Http/RequestMockHelpers.php (1)

36-44: Align the docblock with the method signature

Line 36 still advertises that generateRequestUserModel “also returns the generated model,” but the method now returns void. To avoid confusion for future tests that might rely on the doc, please update the docblock (or reintroduce the return). For example:

-    /**
-     * Generates a new request user model and also returns the generated model.
-     */
+    /**
+     * Generates a new request user model and wires it into the mocked request.
+     */
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed78b90 and b1ecb04.

📒 Files selected for processing (2)
  • tests/Traits/Http/RequestMockHelpers.php (1 hunks)
  • tests/Unit/Http/Middleware/Api/Application/AuthenticateUserTest.php (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/Traits/Http/RequestMockHelpers.php (2)
app/Models/User.php (3)
  • isAdmin (385-388)
  • isRootAdmin (380-383)
  • User (95-493)
app/Models/Role.php (1)
  • isRootAdmin (124-127)
tests/Unit/Http/Middleware/Api/Application/AuthenticateUserTest.php (3)
tests/Traits/Http/RequestMockHelpers.php (1)
  • generateRequestUserModel (38-47)
app/Http/Middleware/Api/Application/AuthenticateApplicationUser.php (1)
  • handle (16-25)
tests/Traits/Http/MocksMiddlewareClosure.php (1)
  • getClosureAssertions (14-24)
🔇 Additional comments (1)
tests/Unit/Http/Middleware/Api/Application/AuthenticateUserTest.php (1)

48-52: Nice coverage for the root-admin path

Line 48 ensures we exercise the session-authenticated root admin case, so we have explicit protection against regressions when tightening the middleware earlier in the stack. 👍

@Boy132 Boy132 merged commit a58ae87 into main Oct 7, 2025
25 checks passed
@Boy132 Boy132 deleted the boy132/fix-egg-exports branch October 7, 2025 21:41
@github-actions github-actions bot locked and limited conversation to collaborators Oct 7, 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.

Exporting an egg darkens the panel until the next mouse click

3 participants