Skip to content

Apply cache prefix, drop vendored Folder, tighten route-slot matchers#169

Open
dereuromark wants to merge 2 commits intomasterfrom
tinyauth-correctness-batch
Open

Apply cache prefix, drop vendored Folder, tighten route-slot matchers#169
dereuromark wants to merge 2 commits intomasterfrom
tinyauth-correctness-batch

Conversation

@dereuromark
Copy link
Copy Markdown
Owner

Summary

  • Cache::key() never applied the configured cachePrefix, so two TinyAuth installs sharing a Cake cache pool collided on the bare acl / allow keys. Multi-tenant or test environments where Cache pools survive across plugin boots could read another install's permissions data. The prefix is now applied, yielding tiny_auth_acl / tiny_auth_allow by default. Apps that set a custom or empty prefix work as written. Existing caches under the old bare keys go cold once and repopulate on next request.
  • Removed src/Filesystem/Folder.php — a vendored 946-line copy of the legacy CakePHP Folder class that the rest of the framework deleted long ago. Internally it was used only to scan controller directories from Syncer and Adder; replaced with a local _listDirectory() using scandir() that returns the same [folders, files] shape, so the $folderContent[0] / $folderContent[1] callsites work unchanged. Two test files used Folder::copy() to seed /tmp; replaced with a RecursiveDirectoryIterator-based copyDirectory() helper.
  • AclTrait::_isPublic and AllowTrait::_getAllowRule mixed isset() with !empty() to compare plugin/prefix slots between request and rule. The mismatch swallowed PHP-falsy values ('0', empty string) where it should not and treated them inconsistently between the two sides. Extracted a _matchesRouteSlot / _matchesAllowSlot helper that treats null and empty-string as the "no plugin / no prefix" sentinel and requires exact match otherwise.
  • Replaced two strpos(..., $needle) === 0 calls with str_starts_with for clarity (PHP 8 has it natively).

3 new tests cover the cache-prefix application: default prefix, custom prefix, empty prefix yields bare key. All 118 tests, phpstan, and phpcs pass.

Cache::key() never applied the configured cachePrefix, so two TinyAuth
installs sharing a Cake cache pool collided on the bare `acl` / `allow`
keys. Multi-tenant or test environments where Cache pools survive across
plugin boots could read another install's permissions data. The prefix
is now applied, yielding `tiny_auth_acl` / `tiny_auth_allow` by default.
Apps that set a custom or empty prefix work as written. Existing caches
under the old bare keys go cold once and repopulate on next request.

Removed src/Filesystem/Folder.php — a vendored 946-line copy of the
legacy CakePHP Folder class that the rest of the framework deleted long
ago. Internally it was used only to scan controller directories from
Syncer and Adder; replaced with a local _listDirectory(...) using
scandir() that returns the same [folders, files] shape, so the
$folderContent[0] / $folderContent[1] callsites work unchanged. Two
test files used Folder::copy() to seed /tmp; replaced with a
RecursiveDirectoryIterator-based copyDirectory() helper in each test.

AclTrait::_isPublic and AllowTrait::_getAllowRule mixed isset() with
!empty() to compare plugin/prefix slots between request and rule. The
mismatch swallowed PHP-falsy values ('0', empty string) where it
shouldn't and treated them inconsistently between the two sides.
Extracted a _matchesRouteSlot / _matchesAllowSlot helper that treats
null and empty-string as the "no plugin / no prefix" sentinel and
requires exact match otherwise. Also replaced two strpos(..., $needle)
=== 0 calls with str_starts_with for clarity (PHP 8 has it natively).

3 new tests cover the cache-prefix application: default prefix, custom
prefix, empty prefix yields bare key. All 118 tests, phpstan, and phpcs
pass.
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 10, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 67.16418% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.65%. Comparing base (8aa1555) to head (1203dea).

