This repository was archived by the owner on May 29, 2026. It is now read-only.
feat(resources): public resource serve + listing endpoints#53
Merged
Conversation
Contributor
Quality Report — ConductionNL/mydash @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 103/103 | |||
| npm | ✅ | ✅ 342/342 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-04-30 12:34 UTC
Download the full PDF report from the workflow artifacts.
ccb8c0d to
b30cbc7
Compare
Add the read side of the resource-uploads capability that complements the admin-only upload pipeline merged in PR #46: - Non-OCS GET /apps/mydash/resource/{filename} returning a StreamResponse with extension-derived Content-Type (jpeg/png/gif/ svg+xml/webp; default application/octet-stream) and Cache-Control: public, max-age=31536000. - GET /apps/mydash/api/resources listing endpoint returning {status, resources: [{name, url, size, modifiedAt}]} ordered by modifiedAt desc; empty folder yields HTTP 200 with [] (never 404). - Path traversal blocked at routing layer ([^/]+) plus defence-in-depth controller checks for .., backslashes, and empty values. All map to a uniform HTTP 404 with no detail leaked. - 50MB+ files (only reachable via manual filesystem tampering) refused with HTTP 413 BEFORE bytes are loaded — bounding worst-case memory to the 5 MB upload cap from REQ-RES-003. - Cache-busting via uniqid suffix in REQ-RES-004 filenames — a logical asset change yields a brand-new filename, naturally bypassing the one-year immutable cache. Implementation lives in a dedicated ResourceServeController + ResourceServeService pair so the existing upload controller's dependency graph stays under the PHPMD CouplingBetweenObjects limit. Routes registered under the standard `routes` array (mydash currently has no OCS controller infrastructure); both endpoints carry @NoAdminRequired so any logged-in user can fetch dashboard assets. Also fixes a pre-existing PHPStan warning in ImageMimeValidator (getimagesizefromstring always returns mime, ?? '' was dead). Tests: 19 new unit tests (8 ResourceServeController, 11 ResourceServeService) covering all 8 spec scenarios — PNG bytes + headers, SVG content-type, unknown ext fallback, missing file 404, encoded path traversal 404 (8 vectors via dataProvider), oversize 413 with no read, list ordering desc, empty folder empty array. All 208 PHPUnit tests pass. Quality: composer check:strict passes (lint, phpcs, phpmd, psalm, phpstan, test:all). SPDX headers on all new PHP files.
b30cbc7 to
b769a6a
Compare
Contributor
Quality Report — ConductionNL/mydash @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ⏭️ | ||||
| phpcs | ⏭️ | ||||
| phpmd | ⏭️ | ||||
| psalm | ⏭️ | ||||
| phpstan | ⏭️ | ||||
| phpmetrics | ❌ | ||||
| eslint | ❌ | ||||
| stylelint | ⏭️ | ||||
| composer | ⏭️ | ⏭️ | |||
| npm | ⏭️ | ⏭️ | |||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ |
Quality workflow — 2026-04-30 12:36 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Quality Report — ConductionNL/mydash @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 103/103 | |||
| npm | ✅ | ✅ 342/342 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-04-30 12:38 UTC
Download the full PDF report from the workflow artifacts.
This was referenced May 1, 2026
rubenvdlinde
added a commit
that referenced
this pull request
May 3, 2026
…53) Add the read side of the resource-uploads capability that complements the admin-only upload pipeline merged in PR #46: - Non-OCS GET /apps/mydash/resource/{filename} returning a StreamResponse with extension-derived Content-Type (jpeg/png/gif/ svg+xml/webp; default application/octet-stream) and Cache-Control: public, max-age=31536000. - GET /apps/mydash/api/resources listing endpoint returning {status, resources: [{name, url, size, modifiedAt}]} ordered by modifiedAt desc; empty folder yields HTTP 200 with [] (never 404). - Path traversal blocked at routing layer ([^/]+) plus defence-in-depth controller checks for .., backslashes, and empty values. All map to a uniform HTTP 404 with no detail leaked. - 50MB+ files (only reachable via manual filesystem tampering) refused with HTTP 413 BEFORE bytes are loaded — bounding worst-case memory to the 5 MB upload cap from REQ-RES-003. - Cache-busting via uniqid suffix in REQ-RES-004 filenames — a logical asset change yields a brand-new filename, naturally bypassing the one-year immutable cache. Implementation lives in a dedicated ResourceServeController + ResourceServeService pair so the existing upload controller's dependency graph stays under the PHPMD CouplingBetweenObjects limit. Routes registered under the standard `routes` array (mydash currently has no OCS controller infrastructure); both endpoints carry @NoAdminRequired so any logged-in user can fetch dashboard assets. Also fixes a pre-existing PHPStan warning in ImageMimeValidator (getimagesizefromstring always returns mime, ?? '' was dead). Tests: 19 new unit tests (8 ResourceServeController, 11 ResourceServeService) covering all 8 spec scenarios — PNG bytes + headers, SVG content-type, unknown ext fallback, missing file 404, encoded path traversal 404 (8 vectors via dataProvider), oversize 413 with no read, list ordering desc, empty folder empty array. All 208 PHPUnit tests pass. Quality: composer check:strict passes (lint, phpcs, phpmd, psalm, phpstan, test:all). SPDX headers on all new PHP files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the read side of the
resource-uploadscapability per REQ-RES-006..008, complementing the admin-only upload pipeline merged in #46.GET /apps/mydash/resource/{filename}— non-OCS plain web route streaming bytes viaphp://memorywith extension-derivedContent-TypeandCache-Control: public, max-age=31536000.GET /apps/mydash/api/resources— listing endpoint returning{status, resources: [{name, url, size, modifiedAt}]}ordered bymodifiedAtdesc; empty folder returns HTTP 200 with[].[^/]+) plus controller-level defence in depth (..,\\, empty/dot values) yielding uniform HTTP 404.uniqidsuffix on REQ-RES-004 filenames doubles as cache buster — a logical asset change yields a brand-new filename, naturally bypassing the one-year immutable cache.Implementation notes
ResourceServeController+ResourceServeServicepair, kept separate from the uploadResourceControllerso the dependency graph stays under the PHPMDCouplingBetweenObjectslimit.@NoAdminRequired— admin gating would lock dashboards out of their own assets, since uploaded resources are referenced from every dashboard render.routesarray (mydash currently has no OCS controller infrastructure). Pragmatic deviation fromtasks.md2.2 (which suggested registeringlistResourcesunderocs) — keeps the read surface consistent with the existingPOST /api/resourcesupload route on the same path. Behaviourally identical from the dashboard's perspective.ImageMimeValidatorfixed in passing (dead?? ''on a non-nullable field).Test plan
image/svg+xmlcontent-type, unknown ext → octet-stream, missing file → 404, encoded traversal → 404 (8 vectors via@dataProvider), oversize → 413 with nogetContent()call, list ordering desc, empty folder →[]. All 208 tests pass.composer check:strict— lint, phpcs, phpmd, psalm, phpstan, test:all all green.