diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25a1c11b..77a56004 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,11 +11,11 @@ jobs: strategy: fail-fast: false matrix: - php-version: ['8.2', '8.5'] + php-version: ['8.5'] db-type: [sqlite, mysql, pgsql] prefer-lowest: [''] include: - - php-version: '8.2' + - php-version: '8.5' db-type: 'sqlite' prefer-lowest: 'prefer-lowest' @@ -67,7 +67,7 @@ jobs: if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi if [[ ${{ matrix.db-type }} == 'mysql' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp'; fi if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:postgres@127.0.0.1/postgres'; fi - if [[ ${{ matrix.php-version }} == '8.2' ]]; then + if [[ ${{ matrix.php-version }} == '8.5' ]]; then vendor/bin/phpunit --coverage-clover=coverage.xml else vendor/bin/phpunit @@ -77,7 +77,7 @@ jobs: run: vendor/bin/validate-prefer-lowest -m - name: Upload coverage reports to Codecov - if: success() && matrix.php-version == '8.2' + if: success() && matrix.php-version == '8.5' uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -92,7 +92,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: '8.5' extensions: mbstring, intl coverage: none diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 05fb7052..ca61aae9 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -47,6 +47,7 @@ jobs: path: docs/.vitepress/dist deploy: + if: github.ref == 'refs/heads/master' permissions: contents: read pages: write diff --git a/README.md b/README.md index c839aedb..dc9b20d9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ # CakePHP TinyAuth Plugin -[![CI](https://github.com/dereuromark/cakephp-tinyauth/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/dereuromark/cakephp-tinyauth/actions/workflows/ci.yml?query=branch%3Amaster) +This branch targets CakePHP 6 and PHP 8.5 or later. Use the `cake6` branches of companion CakePHP plugins during development. + +Composer applications consuming this development branch must set `minimum-stability` to `dev` and `prefer-stable` to `true`, then require this plugin as `dev-cake6`. Companion plugins also use their `cake6` branches. The published documentation website covers stable CakePHP 5 releases; use this branch's `docs/` directory for the upgrade documentation. + +[![CI](https://github.com/dereuromark/cakephp-tinyauth/actions/workflows/ci.yml/badge.svg?branch=cake6)](https://github.com/dereuromark/cakephp-tinyauth/actions/workflows/ci.yml?query=branch%3Acake6) [![Latest Stable Version](https://poser.pugx.org/dereuromark/cakephp-tinyauth/v/stable.svg)](https://packagist.org/packages/dereuromark/cakephp-tinyauth) [![Coverage Status](https://img.shields.io/codecov/c/github/dereuromark/cakephp-tinyauth/master.svg)](https://codecov.io/github/dereuromark/cakephp-tinyauth/branch/master) [![PHPStan](https://img.shields.io/badge/PHPStan-level%208-brightgreen.svg?style=flat)](https://phpstan.org/) -[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.2-8892BF.svg)](https://php.net/) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.5-8892BF.svg)](https://php.net/) [![License](https://poser.pugx.org/dereuromark/cakephp-tinyauth/license.svg)](LICENSE) [![Total Downloads](https://poser.pugx.org/dereuromark/cakephp-tinyauth/d/total.svg)](https://packagist.org/packages/dereuromark/cakephp-tinyauth) [![Coding Standards](https://img.shields.io/badge/cs-PSR--2--R-purple.svg?style=flat-square)](https://github.com/php-fig-rectified/fig-rectified-standards) diff --git a/composer.json b/composer.json index 381da27e..2ff29313 100644 --- a/composer.json +++ b/composer.json @@ -27,19 +27,19 @@ "docs": "https://dereuromark.github.io/cakephp-tinyauth/" }, "require": { - "php": ">=8.2", - "cakephp/cakephp": "^5.1.1" + "php": ">=8.5", + "cakephp/cakephp": "^6.0@dev" }, "require-dev": { - "cakephp/authentication": "^3.0.1 || ^4.0", - "cakephp/authorization": "^3.0.1", - "cakephp/debug_kit": "^5.0.1", + "cakephp/authentication": "^5.0@dev", + "cakephp/authorization": "^4.0@dev", + "cakephp/debug_kit": "^6.0@dev", "composer/semver": "^3.0", - "dereuromark/cakephp-i18n-lint": "^0.1.1", + "dereuromark/cakephp-i18n-lint": "dev-cake6", "fig-r/psr2r-sniffer": "dev-master", - "phpunit/phpunit": "^11.5 || ^12.1 || ^13.0" + "phpunit/phpunit": "^13.0" }, - "minimum-stability": "stable", + "minimum-stability": "dev", "prefer-stable": true, "autoload": { "psr-4": { diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 9d629d68..1ac529a4 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -90,7 +90,7 @@ export default defineConfig({ provider: 'local', }, editLink: { - pattern: 'https://github.com/dereuromark/cakephp-tinyauth/edit/master/docs/:path', + pattern: 'https://github.com/dereuromark/cakephp-tinyauth/edit/cake6/docs/:path', text: 'Edit this page on GitHub', }, footer: { diff --git a/docs/authentication/impersonation.md b/docs/authentication/impersonation.md index 2686cb38..5133ec3d 100644 --- a/docs/authentication/impersonation.md +++ b/docs/authentication/impersonation.md @@ -4,7 +4,7 @@ TinyAuth ships a `PrimaryKeySessionAuthenticator` that enables the classic "admi ## Setup -With Authentication 4, replace the default Session authenticator in `getAuthenticationService()` with the following configuration. This example assumes a `Users` table with an `id` primary key: +With Authentication 5, replace the default Session authenticator in `getAuthenticationService()` with the following configuration. This example assumes a `Users` table with an `id` primary key: ```php $service->loadAuthenticator('TinyAuth.PrimaryKeySession', [ @@ -22,7 +22,7 @@ $service->loadAuthenticator('TinyAuth.PrimaryKeySession', [ ]); ``` -The authenticator stores only the user’s primary key in the session. With caching disabled, it reloads the identity through the configured identifier on each request. For Authentication 3, configure the Token identifier using its [versioned setup guide](https://book.cakephp.org/authentication/3/en/quick-start.html). +The authenticator stores only the user’s primary key in the session. With caching disabled, it reloads the identity through the configured identifier on each request. Configure the Token identifier using its [versioned setup guide](https://book.cakephp.org/authentication/5/#quick-start). ### Config keys diff --git a/docs/authentication/index.md b/docs/authentication/index.md index 6c364039..1f989a0d 100644 --- a/docs/authentication/index.md +++ b/docs/authentication/index.md @@ -6,7 +6,7 @@ Complete [Installation](/guide/install) first. For a small working rule set, fol ## Official plugin setup -Set up the [CakePHP Authentication plugin](https://github.com/cakephp/authentication) before loading TinyAuth’s component. Use the documentation matching your installed version: [Authentication 4](https://book.cakephp.org/authentication/4/en/quick-start.html) or [Authentication 3](https://book.cakephp.org/authentication/3/en/quick-start.html). +Set up the [CakePHP Authentication plugin](https://github.com/cakephp/authentication) before loading TinyAuth’s component. Use the documentation matching your installed version: [Authentication 5](https://book.cakephp.org/authentication/5/#quick-start). ## Implement Authentication Interface @@ -24,7 +24,7 @@ class Application extends BaseApplication implements AuthenticationServiceProvid } ``` -πŸ“– See: [Application Setup](https://book.cakephp.org/authentication/4/en/quick-start.html#application-setup) in official docs +πŸ“– See: [Application Setup](https://book.cakephp.org/authentication/5/#getting-started) in official docs ## Configure Middleware @@ -46,11 +46,11 @@ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue } ``` -πŸ“– See: [Middleware Setup](https://book.cakephp.org/authentication/4/en/middleware.html) in official docs +πŸ“– See: [Middleware Setup](https://book.cakephp.org/authentication/5/middleware.html) in official docs ## Configure Authentication Service -The example below uses Authentication 4. For Authentication 3, follow its versioned guide to configure identifiers, then load the same TinyAuth component. Implement `getAuthenticationService()` in your `Application` class: +The example below uses Authentication 5 with CakePHP 6. Implement `getAuthenticationService()` in your `Application` class: ```php // src/Application.php @@ -123,7 +123,7 @@ public function getAuthenticationService(ServerRequestInterface $request): Authe Note: Each authenticator has its own `identifier` configuration. The Session authenticator doesn't need one as it uses the stored identity. -πŸ“– See: [Authentication Service](https://book.cakephp.org/authentication/4/en/authentication-service.html) in official docs +πŸ“– See: [Authentication Service](https://book.cakephp.org/authentication/5/#getting-started) in official docs --- @@ -402,7 +402,7 @@ $service->loadAuthenticator('TinyAuth.PrimaryKeySession', [ ]); ``` -πŸ“– See: [Session Authenticator](https://book.cakephp.org/authentication/4/en/authenticators.html#session) in official docs for base functionality +πŸ“– See: [Session Authenticator](https://book.cakephp.org/authentication/5/authenticators.html#session) in official docs for base functionality ### Session Caching with PrimaryKeySession @@ -485,7 +485,7 @@ $service->loadAuthenticator('Tools.LoginLink', [ Note: Requires `composer require dereuromark/cakephp-tools` -πŸ“– See: [Tools Plugin LoginLink](https://github.com/dereuromark/cakephp-tools/blob/master/docs/Authentication/LoginLink.md) +πŸ“– See: [Tools Plugin LoginLink](https://github.com/dereuromark/cakephp-tools/blob/cake6/docs/Authentication/LoginLink.md) ## Accessing User Identity @@ -504,6 +504,6 @@ $user = $this->AuthUser->identity(); # Additional Resources -- πŸ“– Official Authentication Docs: [book.cakephp.org/authentication/3](https://book.cakephp.org/authentication/3/en/index.html) +- πŸ“– Official Authentication Docs: [book.cakephp.org/authentication/5](https://book.cakephp.org/authentication/5/) - πŸ” Authorization: Add role-based access control - See [Authorization](/authorization/) - ❓ Troubleshooting: See [Troubleshooting](/guide/troubleshooting) diff --git a/docs/authorization/index.md b/docs/authorization/index.md index c7bdffc8..61e9374c 100644 --- a/docs/authorization/index.md +++ b/docs/authorization/index.md @@ -6,7 +6,7 @@ Complete [Installation](/guide/install) first. [Getting started](/guide/quick-st ## Official plugin setup -Set up the [CakePHP Authorization plugin](https://github.com/cakephp/authorization) with its [Getting started guide](https://book.cakephp.org/authorization/3/en/getting-started.html). Authentication middleware must run before Authorization middleware so the latter can decorate the authenticated identity. +Set up the [CakePHP Authorization plugin](https://github.com/cakephp/authorization) with its [Getting started guide](https://book.cakephp.org/authorization/4/#getting-started). Authentication middleware must run before Authorization middleware so the latter can decorate the authenticated identity. ## Implement Authorization Interface @@ -34,7 +34,7 @@ class Application extends BaseApplication } ``` -πŸ“– See: [Getting Started](https://book.cakephp.org/authorization/3/en/getting-started.html) in official docs +πŸ“– See: [Getting Started](https://book.cakephp.org/authorization/4/#getting-started) in official docs ## Configure Middleware @@ -73,7 +73,7 @@ public function getAuthorizationService(ServerRequestInterface $request): Author This configures the request policy that reads your `auth_acl.ini` file for role-based permissions. -πŸ“– See: [Authorization Service](https://book.cakephp.org/authorization/3/en/getting-started.html#authorization-service) in official docs +πŸ“– See: [Authorization Service](https://book.cakephp.org/authorization/4/#getting-started) in official docs --- @@ -578,6 +578,6 @@ By default INI files and the IniAdapter will be used. See [AuthorizationAdapter] # Additional Resources -- πŸ“– Official Authorization Docs: [book.cakephp.org/authorization/3](https://book.cakephp.org/authorization/3/en/index.html) +- πŸ“– Official Authorization Docs: [book.cakephp.org/authorization/4](https://book.cakephp.org/authorization/4/) - πŸ” Authentication: Set up authentication first - See [Authentication](/authentication/) - ❓ Troubleshooting: See [Troubleshooting](/guide/troubleshooting) diff --git a/docs/guide/custom-adapters.md b/docs/guide/custom-adapters.md index 770cda2f..5ac8fd45 100644 --- a/docs/guide/custom-adapters.md +++ b/docs/guide/custom-adapters.md @@ -20,7 +20,7 @@ interface AllowAdapterInterface { } ``` -`getAllow()` returns the public-action whitelist, keyed by section. The reference implementation is [`IniAllowAdapter`](https://github.com/dereuromark/cakephp-tinyauth/blob/master/src/Auth/AllowAdapter/IniAllowAdapter.php). +`getAllow()` returns the public-action whitelist, keyed by section. The reference implementation is [`IniAllowAdapter`](https://github.com/dereuromark/cakephp-tinyauth/blob/cake6/src/Auth/AllowAdapter/IniAllowAdapter.php). Each entry should look like: @@ -57,7 +57,7 @@ interface AclAdapterInterface { } ``` -`getAcl()` returns the role-permission map, keyed by section. The reference implementation is [`IniAclAdapter`](https://github.com/dereuromark/cakephp-tinyauth/blob/master/src/Auth/AclAdapter/IniAclAdapter.php). +`getAcl()` returns the role-permission map, keyed by section. The reference implementation is [`IniAclAdapter`](https://github.com/dereuromark/cakephp-tinyauth/blob/cake6/src/Auth/AclAdapter/IniAclAdapter.php). `$availableRoles` is `['admin' => 1, 'user' => 2, ...]` so you can look up role IDs by name. diff --git a/docs/guide/install.md b/docs/guide/install.md index 2b61e601..07401569 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -1,20 +1,25 @@ # Installation +The `cake6` branch requires CakePHP 6 and PHP 8.5. Development dependencies require the application to allow development stability, even when TinyAuth declares its own `@dev` constraints. Keep `prefer-stable` enabled for other packages. + ## Required dependencies TinyAuth wraps CakePHP's official Authentication and Authorization plugins. Before using TinyAuth features, you must install and configure the official plugins: | Feature | Required Plugin | Setup Guide | | --- | --- | --- | -| Authentication (login/logout) | [cakephp/authentication](https://github.com/cakephp/authentication) | [/authentication/](/authentication/) + [Authentication 4](https://book.cakephp.org/authentication/4/en/index.html) / [Authentication 3](https://book.cakephp.org/authentication/3/en/index.html) | -| Authorization (roles / ACL) | [cakephp/authorization](https://github.com/cakephp/authorization) | [/authorization/](/authorization/) + [Official Docs](https://book.cakephp.org/authorization/3/en/index.html) | +| Authentication (login/logout) | [cakephp/authentication](https://github.com/cakephp/authentication) | [/authentication/](/authentication/) + [Authentication 5](https://book.cakephp.org/authentication/5/) | +| Authorization (roles / ACL) | [cakephp/authorization](https://github.com/cakephp/authorization) | [/authorization/](/authorization/) + [Official Docs](https://book.cakephp.org/authorization/4/) | ```bash +composer config minimum-stability dev +composer config prefer-stable true + # For authentication features -composer require cakephp/authentication +composer require 'cakephp/authentication:^5.0@dev' # For authorization features -composer require cakephp/authorization +composer require 'cakephp/authorization:^4.0@dev' ``` > Standalone exception: the [AuthUser component and helper](/auth-user) work without the official plugins: they integrate with any authentication solution that sets an identity in the request. @@ -22,7 +27,7 @@ composer require cakephp/authorization ## Install TinyAuth ```bash -composer require dereuromark/cakephp-tinyauth +composer require dereuromark/cakephp-tinyauth:dev-cake6 bin/cake plugin load TinyAuth ``` diff --git a/docs/guide/upgrade.md b/docs/guide/upgrade.md index ae1490ae..4ac012ab 100644 --- a/docs/guide/upgrade.md +++ b/docs/guide/upgrade.md @@ -1,5 +1,13 @@ # Upgrade Guide +## CakePHP 6 development branch + +The `cake6` branch requires PHP 8.5 and CakePHP 6. Authentication features use Authentication 5; authorization features use Authorization 4. Follow the [installation guide](/guide/install) to select the development branches and configure Composer stability. + +Custom components and helpers must follow the CakePHP 6 configuration and view property names. Custom commands implement `execute(): int` and access the inherited argument and console properties. Review overrides against the native parameter and return types in this branch. INI allow-file configuration still accepts one directory or an array of directories. + +The test suite uses PHPUnit 13. The published documentation website describes the stable CakePHP 5 branch; use the `docs/` files in this branch for CakePHP 6. + ## Upgrading from TinyAuth 3.x (CakePHP 4.x) **Breaking changes:** TinyAuth has fundamentally changed from a standalone auth solution to a wrapper around the official CakePHP plugins. diff --git a/src/Auth/AclTrait.php b/src/Auth/AclTrait.php index 61e1e59f..b8f3c5ed 100644 --- a/src/Auth/AclTrait.php +++ b/src/Auth/AclTrait.php @@ -4,6 +4,7 @@ use ArrayAccess; use BackedEnum; +use Cake\Collection\CollectionInterface; use Cake\Core\Configure; use Cake\Core\Exception\CakeException; use Cake\Database\Type\EnumLabelInterface; @@ -24,32 +25,32 @@ trait AclTrait { /** * @var array|null */ - protected $_acl; + protected ?array $_acl = null; /** * @var array|null */ - protected $_roles; + protected ?array $_roles = null; /** * @var array|null */ - protected $_prefixMap; + protected ?array $_prefixMap = null; /** * @var array|null */ - protected $_userRoles; + protected ?array $_userRoles = null; /** * @var \TinyAuth\Auth\AclAdapter\AclAdapterInterface|null */ - protected $_aclAdapter; + protected ?AclAdapterInterface $_aclAdapter = null; /** * @var array|null */ - protected $auth; + protected ?array $auth = null; /** * Finds the authorization adapter to use for this request. @@ -59,7 +60,7 @@ trait AclTrait { * @throws \InvalidArgumentException * @return \TinyAuth\Auth\AclAdapter\AclAdapterInterface */ - protected function _loadAclAdapter($adapter) { + protected function _loadAclAdapter(string $adapter): AclAdapterInterface { if ($this->_aclAdapter !== null) { return $this->_aclAdapter; } @@ -136,7 +137,7 @@ protected function _checkUser(ArrayAccess|array $user, array $params): bool { * * @return bool */ - protected function _isProtectedPrefix($prefix, array $protectedPrefixes) { + protected function _isProtectedPrefix($prefix, array $protectedPrefixes): bool { foreach ($protectedPrefixes as $protectedPrefix) { if ($prefix === $protectedPrefix || str_starts_with((string)$prefix, $protectedPrefix . '/')) { return true; @@ -159,7 +160,7 @@ protected function _isProtectedPrefix($prefix, array $protectedPrefixes) { * @param mixed $rule The value declared on the ACL rule. * @return bool True when both sides describe the same slot. */ - protected function _matchesRouteSlot($request, $rule): bool { + protected function _matchesRouteSlot(mixed $request, mixed $rule): bool { $requestEmpty = $request === null || $request === ''; $ruleEmpty = $rule === null || $rule === ''; @@ -179,7 +180,7 @@ protected function _matchesRouteSlot($request, $rule): bool { * * @return bool */ - protected function _check(array $userRoles, array $params) { + protected function _check(array $userRoles, array $params): bool { // Allow access to all prefixed actions for users belonging to // the specified role that matches the prefix. $prefixMap = $this->getConfig('authorizeByPrefix'); @@ -271,7 +272,7 @@ protected function _prefixMap(array $roles): array { * * @return array */ - protected function _prefixesFromRoles(array $roles) { + protected function _prefixesFromRoles(array $roles): array { $names = array_keys($roles); $prefixMap = []; foreach ($names as $name) { @@ -290,7 +291,7 @@ protected function _prefixesFromRoles(array $roles) { * * @return bool */ - protected function _isAuthorizedByPrefix($prefix, array $prefixMap, array $userRoles, array $availableRoles) { + protected function _isAuthorizedByPrefix($prefix, array $prefixMap, array $userRoles, array $availableRoles): bool { if (!$userRoles || !$prefixMap || !$availableRoles) { return false; } @@ -317,7 +318,7 @@ protected function _isAuthorizedByPrefix($prefix, array $prefixMap, array $userR * * @return array */ - protected function _normalizePrefixes(array $prefixes) { + protected function _normalizePrefixes(array $prefixes): array { $normalized = []; foreach ($prefixes as $prefix => $role) { if (is_int($prefix)) { @@ -336,7 +337,7 @@ protected function _normalizePrefixes(array $prefixes) { * * @return bool */ - protected function _isPublic(array $params) { + protected function _isPublic(array $params): bool { $rule = $this->_getAllowRule($params); return $this->_isActionAllowed($rule, $params['action']); @@ -349,7 +350,7 @@ protected function _isPublic(array $params) { * @throws \Cake\Core\Exception\CakeException * @return array */ - protected function _getAuth() { + protected function _getAuth(): array { if ($this->auth) { return $this->auth; } @@ -372,7 +373,7 @@ protected function _getAuth() { * @param array|string|null $path * @return array */ - protected function _getAcl($path = null) { + protected function _getAcl(array|string|null $path = null): array { if ($this->getConfig('autoClearCache') && Configure::read('debug')) { Cache::clear(Cache::KEY_ACL); } @@ -413,7 +414,7 @@ protected function _getAcl($path = null) { * @param string $file INI file name. * @return array List with all found files. */ - protected function _parseFiles($paths, $file) { + protected function _parseFiles(array|string|null $paths, string $file): array { return Utility::parseFiles($paths, $file); } @@ -423,7 +424,7 @@ protected function _parseFiles($paths, $file) { * @param string $key INI section key as found in acl.ini * @return array Array with named keys for controller, plugin and prefix */ - protected function _deconstructIniKey($key) { + protected function _deconstructIniKey(string $key): array { return Utility::deconstructIniKey($key); } @@ -433,7 +434,7 @@ protected function _deconstructIniKey($key) { * @param array $params The request params * @return string|null Hash with named keys for controller, plugin and prefix */ - protected function _constructIniKey($params): ?string { + protected function _constructIniKey(array $params): ?string { $res = $params['controller'] ?? null; if ($res === null) { return null; @@ -457,7 +458,7 @@ protected function _constructIniKey($params): ?string { * @throws \Cake\Core\Exception\CakeException * @return array List with all available roles */ - protected function _getAvailableRoles() { + protected function _getAvailableRoles(): array { if ($this->_roles !== null) { return $this->_roles; } @@ -509,7 +510,7 @@ protected function _getRolesFromDb(string $rolesTableKey): array { try { $rolesTable = TableRegistry::getTableLocator()->get($rolesTableKey); $roleIdColumn = $this->getConfig('roleIdColumn') ?: 'id'; - $result = $rolesTable->find()->formatResults(function (ResultSetInterface $results) use ($roleIdColumn) { + $result = $rolesTable->find()->formatResults(function (ResultSetInterface $results) use ($roleIdColumn): CollectionInterface { return $results->combine($this->getConfig('aliasColumn'), $roleIdColumn); }); } catch (RuntimeException $e) { @@ -531,7 +532,7 @@ protected function _getRolesFromDb(string $rolesTableKey): array { * @param \ArrayAccess|array $user The user to get the roles for * @return array List with all role ids belonging to the user */ - protected function _getUserRoles(ArrayAccess|array $user) { + protected function _getUserRoles(ArrayAccess|array $user): array { // Single-role from session if (!$this->getConfig('multiRole')) { $roleColumn = $this->getConfig('roleColumn'); @@ -594,7 +595,7 @@ protected function _getUserRoles(ArrayAccess|array $user) { /** * @return string */ - protected function _pivotTableName() { + protected function _pivotTableName(): string { $pivotTableName = $this->getConfig('pivotTable'); if (!$pivotTableName) { [, $rolesTableName] = pluginSplit($this->getConfig('rolesTable')); @@ -615,7 +616,7 @@ protected function _pivotTableName() { * @param int $id User ID * @return array */ - protected function _getRolesFromJunction($pivotTableName, $id) { + protected function _getRolesFromJunction(string $pivotTableName, $id): array { if (isset($this->_userRoles[$id])) { return $this->_userRoles[$id]; } @@ -640,7 +641,7 @@ protected function _getRolesFromJunction($pivotTableName, $id) { * @param array $roles * @return array */ - protected function _mapped(array $roles) { + protected function _mapped(array $roles): array { $availableRoles = $this->_getAvailableRoles(); $array = []; diff --git a/src/Auth/AllowTrait.php b/src/Auth/AllowTrait.php index 383d0e1a..5197dfc7 100644 --- a/src/Auth/AllowTrait.php +++ b/src/Auth/AllowTrait.php @@ -15,7 +15,7 @@ trait AllowTrait { /** * @var \TinyAuth\Auth\AllowAdapter\AllowAdapterInterface|null */ - protected $_allowAdapter; + protected ?AllowAdapterInterface $_allowAdapter = null; /** * Get the rules for a specific controller. @@ -26,7 +26,7 @@ trait AllowTrait { * @param array $params * @return array */ - protected function _getAllowRule(array $params) { + protected function _getAllowRule(array $params): array { $rules = $this->_getAllow($this->getConfig('allowFilePath')); $allowDefaults = $this->_getAllowDefaultsForCurrentParams($params); @@ -69,7 +69,7 @@ protected function _getAllowRule(array $params) { * @param mixed $rule * @return bool */ - protected function _matchesAllowSlot($request, $rule): bool { + protected function _matchesAllowSlot(mixed $request, mixed $rule): bool { $requestEmpty = $request === null || $request === ''; $ruleEmpty = $rule === null || $rule === ''; @@ -85,11 +85,11 @@ protected function _matchesAllowSlot($request, $rule): bool { /** * @param array $rule - * @param string $action + * @param string|null $action * * @return bool */ - protected function _isActionAllowed(array $rule, $action) { + protected function _isActionAllowed(array $rule, ?string $action): bool { $rule += [ 'deny' => [], 'allow' => [], @@ -106,7 +106,7 @@ protected function _isActionAllowed(array $rule, $action) { * @param array $params * @return array */ - protected function _getAllowDefaultsForCurrentParams(array $params) { + protected function _getAllowDefaultsForCurrentParams(array $params): array { if ($this->getConfig('allowNonPrefixed') && empty($params['prefix'])) { return ['*']; } @@ -131,10 +131,10 @@ protected function _getAllowDefaultsForCurrentParams(array $params) { } /** - * @param string|null $path + * @param array|string|null $path * @return array */ - protected function _getAllow($path = null) { + protected function _getAllow(array|string|null $path = null): array { if ($this->getConfig('autoClearCache') && Configure::read('debug')) { Cache::clear(Cache::KEY_ALLOW); } @@ -175,7 +175,7 @@ protected function _getAllow($path = null) { * @throws \InvalidArgumentException * @return \TinyAuth\Auth\AllowAdapter\AllowAdapterInterface */ - protected function _loadAllowAdapter($adapter) { + protected function _loadAllowAdapter(string $adapter): AllowAdapterInterface { if ($this->_allowAdapter !== null) { return $this->_allowAdapter; } diff --git a/src/Auth/AuthUserTrait.php b/src/Auth/AuthUserTrait.php index e92e3cae..240ef54f 100644 --- a/src/Auth/AuthUserTrait.php +++ b/src/Auth/AuthUserTrait.php @@ -25,7 +25,7 @@ trait AuthUserTrait { * * @return string|int|null User id if existent, null otherwise. */ - public function id() { + public function id(): string|int|null { $field = $this->getConfig('idColumn'); return $this->user($field); @@ -50,7 +50,7 @@ public function isMe($userId): bool { * @param string|null $key Key in dot syntax. * @return mixed Data */ - public function user(?string $key = null) { + public function user(?string $key = null): mixed { $user = $this->_getUser(); if ($key === null) { return $user; @@ -91,7 +91,7 @@ public function roles(): array { * @param mixed|null $providedRoles * @return bool Success */ - public function hasRole($expectedRole, $providedRoles = null) { + public function hasRole(mixed $expectedRole, mixed $providedRoles = null): bool { $roles = $providedRoles !== null ? (array)$providedRoles : $this->roles(); if (!$roles) { @@ -131,7 +131,7 @@ public function hasRole($expectedRole, $providedRoles = null) { * @param mixed|null $providedRoles * @return bool Success */ - public function hasRoles($expectedRoles, $oneRoleIsEnough = true, $providedRoles = null): bool { + public function hasRoles(mixed $expectedRoles, $oneRoleIsEnough = true, mixed $providedRoles = null): bool { $roles = $providedRoles ?? $this->roles(); $expectedRoles = (array)$expectedRoles; diff --git a/src/Auth/BaseAuthorize.php b/src/Auth/BaseAuthorize.php index 6190503e..da221455 100644 --- a/src/Auth/BaseAuthorize.php +++ b/src/Auth/BaseAuthorize.php @@ -30,17 +30,15 @@ abstract class BaseAuthorize { /** * ComponentRegistry instance for getting more components. - * - * @var \Cake\Controller\ComponentRegistry */ - protected $_registry; + protected ComponentRegistry $_registry; /** * Default config for authorize objects. * * @var array */ - protected $_defaultConfig = []; + protected array $defaultConfig = []; /** * Constructor diff --git a/src/Command/AddCommand.php b/src/Command/AddCommand.php index 0d20cc79..40f3a5fc 100644 --- a/src/Command/AddCommand.php +++ b/src/Command/AddCommand.php @@ -3,8 +3,6 @@ namespace TinyAuth\Command; use Cake\Command\Command; -use Cake\Console\Arguments; -use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; use Cake\Core\Configure; use TinyAuth\Sync\Adder; @@ -43,11 +41,11 @@ public static function getDescription(): string { * 2. Add or update the specified controller/action with the given roles * 3. Write the updated configuration back to the INI file * - * @param \Cake\Console\Arguments $args The command arguments. - * @param \Cake\Console\ConsoleIo $io The console io * @return int */ - public function execute(Arguments $args, ConsoleIo $io) { + public function execute(): int { + $args = $this->args; + $io = $this->io; $adder = $this->_getAdder(); $controller = $args->getArgument('controller'); @@ -83,7 +81,7 @@ public function execute(Arguments $args, ConsoleIo $io) { /** * @return \TinyAuth\Sync\Adder */ - protected function _getAdder() { + protected function _getAdder(): Adder { return new Adder(); } @@ -135,7 +133,7 @@ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOption /** * @return array */ - protected function _getAvailableRoles() { + protected function _getAvailableRoles(): array { $roles = (new TinyAuth())->getAvailableRoles(); return array_keys($roles); diff --git a/src/Command/SyncCommand.php b/src/Command/SyncCommand.php index d71434e7..568672e0 100644 --- a/src/Command/SyncCommand.php +++ b/src/Command/SyncCommand.php @@ -3,8 +3,6 @@ namespace TinyAuth\Command; use Cake\Command\Command; -use Cake\Console\Arguments; -use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; use Cake\Core\Configure; use TinyAuth\Sync\Syncer; @@ -46,11 +44,11 @@ public static function getDescription(): string { * * Note: Existing entries are never modified, only new controllers are added. * - * @param \Cake\Console\Arguments $args The command arguments. - * @param \Cake\Console\ConsoleIo $io The console io * @return int */ - public function execute(Arguments $args, ConsoleIo $io) { + public function execute(): int { + $args = $this->args; + $io = $this->io; $syncer = $this->_getSyncer(); $syncer->syncAcl($args, $io); @@ -65,7 +63,7 @@ public function execute(Arguments $args, ConsoleIo $io) { /** * @return \TinyAuth\Sync\Syncer */ - protected function _getSyncer() { + protected function _getSyncer(): Syncer { return new Syncer(); } @@ -116,7 +114,7 @@ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOption /** * @return array */ - protected function _getAvailableRoles() { + protected function _getAvailableRoles(): array { $roles = (new TinyAuth())->getAvailableRoles(); return array_keys($roles); diff --git a/src/Controller/Component/AuthenticationComponent.php b/src/Controller/Component/AuthenticationComponent.php index 10d0f8a5..5e044380 100644 --- a/src/Controller/Component/AuthenticationComponent.php +++ b/src/Controller/Component/AuthenticationComponent.php @@ -51,7 +51,7 @@ public function startup(): void { * @throws \Cake\Core\Exception\CakeException * @return bool */ - public function isPublic(array $url = []) { + public function isPublic(array $url = []): bool { if (!$url) { $url = $this->getController()->getRequest()->getAttribute('params'); } @@ -88,8 +88,8 @@ public function isPublic(array $url = []) { /** * @return void */ - protected function _prepareAuthentication() { - $params = $this->_registry->getController()->getRequest()->getAttribute('params'); + protected function _prepareAuthentication(): void { + $params = $this->registry->getController()->getRequest()->getAttribute('params'); if (!isset($params['plugin'])) { $params['plugin'] = null; } @@ -133,8 +133,8 @@ protected function _prepareAuthentication() { /** * @return array */ - protected function _getAllActions() { - $controller = $this->_registry->getController(); + protected function _getAllActions(): array { + $controller = $this->registry->getController(); return get_class_methods($controller); } diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index 0ca3e377..f64ca190 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -23,7 +23,7 @@ class AuthorizationComponent extends CakeAuthorizationComponent { /** * @var \TinyAuth\Controller\Component\AuthenticationComponent|null */ - protected $_authentication; + protected ?AuthenticationComponent $_authentication = null; /** * @param \Cake\Controller\ComponentRegistry $registry @@ -76,7 +76,7 @@ public function authorizeAction(): void { * * @return bool */ - protected function _isUnauthenticatedAction() { + protected function _isUnauthenticatedAction(): bool { if ($this->_authentication === null) { return false; } diff --git a/src/Panel/AuthPanel.php b/src/Panel/AuthPanel.php index 60eefffa..9bb6c893 100644 --- a/src/Panel/AuthPanel.php +++ b/src/Panel/AuthPanel.php @@ -40,12 +40,12 @@ class AuthPanel extends DebugPanel { /** * @var bool|null */ - protected $isPublic; + protected ?bool $isPublic = null; /** * @var array */ - protected array $_defaultConfig = []; + protected array $defaultConfig = []; public function __construct() { $this->setConfig(Config::all()); @@ -119,7 +119,7 @@ public function shutdown(EventInterface $event): void { } $data['identificationProvider'] = $identificationProvider ? get_class($identificationProvider) : null; - $this->_data = $data; + $this->data = $data; } /** @@ -132,7 +132,7 @@ public function data(): array { 'isPublic' => $this->isPublic, ]; - return $this->_data + $data; + return $this->data + $data; } /** @@ -157,7 +157,7 @@ public function summary(): string { * * @return array */ - protected function _injectRole(array $user, $role, $id) { + protected function _injectRole(array $user, $role, string|int $id): array { if (!$this->getConfig('multiRole')) { $user[$this->getConfig('roleColumn')] = $id; @@ -188,7 +188,7 @@ protected function _injectRole(array $user, $role, $id) { * * @return array */ - protected function _generateUser($role, $id): array { + protected function _generateUser($role, string|int $id): array { $user = [ 'id' => 0, ]; @@ -208,7 +208,7 @@ protected function _generateUser($role, $id): array { * * @return array */ - protected function _getParams(array $params) { + protected function _getParams(array $params): array { $params += [ 'prefix' => null, 'plugin' => null, @@ -223,9 +223,9 @@ protected function _getParams(array $params) { /** * @param array $params * - * @return string + * @return string|null */ - protected function _getPath(array $params) { + protected function _getPath(array $params): ?string { $path = $params['controller']; if ($params['prefix']) { $path = $params['prefix'] . '/' . $path; diff --git a/src/Policy/RequestPolicy.php b/src/Policy/RequestPolicy.php index 08d7af09..51a5a936 100644 --- a/src/Policy/RequestPolicy.php +++ b/src/Policy/RequestPolicy.php @@ -23,7 +23,7 @@ class RequestPolicy implements RequestPolicyInterface { /** * @var array */ - protected array $_defaultConfig = []; + protected array $defaultConfig = []; /** * @param array $config diff --git a/src/Sync/Adder.php b/src/Sync/Adder.php index b5a22436..f87a11a6 100644 --- a/src/Sync/Adder.php +++ b/src/Sync/Adder.php @@ -3,7 +3,7 @@ namespace TinyAuth\Sync; use Cake\Console\Arguments; -use Cake\Console\ConsoleIo; +use Cake\Console\ConsoleIoInterface; use Cake\Core\App; use Cake\Core\Configure; use Cake\Core\Plugin; @@ -35,7 +35,7 @@ public function __construct() { /** * @var array|null */ - protected $authAllow; + protected ?array $authAllow = null; /** * Adds or updates a controller/action entry in the ACL INI file. @@ -55,11 +55,11 @@ public function __construct() { * @param string $action Action name (e.g., 'index') or '*' for all actions * @param array $roles Role names to grant access (e.g., ['user', 'admin']) * @param \Cake\Console\Arguments $args - * @param \Cake\Console\ConsoleIo $io + * @param \Cake\Console\ConsoleIoInterface $io * * @return void */ - public function addAcl(string $controller, string $action, array $roles, Arguments $args, ConsoleIo $io) { + public function addAcl(string $controller, string $action, array $roles, Arguments $args, ConsoleIoInterface $io): void { $path = $this->config['aclFilePath'] ?: ROOT . DS . 'config' . DS; $file = $path . $this->config['aclFile']; $content = Utility::parseFile($file); @@ -96,7 +96,7 @@ public function addAcl(string $controller, string $action, array $roles, Argumen * @param string|null $plugin * @return array */ - protected function _getControllers($plugin) { + protected function _getControllers(?string $plugin): array { if ($plugin === 'all') { $plugins = Plugin::loaded(); @@ -125,7 +125,7 @@ protected function _getControllers($plugin) { * * @return array */ - protected function _parseControllers($folder, $plugin, $prefix = null) { + protected function _parseControllers(string $folder, ?string $plugin, ?string $prefix = null): array { $folderContent = $this->_listDirectory($folder); $controllers = []; @@ -204,7 +204,7 @@ protected function _listDirectory(string $folder): array { * @param string|null $prefix * @return bool */ - protected function _noAuthenticationNeeded($name, $plugin, $prefix) { + protected function _noAuthenticationNeeded(string $name, ?string $plugin, ?string $prefix): bool { if ($this->authAllow === null) { $this->authAllow = $this->_parseAuthAllow(); } @@ -221,7 +221,7 @@ protected function _noAuthenticationNeeded($name, $plugin, $prefix) { /** * @return array */ - protected function _parseAuthAllow() { + protected function _parseAuthAllow(): array { $defaults = [ 'allowFilePath' => null, 'allowFile' => 'auth_allow.ini', @@ -252,11 +252,11 @@ public function controllers(Arguments $args): array { /** * @param array $roles * @param array $mappedRoles - * @param \Cake\Console\ConsoleIo $io + * @param \Cake\Console\ConsoleIoInterface $io * * @return void */ - protected function checkRoles(array $roles, array $mappedRoles, ConsoleIo $io): void { + protected function checkRoles(array $roles, array $mappedRoles, ConsoleIoInterface $io): void { foreach ($roles as $role) { if (!in_array($role, $mappedRoles, true) && !in_array('*', $mappedRoles, true)) { return; diff --git a/src/Sync/Syncer.php b/src/Sync/Syncer.php index 3e4d1e0e..b9a46599 100644 --- a/src/Sync/Syncer.php +++ b/src/Sync/Syncer.php @@ -3,7 +3,7 @@ namespace TinyAuth\Sync; use Cake\Console\Arguments; -use Cake\Console\ConsoleIo; +use Cake\Console\ConsoleIoInterface; use Cake\Core\App; use Cake\Core\Configure; use Cake\Core\Plugin; @@ -14,7 +14,7 @@ class Syncer { /** * @var array|null */ - protected $authAllow; + protected ?array $authAllow = null; /** * Synchronizes all discovered controllers with the ACL INI file. @@ -36,10 +36,10 @@ class Syncer { * Note: Existing controller entries are preserved and not modified. * * @param \Cake\Console\Arguments $args Command arguments including roles - * @param \Cake\Console\ConsoleIo $io Console I/O for output + * @param \Cake\Console\ConsoleIoInterface $io Console I/O for output * @return void */ - public function syncAcl(Arguments $args, ConsoleIo $io) { + public function syncAcl(Arguments $args, ConsoleIoInterface $io): void { $defaults = [ 'aclFile' => 'auth_acl.ini', 'aclFilePath' => null, @@ -86,7 +86,7 @@ public function syncAcl(Arguments $args, ConsoleIo $io) { * @param string|null $plugin * @return array */ - protected function _getControllers($plugin) { + protected function _getControllers(?string $plugin): array { if ($plugin === 'all') { $plugins = Plugin::loaded(); @@ -115,7 +115,7 @@ protected function _getControllers($plugin) { * * @return array */ - protected function _parseControllers($folder, $plugin, $prefix = null) { + protected function _parseControllers(string $folder, ?string $plugin, ?string $prefix = null): array { $folderContent = $this->_listDirectory($folder); $controllers = []; @@ -196,7 +196,7 @@ protected function _listDirectory(string $folder): array { * @param string|null $prefix * @return bool */ - protected function _noAuthenticationNeeded($name, $plugin, $prefix) { + protected function _noAuthenticationNeeded(string $name, ?string $plugin, ?string $prefix): bool { if ($this->authAllow === null) { $this->authAllow = $this->_parseAuthAllow(); } @@ -213,7 +213,7 @@ protected function _noAuthenticationNeeded($name, $plugin, $prefix) { /** * @return array */ - protected function _parseAuthAllow() { + protected function _parseAuthAllow(): array { $defaults = [ 'allowFilePath' => null, 'allowFile' => 'auth_allow.ini', diff --git a/src/Utility/Cache.php b/src/Utility/Cache.php index 7b138fe9..7c2ee93a 100644 --- a/src/Utility/Cache.php +++ b/src/Utility/Cache.php @@ -27,7 +27,7 @@ class Cache { /** * @var array */ - protected static array $_defaultConfig = [ + protected static array $defaultConfig = [ 'cache' => '_cake_model_', 'cachePrefix' => 'tiny_auth_', 'allowCacheKey' => self::KEY_ALLOW, @@ -161,7 +161,7 @@ protected static function assertValidCacheSetup(array $config): void { * @return array */ protected static function prepareConfig(): array { - $defaultConfig = static::$_defaultConfig; + $defaultConfig = static::$defaultConfig; //BC with 5.0.x if (in_array('_cake_core_', CoreCache::configured(), true)) { diff --git a/src/Utility/Config.php b/src/Utility/Config.php index c224a174..5b44a90b 100644 --- a/src/Utility/Config.php +++ b/src/Utility/Config.php @@ -14,12 +14,12 @@ class Config { * * @var array */ - protected static $_config = []; + protected static array $_config = []; /** * @var array */ - protected static $_defaultConfig = [ + protected static array $defaultConfig = [ // allow 'allowAdapter' => IniAllowAdapter::class, 'allowFilePath' => null, // Possible to locate INI file at given path e.g. Plugin::configPath('Admin'), filePath is also available for shared config @@ -52,9 +52,9 @@ class Config { /** * @return array */ - public static function all() { + public static function all(): array { if (!static::$_config) { - $config = (array)Configure::read('TinyAuth') + static::$_defaultConfig; + $config = (array)Configure::read('TinyAuth') + static::$defaultConfig; if ($config['autoClearCache'] === null) { $config['autoClearCache'] = Configure::read('debug'); @@ -71,7 +71,7 @@ public static function all() { * @throws \Cake\Core\Exception\CakeException * @return mixed */ - public static function get($key) { + public static function get(string $key): mixed { $config = static::all(); if (!isset($config[$key])) { throw new CakeException('Key ' . $key . ' not found in config.'); @@ -83,7 +83,7 @@ public static function get($key) { /** * @return void */ - public static function drop() { + public static function drop(): void { static::$_config = []; } diff --git a/src/Utility/SessionCache.php b/src/Utility/SessionCache.php index a152030c..9ed66ecf 100644 --- a/src/Utility/SessionCache.php +++ b/src/Utility/SessionCache.php @@ -15,7 +15,7 @@ class SessionCache { use StaticConfigTrait; - protected static array $_defaultConfig = [ + protected static array $defaultConfig = [ 'cache' => 'default', 'prefix' => 'auth_user_', ]; @@ -101,7 +101,7 @@ protected static function assertValidCacheSetup(array $config): void { * @return array */ protected static function prepareConfig(): array { - $defaultConfig = static::$_defaultConfig; + $defaultConfig = static::$defaultConfig; return (array)Configure::read('TinyAuth') + $defaultConfig; } diff --git a/src/Utility/TinyAuth.php b/src/Utility/TinyAuth.php index dab91817..3611cebd 100644 --- a/src/Utility/TinyAuth.php +++ b/src/Utility/TinyAuth.php @@ -15,7 +15,7 @@ class TinyAuth { /** * @var array */ - protected array $_defaultConfig = []; + protected array $defaultConfig = []; /** * @param array $config @@ -29,7 +29,7 @@ public function __construct(array $config = []) { /** * @return array */ - public function getAvailableRoles() { + public function getAvailableRoles(): array { return $this->_getAvailableRoles(); } diff --git a/src/Utility/Utility.php b/src/Utility/Utility.php index 0874c2a3..0df85b24 100644 --- a/src/Utility/Utility.php +++ b/src/Utility/Utility.php @@ -13,7 +13,7 @@ class Utility { * @param string $key INI section key as found in authentication.ini * @return array Array with named keys for controller, plugin and prefix */ - public static function deconstructIniKey($key) { + public static function deconstructIniKey(string $key): array { $res = [ 'plugin' => null, 'prefix' => null, @@ -40,7 +40,7 @@ public static function deconstructIniKey($key) { * @param string $file INI file name. * @return array List with all found files. */ - public static function parseFiles($paths, $file) { + public static function parseFiles(array|string|null $paths, string $file): array { if ($paths === null) { $paths = ROOT . DS . 'config' . DS; } @@ -60,7 +60,7 @@ public static function parseFiles($paths, $file) { * @throws \Cake\Core\Exception\CakeException * @return array List */ - public static function parseFile($ini) { + public static function parseFile(string $ini): array { if (!file_exists($ini)) { throw new CakeException(sprintf('Missing TinyAuth config file (%s)', $ini)); } @@ -88,7 +88,7 @@ public static function parseFile($ini) { * * @return bool */ - public static function generateFile($file, array $content) { + public static function generateFile(string $file, array $content): bool { $string = static::buildIniString($content); return file_put_contents($file, $string) !== false; @@ -99,7 +99,7 @@ public static function generateFile($file, array $content) { * * @return string */ - public static function buildIniString(array $a) { + public static function buildIniString(array $a): string { $out = []; foreach ($a as $rootkey => $rootvalue) { $out[] = "[$rootkey]"; diff --git a/src/View/Helper/AuthUserHelper.php b/src/View/Helper/AuthUserHelper.php index a9e42e01..10617894 100644 --- a/src/View/Helper/AuthUserHelper.php +++ b/src/View/Helper/AuthUserHelper.php @@ -43,7 +43,7 @@ public function __construct(View $View, array $config = []) { */ public function identity(): ArrayAccess|array|null { /** @var \Authorization\Identity|\Authentication\Identity|null $identity */ - $identity = $this->_View->getRequest()->getAttribute('identity'); + $identity = $this->View->getRequest()->getAttribute('identity'); if (!$identity) { return null; } @@ -62,7 +62,7 @@ public function identity(): ArrayAccess|array|null { * @throws \Cake\Core\Exception\CakeException * @return bool */ - public function hasAccess(array $url) { + public function hasAccess(array $url): bool { if (isset($url['_name'])) { //throw MissingRouteException if necessary Router::url($url); @@ -78,7 +78,7 @@ public function hasAccess(array $url) { 'action' => $defaults['action'], ]; } else { - $params = $this->_View->getRequest()->getAttribute('params'); + $params = $this->View->getRequest()->getAttribute('params'); $url += [ 'prefix' => !empty($params['prefix']) ? $params['prefix'] : null, 'plugin' => !empty($params['plugin']) ? $params['plugin'] : null, @@ -87,7 +87,7 @@ public function hasAccess(array $url) { ]; } - $authUser = $this->_View->get('_authUser'); + $authUser = $this->View->get('_authUser'); if ($authUser === null && !$this->getConfig('includeAuthentication')) { throw new CakeException('Variable _authUser containing the user data needs to be passed down. The TinyAuth.Auth component does it automatically, if loaded.'); } @@ -107,7 +107,7 @@ public function hasAccess(array $url) { * @param array $options * @return string */ - public function link($title, array $url, array $options = []) { + public function link(string $title, array $url, array $options = []) { if (!$this->hasAccess($url)) { return $this->_default($title, $options); } @@ -127,7 +127,7 @@ public function link($title, array $url, array $options = []) { * @param array $options * @return string */ - public function postLink($title, array $url, array $options = []) { + public function postLink(string $title, array $url, array $options = []) { if (!$this->hasAccess($url)) { return $this->_default($title, $options); } @@ -141,7 +141,7 @@ public function postLink($title, array $url, array $options = []) { * @param array $options * @return string */ - protected function _default($title, array $options) { + protected function _default(string $title, array $options) { $options += [ 'default' => '', 'escape' => true, @@ -165,7 +165,7 @@ protected function _getUser(): array { return $identity ? $this->_toArray($identity) : []; } - $authUser = $this->_View->get('_authUser'); + $authUser = $this->View->get('_authUser'); if ($authUser === null) { throw new CakeException('TinyAuth.AuthUser helper needs TinyAuth.AuthUser component to function. Please make sure it is loaded in your controller.'); } diff --git a/src/View/Helper/AuthenticationHelper.php b/src/View/Helper/AuthenticationHelper.php index 970e5247..188909e3 100644 --- a/src/View/Helper/AuthenticationHelper.php +++ b/src/View/Helper/AuthenticationHelper.php @@ -38,9 +38,9 @@ public function __construct(View $View, array $config = []) { * @param array $url * @return bool */ - public function isPublic(array $url = []) { + public function isPublic(array $url = []): bool { if (!$url) { - $url = $this->_View->getRequest()->getAttribute('params'); + $url = $this->View->getRequest()->getAttribute('params'); } if (isset($url['_name'])) { @@ -58,7 +58,7 @@ public function isPublic(array $url = []) { 'action' => $defaults['action'], ]; } else { - $params = $this->_View->getRequest()->getAttribute('params'); + $params = $this->View->getRequest()->getAttribute('params'); $url += [ 'prefix' => !empty($params['prefix']) ? $params['prefix'] : null, 'plugin' => !empty($params['plugin']) ? $params['plugin'] : null, diff --git a/tests/TestCase/Command/AddCommandTest.php b/tests/TestCase/Command/AddCommandTest.php index 2123d937..96e033b0 100644 --- a/tests/TestCase/Command/AddCommandTest.php +++ b/tests/TestCase/Command/AddCommandTest.php @@ -3,7 +3,6 @@ namespace TinyAuth\Test\TestCase\Command; use Cake\Command\Command; -use Cake\Console\Arguments; use Cake\Console\ConsoleIo; use Cake\Console\TestSuite\ConsoleIntegrationTestTrait; use Cake\Core\Configure; @@ -29,7 +28,7 @@ public function testNoControllersReturnsErrorWithoutPrompt(): void { $io->expects($this->never())->method('ask'); $io->expects($this->once())->method('err')->with('No controllers available. Supply a controller name explicitly.'); - $this->assertSame(Command::CODE_ERROR, $command->execute(new Arguments([], [], ['controller']), $io)); + $this->assertSame(Command::CODE_ERROR, $command->run([], $io)); } /** diff --git a/tests/TestCase/Controller/Component/AuthenticationComponentTest.php b/tests/TestCase/Controller/Component/AuthenticationComponentTest.php index 0fca68cd..73bbf5fa 100644 --- a/tests/TestCase/Controller/Component/AuthenticationComponentTest.php +++ b/tests/TestCase/Controller/Component/AuthenticationComponentTest.php @@ -77,6 +77,36 @@ public function testIsPublic() { $this->assertTrue($result); } + /** + * @return void + */ + public function testAllowFilePathsMergeDirectories() { + $directory = TMP . 'tiny-auth-allow-' . uniqid() . DS; + mkdir($directory); + file_put_contents($directory . 'auth_allow.ini', 'Sales = view'); + try { + $config = $this->componentConfig; + $config['allowFilePath'] = [$config['allowFilePath'], $directory]; + foreach (['Users', 'Sales'] as $controllerName) { + $request = new ServerRequest([ + 'params' => [ + 'controller' => $controllerName, + 'action' => 'view', + 'plugin' => null, + '_ext' => null, + 'pass' => [], + ], + ]); + $registry = new ComponentRegistry($this->getControllerMock($request)); + $component = new AuthenticationComponent($registry, $config); + $this->assertTrue($component->isPublic(), $controllerName); + } + } finally { + unlink($directory . 'auth_allow.ini'); + rmdir($directory); + } + } + /** * @return void */ diff --git a/tests/test_app/Auth/TestTinyAuthorize.php b/tests/test_app/Auth/TestTinyAuthorize.php index 3f17e034..84e6500e 100644 --- a/tests/test_app/Auth/TestTinyAuthorize.php +++ b/tests/test_app/Auth/TestTinyAuthorize.php @@ -24,11 +24,11 @@ public function getAcl() { } /** - * @param string|null $path + * @param array|string|null $path * * @return array */ - protected function _getAcl($path = null) { + protected function _getAcl(array|string|null $path = null): array { $path = Plugin::path('TinyAuth') . 'tests' . DS . 'test_files' . DS; return parent::_getAcl($path); diff --git a/tests/test_app/Controller/Component/TestAuthUserComponent.php b/tests/test_app/Controller/Component/TestAuthUserComponent.php index 2548116a..8426ec70 100644 --- a/tests/test_app/Controller/Component/TestAuthUserComponent.php +++ b/tests/test_app/Controller/Component/TestAuthUserComponent.php @@ -16,11 +16,11 @@ public function getAcl() { } /** - * @param string|null $path + * @param array|string|null $path * * @return array */ - protected function _getAcl($path = null) { + protected function _getAcl(array|string|null $path = null): array { $path = Plugin::path('TinyAuth') . 'tests' . DS . 'test_files' . DS; return parent::_getAcl($path);