From 6ba307319858416ed910b7df389be636f3f2cca0 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 15:30:34 +0100 Subject: [PATCH 01/20] opened 4.0-dev --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 16f8e372..0d0db4f4 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 911d1facdbcc3e8edbc713655d48031ffc91e81d Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 17:38:22 +0100 Subject: [PATCH 02/20] 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 cf1784de..58b8cf7c 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', '8.3'] + php: ['8.0', '8.1', '8.2', '8.3'] 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 0d0db4f4..40d4c49c 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 || ~4.0.0" }, "require-dev": { diff --git a/readme.md b/readme.md index 74854f9c..354f7ce6 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.3. +It requires PHP version 8.0 and supports PHP up to 8.3. [Support Me](https://github.com/sponsors/dg) From 1d54349eaf9ef7b09628553f82064c85198e9605 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 16:43:32 +0100 Subject: [PATCH 03/20] composer: updated dependencies --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 40d4c49c..16a5c1b9 100644 --- a/composer.json +++ b/composer.json @@ -19,12 +19,12 @@ "nette/utils": "^3.2.1 || ~4.0.0" }, "require-dev": { - "nette/di": "^3.0.1", - "nette/http": "^3.0.0", - "nette/tester": "^2.0", - "tracy/tracy": "^2.4", + "nette/di": "^3.1 || ^4.0", + "nette/http": "^4.0", + "nette/tester": "^2.4", + "tracy/tracy": "^2.9", "phpstan/phpstan-nette": "^1.0", - "mockery/mockery": "^1.3.6" + "mockery/mockery": "^1.5" }, "conflict": { "nette/di": "<3.0-stable", From 968b8eebf3ff5f24d1e4b6f93df55ab8149382bb Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 12 Dec 2021 18:12:40 +0100 Subject: [PATCH 04/20] 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 12764efd..41f69043 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 d1a801bc..7931611d 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 10dafe72..1503030d 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -76,7 +76,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 a0c48ab2..e093ee56 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 773d7d3bd5a7ad4ec609d347897ae30074417aeb Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 7 Apr 2022 18:04:32 +0200 Subject: [PATCH 05/20] 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 9a94a8db..558aa40e 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 e093ee56..118890be 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 78178b172aef30c738d90f63f499d065580fcb3d Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Mar 2021 19:15:45 +0100 Subject: [PATCH 06/20] 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 41f69043..6c5e77cb 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 MinLength = 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 c1d2d491..6c208e22 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 476514b3..a5db7d88 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 7931611d..7cbcbd5b 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 cbf2aae8..726a5cf6 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 1503030d..5bb9d7fd 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -41,35 +41,25 @@ class User public const LOGOUT_MANUAL = self::LogoutManual; public const LOGOUT_INACTIVITY = self::LogoutInactivity; - /** @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 array $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 array $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 8efcf6d075b1c180b4155a18e41bd5a73a286e01 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 12 Dec 2021 18:12:59 +0100 Subject: [PATCH 07/20] 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 | 4 ++-- src/Security/User.php | 26 ++++++--------------- tests/Security/MockUserStorage.legacy.php | 3 ++- 8 files changed, 19 insertions(+), 43 deletions(-) diff --git a/src/Bridges/SecurityHttp/SessionStorage.php b/src/Bridges/SecurityHttp/SessionStorage.php index 6c208e22..a2f18abf 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 267fcccd..106f6cb8 100644 --- a/src/Security/Authorizator.php +++ b/src/Security/Authorizator.php @@ -31,11 +31,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 a5db7d88..460f49ff 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 7cbcbd5b..e69ca4f4 100644 --- a/src/Security/Permission.php +++ b/src/Security/Permission.php @@ -424,7 +424,7 @@ public function deny( * @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; @@ -439,7 +439,7 @@ public function removeAllow($roles = self::All, $resources = self::All, $privile * @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; diff --git a/src/Security/User.php b/src/Security/User.php index 5bb9d7fd..8a1c1b8b 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 @@ -78,10 +78,7 @@ public function __construct( } - /** - * @return UserStorage|IUserStorage - */ - final public function getStorage() + final public function getStorage(): UserStorage|IUserStorage { return $this->storage; } @@ -96,7 +93,7 @@ final public function getStorage() * @throws AuthenticationException if authentication was not successful */ public function login( - $user, + string|IIdentity $user, #[\SensitiveParameter] ?string $password = null ): void @@ -202,9 +199,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; @@ -219,9 +215,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; @@ -264,15 +259,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); @@ -346,9 +335,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 7ca9448117170a77c07f4c5dd4bed776ec9e095e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 2 Mar 2021 15:03:47 +0100 Subject: [PATCH 08/20] 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 8a1c1b8b..4a7469ee 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -226,14 +226,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.'); } @@ -262,12 +257,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); @@ -346,14 +335,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 382438465e154a0f0d7c7f047db79c23020ae6b6 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 12 Dec 2021 18:13:42 +0100 Subject: [PATCH 09/20] 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 4a7469ee..0ebc3589 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -54,7 +54,7 @@ class User public array $onLoggedOut = []; /** Session storage for current user */ - private UserStorage|IUserStorage $storage; + private UserStorage $storage; private ?IAuthenticator $authenticator; private ?Authorizator $authorizator; private ?IIdentity $identity = null; @@ -63,22 +63,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; } @@ -111,13 +106,8 @@ public function login( $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); @@ -130,16 +120,7 @@ public function login( 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) { @@ -178,17 +159,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) @@ -255,12 +230,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 558aa40e..5d6413e6 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 118890be..ee26305e 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 982fc3e40ff9594ff4692b6baf81bd7538be9d5c Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 11 Mar 2021 21:55:20 +0100 Subject: [PATCH 10/20] 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 ca2fc326c8f05e9722a1f7875fc936a5b03a4488 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 18:40:59 +0200 Subject: [PATCH 11/20] 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 12/20] 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 d79e6364..05a2ac1d 100644 --- a/src/Security/Authenticator.php +++ b/src/Security/Authenticator.php @@ -13,7 +13,7 @@ /** * Performs authentication. */ -interface Authenticator extends IAuthenticator +interface Authenticator { /** Exception error code */ public const @@ -22,6 +22,13 @@ interface Authenticator extends IAuthenticator Failure = 3, NotApproved = 4; + /** Deprecated */ + public const + IDENTITY_NOT_FOUND = self::IdentityNotFound, + INVALID_CREDENTIAL = self::InvalidCredential, + FAILURE = self::Failure, + NOT_APPROVED = self::NotApproved; + /** * 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; @@ -98,9 +98,7 @@ public function login( $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 @@ -191,7 +189,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; @@ -201,7 +199,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.'); @@ -214,7 +212,7 @@ final public function getAuthenticator(): IAuthenticator /** * Returns authentication handler. */ - final public function getAuthenticatorIfExists(): ?IAuthenticator + final public function getAuthenticatorIfExists(): ?Authenticator { return $this->authenticator; } From fb0c4951f9382fc2b9defb177843514150e18cec Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 17:35:17 +0200 Subject: [PATCH 13/20] 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 2b5031a33de8c67430b5c40338fc7e2ba6dc4c79 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 20 Sep 2021 18:29:35 +0200 Subject: [PATCH 14/20] 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 bbd96df5a43a0aa747e4220b75e6c38306e72ae3 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 21 Jun 2022 16:15:47 +0200 Subject: [PATCH 15/20] used promoted properties --- src/Security/Passwords.php | 12 ++++-------- src/Security/SimpleAuthenticator.php | 14 +++----------- src/Security/User.php | 13 +++---------- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/src/Security/Passwords.php b/src/Security/Passwords.php index 460f49ff..f7b55b9a 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 726a5cf6..9f9b0efb 100644 --- a/src/Security/SimpleAuthenticator.php +++ b/src/Security/SimpleAuthenticator.php @@ -19,11 +19,6 @@ 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[] @@ -31,13 +26,10 @@ class SimpleAuthenticator implements Authenticator */ public function __construct( #[\SensitiveParameter] - array $passwords, - array $roles = [], - array $data = [] + private array $passwords, + private array $roles = [], + private array $data = [], ) { - $this->passwords = $passwords; - $this->roles = $roles; - $this->data = $data; } diff --git a/src/Security/User.php b/src/Security/User.php index f51824e2..b04b790f 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -53,23 +53,16 @@ class User /** @var callable[] function (User $sender): void; Occurs when the user is logged out */ public array $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 0bee0e07780673b192fdedffafaa03aa3f7318e7 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Fri, 24 Sep 2021 14:12:52 +0200 Subject: [PATCH 16/20] 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 b04b790f..baae406f 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 fdd4ba0e2ce445d5569301ee15d46b4e255fa60b Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sun, 27 Nov 2022 22:32:30 +0100 Subject: [PATCH 17/20] uppercase constants marked as deprecated --- src/Security/Authenticator.php | 17 +++++++++++------ src/Security/Authorizator.php | 5 +++++ src/Security/User.php | 14 +++++++++----- src/Security/UserStorage.php | 3 +++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/Security/Authenticator.php b/src/Security/Authenticator.php index 05a2ac1d..4bc1df39 100644 --- a/src/Security/Authenticator.php +++ b/src/Security/Authenticator.php @@ -22,12 +22,17 @@ interface Authenticator Failure = 3, NotApproved = 4; - /** Deprecated */ - public const - IDENTITY_NOT_FOUND = self::IdentityNotFound, - INVALID_CREDENTIAL = self::InvalidCredential, - FAILURE = self::Failure, - NOT_APPROVED = self::NotApproved; + /** @deprecated use Authenticator::IdentityNotFound */ + public const IDENTITY_NOT_FOUND = self::IdentityNotFound; + + /** @deprecated use Authenticator::InvalidCredential */ + public const INVALID_CREDENTIAL = self::InvalidCredential; + + /** @deprecated use Authenticator::Failure */ + public const FAILURE = self::Failure; + + /** @deprecated use Authenticator::NotApproved */ + public const NOT_APPROVED = self::NotApproved; /** * Performs an authentication. diff --git a/src/Security/Authorizator.php b/src/Security/Authorizator.php index 106f6cb8..a8fa356e 100644 --- a/src/Security/Authorizator.php +++ b/src/Security/Authorizator.php @@ -25,8 +25,13 @@ interface Authorizator /** Permission type: deny */ public const Deny = false; + /** @deprecated use Authorizator::All */ public const ALL = self::All; + + /** @deprecated use Authorizator::Allow */ public const ALLOW = self::Allow; + + /** @deprecated use Authorizator::Deny */ public const DENY = self::Deny; /** diff --git a/src/Security/User.php b/src/Security/User.php index baae406f..96e0a5c2 100644 --- a/src/Security/User.php +++ b/src/Security/User.php @@ -28,19 +28,23 @@ class User { use Nette\SmartObject; - /** @deprecated */ - public const - MANUAL = UserStorage::LOGOUT_MANUAL, - INACTIVITY = UserStorage::LOGOUT_INACTIVITY; - /** Log-out reason */ public const LogoutManual = UserStorage::LogoutManual, LogoutInactivity = UserStorage::LogoutInactivity; + /** @deprecated use User::LogoutManual */ public const LOGOUT_MANUAL = self::LogoutManual; + + /** @deprecated use User::LogoutManual */ + public const MANUAL = self::LogoutManual; + + /** @deprecated use User::LogoutInactivity */ public const LOGOUT_INACTIVITY = self::LogoutInactivity; + /** @deprecated use User::LogoutInactivity */ + public const INACTIVITY = self::LogoutInactivity; + /** default role for unauthenticated user */ public string $guestRole = 'guest'; diff --git a/src/Security/UserStorage.php b/src/Security/UserStorage.php index 1b5e97e3..e4ca9427 100644 --- a/src/Security/UserStorage.php +++ b/src/Security/UserStorage.php @@ -20,7 +20,10 @@ interface UserStorage LogoutManual = 1, LogoutInactivity = 2; + /** @deprecated use User::LogoutManual */ public const LOGOUT_MANUAL = self::LogoutManual; + + /** @deprecated use User::LogoutInactivity */ public const LOGOUT_INACTIVITY = self::LogoutInactivity; /** From 47bdb6fb83dddada515f6f0bc2d8e0d575680c80 Mon Sep 17 00:00:00 2001 From: Blazik Date: Tue, 29 Aug 2023 17:14:32 +0200 Subject: [PATCH 18/20] updated package name --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 16a5c1b9..38684854 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "nette/security", + "name": "involve-digital/security", "description": "🔑 Nette Security: provides authentication, authorization and a role-based access control management via ACL (Access Control List)", "keywords": ["nette", "authentication", "authorization", "ACL"], "homepage": "https://nette.org", From 83e4df4c7f62545850fa4f26e8f147072a61dd3b Mon Sep 17 00:00:00 2001 From: Blazik Date: Tue, 29 Aug 2023 17:35:18 +0200 Subject: [PATCH 19/20] updated package name --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 38684854..16a5c1b9 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "involve-digital/security", + "name": "nette/security", "description": "🔑 Nette Security: provides authentication, authorization and a role-based access control management via ACL (Access Control List)", "keywords": ["nette", "authentication", "authorization", "ACL"], "homepage": "https://nette.org", From e1cd3a623e93ca9e4b7f8d9d90730875daae7a07 Mon Sep 17 00:00:00 2001 From: Blazik Date: Tue, 29 Aug 2023 18:44:03 +0200 Subject: [PATCH 20/20] updated package name --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 16a5c1b9..38684854 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "nette/security", + "name": "involve-digital/security", "description": "🔑 Nette Security: provides authentication, authorization and a role-based access control management via ACL (Access Control List)", "keywords": ["nette", "authentication", "authorization", "ACL"], "homepage": "https://nette.org",