From 648eb20612f074ac38557a51ceb562fe1aa43b01 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 13 Oct 2022 00:34:14 +0200 Subject: [PATCH 01/22] updated github workflow --- .github/workflows/coding-style.yml | 4 ++-- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index a5618ecd..d8020f6f 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -7,7 +7,7 @@ jobs: name: Nette Code Checker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 7.2 @@ -21,7 +21,7 @@ jobs: name: Nette Coding Standard runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 7.4 diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 0ae1a544..08f1414a 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -10,7 +10,7 @@ jobs: name: PHPStan runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 7.4 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e87ca57d..23cfd728 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: name: PHP ${{ matrix.php }} tests steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} @@ -22,7 +22,7 @@ jobs: - run: composer install --no-progress --prefer-dist - run: vendor/bin/tester tests -s -C - if: failure() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: output path: tests/**/output @@ -32,7 +32,7 @@ jobs: name: Lowest Dependencies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 7.2 @@ -46,7 +46,7 @@ jobs: name: Code Coverage runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: php-version: 7.4 From 130c7fd8602cc31abd35dced0094ae1c5476599b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 15:30:34 +0100 Subject: [PATCH 02/22] opened 4.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5d18b252..4200fb8a 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "4.0-dev" } } } From f8d8f8368081abbb88a7d69e2f162c49a74446d0 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 17:38:22 +0100 Subject: [PATCH 03/22] requires PHP 8.0 --- .github/workflows/coding-style.yml | 4 ++-- .github/workflows/static-analysis.yml | 2 +- .github/workflows/tests.yml | 6 +++--- composer.json | 2 +- readme.md | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index d8020f6f..23019765 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: - php-version: 7.2 + php-version: 8.0 coverage: none - run: composer create-project nette/code-checker temp/code-checker ^3 --no-progress @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer create-project nette/coding-standard temp/coding-standard ^3 --no-progress diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 08f1414a..b23bf1a1 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer install --no-progress --prefer-dist diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 23cfd728..239bdc4d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2'] + php: ['8.0', '8.1', '8.2'] fail-fast: false @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: - php-version: 7.2 + php-version: 8.0 coverage: none - run: composer update --no-progress --prefer-dist --prefer-lowest --prefer-stable @@ -49,7 +49,7 @@ jobs: - uses: actions/checkout@v3 - uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 coverage: none - run: composer install --no-progress --prefer-dist diff --git a/composer.json b/composer.json index 4200fb8a..727a2b83 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=7.2 <8.3", + "php": ">=8.0 <8.3", "nette/utils": "^3.2.1" }, "require-dev": { diff --git a/readme.md b/readme.md index 8bfa4d96..eaf495ea 100644 --- a/readme.md +++ b/readme.md @@ -20,7 +20,7 @@ Authentication & Authorization library for Nette. Documentation can be found on the [website](https://doc.nette.org/access-control). -It requires PHP version 7.2 and supports PHP up to 8.2. +It requires PHP version 8.0 and supports PHP up to 8.2. [Support Me](https://github.com/sponsors/dg) From feba6fc50ede36a77f01123d4c7d936290d1cb2a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 16:43:32 +0100 Subject: [PATCH 04/22] composer: updated dependencies --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 727a2b83..0f74ac92 100644 --- a/composer.json +++ b/composer.json @@ -16,13 +16,13 @@ ], "require": { "php": ">=8.0 <8.3", - "nette/utils": "^3.2.1" + "nette/utils": "^4.0" }, "require-dev": { - "nette/di": "^3.0.1", - "nette/http": "^3.0.0", - "nette/tester": "^2.0", - "tracy/tracy": "^2.4", + "nette/di": "^4.0", + "nette/http": "^4.0", + "nette/tester": "^2.4", + "tracy/tracy": "^2.8", "phpstan/phpstan-nette": "^1.0", "mockery/mockery": "^1.5" }, From f90f922650660941b25f25c4608c6f5648879ba9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 12 Dec 2021 18:12:40 +0100 Subject: [PATCH 05/22] coding style --- src/Bridges/SecurityDI/SecurityExtension.php | 4 ++-- src/Bridges/SecurityHttp/CookieStorage.php | 12 ++++-------- src/Security/Permission.php | 4 ++-- src/Security/User.php | 2 +- tests/Security.Http/CookieStorage.getState.phpt | 6 +++--- tests/Security/Passwords.hash().phpt | 4 ++-- tests/Security/User.authorization.phpt | 2 +- 7 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/Bridges/SecurityDI/SecurityExtension.php b/src/Bridges/SecurityDI/SecurityExtension.php index b2e3b145..41f7649b 100644 --- a/src/Bridges/SecurityDI/SecurityExtension.php +++ b/src/Bridges/SecurityDI/SecurityExtension.php @@ -40,8 +40,8 @@ public function getConfigSchema(): Nette\Schema\Schema 'password' => Expect::string(), 'roles' => Expect::anyOf(Expect::string(), Expect::listOf('string')), 'data' => Expect::array(), - ])->castTo('array') - ) + ])->castTo('array'), + ), ), 'roles' => Expect::arrayOf('string|array|null'), // role => parent(s) 'resources' => Expect::arrayOf('string|null'), // resource => parent diff --git a/src/Bridges/SecurityHttp/CookieStorage.php b/src/Bridges/SecurityHttp/CookieStorage.php index 0ee6e8a2..33ff00dd 100644 --- a/src/Bridges/SecurityHttp/CookieStorage.php +++ b/src/Bridges/SecurityHttp/CookieStorage.php @@ -64,11 +64,8 @@ public function saveAuthentication(IIdentity $identity): void $this->cookieName, $uid, $this->cookieExpiration, - null, - $this->cookieDomain, - null, - true, - $this->cookieSameSite + domain: $this->cookieDomain, + sameSite: $this->cookieSameSite, ); } @@ -78,8 +75,7 @@ public function clearAuthentication(bool $clearIdentity): void $this->uid = ''; $this->response->deleteCookie( $this->cookieName, - null, - $this->cookieDomain + domain: $this->cookieDomain, ); } @@ -106,7 +102,7 @@ public function setExpiration(?string $expire, bool $clearIdentity): void public function setCookieParameters( ?string $name = null, ?string $domain = null, - ?string $sameSite = null + ?string $sameSite = null, ) { $this->cookieName = $name ?? $this->cookieName; $this->cookieDomain = $domain ?? $this->cookieDomain; diff --git a/src/Security/Permission.php b/src/Security/Permission.php index b825edd6..ee011205 100644 --- a/src/Security/Permission.php +++ b/src/Security/Permission.php @@ -391,7 +391,7 @@ public function allow( $roles = self::ALL, $resources = self::ALL, $privileges = self::ALL, - ?callable $assertion = null + ?callable $assertion = null, ) { $this->setRule(true, self::ALLOW, $roles, $resources, $privileges, $assertion); return $this; @@ -411,7 +411,7 @@ public function deny( $roles = self::ALL, $resources = self::ALL, $privileges = self::ALL, - ?callable $assertion = null + ?callable $assertion = null, ) { $this->setRule(true, self::DENY, $roles, $resources, $privileges, $assertion); return $this; diff --git a/src/Security/User.php b/src/Security/User.php index 951e599f..4ed1e055 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -73,7 +73,7 @@ public function __construct( ?IUserStorage $legacyStorage = null, ?IAuthenticator $authenticator = null, ?Authorizator $authorizator = null, - ?UserStorage $storage = null + ?UserStorage $storage = null, ) { $this->storage = $storage ?? $legacyStorage; // back compatibility if (!$this->storage) { diff --git a/tests/Security.Http/CookieStorage.getState.phpt b/tests/Security.Http/CookieStorage.getState.phpt index 148a0102..ba4d0961 100644 --- a/tests/Security.Http/CookieStorage.getState.phpt +++ b/tests/Security.Http/CookieStorage.getState.phpt @@ -15,18 +15,18 @@ $storage = new CookieStorage($request, $response); Assert::same([false, null, null], $storage->getState()); // short id -$request = new Nette\Http\Request(new Nette\Http\UrlScript, [], [], ['userid' => 'short']); +$request = new Nette\Http\Request(new Nette\Http\UrlScript, cookies: ['userid' => 'short']); $storage = new CookieStorage($request, $response); Assert::same([false, null, null], $storage->getState()); // correct id $id = '123456789123456'; -$request = new Nette\Http\Request(new Nette\Http\UrlScript, [], [], ['userid' => $id]); +$request = new Nette\Http\Request(new Nette\Http\UrlScript, cookies: ['userid' => $id]); $storage = new CookieStorage($request, $response); Assert::equal([true, new SimpleIdentity($id), null], $storage->getState()); // custom cookie -$request = new Nette\Http\Request(new Nette\Http\UrlScript, [], [], ['foo' => $id]); +$request = new Nette\Http\Request(new Nette\Http\UrlScript, cookies: ['foo' => $id]); $storage = new CookieStorage($request, $response); $storage->setCookieParameters('foo'); Assert::equal([true, new SimpleIdentity($id), null], $storage->getState()); diff --git a/tests/Security/Passwords.hash().phpt b/tests/Security/Passwords.hash().phpt index c8b7d376..b8dfdeb7 100644 --- a/tests/Security/Passwords.hash().phpt +++ b/tests/Security/Passwords.hash().phpt @@ -14,11 +14,11 @@ require __DIR__ . '/../bootstrap.php'; Assert::truthy( - preg_match('#^\$.{50,}\z#', (new Passwords)->hash('my-password')) + preg_match('#^\$.{50,}\z#', (new Passwords)->hash('my-password')), ); Assert::truthy( - preg_match('#^\$2y\$05\$.{53}\z#', (new Passwords(PASSWORD_BCRYPT, ['cost' => 5]))->hash('dg')) + preg_match('#^\$2y\$05\$.{53}\z#', (new Passwords(PASSWORD_BCRYPT, ['cost' => 5]))->hash('dg')), ); $hash = (new Passwords(PASSWORD_BCRYPT))->hash('dg'); diff --git a/tests/Security/User.authorization.phpt b/tests/Security/User.authorization.phpt index 9061096d..d6ce4718 100644 --- a/tests/Security/User.authorization.phpt +++ b/tests/Security/User.authorization.phpt @@ -42,7 +42,7 @@ class Authorizator implements Nette\Security\Authorizator { public function isAllowed($role = self::ALL, $resource = self::ALL, $privilege = self::ALL): bool { - return $role === 'admin' && strpos($resource, 'jany') === false; + return $role === 'admin' && !str_contains($resource, 'jany'); } } From 2bb3d3fb16426fa001b05c0614110e6a5c080418 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 7 Apr 2022 18:04:32 +0200 Subject: [PATCH 06/22] coding style: reformatted Assert::exception --- .../CookieStorage.authentication.phpt | 7 +++-- tests/Security/Passwords.hash().phpt | 15 ++++++---- .../Permission.IsAllowedNonExistent.phpt | 22 ++++++++------ ...ission.ResourceAddInheritsNonExistent.phpt | 8 +++-- .../Permission.ResourceDuplicate.phpt | 12 ++++---- ...ermission.ResourceInheritsNonExistent.phpt | 18 +++++++----- ...rmission.ResourceRemoveOneNonExistent.phpt | 8 +++-- ...on.RoleRegistryAddInheritsNonExistent.phpt | 8 +++-- .../Permission.RoleRegistryDuplicate.phpt | 10 ++++--- ...ssion.RoleRegistryInheritsNonExistent.phpt | 18 +++++++----- ...sion.RoleRegistryRemoveOneNonExistent.phpt | 8 +++-- tests/Security/Permission.RuleRoleRemove.phpt | 8 +++-- .../Permission.RuleRoleRemoveAll.phpt | 8 +++-- .../Permission.RulesResourceRemove.phpt | 8 +++-- .../Permission.RulesResourceRemoveAll.phpt | 8 +++-- tests/Security/SimpleAuthenticator.phpt | 18 +++++++----- tests/Security/User.authentication.phpt | 29 ++++++++++--------- tests/Security/User.authorization.phpt | 8 +++-- 18 files changed, 133 insertions(+), 88 deletions(-) diff --git a/tests/Security.Http/CookieStorage.authentication.phpt b/tests/Security.Http/CookieStorage.authentication.phpt index 8debb1ae..f88f01a6 100644 --- a/tests/Security.Http/CookieStorage.authentication.phpt +++ b/tests/Security.Http/CookieStorage.authentication.phpt @@ -12,9 +12,10 @@ require __DIR__ . '/../bootstrap.php'; $request = new Nette\Http\Request(new Nette\Http\UrlScript); $response = Mockery::mock(Nette\Http\IResponse::class); $storage = new CookieStorage($request, $response); -Assert::exception(function () use ($storage) { - $storage->saveAuthentication(new SimpleIdentity('short')); -}, LogicException::class); +Assert::exception( + fn() => $storage->saveAuthentication(new SimpleIdentity('short')), + LogicException::class, +); // correct id $id = '123456789123456'; diff --git a/tests/Security/Passwords.hash().phpt b/tests/Security/Passwords.hash().phpt index b8dfdeb7..a6acbcd1 100644 --- a/tests/Security/Passwords.hash().phpt +++ b/tests/Security/Passwords.hash().phpt @@ -24,10 +24,13 @@ Assert::truthy( $hash = (new Passwords(PASSWORD_BCRYPT))->hash('dg'); Assert::same($hash, crypt('dg', $hash)); -Assert::exception(function () { - (new Passwords(PASSWORD_BCRYPT, ['cost' => 3]))->hash('dg'); -}, PHP_VERSION_ID < 80000 ? Nette\InvalidStateException::class : ValueError::class); +Assert::exception( + fn() => (new Passwords(PASSWORD_BCRYPT, ['cost' => 3]))->hash('dg'), + PHP_VERSION_ID < 80000 ? Nette\InvalidStateException::class : ValueError::class, +); -Assert::exception(function () { - (new Passwords)->hash(''); -}, Nette\InvalidArgumentException::class, 'Password can not be empty.'); +Assert::exception( + fn() => (new Passwords)->hash(''), + Nette\InvalidArgumentException::class, + 'Password can not be empty.', +); diff --git a/tests/Security/Permission.IsAllowedNonExistent.phpt b/tests/Security/Permission.IsAllowedNonExistent.phpt index 260303c6..437e5085 100644 --- a/tests/Security/Permission.IsAllowedNonExistent.phpt +++ b/tests/Security/Permission.IsAllowedNonExistent.phpt @@ -13,12 +13,16 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::exception(function () { - $acl = new Permission; - $acl->isAllowed('nonexistent'); -}, Nette\InvalidStateException::class, "Role 'nonexistent' does not exist."); - -Assert::exception(function () { - $acl = new Permission; - $acl->isAllowed(null, 'nonexistent'); -}, Nette\InvalidStateException::class, "Resource 'nonexistent' does not exist."); +$acl = new Permission; +Assert::exception( + fn() => $acl->isAllowed('nonexistent'), + Nette\InvalidStateException::class, + "Role 'nonexistent' does not exist.", +); + +$acl = new Permission; +Assert::exception( + fn() => $acl->isAllowed(null, 'nonexistent'), + Nette\InvalidStateException::class, + "Resource 'nonexistent' does not exist.", +); diff --git a/tests/Security/Permission.ResourceAddInheritsNonExistent.phpt b/tests/Security/Permission.ResourceAddInheritsNonExistent.phpt index 9bdf4678..0351edcf 100644 --- a/tests/Security/Permission.ResourceAddInheritsNonExistent.phpt +++ b/tests/Security/Permission.ResourceAddInheritsNonExistent.phpt @@ -14,6 +14,8 @@ require __DIR__ . '/../bootstrap.php'; $acl = new Permission; -Assert::exception(function () use ($acl) { - $acl->addResource('area', 'nonexistent'); -}, Nette\InvalidStateException::class, "Resource 'nonexistent' does not exist."); +Assert::exception( + fn() => $acl->addResource('area', 'nonexistent'), + Nette\InvalidStateException::class, + "Resource 'nonexistent' does not exist.", +); diff --git a/tests/Security/Permission.ResourceDuplicate.phpt b/tests/Security/Permission.ResourceDuplicate.phpt index 25788827..983e8308 100644 --- a/tests/Security/Permission.ResourceDuplicate.phpt +++ b/tests/Security/Permission.ResourceDuplicate.phpt @@ -13,8 +13,10 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; -Assert::exception(function () { - $acl = new Permission; - $acl->addResource('area'); - $acl->addResource('area'); -}, Nette\InvalidStateException::class, "Resource 'area' already exists in the list."); +$acl = new Permission; +$acl->addResource('area'); +Assert::exception( + fn() => $acl->addResource('area'), + Nette\InvalidStateException::class, + "Resource 'area' already exists in the list.", +); diff --git a/tests/Security/Permission.ResourceInheritsNonExistent.phpt b/tests/Security/Permission.ResourceInheritsNonExistent.phpt index 5503d6e6..5f1c88cf 100644 --- a/tests/Security/Permission.ResourceInheritsNonExistent.phpt +++ b/tests/Security/Permission.ResourceInheritsNonExistent.phpt @@ -15,10 +15,14 @@ require __DIR__ . '/../bootstrap.php'; $acl = new Permission; $acl->addResource('area'); -Assert::exception(function () use ($acl) { - $acl->resourceInheritsFrom('nonexistent', 'area'); -}, Nette\InvalidStateException::class, "Resource 'nonexistent' does not exist."); - -Assert::exception(function () use ($acl) { - $acl->resourceInheritsFrom('area', 'nonexistent'); -}, Nette\InvalidStateException::class, "Resource 'nonexistent' does not exist."); +Assert::exception( + fn() => $acl->resourceInheritsFrom('nonexistent', 'area'), + Nette\InvalidStateException::class, + "Resource 'nonexistent' does not exist.", +); + +Assert::exception( + fn() => $acl->resourceInheritsFrom('area', 'nonexistent'), + Nette\InvalidStateException::class, + "Resource 'nonexistent' does not exist.", +); diff --git a/tests/Security/Permission.ResourceRemoveOneNonExistent.phpt b/tests/Security/Permission.ResourceRemoveOneNonExistent.phpt index 2b981b95..b3c79077 100644 --- a/tests/Security/Permission.ResourceRemoveOneNonExistent.phpt +++ b/tests/Security/Permission.ResourceRemoveOneNonExistent.phpt @@ -14,6 +14,8 @@ require __DIR__ . '/../bootstrap.php'; $acl = new Permission; -Assert::exception(function () use ($acl) { - $acl->removeResource('nonexistent'); -}, Nette\InvalidStateException::class, "Resource 'nonexistent' does not exist."); +Assert::exception( + fn() => $acl->removeResource('nonexistent'), + Nette\InvalidStateException::class, + "Resource 'nonexistent' does not exist.", +); diff --git a/tests/Security/Permission.RoleRegistryAddInheritsNonExistent.phpt b/tests/Security/Permission.RoleRegistryAddInheritsNonExistent.phpt index d2305cd5..4b91c0ca 100644 --- a/tests/Security/Permission.RoleRegistryAddInheritsNonExistent.phpt +++ b/tests/Security/Permission.RoleRegistryAddInheritsNonExistent.phpt @@ -14,6 +14,8 @@ require __DIR__ . '/../bootstrap.php'; $acl = new Permission; -Assert::exception(function () use ($acl) { - $acl->addRole('guest', 'nonexistent'); -}, Nette\InvalidStateException::class, "Role 'nonexistent' does not exist."); +Assert::exception( + fn() => $acl->addRole('guest', 'nonexistent'), + Nette\InvalidStateException::class, + "Role 'nonexistent' does not exist.", +); diff --git a/tests/Security/Permission.RoleRegistryDuplicate.phpt b/tests/Security/Permission.RoleRegistryDuplicate.phpt index 9389568d..7eafc570 100644 --- a/tests/Security/Permission.RoleRegistryDuplicate.phpt +++ b/tests/Security/Permission.RoleRegistryDuplicate.phpt @@ -14,7 +14,9 @@ require __DIR__ . '/../bootstrap.php'; $acl = new Permission; -Assert::exception(function () use ($acl) { - $acl->addRole('guest'); - $acl->addRole('guest'); -}, Nette\InvalidStateException::class, "Role 'guest' already exists in the list."); +$acl->addRole('guest'); +Assert::exception( + fn() => $acl->addRole('guest'), + Nette\InvalidStateException::class, + "Role 'guest' already exists in the list.", +); diff --git a/tests/Security/Permission.RoleRegistryInheritsNonExistent.phpt b/tests/Security/Permission.RoleRegistryInheritsNonExistent.phpt index 8001493d..3840c06e 100644 --- a/tests/Security/Permission.RoleRegistryInheritsNonExistent.phpt +++ b/tests/Security/Permission.RoleRegistryInheritsNonExistent.phpt @@ -15,10 +15,14 @@ require __DIR__ . '/../bootstrap.php'; $acl = new Permission; $acl->addRole('guest'); -Assert::exception(function () use ($acl) { - $acl->roleInheritsFrom('nonexistent', 'guest'); -}, Nette\InvalidStateException::class, "Role 'nonexistent' does not exist."); - -Assert::exception(function () use ($acl) { - $acl->roleInheritsFrom('guest', 'nonexistent'); -}, Nette\InvalidStateException::class, "Role 'nonexistent' does not exist."); +Assert::exception( + fn() => $acl->roleInheritsFrom('nonexistent', 'guest'), + Nette\InvalidStateException::class, + "Role 'nonexistent' does not exist.", +); + +Assert::exception( + fn() => $acl->roleInheritsFrom('guest', 'nonexistent'), + Nette\InvalidStateException::class, + "Role 'nonexistent' does not exist.", +); diff --git a/tests/Security/Permission.RoleRegistryRemoveOneNonExistent.phpt b/tests/Security/Permission.RoleRegistryRemoveOneNonExistent.phpt index cbc0e6a5..e49801a1 100644 --- a/tests/Security/Permission.RoleRegistryRemoveOneNonExistent.phpt +++ b/tests/Security/Permission.RoleRegistryRemoveOneNonExistent.phpt @@ -14,6 +14,8 @@ require __DIR__ . '/../bootstrap.php'; $acl = new Permission; -Assert::exception(function () use ($acl) { - $acl->removeRole('nonexistent'); -}, Nette\InvalidStateException::class, "Role 'nonexistent' does not exist."); +Assert::exception( + fn() => $acl->removeRole('nonexistent'), + Nette\InvalidStateException::class, + "Role 'nonexistent' does not exist.", +); diff --git a/tests/Security/Permission.RuleRoleRemove.phpt b/tests/Security/Permission.RuleRoleRemove.phpt index 39f76f0f..a4a2b13a 100644 --- a/tests/Security/Permission.RuleRoleRemove.phpt +++ b/tests/Security/Permission.RuleRoleRemove.phpt @@ -18,9 +18,11 @@ $acl->addRole('guest'); $acl->allow('guest'); Assert::true($acl->isAllowed('guest')); $acl->removeRole('guest'); -Assert::exception(function () use ($acl) { - $acl->isAllowed('guest'); -}, Nette\InvalidStateException::class, "Role 'guest' does not exist."); +Assert::exception( + fn() => $acl->isAllowed('guest'), + Nette\InvalidStateException::class, + "Role 'guest' does not exist.", +); $acl->addRole('guest'); Assert::false($acl->isAllowed('guest')); diff --git a/tests/Security/Permission.RuleRoleRemoveAll.phpt b/tests/Security/Permission.RuleRoleRemoveAll.phpt index 245caeca..d6b6a436 100644 --- a/tests/Security/Permission.RuleRoleRemoveAll.phpt +++ b/tests/Security/Permission.RuleRoleRemoveAll.phpt @@ -18,9 +18,11 @@ $acl->addRole('guest'); $acl->allow('guest'); Assert::true($acl->isAllowed('guest')); $acl->removeAllRoles(); -Assert::exception(function () use ($acl) { - $acl->isAllowed('guest'); -}, Nette\InvalidStateException::class, "Role 'guest' does not exist."); +Assert::exception( + fn() => $acl->isAllowed('guest'), + Nette\InvalidStateException::class, + "Role 'guest' does not exist.", +); $acl->addRole('guest'); Assert::false($acl->isAllowed('guest')); diff --git a/tests/Security/Permission.RulesResourceRemove.phpt b/tests/Security/Permission.RulesResourceRemove.phpt index ee1b902e..c51cc11b 100644 --- a/tests/Security/Permission.RulesResourceRemove.phpt +++ b/tests/Security/Permission.RulesResourceRemove.phpt @@ -18,9 +18,11 @@ $acl->addResource('area'); $acl->allow(null, 'area'); Assert::true($acl->isAllowed(null, 'area')); $acl->removeResource('area'); -Assert::exception(function () use ($acl) { - $acl->isAllowed(null, 'area'); -}, Nette\InvalidStateException::class, "Resource 'area' does not exist."); +Assert::exception( + fn() => $acl->isAllowed(null, 'area'), + Nette\InvalidStateException::class, + "Resource 'area' does not exist.", +); $acl->addResource('area'); Assert::false($acl->isAllowed(null, 'area')); diff --git a/tests/Security/Permission.RulesResourceRemoveAll.phpt b/tests/Security/Permission.RulesResourceRemoveAll.phpt index c346c096..4f14e870 100644 --- a/tests/Security/Permission.RulesResourceRemoveAll.phpt +++ b/tests/Security/Permission.RulesResourceRemoveAll.phpt @@ -18,9 +18,11 @@ $acl->addResource('area'); $acl->allow(null, 'area'); Assert::true($acl->isAllowed(null, 'area')); $acl->removeAllResources(); -Assert::exception(function () use ($acl) { - $acl->isAllowed(null, 'area'); -}, Nette\InvalidStateException::class, "Resource 'area' does not exist."); +Assert::exception( + fn() => $acl->isAllowed(null, 'area'), + Nette\InvalidStateException::class, + "Resource 'area' does not exist.", +); $acl->addResource('area'); Assert::false($acl->isAllowed(null, 'area')); diff --git a/tests/Security/SimpleAuthenticator.phpt b/tests/Security/SimpleAuthenticator.phpt index a2c2370f..ed0ecfc4 100644 --- a/tests/Security/SimpleAuthenticator.phpt +++ b/tests/Security/SimpleAuthenticator.phpt @@ -28,10 +28,14 @@ $identity = $authenticator->authenticate('admin', 'admin'); Assert::type(Nette\Security\IIdentity::class, $identity); Assert::equal('admin', $identity->getId()); -Assert::exception(function () use ($authenticator) { - $authenticator->authenticate('admin', 'wrong password'); -}, Nette\Security\AuthenticationException::class, 'Invalid password.'); - -Assert::exception(function () use ($authenticator) { - $authenticator->authenticate('nobody', 'password'); -}, Nette\Security\AuthenticationException::class, "User 'nobody' not found."); +Assert::exception( + fn() => $authenticator->authenticate('admin', 'wrong password'), + Nette\Security\AuthenticationException::class, + 'Invalid password.', +); + +Assert::exception( + fn() => $authenticator->authenticate('nobody', 'password'), + Nette\Security\AuthenticationException::class, + "User 'nobody' not found.", +); diff --git a/tests/Security/User.authentication.phpt b/tests/Security/User.authentication.phpt index b66f7f1c..892c4086 100644 --- a/tests/Security/User.authentication.phpt +++ b/tests/Security/User.authentication.phpt @@ -58,23 +58,26 @@ Assert::null($user->getId()); // authenticate -Assert::exception(function () use ($user) { - // login without handler - $user->login('jane', ''); -}, Nette\InvalidStateException::class, 'Authenticator has not been set.'); +Assert::exception( + fn() => $user->login('jane', ''), + Nette\InvalidStateException::class, + 'Authenticator has not been set.', +); $handler = new Authenticator; $user->setAuthenticator($handler); -Assert::exception(function () use ($user) { - // login as jane - $user->login('jane', ''); -}, Nette\Security\AuthenticationException::class, 'Unknown user'); - -Assert::exception(function () use ($user) { - // login as john - $user->login('john', ''); -}, Nette\Security\AuthenticationException::class, 'Password not match'); +Assert::exception( + fn() => $user->login('jane', ''), + Nette\Security\AuthenticationException::class, + 'Unknown user', +); + +Assert::exception( + fn() => $user->login('john', ''), + Nette\Security\AuthenticationException::class, + 'Password not match', +); // login as john#2 $user->login('john', 'xxx'); diff --git a/tests/Security/User.authorization.phpt b/tests/Security/User.authorization.phpt index d6ce4718..4cfac5e8 100644 --- a/tests/Security/User.authorization.phpt +++ b/tests/Security/User.authorization.phpt @@ -81,9 +81,11 @@ Assert::false($user->isInRole('guest')); // authorization -Assert::exception(function () use ($user) { - $user->isAllowed('delete_file'); -}, Nette\InvalidStateException::class, 'Authorizator has not been set.'); +Assert::exception( + fn() => $user->isAllowed('delete_file'), + Nette\InvalidStateException::class, + 'Authorizator has not been set.', +); $handler = new Authorizator; $user->setAuthorizator($handler); From 980395adac1e208a7eadcdd2c4da9a28d60dd7b9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:15:45 +0100 Subject: [PATCH 07/22] added property typehints --- src/Bridges/SecurityDI/SecurityExtension.php | 3 +- src/Bridges/SecurityHttp/CookieStorage.php | 27 ++++---------- src/Bridges/SecurityHttp/SessionStorage.php | 19 +++------- src/Bridges/SecurityTracy/UserPanel.php | 3 +- src/Security/Identity.php | 13 +++---- src/Security/Passwords.php | 7 ++-- src/Security/Permission.php | 16 ++++----- src/Security/SimpleAuthenticator.php | 11 ++---- src/Security/User.php | 38 ++++++++------------ 9 files changed, 44 insertions(+), 93 deletions(-) diff --git a/src/Bridges/SecurityDI/SecurityExtension.php b/src/Bridges/SecurityDI/SecurityExtension.php index 41f7649b..3dc48c9a 100644 --- a/src/Bridges/SecurityDI/SecurityExtension.php +++ b/src/Bridges/SecurityDI/SecurityExtension.php @@ -19,8 +19,7 @@ */ class SecurityExtension extends Nette\DI\CompilerExtension { - /** @var bool */ - private $debugMode; + private bool $debugMode; public function __construct(bool $debugMode = false) diff --git a/src/Bridges/SecurityHttp/CookieStorage.php b/src/Bridges/SecurityHttp/CookieStorage.php index 33ff00dd..23f19ce2 100644 --- a/src/Bridges/SecurityHttp/CookieStorage.php +++ b/src/Bridges/SecurityHttp/CookieStorage.php @@ -23,26 +23,13 @@ final class CookieStorage implements Nette\Security\UserStorage private const MIN_LENGTH = 13; - /** @var Http\IRequest */ - private $request; - - /** @var Http\IResponse */ - private $response; - - /** @var ?string */ - private $uid; - - /** @var string */ - private $cookieName = 'userid'; - - /** @var ?string */ - private $cookieDomain; - - /** @var string */ - private $cookieSameSite = 'Lax'; - - /** @var ?string */ - private $cookieExpiration; + private Http\IRequest $request; + private Http\IResponse $response; + private ?string $uid = null; + private string $cookieName = 'userid'; + private ?string $cookieDomain = null; + private string $cookieSameSite = 'Lax'; + private ?string $cookieExpiration = null; public function __construct(Http\IRequest $request, Http\IResponse $response) diff --git a/src/Bridges/SecurityHttp/SessionStorage.php b/src/Bridges/SecurityHttp/SessionStorage.php index 87f77efa..1ed8aaf2 100644 --- a/src/Bridges/SecurityHttp/SessionStorage.php +++ b/src/Bridges/SecurityHttp/SessionStorage.php @@ -22,20 +22,11 @@ final class SessionStorage implements Nette\Security\UserStorage { use Nette\SmartObject; - /** @var string */ - private $namespace = ''; - - /** @var Session */ - private $sessionHandler; - - /** @var SessionSection */ - private $sessionSection; - - /** @var ?int */ - private $expireTime; - - /** @var bool */ - private $expireIdentity = false; + private string $namespace = ''; + private Session $sessionHandler; + private ?SessionSection $sessionSection = null; + private ?int $expireTime = null; + private bool $expireIdentity = false; public function __construct(Session $sessionHandler) diff --git a/src/Bridges/SecurityTracy/UserPanel.php b/src/Bridges/SecurityTracy/UserPanel.php index 488757c1..123d86c1 100644 --- a/src/Bridges/SecurityTracy/UserPanel.php +++ b/src/Bridges/SecurityTracy/UserPanel.php @@ -20,8 +20,7 @@ class UserPanel implements Tracy\IBarPanel { use Nette\SmartObject; - /** @var Nette\Security\User */ - private $user; + private Nette\Security\User $user; public function __construct(Nette\Security\User $user) diff --git a/src/Security/Identity.php b/src/Security/Identity.php index 3a78c2e5..ab1f2ce1 100644 --- a/src/Security/Identity.php +++ b/src/Security/Identity.php @@ -14,7 +14,7 @@ /** * @deprecated use Nette\Security\SimpleIdentity - * @property mixed $id + * @property string|int $id * @property array $roles * @property array $data */ @@ -26,14 +26,9 @@ class Identity implements IIdentity __isset as private parentIsSet; } - /** @var mixed */ - private $id; - - /** @var array */ - private $roles; - - /** @var array */ - private $data; + private string|int $id; + private array $roles; + private array $data; public function __construct($id, $roles = null, ?iterable $data = null) diff --git a/src/Security/Passwords.php b/src/Security/Passwords.php index 89f512d2..e3c438dd 100644 --- a/src/Security/Passwords.php +++ b/src/Security/Passwords.php @@ -19,11 +19,8 @@ class Passwords { use Nette\SmartObject; - /** @var int|string string since PHP 7.4 */ - private $algo; - - /** @var array */ - private $options; + private string $algo; + private array $options; /** diff --git a/src/Security/Permission.php b/src/Security/Permission.php index ee011205..4fab11b9 100644 --- a/src/Security/Permission.php +++ b/src/Security/Permission.php @@ -21,14 +21,14 @@ class Permission implements Authorizator { use Nette\SmartObject; - /** @var array Role storage */ - private $roles = []; + /** Role storage */ + private array $roles = []; - /** @var array Resource storage */ - private $resources = []; + /** Resource storage */ + private array $resources = []; - /** @var array Access Control List rules; whitelist (deny everything to all) by default */ - private $rules = [ + /** Access Control List rules; whitelist (deny everything to all) by default */ + private array $rules = [ 'allResources' => [ 'allRoles' => [ 'allPrivileges' => [ @@ -42,9 +42,7 @@ class Permission implements Authorizator 'byResource' => [], ]; - /** @var mixed */ - private $queriedRole; - + private mixed $queriedRole; private $queriedResource; diff --git a/src/Security/SimpleAuthenticator.php b/src/Security/SimpleAuthenticator.php index df8d0bad..f3befcef 100644 --- a/src/Security/SimpleAuthenticator.php +++ b/src/Security/SimpleAuthenticator.php @@ -19,14 +19,9 @@ class SimpleAuthenticator implements Authenticator { use Nette\SmartObject; - /** @var array */ - private $passwords; - - /** @var array */ - private $roles; - - /** @var array */ - private $data; + private array $passwords; + private array $roles; + private array $data; /** diff --git a/src/Security/User.php b/src/Security/User.php index 4ed1e055..f83304e0 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -38,35 +38,25 @@ class User LOGOUT_MANUAL = UserStorage::LOGOUT_MANUAL, LOGOUT_INACTIVITY = UserStorage::LOGOUT_INACTIVITY; - /** @var string default role for unauthenticated user */ - public $guestRole = 'guest'; + /** default role for unauthenticated user */ + public string $guestRole = 'guest'; - /** @var string default role for authenticated user without own identity */ - public $authenticatedRole = 'authenticated'; + /** default role for authenticated user without own identity */ + public string $authenticatedRole = 'authenticated'; /** @var callable[] function (User $sender): void; Occurs when the user is successfully logged in */ - public $onLoggedIn = []; + public iterable $onLoggedIn = []; /** @var callable[] function (User $sender): void; Occurs when the user is logged out */ - public $onLoggedOut = []; - - /** @var UserStorage|IUserStorage Session storage for current user */ - private $storage; - - /** @var IAuthenticator|null */ - private $authenticator; - - /** @var Authorizator|null */ - private $authorizator; - - /** @var IIdentity|null */ - private $identity; - - /** @var bool|null */ - private $authenticated; - - /** @var int|null */ - private $logoutReason; + public iterable $onLoggedOut = []; + + /** Session storage for current user */ + private UserStorage|IUserStorage $storage; + private ?IAuthenticator $authenticator; + private ?Authorizator $authorizator; + private ?IIdentity $identity = null; + private ?bool $authenticated = null; + private ?int $logoutReason = null; public function __construct( From 5abcbf60e29511885067aaf43781d2aed4e9b633 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 12 Dec 2021 18:12:59 +0100 Subject: [PATCH 08/22] added PHP 8 typehints --- src/Bridges/SecurityHttp/SessionStorage.php | 3 +- src/Security/Authorizator.php | 5 +- src/Security/IIdentity.php | 3 +- src/Security/Identity.php | 16 ++--- src/Security/Passwords.php | 2 +- src/Security/Permission.php | 70 +++++++++------------ src/Security/User.php | 26 +++----- tests/Security/MockUserStorage.legacy.php | 3 +- 8 files changed, 47 insertions(+), 81 deletions(-) diff --git a/src/Bridges/SecurityHttp/SessionStorage.php b/src/Bridges/SecurityHttp/SessionStorage.php index 1ed8aaf2..b0554625 100644 --- a/src/Bridges/SecurityHttp/SessionStorage.php +++ b/src/Bridges/SecurityHttp/SessionStorage.php @@ -101,9 +101,8 @@ private function setupExpiration(): void /** * Changes namespace; allows more users to share a session. - * @return static */ - public function setNamespace(string $namespace) + public function setNamespace(string $namespace): static { if ($this->namespace !== $namespace) { $this->namespace = $namespace; diff --git a/src/Security/Authorizator.php b/src/Security/Authorizator.php index 085a8825..66586c1f 100644 --- a/src/Security/Authorizator.php +++ b/src/Security/Authorizator.php @@ -27,11 +27,8 @@ interface Authorizator /** * Performs a role-based authorization. - * @param string|null $role - * @param string|null $resource - * @param string|null $privilege */ - function isAllowed($role, $resource, $privilege): bool; + function isAllowed(?string $role, ?string $resource, ?string $privilege): bool; } diff --git a/src/Security/IIdentity.php b/src/Security/IIdentity.php index 862db78b..3b64ea2e 100644 --- a/src/Security/IIdentity.php +++ b/src/Security/IIdentity.php @@ -18,9 +18,8 @@ interface IIdentity { /** * Returns the ID of user. - * @return mixed */ - function getId(); + function getId(): string|int; /** * Returns a list of roles that the user is a member of. diff --git a/src/Security/Identity.php b/src/Security/Identity.php index ab1f2ce1..f1c47af5 100644 --- a/src/Security/Identity.php +++ b/src/Security/Identity.php @@ -43,14 +43,9 @@ public function __construct($id, $roles = null, ?iterable $data = null) /** * Sets the ID of user. - * @param string|int $id - * @return static */ - public function setId($id) + public function setId(string|int $id): static { - if (!is_string($id) && !is_int($id)) { - throw new Nette\InvalidArgumentException('Identity identifier must be string|int, but type "' . gettype($id) . '" given.'); - } $this->id = is_numeric($id) && !is_float($tmp = $id * 1) ? $tmp : $id; return $this; @@ -59,9 +54,8 @@ public function setId($id) /** * Returns the ID of user. - * @return mixed */ - public function getId() + public function getId(): string|int { return $this->id; } @@ -69,9 +63,8 @@ public function getId() /** * Sets a list of roles that the user is a member of. - * @return static */ - public function setRoles(array $roles) + public function setRoles(array $roles): static { $this->roles = $roles; return $this; @@ -112,9 +105,8 @@ public function __set(string $key, $value): void /** * Returns user data value. - * @return mixed */ - public function &__get(string $key) + public function &__get(string $key): mixed { if ($this->parentIsSet($key)) { return $this->parentGet($key); diff --git a/src/Security/Passwords.php b/src/Security/Passwords.php index e3c438dd..b0b6df9a 100644 --- a/src/Security/Passwords.php +++ b/src/Security/Passwords.php @@ -27,7 +27,7 @@ class Passwords * Chooses which secure algorithm is used for hashing and how to configure it. * @see https://php.net/manual/en/password.constants.php */ - public function __construct($algo = PASSWORD_DEFAULT, array $options = []) + public function __construct(string $algo = PASSWORD_DEFAULT, array $options = []) { $this->algo = $algo; $this->options = $options; diff --git a/src/Security/Permission.php b/src/Security/Permission.php index 4fab11b9..85b97cc8 100644 --- a/src/Security/Permission.php +++ b/src/Security/Permission.php @@ -52,12 +52,10 @@ class Permission implements Authorizator /** * Adds a Role to the list. The most recently added parent * takes precedence over parents that were previously added. - * @param string|array $parents * @throws Nette\InvalidArgumentException * @throws Nette\InvalidStateException - * @return static */ - public function addRole(string $role, $parents = null) + public function addRole(string $role, string|array|null $parents = null): static { $this->checkRole($role, false); if (isset($this->roles[$role])) { @@ -161,9 +159,8 @@ public function roleInheritsFrom(string $role, string $inherit, bool $onlyParent * Removes the Role from the list. * * @throws Nette\InvalidStateException - * @return static */ - public function removeRole(string $role) + public function removeRole(string $role): static { $this->checkRole($role); @@ -199,10 +196,8 @@ public function removeRole(string $role) /** * Removes all Roles from the list. - * - * @return static */ - public function removeAllRoles() + public function removeAllRoles(): static { $this->roles = []; @@ -228,9 +223,8 @@ public function removeAllRoles() * * @throws Nette\InvalidArgumentException * @throws Nette\InvalidStateException - * @return static */ - public function addResource(string $resource, ?string $parent = null) + public function addResource(string $resource, ?string $parent = null): static { $this->checkResource($resource, false); @@ -324,9 +318,8 @@ public function resourceInheritsFrom(string $resource, string $inherit, bool $on * Removes a Resource and all of its children. * * @throws Nette\InvalidStateException - * @return static */ - public function removeResource(string $resource) + public function removeResource(string $resource): static { $this->checkResource($resource); @@ -356,9 +349,8 @@ public function removeResource(string $resource) /** * Removes all Resources. - * @return static */ - public function removeAllResources() + public function removeAllResources(): static { foreach ($this->resources as $resource => $foo) { foreach ($this->rules['byResource'] as $resourceCurrent => $rules) { @@ -383,14 +375,14 @@ public function removeAllResources() * @param string|string[]|null $roles * @param string|string[]|null $resources * @param string|string[]|null $privileges - * @return static */ public function allow( $roles = self::ALL, $resources = self::ALL, $privileges = self::ALL, ?callable $assertion = null, - ) { + ): static + { $this->setRule(true, self::ALLOW, $roles, $resources, $privileges, $assertion); return $this; } @@ -403,14 +395,14 @@ public function allow( * @param string|string[]|null $roles * @param string|string[]|null $resources * @param string|string[]|null $privileges - * @return static */ public function deny( $roles = self::ALL, $resources = self::ALL, $privileges = self::ALL, ?callable $assertion = null, - ) { + ): static + { $this->setRule(true, self::DENY, $roles, $resources, $privileges, $assertion); return $this; } @@ -422,9 +414,8 @@ public function deny( * @param string|string[]|null $roles * @param string|string[]|null $resources * @param string|string[]|null $privileges - * @return static */ - public function removeAllow($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL) + public function removeAllow($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL): static { $this->setRule(false, self::ALLOW, $roles, $resources, $privileges); return $this; @@ -437,9 +428,8 @@ public function removeAllow($roles = self::ALL, $resources = self::ALL, $privile * @param string|string[]|null $roles * @param string|string[]|null $resources * @param string|string[]|null $privileges - * @return static */ - public function removeDeny($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL) + public function removeDeny($roles = self::ALL, $resources = self::ALL, $privileges = self::ALL): static { $this->setRule(false, self::DENY, $roles, $resources, $privileges); return $this; @@ -452,9 +442,15 @@ public function removeDeny($roles = self::ALL, $resources = self::ALL, $privileg * @param string|string[]|null $resources * @param string|string[]|null $privileges * @throws Nette\InvalidStateException - * @return static */ - protected function setRule(bool $toAdd, bool $type, $roles, $resources, $privileges, ?callable $assertion = null) + protected function setRule( + bool $toAdd, + bool $type, + $roles, + $resources, + $privileges, + ?callable $assertion = null, + ): static { // ensure that all specified Roles exist; normalize input to array of Roles or null if ($roles === self::ALL) { @@ -564,12 +560,13 @@ protected function setRule(bool $toAdd, bool $type, $roles, $resources, $privile * and its respective parents are checked similarly before the lower-priority parents of * the Role are checked. * - * @param string|Role|null $role - * @param string|Nette\Security\Resource|null $resource - * @param string|null $privilege * @throws Nette\InvalidStateException */ - public function isAllowed($role = self::ALL, $resource = self::ALL, $privilege = self::ALL): bool + public function isAllowed( + string|Role|null $role = self::ALL, + string|Nette\Security\Resource|null $resource = self::ALL, + ?string $privilege = self::ALL, + ): bool { $this->queriedRole = $role; if ($role !== self::ALL) { @@ -626,9 +623,8 @@ public function isAllowed($role = self::ALL, $resource = self::ALL, $privilege = /** * Returns real currently queried Role. Use by assertion. - * @return mixed */ - public function getQueriedRole() + public function getQueriedRole(): mixed { return $this->queriedRole; } @@ -636,9 +632,8 @@ public function getQueriedRole() /** * Returns real currently queried Resource. Use by assertion. - * @return mixed */ - public function getQueriedResource() + public function getQueriedResource(): mixed { return $this->queriedResource; } @@ -653,7 +648,7 @@ public function getQueriedResource() * @param bool $all (true) or one? * @return mixed null if no applicable rule is found, otherwise returns ALLOW or DENY */ - private function searchRolePrivileges(bool $all, $role, $resource, $privilege) + private function searchRolePrivileges(bool $all, $role, $resource, $privilege): mixed { $dfs = [ 'visited' => [], @@ -698,12 +693,9 @@ private function searchRolePrivileges(bool $all, $role, $resource, $privilege) /** * Returns the rule type associated with the specified Resource, Role, and privilege. - * @param string|null $resource - * @param string|null $role - * @param string|null $privilege * @return bool|null null if a rule does not exist or assertion fails, otherwise returns ALLOW or DENY */ - private function getRuleType($resource, $role, $privilege): ?bool + private function getRuleType(?string $resource, ?string $role, ?string $privilege): ?bool { if (!$rules = $this->getRules($resource, $role)) { return null; @@ -740,10 +732,8 @@ private function getRuleType($resource, $role, $privilege): ?bool /** * Returns the rules associated with a Resource and a Role, or null if no such rules exist. * If the $create parameter is true, then a rule set is first created and then returned to the caller. - * @param string|null $resource - * @param string|null $role */ - private function &getRules($resource, $role, bool $create = false): ?array + private function &getRules(?string $resource, ?string $role, bool $create = false): ?array { $null = null; if ($resource === self::ALL) { diff --git a/src/Security/User.php b/src/Security/User.php index f83304e0..30e4aff7 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -18,7 +18,7 @@ * * @property-read bool $loggedIn * @property-read IIdentity $identity - * @property-read mixed $id + * @property-read string|int $id * @property-read array $roles * @property-read int $logoutReason * @property IAuthenticator $authenticator @@ -75,10 +75,7 @@ public function __construct( } - /** - * @return UserStorage|IUserStorage - */ - final public function getStorage() + final public function getStorage(): UserStorage|IUserStorage { return $this->storage; } @@ -92,7 +89,7 @@ final public function getStorage() * @param string|IIdentity $user name or Identity * @throws AuthenticationException if authentication was not successful */ - public function login($user, ?string $password = null): void + public function login(string|IIdentity $user, ?string $password = null): void { $this->logout(true); if ($user instanceof IIdentity) { @@ -195,9 +192,8 @@ private function getStoredData(): void /** * Returns current user ID, if any. - * @return mixed */ - public function getId() + public function getId(): string|int|null { $identity = $this->getIdentity(); return $identity ? $identity->getId() : null; @@ -212,9 +208,8 @@ final public function refreshStorage(): void /** * Sets authentication handler. - * @return static */ - public function setAuthenticator(IAuthenticator $handler) + public function setAuthenticator(IAuthenticator $handler): static { $this->authenticator = $handler; return $this; @@ -257,15 +252,9 @@ final public function hasAuthenticator(): bool /** * Enables log out after inactivity (like '20 minutes'). - * @param string|null $expire - * @param int|bool $clearIdentity - * @return static */ - public function setExpiration($expire, $clearIdentity = null) + public function setExpiration(?string $expire, bool|int|null $clearIdentity = null) { - if ($expire !== null && !is_string($expire)) { - trigger_error("Expiration should be a string like '20 minutes' etc.", E_USER_DEPRECATED); - } if (func_num_args() > 2) { $clearIdentity = $clearIdentity || func_get_arg(2); @@ -339,9 +328,8 @@ public function isAllowed($resource = Authorizator::ALL, $privilege = Authorizat /** * Sets authorization handler. - * @return static */ - public function setAuthorizator(Authorizator $handler) + public function setAuthorizator(Authorizator $handler): static { $this->authorizator = $handler; return $this; diff --git a/tests/Security/MockUserStorage.legacy.php b/tests/Security/MockUserStorage.legacy.php index d4b134be..679e2b36 100644 --- a/tests/Security/MockUserStorage.legacy.php +++ b/tests/Security/MockUserStorage.legacy.php @@ -9,9 +9,10 @@ class MockUserStorage implements Nette\Security\IUserStorage private $identity; - public function setAuthenticated(bool $state) + public function setAuthenticated(bool $state): self { $this->auth = $state; + return $this; } From d6440993f7ace7cdc1342d81606b6a46c51e9ff7 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 2 Mar 2021 15:03:47 +0100 Subject: [PATCH 09/22] removed deprecated stuff --- src/Security/User.php | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/Security/User.php b/src/Security/User.php index 30e4aff7..3eb33e40 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -219,14 +219,9 @@ public function setAuthenticator(IAuthenticator $handler): static /** * Returns authentication handler. */ - final public function getAuthenticator(): ?IAuthenticator + final public function getAuthenticator(): IAuthenticator { - if (func_num_args()) { - trigger_error(__METHOD__ . '() parameter $throw is deprecated, use getAuthenticatorIfExists()', E_USER_DEPRECATED); - $throw = func_get_arg(0); - } - - if (($throw ?? true) && !$this->authenticator) { + if (!$this->authenticator) { throw new Nette\InvalidStateException('Authenticator has not been set.'); } @@ -255,12 +250,6 @@ final public function hasAuthenticator(): bool */ public function setExpiration(?string $expire, bool|int|null $clearIdentity = null) { - - if (func_num_args() > 2) { - $clearIdentity = $clearIdentity || func_get_arg(2); - trigger_error(__METHOD__ . '() third parameter is deprecated, use second one: setExpiration($time, true|false)', E_USER_DEPRECATED); - } - $arg = $this->storage instanceof UserStorage ? (bool) $clearIdentity : ($clearIdentity ? IUserStorage::CLEAR_IDENTITY : 0); @@ -339,14 +328,9 @@ public function setAuthorizator(Authorizator $handler): static /** * Returns current authorization handler. */ - final public function getAuthorizator(): ?Authorizator + final public function getAuthorizator(): Authorizator { - if (func_num_args()) { - trigger_error(__METHOD__ . '() parameter $throw is deprecated, use getAuthorizatorIfExists()', E_USER_DEPRECATED); - $throw = func_get_arg(0); - } - - if (($throw ?? true) && !$this->authorizator) { + if (!$this->authorizator) { throw new Nette\InvalidStateException('Authorizator has not been set.'); } From cc83b6e552033769f54f035b50646ba7fb3b4541 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 12 Dec 2021 18:13:42 +0100 Subject: [PATCH 10/22] removed usage of IUserStorage (BC break) --- src/Bridges/SecurityDI/SecurityExtension.php | 4 - src/Security/IUserStorage.php | 35 +----- src/Security/User.php | 54 ++------ tests/Security.DI/SecurityExtension.user.phpt | 1 - tests/Security/MockUserStorage.legacy.php | 46 ------- .../Security/User.authentication.legacy.phpt | 117 ------------------ tests/Security/User.authentication.phpt | 2 +- tests/Security/User.authorization.phpt | 2 +- 8 files changed, 16 insertions(+), 245 deletions(-) delete mode 100644 tests/Security/MockUserStorage.legacy.php delete mode 100644 tests/Security/User.authentication.legacy.phpt diff --git a/src/Bridges/SecurityDI/SecurityExtension.php b/src/Bridges/SecurityDI/SecurityExtension.php index 3dc48c9a..24fda5d4 100644 --- a/src/Bridges/SecurityDI/SecurityExtension.php +++ b/src/Bridges/SecurityDI/SecurityExtension.php @@ -80,10 +80,6 @@ public function loadConfiguration() $storage->addSetup('setCookieParameters', [$auth->cookieName, $auth->cookieDomain, $auth->cookieSamesite]); } - $builder->addDefinition($this->prefix('legacyUserStorage')) // deprecated - ->setType(Nette\Security\IUserStorage::class) - ->setFactory(Nette\Http\UserStorage::class); - $user = $builder->addDefinition($this->prefix('user')) ->setFactory(Nette\Security\User::class); diff --git a/src/Security/IUserStorage.php b/src/Security/IUserStorage.php index 061e52c6..c756cc6f 100644 --- a/src/Security/IUserStorage.php +++ b/src/Security/IUserStorage.php @@ -21,38 +21,5 @@ interface IUserStorage INACTIVITY = 0b0010; /** Log-out behavior */ - public const CLEAR_IDENTITY = 0b1000; - - /** - * Sets the authenticated status of this user. - * @return static - */ - function setAuthenticated(bool $state); - - /** - * Is this user authenticated? - */ - function isAuthenticated(): bool; - - /** - * Sets the user identity. - * @return static - */ - function setIdentity(?IIdentity $identity); - - /** - * Returns current user identity, if any. - */ - function getIdentity(): ?IIdentity; - - /** - * Enables log out from the persistent storage after inactivity (like '20 minutes'). Accepts flag IUserStorage::CLEAR_IDENTITY. - * @return static - */ - function setExpiration(?string $expire, int $flags = 0); - - /** - * Why was user logged out? - */ - function getLogoutReason(): ?int; + public const CLEAR_IDENTITY = true; } diff --git a/src/Security/User.php b/src/Security/User.php index 3eb33e40..467741e9 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -51,7 +51,7 @@ class User public iterable $onLoggedOut = []; /** Session storage for current user */ - private UserStorage|IUserStorage $storage; + private UserStorage $storage; private ?IAuthenticator $authenticator; private ?Authorizator $authorizator; private ?IIdentity $identity = null; @@ -60,22 +60,17 @@ class User public function __construct( - ?IUserStorage $legacyStorage = null, + UserStorage $storage, ?IAuthenticator $authenticator = null, ?Authorizator $authorizator = null, - ?UserStorage $storage = null, ) { - $this->storage = $storage ?? $legacyStorage; // back compatibility - if (!$this->storage) { - throw new Nette\InvalidStateException('UserStorage has not been set.'); - } - + $this->storage = $storage; $this->authenticator = $authenticator; $this->authorizator = $authorizator; } - final public function getStorage(): UserStorage|IUserStorage + final public function getStorage(): UserStorage { return $this->storage; } @@ -104,13 +99,8 @@ public function login(string|IIdentity $user, ?string $password = null): void $id = $this->authenticator instanceof IdentityHandler ? $this->authenticator->sleepIdentity($this->identity) : $this->identity; - if ($this->storage instanceof UserStorage) { - $this->storage->saveAuthentication($id); - } else { - $this->storage->setIdentity($id); - $this->storage->setAuthenticated(true); - } + $this->storage->saveAuthentication($id); $this->authenticated = true; $this->logoutReason = null; Arrays::invoke($this->onLoggedIn, $this); @@ -123,16 +113,7 @@ public function login(string|IIdentity $user, ?string $password = null): void final public function logout(bool $clearIdentity = false): void { $logged = $this->isLoggedIn(); - - if ($this->storage instanceof UserStorage) { - $this->storage->clearAuthentication($clearIdentity); - } else { - $this->storage->setAuthenticated(false); - if ($clearIdentity) { - $this->storage->setIdentity(null); - } - } - + $this->storage->clearAuthentication($clearIdentity); $this->authenticated = false; $this->logoutReason = self::MANUAL; if ($logged) { @@ -171,17 +152,11 @@ final public function getIdentity(): ?IIdentity private function getStoredData(): void { - if ($this->storage instanceof UserStorage) { - (function (bool $state, ?IIdentity $id, ?int $reason) use (&$identity) { - $identity = $id; - $this->authenticated = $state; - $this->logoutReason = $reason; - })(...$this->storage->getState()); - } else { - $identity = $this->storage->getIdentity(); - $this->authenticated = $this->storage->isAuthenticated(); - $this->logoutReason = $this->storage->getLogoutReason(); - } + (function (bool $state, ?IIdentity $id, ?int $reason) use (&$identity) { + $identity = $id; + $this->authenticated = $state; + $this->logoutReason = $reason; + })(...$this->storage->getState()); $this->identity = $identity && $this->authenticator instanceof IdentityHandler ? $this->authenticator->wakeupIdentity($identity) @@ -248,12 +223,9 @@ final public function hasAuthenticator(): bool /** * Enables log out after inactivity (like '20 minutes'). */ - public function setExpiration(?string $expire, bool|int|null $clearIdentity = null) + public function setExpiration(?string $expire, bool $clearIdentity = false) { - $arg = $this->storage instanceof UserStorage - ? (bool) $clearIdentity - : ($clearIdentity ? IUserStorage::CLEAR_IDENTITY : 0); - $this->storage->setExpiration($expire, $arg); + $this->storage->setExpiration($expire, $clearIdentity); return $this; } diff --git a/tests/Security.DI/SecurityExtension.user.phpt b/tests/Security.DI/SecurityExtension.user.phpt index f4f3e9ff..fa0706e5 100644 --- a/tests/Security.DI/SecurityExtension.user.phpt +++ b/tests/Security.DI/SecurityExtension.user.phpt @@ -25,7 +25,6 @@ eval($compiler->compile()); $container = new Container; Assert::type(Nette\Bridges\SecurityHttp\SessionStorage::class, $container->getService('security.userStorage')); -Assert::type(Nette\Http\UserStorage::class, $container->getService('security.legacyUserStorage')); Assert::type(Nette\Security\User::class, $container->getService('security.user')); // aliases diff --git a/tests/Security/MockUserStorage.legacy.php b/tests/Security/MockUserStorage.legacy.php deleted file mode 100644 index 679e2b36..00000000 --- a/tests/Security/MockUserStorage.legacy.php +++ /dev/null @@ -1,46 +0,0 @@ -auth = $state; - return $this; - } - - - public function isAuthenticated(): bool - { - return $this->auth; - } - - - public function setIdentity(?Nette\Security\IIdentity $identity = null) - { - $this->identity = $identity; - } - - - public function getIdentity(): ?Nette\Security\IIdentity - { - return $this->identity; - } - - - public function setExpiration(?string $time, int $flags = 0) - { - } - - - public function getLogoutReason(): ?int - { - return null; - } -} diff --git a/tests/Security/User.authentication.legacy.phpt b/tests/Security/User.authentication.legacy.phpt deleted file mode 100644 index 8c0e559d..00000000 --- a/tests/Security/User.authentication.legacy.phpt +++ /dev/null @@ -1,117 +0,0 @@ - 0, - 'logout' => 0, -]; - -$user->onLoggedIn[] = function () use ($counter) { - $counter->login++; -}; - -$user->onLoggedOut[] = function () use ($counter) { - $counter->logout++; -}; - - -Assert::false($user->isLoggedIn()); -Assert::null($user->getIdentity()); -Assert::null($user->getId()); - - -// authenticate -Assert::exception(function () use ($user) { - // login without handler - $user->login('jane', ''); -}, Nette\InvalidStateException::class, 'Authenticator has not been set.'); - -$handler = new Authenticator; -$user->setAuthenticator($handler); - -Assert::exception(function () use ($user) { - // login as jane - $user->login('jane', ''); -}, Nette\Security\AuthenticationException::class, 'Unknown user'); - -Assert::exception(function () use ($user) { - // login as john - $user->login('john', ''); -}, Nette\Security\AuthenticationException::class, 'Password not match'); - -// login as john#2 -$user->login('john', 'xxx'); -Assert::same(1, $counter->login); -Assert::true($user->isLoggedIn()); -Assert::equal(new Identity('John Doe', 'admin'), $user->getIdentity()); -Assert::same('John Doe', $user->getId()); - -// login as john#3 -$user->logout(true); -Assert::same(1, $counter->logout); -$user->login(new Identity('John Doe', 'admin')); -Assert::same(2, $counter->login); -Assert::true($user->isLoggedIn()); -Assert::equal(new Identity('John Doe', 'admin'), $user->getIdentity()); - - -// log out -// logging out... -$user->logout(false); -Assert::same(2, $counter->logout); - -Assert::false($user->isLoggedIn()); -Assert::equal(new Identity('John Doe', 'admin'), $user->getIdentity()); - - -// logging out and clearing identity... -$user->logout(true); -Assert::same(2, $counter->logout); // not logged in -> logout event not triggered - -Assert::false($user->isLoggedIn()); -Assert::null($user->getIdentity()); - - -// namespace -// login as john#2? -$user->login('john', 'xxx'); -Assert::same(3, $counter->login); -Assert::true($user->isLoggedIn()); diff --git a/tests/Security/User.authentication.phpt b/tests/Security/User.authentication.phpt index 892c4086..0314d2a5 100644 --- a/tests/Security/User.authentication.phpt +++ b/tests/Security/User.authentication.phpt @@ -36,7 +36,7 @@ class Authenticator implements Nette\Security\Authenticator } -$user = new Nette\Security\User(null, null, null, new MockUserStorage); +$user = new Nette\Security\User(new MockUserStorage); $counter = (object) [ 'login' => 0, diff --git a/tests/Security/User.authorization.phpt b/tests/Security/User.authorization.phpt index 4cfac5e8..c6a18f87 100644 --- a/tests/Security/User.authorization.phpt +++ b/tests/Security/User.authorization.phpt @@ -54,7 +54,7 @@ class TesterRole implements Role } } -$user = new Nette\Security\User(null, null, null, new MockUserStorage); +$user = new Nette\Security\User(new MockUserStorage); // guest Assert::false($user->isLoggedIn()); From 8245f81f73f934dedca2281a3d9ff6c8ddfe1599 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 11 Mar 2021 21:55:20 +0100 Subject: [PATCH 11/22] removed community health files --- .github/ISSUE_TEMPLATE/Bug_report.md | 19 ------------- .github/ISSUE_TEMPLATE/Feature_request.md | 9 ------ .github/ISSUE_TEMPLATE/Support_question.md | 12 -------- .github/ISSUE_TEMPLATE/Support_us.md | 21 -------------- .github/funding.yml | 2 -- .github/pull_request_template.md | 11 -------- contributing.md | 33 ---------------------- 7 files changed, 107 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/Bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/Feature_request.md delete mode 100644 .github/ISSUE_TEMPLATE/Support_question.md delete mode 100644 .github/ISSUE_TEMPLATE/Support_us.md delete mode 100644 .github/funding.yml delete mode 100644 .github/pull_request_template.md delete mode 100644 contributing.md diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md deleted file mode 100644 index a4cd1263..00000000 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: "🐛 Bug Report" -about: "If something isn't working as expected 🤔" - ---- - -Version: ?.?.? - -### Bug Description -... A clear and concise description of what the bug is. A good bug report shouldn't leave others needing to chase you up for more information. - -### Steps To Reproduce -... If possible a minimal demo of the problem ... - -### Expected Behavior -... A clear and concise description of what you expected to happen. - -### Possible Solution -... Only if you have suggestions on a fix for the bug diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md deleted file mode 100644 index d2e21948..00000000 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: "🚀 Feature Request" -about: "I have a suggestion (and may want to implement it) 🙂" - ---- - -- Is your feature request related to a problem? Please describe. -- Explain your intentions. -- It's up to you to make a strong case to convince the project's developers of the merits of this feature. diff --git a/.github/ISSUE_TEMPLATE/Support_question.md b/.github/ISSUE_TEMPLATE/Support_question.md deleted file mode 100644 index 75c48b6e..00000000 --- a/.github/ISSUE_TEMPLATE/Support_question.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: "🤗 Support Question" -about: "If you have a question 💬, please check out our forum!" - ---- - ---------------^ Click "Preview" for a nicer view! -We primarily use GitHub as an issue tracker; for usage and support questions, please check out these resources below. Thanks! 😁. - -* Nette Forum: https://forum.nette.org -* Nette Gitter: https://gitter.im/nette/nette -* Slack (czech): https://pehapkari.slack.com/messages/C2R30BLKA diff --git a/.github/ISSUE_TEMPLATE/Support_us.md b/.github/ISSUE_TEMPLATE/Support_us.md deleted file mode 100644 index 92d8a4c3..00000000 --- a/.github/ISSUE_TEMPLATE/Support_us.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: "❤️ Support us" -about: "If you would like to support our efforts in maintaining this project 🙌" - ---- - ---------------^ Click "Preview" for a nicer view! - -> https://nette.org/donate - -Help support Nette! - -We develop Nette Framework for more than 14 years. In order to make your life more comfortable. Nette cares about the safety of your sites. Nette saves you time. And gives job opportunities. - -Nette earns you money. And is absolutely free. - -To ensure future development and improving the documentation, we need your donation. - -Whether you are chief of IT company which benefits from Nette, or developer who goes for advice on our forum, if you like Nette, [please make a donation now](https://nette.org/donate). - -Thank you! diff --git a/.github/funding.yml b/.github/funding.yml deleted file mode 100644 index 25adc952..00000000 --- a/.github/funding.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: dg -custom: "https://nette.org/donate" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index f8aa3f40..00000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,11 +0,0 @@ -- bug fix / new feature? -- BC break? yes/no -- doc PR: nette/docs#??? - - diff --git a/contributing.md b/contributing.md deleted file mode 100644 index 184152c0..00000000 --- a/contributing.md +++ /dev/null @@ -1,33 +0,0 @@ -How to contribute & use the issue tracker -========================================= - -Nette welcomes your contributions. There are several ways to help out: - -* Create an issue on GitHub, if you have found a bug -* Write test cases for open bug issues -* Write fixes for open bug/feature issues, preferably with test cases included -* Contribute to the [documentation](https://nette.org/en/writing) - -Issues ------- - -Please **do not use the issue tracker to ask questions**. We will be happy to help you -on [Nette forum](https://forum.nette.org) or chat with us on [Gitter](https://gitter.im/nette/nette). - -A good bug report shouldn't leave others needing to chase you up for more -information. Please try to be as detailed as possible in your report. - -**Feature requests** are welcome. But take a moment to find out whether your idea -fits with the scope and aims of the project. It's up to *you* to make a strong -case to convince the project's developers of the merits of this feature. - -Contributing ------------- - -If you'd like to contribute, please take a moment to read [the contributing guide](https://nette.org/en/contributing). - -The best way to propose a feature is to discuss your ideas on [Nette forum](https://forum.nette.org) before implementing them. - -Please do not fix whitespace, format code, or make a purely cosmetic patch. - -Thanks! :heart: From 3baa26799fb2c39d19c110135eaa7974fef616f7 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 18:40:59 +0200 Subject: [PATCH 12/22] removed deprecated IUserStorage (BC break) --- src/Security/IUserStorage.php | 25 ------------------------- src/Security/User.php | 4 ++-- 2 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 src/Security/IUserStorage.php diff --git a/src/Security/IUserStorage.php b/src/Security/IUserStorage.php deleted file mode 100644 index c756cc6f..00000000 --- a/src/Security/IUserStorage.php +++ /dev/null @@ -1,25 +0,0 @@ - Date: Mon, 20 Sep 2021 18:39:13 +0200 Subject: [PATCH 13/22] removed deprecated IAuthenticator (BC break) --- src/Bridges/SecurityDI/SecurityExtension.php | 2 +- src/Security/Authenticator.php | 9 ++++- src/Security/IAuthenticator.php | 37 -------------------- src/Security/User.php | 16 ++++----- 4 files changed, 16 insertions(+), 48 deletions(-) delete mode 100644 src/Security/IAuthenticator.php diff --git a/src/Bridges/SecurityDI/SecurityExtension.php b/src/Bridges/SecurityDI/SecurityExtension.php index 24fda5d4..14796df5 100644 --- a/src/Bridges/SecurityDI/SecurityExtension.php +++ b/src/Bridges/SecurityDI/SecurityExtension.php @@ -97,7 +97,7 @@ public function loadConfiguration() } $builder->addDefinition($this->prefix('authenticator')) - ->setType(Nette\Security\IAuthenticator::class) + ->setType(Nette\Security\Authenticator::class) ->setFactory(Nette\Security\SimpleAuthenticator::class, [$usersList, $usersRoles, $usersData]); if ($this->name === 'security') { diff --git a/src/Security/Authenticator.php b/src/Security/Authenticator.php index fc40ea3c..a08ee055 100644 --- a/src/Security/Authenticator.php +++ b/src/Security/Authenticator.php @@ -13,8 +13,15 @@ /** * Performs authentication. */ -interface Authenticator extends IAuthenticator +interface Authenticator { + /** Exception error code */ + public const + IDENTITY_NOT_FOUND = 1, + INVALID_CREDENTIAL = 2, + FAILURE = 3, + NOT_APPROVED = 4; + /** * Performs an authentication. * @throws AuthenticationException diff --git a/src/Security/IAuthenticator.php b/src/Security/IAuthenticator.php deleted file mode 100644 index 4d845ad6..00000000 --- a/src/Security/IAuthenticator.php +++ /dev/null @@ -1,37 +0,0 @@ -storage = $storage; @@ -91,9 +91,7 @@ public function login(string|IIdentity $user, ?string $password = null): void $this->identity = $user; } else { $authenticator = $this->getAuthenticator(); - $this->identity = $authenticator instanceof Authenticator - ? $authenticator->authenticate(...func_get_args()) - : $authenticator->authenticate(func_get_args()); + $this->identity = $authenticator->authenticate(...func_get_args()); } $id = $this->authenticator instanceof IdentityHandler @@ -184,7 +182,7 @@ final public function refreshStorage(): void /** * Sets authentication handler. */ - public function setAuthenticator(IAuthenticator $handler): static + public function setAuthenticator(Authenticator $handler): static { $this->authenticator = $handler; return $this; @@ -194,7 +192,7 @@ public function setAuthenticator(IAuthenticator $handler): static /** * Returns authentication handler. */ - final public function getAuthenticator(): IAuthenticator + final public function getAuthenticator(): Authenticator { if (!$this->authenticator) { throw new Nette\InvalidStateException('Authenticator has not been set.'); @@ -207,7 +205,7 @@ final public function getAuthenticator(): IAuthenticator /** * Returns authentication handler. */ - final public function getAuthenticatorIfExists(): ?IAuthenticator + final public function getAuthenticatorIfExists(): ?Authenticator { return $this->authenticator; } From b3e49115e20a43224058536643538150a09f2a3d Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 17:35:17 +0200 Subject: [PATCH 14/22] Identity -> SimpleIdentity Identity class must exist as an alias in order to read it from session --- src/Security/Identity.php | 124 -------------------------------- src/Security/SimpleIdentity.php | 107 ++++++++++++++++++++++++++- src/compatibility-intf.php | 37 ++++++++++ src/compatibility.php | 26 ++----- tests/Security/Identity.phpt | 10 +-- 5 files changed, 152 insertions(+), 152 deletions(-) delete mode 100644 src/Security/Identity.php create mode 100644 src/compatibility-intf.php diff --git a/src/Security/Identity.php b/src/Security/Identity.php deleted file mode 100644 index f1c47af5..00000000 --- a/src/Security/Identity.php +++ /dev/null @@ -1,124 +0,0 @@ -setId($id); - $this->setRoles((array) $roles); - $this->data = $data instanceof \Traversable - ? iterator_to_array($data) - : (array) $data; - } - - - /** - * Sets the ID of user. - */ - public function setId(string|int $id): static - { - - $this->id = is_numeric($id) && !is_float($tmp = $id * 1) ? $tmp : $id; - return $this; - } - - - /** - * Returns the ID of user. - */ - public function getId(): string|int - { - return $this->id; - } - - - /** - * Sets a list of roles that the user is a member of. - */ - public function setRoles(array $roles): static - { - $this->roles = $roles; - return $this; - } - - - /** - * Returns a list of roles that the user is a member of. - */ - public function getRoles(): array - { - return $this->roles; - } - - - /** - * Returns a user data. - */ - public function getData(): array - { - return $this->data; - } - - - /** - * Sets user data value. - */ - public function __set(string $key, $value): void - { - if ($this->parentIsSet($key)) { - $this->parentSet($key, $value); - - } else { - $this->data[$key] = $value; - } - } - - - /** - * Returns user data value. - */ - public function &__get(string $key): mixed - { - if ($this->parentIsSet($key)) { - return $this->parentGet($key); - - } else { - return $this->data[$key]; - } - } - - - public function __isset(string $key): bool - { - return isset($this->data[$key]) || $this->parentIsSet($key); - } -} diff --git a/src/Security/SimpleIdentity.php b/src/Security/SimpleIdentity.php index 279aadd0..68579589 100644 --- a/src/Security/SimpleIdentity.php +++ b/src/Security/SimpleIdentity.php @@ -9,10 +9,115 @@ namespace Nette\Security; +use Nette; + /** * Default implementation of IIdentity. + * @property string|int $id + * @property array $roles + * @property array $data */ -class SimpleIdentity extends Identity +class SimpleIdentity implements IIdentity { + use Nette\SmartObject { + __get as private parentGet; + __set as private parentSet; + __isset as private parentIsSet; + } + + private string|int $id; + private array $roles; + private array $data; + + + public function __construct($id, $roles = null, ?iterable $data = null) + { + $this->setId($id); + $this->setRoles((array) $roles); + $this->data = $data instanceof \Traversable + ? iterator_to_array($data) + : (array) $data; + } + + + /** + * Sets the ID of user. + */ + public function setId(string|int $id): static + { + $this->id = is_numeric($id) && !is_float($tmp = $id * 1) ? $tmp : $id; + return $this; + } + + + /** + * Returns the ID of user. + */ + public function getId(): string|int + { + return $this->id; + } + + + /** + * Sets a list of roles that the user is a member of. + */ + public function setRoles(array $roles): static + { + $this->roles = $roles; + return $this; + } + + + /** + * Returns a list of roles that the user is a member of. + */ + public function getRoles(): array + { + return $this->roles; + } + + + /** + * Returns a user data. + */ + public function getData(): array + { + return $this->data; + } + + + /** + * Sets user data value. + */ + public function __set(string $key, $value): void + { + if ($this->parentIsSet($key)) { + $this->parentSet($key, $value); + + } else { + $this->data[$key] = $value; + } + } + + + /** + * Returns user data value. + */ + public function &__get(string $key): mixed + { + if ($this->parentIsSet($key)) { + return $this->parentGet($key); + + } else { + return $this->data[$key]; + } + } + + + public function __isset(string $key): bool + { + return isset($this->data[$key]) || $this->parentIsSet($key); + } } diff --git a/src/compatibility-intf.php b/src/compatibility-intf.php new file mode 100644 index 00000000..ebfd19d1 --- /dev/null +++ b/src/compatibility-intf.php @@ -0,0 +1,37 @@ + 'John']); + $id = new SimpleIdentity(12, 'admin', ['name' => 'John']); Assert::same(12, $id->getId()); Assert::same(12, $id->id); @@ -27,10 +27,10 @@ test('', function () { test('', function () { - $id = new Identity('12'); + $id = new SimpleIdentity('12'); Assert::same(12, $id->getId()); - $id = new Identity('12345678901234567890'); + $id = new SimpleIdentity('12345678901234567890'); Assert::same('12345678901234567890', $id->getId()); }); From 2ca88d3979871973fa1255fc046f8f90a27e247c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 18:29:35 +0200 Subject: [PATCH 15/22] SimpleIdentity: uses __serialize & __unserialize --- src/Security/SimpleIdentity.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Security/SimpleIdentity.php b/src/Security/SimpleIdentity.php index 68579589..3c5ab1b1 100644 --- a/src/Security/SimpleIdentity.php +++ b/src/Security/SimpleIdentity.php @@ -120,4 +120,22 @@ public function __isset(string $key): bool { return isset($this->data[$key]) || $this->parentIsSet($key); } + + + public function __serialize(): array + { + return [ + 'id' => $this->id, + 'roles' => $this->roles, + 'data' => $this->data, + ]; + } + + + public function __unserialize(array $data): void + { + $this->id = $data['id'] ?? $data["\00Nette\\Security\\Identity\00id"] ?? 0; + $this->roles = $data['roles'] ?? $data["\00Nette\\Security\\Identity\00roles"] ?? []; + $this->data = $data['data'] ?? $data["\00Nette\\Security\\Identity\00data"] ?? []; + } } From fca6aa8cd5027b179ba74f1ee2ffdabcf8598a2b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 21 Jun 2022 16:15:47 +0200 Subject: [PATCH 16/22] used promoted properties --- src/Security/Passwords.php | 12 ++++-------- src/Security/SimpleAuthenticator.php | 15 +++++---------- src/Security/User.php | 13 +++---------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/Security/Passwords.php b/src/Security/Passwords.php index b0b6df9a..0117b4c0 100644 --- a/src/Security/Passwords.php +++ b/src/Security/Passwords.php @@ -19,18 +19,14 @@ class Passwords { use Nette\SmartObject; - private string $algo; - private array $options; - - /** * Chooses which secure algorithm is used for hashing and how to configure it. * @see https://php.net/manual/en/password.constants.php */ - public function __construct(string $algo = PASSWORD_DEFAULT, array $options = []) - { - $this->algo = $algo; - $this->options = $options; + public function __construct( + private string $algo = PASSWORD_DEFAULT, + private array $options = [], + ) { } diff --git a/src/Security/SimpleAuthenticator.php b/src/Security/SimpleAuthenticator.php index f3befcef..6a34a68a 100644 --- a/src/Security/SimpleAuthenticator.php +++ b/src/Security/SimpleAuthenticator.php @@ -19,21 +19,16 @@ class SimpleAuthenticator implements Authenticator { use Nette\SmartObject; - private array $passwords; - private array $roles; - private array $data; - - /** * @param array $passwords list of pairs username => password * @param array $roles list of pairs username => role[] * @param array $data list of pairs username => mixed[] */ - public function __construct(array $passwords, array $roles = [], array $data = []) - { - $this->passwords = $passwords; - $this->roles = $roles; - $this->data = $data; + public function __construct( + private array $passwords, + private array $roles = [], + private array $data = [], + ) { } diff --git a/src/Security/User.php b/src/Security/User.php index b98ec480..12daf570 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -50,23 +50,16 @@ class User /** @var callable[] function (User $sender): void; Occurs when the user is logged out */ public iterable $onLoggedOut = []; - /** Session storage for current user */ - private UserStorage $storage; - private ?Authenticator $authenticator; - private ?Authorizator $authorizator; private ?IIdentity $identity = null; private ?bool $authenticated = null; private ?int $logoutReason = null; public function __construct( - UserStorage $storage, - ?Authenticator $authenticator = null, - ?Authorizator $authorizator = null, + private UserStorage $storage, + private ?Authenticator $authenticator = null, + private ?Authorizator $authorizator = null, ) { - $this->storage = $storage; - $this->authenticator = $authenticator; - $this->authorizator = $authorizator; } From 8e88bb4b0d687a7122651f1242d880ef903c7b5a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 24 Sep 2021 14:12:52 +0200 Subject: [PATCH 17/22] deprecated magic properties except for SimpleIdentity (BC break) --- src/Security/User.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Security/User.php b/src/Security/User.php index 12daf570..e16d8b97 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -16,13 +16,13 @@ /** * User authentication and authorization. * - * @property-read bool $loggedIn - * @property-read IIdentity $identity - * @property-read string|int $id - * @property-read array $roles - * @property-read int $logoutReason - * @property Authenticator $authenticator - * @property Authorizator $authorizator + * @property-deprecated bool $loggedIn + * @property-deprecated IIdentity $identity + * @property-deprecated string|int $id + * @property-deprecated array $roles + * @property-deprecated int $logoutReason + * @property-deprecated Authenticator $authenticator + * @property-deprecated Authorizator $authorizator */ class User { From 4926c82fec515556f924389f7fd3acbc7c3f1dcb Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 18:36:34 +0200 Subject: [PATCH 18/22] readme: updated [WIP] --- readme.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/readme.md b/readme.md index eaf495ea..6cf404f1 100644 --- a/readme.md +++ b/readme.md @@ -72,7 +72,7 @@ $user->setExpiration(null); Expiration must be set to value equal or lower than the expiration of sessions. -The reason of the last logout can be obtained by method `$user->getLogoutReason()`, which returns either the constant `Nette\Security\IUserStorage::INACTIVITY` if the time expired or `IUserStorage::MANUAL` when the `logout()` method was called. +The reason of the last logout can be obtained by method `$user->getLogoutReason()`, which returns either the constant `Nette\Security\UserStorage::LOGOUT_INACTIVITY` if the time expired or `UserStorage::LOGOUT_MANUAL` when the `logout()` method was called. In presenters, you can verify login in the `startup()` method: @@ -102,12 +102,12 @@ $authenticator = new Nette\Security\SimpleAuthenticator([ This solution is more suitable for testing purposes. We will show you how to create an authenticator that will verify credentials against a database table. -An authenticator is an object that implements the [Nette\Security\IAuthenticator](https://api.nette.org/3.0/Nette/Security/IAuthenticator.html) interface with method `authenticate()`. Its task is either to return the so-called [identity](#Identity) or to throw an exception `Nette\Security\AuthenticationException`. It would also be possible to provide an fine-grain error code `IAuthenticator::IDENTITY_NOT_FOUND` or `IAuthenticator::INVALID_CREDENTIAL`. +An authenticator is an object that implements the [Nette\Security\Authenticator](https://api.nette.org/3.0/Nette/Security/Authenticator.html) interface with method `authenticate()`. Its task is either to return the so-called [identity](#Identity) or to throw an exception `Nette\Security\AuthenticationException`. It would also be possible to provide an fine-grain error code `Authenticator::IDENTITY_NOT_FOUND` or `Authenticator::INVALID_CREDENTIAL`. ```php use Nette; -class MyAuthenticator implements Nette\Security\IAuthenticator +class MyAuthenticator implements Nette\Security\Authenticator { private $database; private $passwords; @@ -118,10 +118,8 @@ class MyAuthenticator implements Nette\Security\IAuthenticator $this->passwords = $passwords; } - public function authenticate(array $credentials): Nette\Security\IIdentity + public function authenticate($username, $password): Nette\Security\IIdentity { - [$username, $password] = $credentials; - $row = $this->database->table('users') ->where('username', $username) ->fetch(); @@ -134,7 +132,7 @@ class MyAuthenticator implements Nette\Security\IAuthenticator throw new Nette\Security\AuthenticationException('Invalid password.'); } - return new Nette\Security\Identity( + return new Nette\Security\SimpleIdentity( $row->id, $row->role, // or array of roles ['name' => $row->username] @@ -180,7 +178,7 @@ Importantly, **when user logs out, identity is not deleted** and is still availa Thanks to this, you can still assume which user is at the computer and, for example, display personalized offers in the e-shop, however, you can only display his personal data after logging in. -Identity is an object that implements the [Nette\Security\IIdentity](https://api.nette.org/3.0/Nette/Security/IIdentity.html) interface, the default implementation is [Nette\Security\Identity](https://api.nette.org/3.0/Nette/Security/Identity.html). And as mentioned, identity is stored in the session, so if, for example, we change the role of some of the logged-in users, old data will be kept in the identity until he logs in again. +Identity is an object that implements the [Nette\Security\IIdentity](https://api.nette.org/3.0/Nette/Security/IIdentity.html) interface, the default implementation is [Nette\Security\SimpleIdentity](https://api.nette.org/3.0/Nette/Security/SimpleIdentity.html). And as mentioned, identity is stored in the session, so if, for example, we change the role of some of the logged-in users, old data will be kept in the identity until he logs in again. @@ -201,7 +199,7 @@ if ($user->isLoggedIn()) { // is user logged in? Roles ----- -The purpose of roles is to offer a more precise permission management and remain independent on the user name. As soon as user logs in, he is assigned one or more roles. Roles themselves may be simple strings, for example, `admin`, `member`, `guest`, etc. They are specified in the second argument of `Identity` constructor, either as a string or an array. +The purpose of roles is to offer a more precise permission management and remain independent on the user name. As soon as user logs in, he is assigned one or more roles. Roles themselves may be simple strings, for example, `admin`, `member`, `guest`, etc. They are specified in the second argument of `SimpleIdentity` constructor, either as a string or an array. As an authorization criterion, we will now use the method `isInRole()`, which checks whether the user is in the given role: @@ -211,7 +209,7 @@ if ($user->isInRole('admin')) { // is the admin role assigned to the user? } ``` -As you already know, logging the user out does not erase his identity. Thus, method `getIdentity()` still returns object `Identity`, including all granted roles. The Nette Framework adheres to the principle of "less code, more security", so when you are checking roles, you do not have to check whether the user is logged in too. Method `isInRole()` works with **effective roles**, ie if the user is logged in, roles assigned to identity are used, if he is not logged in, an automatic special role `guest` is used instead. +As you already know, logging the user out does not erase his identity. Thus, method `getIdentity()` still returns object `SimpleIdentity`, including all granted roles. The Nette Framework adheres to the principle of "less code, more security", so when you are checking roles, you do not have to check whether the user is logged in too. Method `isInRole()` works with **effective roles**, ie if the user is logged in, roles assigned to identity are used, if he is not logged in, an automatic special role `guest` is used instead. Authorizator @@ -223,10 +221,10 @@ In addition to roles, we will introduce the terms resource and operation: - **resource** is a logical unit of the application - article, page, user, menu item, poll, presenter, ... - **operation** is a specific activity, which user may or may not do with *resource* - view, edit, delete, vote, ... -An authorizer is an object that decides whether a given *role* has permission to perform a certain *operation* with specific *resource*. It is an object implementing the [Nette\Security\IAuthorizator](https://api.nette.org/3.0/Nette/Security/IAuthorizator.html) interface with only one method `isAllowed()`: +An authorizer is an object that decides whether a given *role* has permission to perform a certain *operation* with specific *resource*. It is an object implementing the [Nette\Security\Authorizator](https://api.nette.org/3.0/Nette/Security/Authorizator.html) interface with only one method `isAllowed()`: ```php -class MyAuthorizator implements Nette\Security\IAuthorizator +class MyAuthorizator implements Nette\Security\Authorizator { public function isAllowed($role, $resource, $operation): bool { @@ -434,3 +432,5 @@ It is possible to have several independent logged users within one site and one ```php $user->getStorage()->setNamespace('forum'); ``` + +[Continue...](https://doc.nette.org/en/3.0/access-control) From feb3af1d8df786065fdb139b8b29f410f5fe65a6 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 21 Jun 2022 16:21:33 +0200 Subject: [PATCH 19/22] SimpleAuthenticator: passwords can be hashed --- src/Security/SimpleAuthenticator.php | 4 ++++ tests/Security/SimpleAuthenticator.phpt | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Security/SimpleAuthenticator.php b/src/Security/SimpleAuthenticator.php index 6a34a68a..2af590b0 100644 --- a/src/Security/SimpleAuthenticator.php +++ b/src/Security/SimpleAuthenticator.php @@ -28,6 +28,7 @@ public function __construct( private array $passwords, private array $roles = [], private array $data = [], + private ?Passwords $verifier = null, ) { } @@ -55,6 +56,9 @@ public function authenticate(string $username, string $password): IIdentity protected function verifyPassword(string $password, string $passOrHash): bool { + if (preg_match('~\$.{50,}~A', $passOrHash)) { + return $this->verifier->verify($password, $passOrHash); + } return $password === $passOrHash; } } diff --git a/tests/Security/SimpleAuthenticator.phpt b/tests/Security/SimpleAuthenticator.phpt index ed0ecfc4..a8ebded2 100644 --- a/tests/Security/SimpleAuthenticator.phpt +++ b/tests/Security/SimpleAuthenticator.phpt @@ -6,6 +6,7 @@ declare(strict_types=1); +use Nette\Security\Passwords; use Nette\Security\SimpleAuthenticator; use Tester\Assert; @@ -14,16 +15,12 @@ require __DIR__ . '/../bootstrap.php'; $users = [ - 'john' => 'password123!', + 'john' => '$2a$12$dliX6LynG/iChDUF7DhKzulN7d3nU.l3/RozE1MmEaxxBWdZXppm2', 'admin' => 'admin', ]; $authenticator = new SimpleAuthenticator($users); -$identity = $authenticator->authenticate('john', 'password123!'); -Assert::type(Nette\Security\IIdentity::class, $identity); -Assert::equal('john', $identity->getId()); - $identity = $authenticator->authenticate('admin', 'admin'); Assert::type(Nette\Security\IIdentity::class, $identity); Assert::equal('admin', $identity->getId()); @@ -39,3 +36,16 @@ Assert::exception( Nette\Security\AuthenticationException::class, "User 'nobody' not found.", ); + + +$authenticator = new SimpleAuthenticator($users, verifier: new Passwords); + +$identity = $authenticator->authenticate('john', 'password123!'); +Assert::type(Nette\Security\IIdentity::class, $identity); +Assert::equal('john', $identity->getId()); + +Assert::exception( + fn() => $authenticator->authenticate('john', $users['john']), + Nette\Security\AuthenticationException::class, + 'Invalid password.', +); From 994938b242d62335d7ab1e2f7cb670c8dfc3344b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 6 Oct 2022 17:59:54 +0200 Subject: [PATCH 20/22] CookieIdentity WIP --- src/Bridges/SecurityHttp/CookieIdentity.php | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/Bridges/SecurityHttp/CookieIdentity.php diff --git a/src/Bridges/SecurityHttp/CookieIdentity.php b/src/Bridges/SecurityHttp/CookieIdentity.php new file mode 100644 index 00000000..915a8a8f --- /dev/null +++ b/src/Bridges/SecurityHttp/CookieIdentity.php @@ -0,0 +1,53 @@ +uid = $uid; + } + + + public function getId(): string + { + return $this->uid; + } + + + public function getRoles(): array + { + throw new Nette\NotSupportedException; + } + + + public function getData(): array + { + throw new Nette\NotSupportedException; + } +} From b8d9a6efee8451f98ee8d05abdd521a357b843ca Mon Sep 17 00:00:00 2001 From: Daniel Kurowski Date: Wed, 19 Oct 2022 15:10:08 +0200 Subject: [PATCH 21/22] UserStorage: support int in setExpiration() --- src/Bridges/SecurityHttp/CookieStorage.php | 4 ++-- src/Bridges/SecurityHttp/SessionStorage.php | 2 +- src/Security/UserStorage.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Bridges/SecurityHttp/CookieStorage.php b/src/Bridges/SecurityHttp/CookieStorage.php index 23f19ce2..26462f22 100644 --- a/src/Bridges/SecurityHttp/CookieStorage.php +++ b/src/Bridges/SecurityHttp/CookieStorage.php @@ -29,7 +29,7 @@ final class CookieStorage implements Nette\Security\UserStorage private string $cookieName = 'userid'; private ?string $cookieDomain = null; private string $cookieSameSite = 'Lax'; - private ?string $cookieExpiration = null; + private string|int|null $cookieExpiration = null; public function __construct(Http\IRequest $request, Http\IResponse $response) @@ -80,7 +80,7 @@ public function getState(): array } - public function setExpiration(?string $expire, bool $clearIdentity): void + public function setExpiration(string|int|null $expire, bool $clearIdentity): void { $this->cookieExpiration = $expire; } diff --git a/src/Bridges/SecurityHttp/SessionStorage.php b/src/Bridges/SecurityHttp/SessionStorage.php index b0554625..1ebe6677 100644 --- a/src/Bridges/SecurityHttp/SessionStorage.php +++ b/src/Bridges/SecurityHttp/SessionStorage.php @@ -73,7 +73,7 @@ public function getState(): array } - public function setExpiration(?string $time, bool $clearIdentity = false): void + public function setExpiration(string|int|null $time, bool $clearIdentity = false): void { $this->expireTime = $time ? (int) Nette\Utils\DateTime::from($time)->format('U') : null; $this->expireIdentity = $clearIdentity; diff --git a/src/Security/UserStorage.php b/src/Security/UserStorage.php index 7abedac4..4e3d470d 100644 --- a/src/Security/UserStorage.php +++ b/src/Security/UserStorage.php @@ -39,5 +39,5 @@ function getState(): array; /** * Enables log out from the persistent storage after inactivity (like '20 minutes'). */ - function setExpiration(?string $expire, bool $clearIdentity): void; + function setExpiration(string|int|null $expire, bool $clearIdentity): void; } From f6d60e9ce036896cea9e6cb8d20cbc772937426f Mon Sep 17 00:00:00 2001 From: Daniel Kurowski Date: Wed, 19 Oct 2022 15:17:03 +0200 Subject: [PATCH 22/22] update expiration type in test as well --- tests/Security/MockUserStorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Security/MockUserStorage.php b/tests/Security/MockUserStorage.php index a162ee01..8b59bcdf 100644 --- a/tests/Security/MockUserStorage.php +++ b/tests/Security/MockUserStorage.php @@ -29,7 +29,7 @@ public function getState(): array } - public function setExpiration(?string $expire, bool $clearIdentity): void + public function setExpiration(string|int|null $expire, bool $clearIdentity): void { } }