Skip to content

Commit

Permalink
added UserStorage, successor for IUserStorage
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Jan 3, 2021
1 parent d7b8fa1 commit 8a38f25
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/Security/IUserStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


/**
* Interface for persistent storage for user object data.
* @deprecated use Nette\Security\UserStorage
*/
interface IUserStorage
{
Expand Down
61 changes: 45 additions & 16 deletions src/Security/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class User
/** @var callable[] function (User $sender): void; Occurs when the user is logged out */
public $onLoggedOut;

/** @var IUserStorage Session storage for current user */
/** @var UserStorage|IUserStorage Session storage for current user */
private $storage;

/** @var IAuthenticator|null */
Expand All @@ -64,17 +64,24 @@ class User


public function __construct(
IUserStorage $storage,
UserStorage $storage = null,
IAuthenticator $authenticator = null,
Authorizator $authorizator = null
Authorizator $authorizator = null,
IUserStorage $legacyStorage = null
) {
$this->storage = $storage;
$this->storage = $storage ?? $legacyStorage; // back compatibility
if (!$this->storage) {
throw new Nette\InvalidStateException('UserStorage has not been set.');
}
$this->authenticator = $authenticator;
$this->authorizator = $authorizator;
}


final public function getStorage(): IUserStorage
/**
* @return UserStorage|IUserStorage
*/
final public function getStorage()
{
return $this->storage;
}
Expand All @@ -97,8 +104,12 @@ public function login($user, string $password = null): void
? $authenticator->authenticate($user, $password)
: $authenticator->authenticate(func_get_args());
}
$this->storage->setIdentity($user);
$this->storage->setAuthenticated(true);
if ($this->storage instanceof UserStorage) {
$this->storage->saveAuthentication($user);
} else {
$this->storage->setIdentity($user);
$this->storage->setAuthenticated(true);
}
$this->identity = $user;
$this->authenticated = true;
$this->logoutReason = null;
Expand All @@ -113,14 +124,20 @@ final public function logout(bool $clearIdentity = false): void
{
if ($this->isLoggedIn()) {
$this->onLoggedOut($this);
}

if ($this->storage instanceof UserStorage) {
$this->storage->clearAuthentication($clearIdentity);
} else {
$this->storage->setAuthenticated(false);
$this->authenticated = false;
if ($clearIdentity) {
$this->storage->setIdentity(null);
}
$this->logoutReason = self::MANUAL;
}
if ($clearIdentity) {
$this->storage->setIdentity(null);
$this->identity = null;
}

$this->authenticated = false;
$this->identity = $clearIdentity ? null : $this->identity;
}


Expand Down Expand Up @@ -150,9 +167,17 @@ final public function getIdentity(): ?IIdentity

private function getStoredData(): void
{
$this->authenticated = $this->storage->isAuthenticated();
$this->identity = $this->storage->getIdentity();
$this->logoutReason = $this->storage->getLogoutReason();
if ($this->storage instanceof UserStorage) {
(function (bool $state, ?IIdentity $identity, ?int $reason) {
$this->authenticated = $state;
$this->identity = $identity;
$this->logoutReason = $reason;
})(...$this->storage->getState());
} else {
$this->authenticated = $this->storage->isAuthenticated();
$this->identity = $this->storage->getIdentity();
$this->logoutReason = $this->storage->getLogoutReason();
}
}


Expand Down Expand Up @@ -235,7 +260,11 @@ public function setExpiration($expire, /*int*/$flags = 0)
$clearIdentity = $clearIdentity || func_get_arg(2);
trigger_error(__METHOD__ . '() third parameter is deprecated, use flag setExpiration($time, IUserStorage::CLEAR_IDENTITY)', E_USER_DEPRECATED);
}
$this->storage->setExpiration($expire, $clearIdentity ? IUserStorage::CLEAR_IDENTITY : 0);

$arg = $this->storage instanceof UserStorage
? $clearIdentity
: ($clearIdentity ? IUserStorage::CLEAR_IDENTITY : 0);
$this->storage->setExpiration($expire, $arg);
return $this;
}

Expand Down
43 changes: 43 additions & 0 deletions src/Security/UserStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/

declare(strict_types=1);

namespace Nette\Security;


/**
* Interface for persistent storage for user object data.
*/
interface UserStorage
{
/** Log-out reason */
public const
LOGOUT_MANUAL = 1,
LOGOUT_INACTIVITY = 2;

/**
* Sets the authenticated state of user.
*/
function saveAuthentication(IIdentity $identity): void;

/**
* Removed authenticated state of user.
*/
function clearAuthentication(bool $clearIdentity): void;

/**
* Returns user authenticated state, identity and logout reason.
* @return array{bool, ?IIdentity, ?int}
*/
function getState(): array;

/**
* Enables log out from the persistent storage after inactivity (like '20 minutes').
*/
function setExpiration(?string $expire, bool $clearIdentity): void;
}
45 changes: 45 additions & 0 deletions tests/Security/MockUserStorage.legacy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

class MockUserStorage implements Nette\Security\IUserStorage
{
private $auth = false;

private $identity;


public function setAuthenticated(bool $state)
{
$this->auth = $state;
}


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;
}
}
28 changes: 9 additions & 19 deletions tests/Security/MockUserStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,34 @@

declare(strict_types=1);

class MockUserStorage implements Nette\Security\IUserStorage
class MockUserStorage implements Nette\Security\UserStorage
{
private $auth = false;

private $identity;


public function setAuthenticated(bool $state)
{
$this->auth = $state;
}


public function isAuthenticated(): bool
{
return $this->auth;
}


public function setIdentity(Nette\Security\IIdentity $identity = null)
public function saveAuthentication(Nette\Security\IIdentity $identity): void
{
$this->auth = true;
$this->identity = $identity;
}


public function getIdentity(): ?Nette\Security\IIdentity
public function clearAuthentication(bool $clearIdentity): void
{
return $this->identity;
$this->auth = false;
$this->identity = $clearIdentity ? null : $this->identity;
}


public function setExpiration(?string $time, int $flags = 0)
public function getState(): array
{
return [$this->auth, $this->identity, null];
}


public function getLogoutReason(): ?int
public function setExpiration(?string $expire, bool $clearIdentity): void
{
return null;
}
}
4 changes: 2 additions & 2 deletions tests/Security/User.authentication.legacy.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use Tester\Assert;


require __DIR__ . '/../bootstrap.php';
require __DIR__ . '/MockUserStorage.php';
require __DIR__ . '/MockUserStorage.legacy.php';

// Setup environment
$_COOKIE = [];
Expand All @@ -37,7 +37,7 @@ class Authenticator implements IAuthenticator
}


$user = new Nette\Security\User(new MockUserStorage);
$user = new Nette\Security\User(null, null, null, new MockUserStorage);

$counter = (object) [
'login' => 0,
Expand Down

0 comments on commit 8a38f25

Please sign in to comment.