Files with missing lines Patch % Lines
src/Sync/Adder.php 0.00% 18 Missing ⚠️
src/Auth/AclTrait.php 84.61% 2 Missing ⚠️
src/Sync/Syncer.php 94.44% 1 Missing ⚠️
src/Utility/Cache.php 80.00% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #169      +/-   ##
============================================
+ Coverage     67.98%   77.65%   +9.66%     
+ Complexity      639      494     -145     
============================================
  Files            33       32       -1     
  Lines          1646     1329     -317     
============================================
- Hits           1119     1032      -87     
+ Misses          527      297     -230     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates TinyAuth’s caching and route-matching behavior to avoid cross-install collisions, removes a vendored legacy filesystem dependency, and makes route slot matching semantics consistent.

Changes:

  • Apply TinyAuth.cachePrefix when computing cache keys (defaulting to tiny_auth_) and add tests covering default/custom/empty prefixes.
  • Remove the vendored legacy Folder implementation and replace controller-directory scanning with a local scandir()-based helper; update affected command tests with a new directory copy helper.
  • Normalize plugin/prefix “route slot” comparisons in AclTrait/AllowTrait and replace strpos(... ) === 0 with str_starts_with().

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/TestCase/Utility/CacheTest.php Adds tests validating cache key prefix behavior (default/custom/empty prefix).
tests/TestCase/Command/SyncCommandTest.php Replaces Folder::copy() usage with a local recursive directory copy helper.
tests/TestCase/Command/AddCommandTest.php Replaces Folder::copy() usage with a local recursive directory copy helper.
src/Utility/Cache.php Updates Cache::key() to prepend the configured cache prefix.
src/Sync/Syncer.php Replaces Folder::read() with a local _listDirectory() helper for controller discovery.
src/Sync/Adder.php Replaces Folder::read() with a local _listDirectory() helper for controller discovery.
src/Filesystem/Folder.php Removes the vendored legacy CakePHP Folder class implementation.
src/Auth/AllowTrait.php Introduces consistent “empty slot” matching helper for plugin/prefix and uses str_starts_with().
src/Auth/AclTrait.php Introduces consistent “empty slot” matching helper for plugin/prefix and uses str_starts_with().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Sync/Syncer.php Outdated
Comment thread src/Sync/Adder.php Outdated
Addresses two PR-review concerns:

1. _listDirectory() in Syncer/Adder must skip hidden entries (.git, .svn,
   .DS_Store, ...) the way the previously-vendored Folder::read did.
   Adding 'is the first char a dot' to the existing '.'/'..' filter
   restores the prior behavior — without this, the scan would recurse
   into editor/VCS metadata directories and potentially pick up
   controller-shaped files inside them.

2. Codecov flagged Adder.php at 0% patch coverage and AclTrait at 61%.
   Adder's controller-discovery loop was previously only reachable via
   the AddCommand integration test, and the trait's new _matchesRouteSlot
   helper had no direct coverage. Added:

   - SyncCommandTest::testSyncSkipsHiddenDirectories and
     AddCommandTest::testAddSkipsHiddenDirectories — drop a .git /
     .svn directory with a controller-shaped file in tmp, run the
     command, assert the controller name doesn't surface in output.
     This exercises Adder._listDirectory and Syncer._listDirectory
     with hidden-entry rejection in the same path.
   - AclTraitRouteSlotMatcherTest — anonymous classes hosting AclTrait
     and AllowTrait expose the protected matchers via a thin wrapper,
     plus a 11-row dataProvider covers all (null, '', value) crossings
     including the 'distinct types must not collapse' case the previous
     !empty() implementation got wrong.

phpunit (145/145), phpstan, and phpcs all pass.
@dereuromark
Copy link
Copy Markdown
Owner Author

Addressed Copilot's feedback on _listDirectory() in both Syncer.php and Adder.php — entries starting with . are now skipped, matching the previously-vendored Folder::read() behavior. Added two regression tests (testSync/testAdd SkipsHiddenDirectories) that drop a .git/.svn directory with a controller-shaped file in tmp and confirm it doesn't surface in command output. Also added a dedicated dataProvider-driven AclTraitRouteSlotMatcherTest to cover the codecov-flagged coverage gap on _matchesRouteSlot edge cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants